Merge remote-tracking branches 'spi/fix/atmel', 'spi/fix/bcm63xx', 'spi/fix/doc'...
authorMark Brown <broonie@kernel.org>
Mon, 3 Jul 2017 15:21:02 +0000 (16:21 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 3 Jul 2017 15:21:02 +0000 (16:21 +0100)
1707 files changed:
Documentation/acpi/acpi-lid.txt
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/pm/cpufreq.rst
Documentation/admin-guide/pm/index.rst
Documentation/admin-guide/pm/intel_pstate.rst [new file with mode: 0644]
Documentation/cpu-freq/intel-pstate.txt [deleted file]
Documentation/devicetree/bindings/clock/sunxi-ccu.txt
Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt
Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
Documentation/devicetree/bindings/mfd/stm32-timers.txt
Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt
Documentation/devicetree/bindings/net/dsa/b53.txt
Documentation/devicetree/bindings/net/dsa/marvell.txt
Documentation/devicetree/bindings/net/fsl-fec.txt
Documentation/devicetree/bindings/net/smsc911x.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Documentation/devicetree/bindings/staging/ion/hi6220-ion.txt [deleted file]
Documentation/devicetree/bindings/usb/dwc2.txt
Documentation/input/devices/edt-ft5x06.rst
Documentation/networking/dpaa.txt [new file with mode: 0644]
Documentation/networking/scaling.txt
Documentation/networking/tcp.txt
Documentation/sound/hd-audio/models.rst
Documentation/usb/typec.rst
Documentation/watchdog/watchdog-parameters.txt
MAINTAINERS
Makefile
arch/alpha/kernel/osf_sys.c
arch/arc/include/asm/processor.h
arch/arc/mm/mmap.c
arch/arm/Kconfig
arch/arm/boot/compressed/efi-header.S
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/am335x-sl50.dts
arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/imx53-qsrb.dts
arch/arm/boot/dts/imx6sx-sdb.dts
arch/arm/boot/dts/imx6ul-14x14-evk.dts
arch/arm/boot/dts/include/arm [deleted symlink]
arch/arm/boot/dts/include/arm64 [deleted symlink]
arch/arm/boot/dts/include/dt-bindings [deleted symlink]
arch/arm/boot/dts/keystone-k2l-netcp.dtsi
arch/arm/boot/dts/keystone-k2l.dtsi
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/mt7623.dtsi
arch/arm/boot/dts/omap3-gta04.dtsi
arch/arm/boot/dts/omap4-panda-a4.dts
arch/arm/boot/dts/omap4-panda-es.dts
arch/arm/boot/dts/sunxi-h3-h5.dtsi
arch/arm/boot/dts/versatile-pb.dts
arch/arm/common/mcpm_entry.c
arch/arm/configs/gemini_defconfig [new file with mode: 0644]
arch/arm/include/asm/device.h
arch/arm/include/asm/kvm_coproc.h
arch/arm/include/asm/pgtable-nommu.h
arch/arm/kernel/setup.c
arch/arm/kvm/coproc.c
arch/arm/kvm/handle_exit.c
arch/arm/kvm/hyp/Makefile
arch/arm/kvm/hyp/switch.c
arch/arm/kvm/init.S
arch/arm/kvm/trace.h
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/pm.c
arch/arm/mach-bcm/bcm_kona_smc.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-davinci/pm.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-spear/time.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmap.c
arch/arm/mm/mmu.c
arch/arm64/Kconfig
arch/arm64/Kconfig.platforms
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi [deleted symlink]
arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
arch/arm64/boot/dts/hisilicon/hi6220.dtsi
arch/arm64/boot/dts/include/arm [deleted symlink]
arch/arm64/boot/dts/include/arm64 [deleted symlink]
arch/arm64/boot/dts/include/dt-bindings [deleted symlink]
arch/arm64/boot/dts/marvell/armada-3720-db.dts
arch/arm64/boot/dts/marvell/armada-37xx.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
arch/arm64/boot/dts/mediatek/mt8173-evb.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/configs/defconfig
arch/arm64/include/asm/acpi.h
arch/arm64/include/asm/atomic_ll_sc.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/pci.c
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/vdso.c
arch/arm64/kernel/vdso/gettimeofday.S
arch/arm64/kvm/hyp-init.S
arch/arm64/kvm/hyp/Makefile
arch/arm64/kvm/vgic-sys-reg-v3.c
arch/arm64/net/bpf_jit_comp.c
arch/blackfin/include/asm/processor.h
arch/c6x/include/asm/processor.h
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v32/kernel/process.c
arch/cris/boot/dts/include/dt-bindings [deleted symlink]
arch/cris/include/asm/processor.h
arch/frv/include/asm/processor.h
arch/frv/include/asm/timex.h
arch/frv/kernel/process.c
arch/frv/mm/elf-fdpic.c
arch/h8300/include/asm/processor.h
arch/h8300/kernel/process.c
arch/hexagon/include/asm/processor.h
arch/hexagon/kernel/process.c
arch/hexagon/mm/uaccess.c
arch/ia64/include/asm/processor.h
arch/m32r/include/asm/processor.h
arch/m32r/kernel/process.c
arch/m68k/include/asm/processor.h
arch/m68k/kernel/process.c
arch/metag/boot/dts/include/dt-bindings [deleted symlink]
arch/microblaze/include/asm/processor.h
arch/microblaze/kernel/process.c
arch/mips/boot/Makefile
arch/mips/boot/dts/include/dt-bindings [deleted symlink]
arch/mips/include/asm/highmem.h
arch/mips/include/asm/kprobes.h
arch/mips/include/asm/pgtable-32.h
arch/mips/kernel/branch.c
arch/mips/kernel/entry.S
arch/mips/kernel/ftrace.c
arch/mips/kernel/head.S
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/pm-cps.c
arch/mips/kernel/process.c
arch/mips/kernel/traps.c
arch/mips/kvm/tlb.c
arch/mips/math-emu/dp_maddf.c
arch/mips/math-emu/sp_maddf.c
arch/mips/mm/dma-default.c
arch/mips/mm/mmap.c
arch/mips/mm/pgtable-32.c
arch/mn10300/include/asm/processor.h
arch/mn10300/kernel/process.c
arch/nios2/include/asm/processor.h
arch/openrisc/include/asm/processor.h
arch/openrisc/kernel/process.c
arch/parisc/include/asm/processor.h
arch/parisc/kernel/process.c
arch/parisc/kernel/sys_parisc.c
arch/powerpc/Kconfig
arch/powerpc/boot/dts/include/dt-bindings [deleted symlink]
arch/powerpc/include/asm/book3s/64/hash-4k.h
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/kprobes.h
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/topology.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/include/asm/xive.h
arch/powerpc/include/uapi/asm/cputable.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/dt_cpu_ftrs.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/idle_book3s.S
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/trace/ftrace_64_mprofile.S
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/Makefile
arch/powerpc/kvm/book3s_64_vio_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_interrupts.S
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/book3s_xive_template.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/dump_linuxpagetables.c
arch/powerpc/mm/hugetlbpage-radix.c
arch/powerpc/mm/mmap.c
arch/powerpc/mm/mmu_context_book3s64.c
arch/powerpc/mm/slice.c
arch/powerpc/perf/perf_regs.c
arch/powerpc/perf/power9-pmu.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/cell/spufs/coredump.c
arch/powerpc/platforms/powernv/npu-dma.c
arch/powerpc/platforms/powernv/subcore.c
arch/powerpc/platforms/pseries/hotplug-memory.c
arch/powerpc/sysdev/simple_gpio.c
arch/powerpc/sysdev/xive/common.c
arch/s390/Kconfig
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/debug.h
arch/s390/include/asm/dis.h
arch/s390/include/asm/kprobes.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/sysinfo.h
arch/s390/kernel/debug.c
arch/s390/kernel/entry.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/ipl.c
arch/s390/kernel/process.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/gaccess.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/lib/probes.c
arch/s390/lib/uaccess.c
arch/s390/mm/mmap.c
arch/score/include/asm/processor.h
arch/score/kernel/process.c
arch/sh/mm/mmap.c
arch/sparc/Kconfig
arch/sparc/include/asm/hugetlb.h
arch/sparc/include/asm/mmu_64.h
arch/sparc/include/asm/mmu_context_64.h
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pil.h
arch/sparc/include/asm/processor_32.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/setup.h
arch/sparc/include/asm/vio.h
arch/sparc/kernel/ds.c
arch/sparc/kernel/ftrace.c
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/kernel.h
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/tsb.S
arch/sparc/kernel/ttable_64.S
arch/sparc/kernel/vio.c
arch/sparc/lib/Makefile
arch/sparc/lib/multi3.S [new file with mode: 0644]
arch/sparc/mm/hugetlbpage.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/sparc/mm/tsb.c
arch/sparc/mm/ultra.S
arch/tile/include/asm/processor.h
arch/tile/mm/hugetlbpage.c
arch/um/include/asm/processor-generic.h
arch/um/kernel/um_arch.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/kaslr.c
arch/x86/boot/compressed/misc.c
arch/x86/boot/compressed/misc.h
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/events/intel/core.c
arch/x86/events/intel/uncore.c
arch/x86/include/asm/extable.h
arch/x86/include/asm/kvm_emulate.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/uaccess.h
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/fpu/init.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kvm.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/setup.c
arch/x86/kernel/sys_x86_64.c
arch/x86/kernel/tboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/unwind_frame.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu.h
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/pmu_intel.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/extable.c
arch/x86/mm/hugetlbpage.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/pageattr.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/quirks.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/mmu.c
arch/x86/xen/mmu_pv.c
arch/xtensa/include/asm/irq.h
arch/xtensa/include/asm/processor.h
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/syscall.c
arch/xtensa/kernel/vmlinux.lds.S
arch/xtensa/platforms/iss/simdisk.c
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
arch/xtensa/platforms/xtfpga/setup.c
block/bfq-cgroup.c
block/bfq-iosched.c
block/bfq-iosched.h
block/bio-integrity.c
block/bio.c
block/blk-cgroup.c
block/blk-core.c
block/blk-mq-sched.c
block/blk-mq-sched.h
block/blk-mq.c
block/blk-sysfs.c
block/blk-throttle.c
block/blk.h
block/cfq-iosched.c
block/partition-generic.c
block/partitions/msdos.c
crypto/asymmetric_keys/public_key.c
crypto/asymmetric_keys/verify_pefile.c
crypto/asymmetric_keys/x509_cert_parser.c
crypto/drbg.c
crypto/gcm.c
crypto/skcipher.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/utresrc.c
drivers/acpi/arm64/iort.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/device_pm.c
drivers/acpi/nfit/mce.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/ata/ahci.c
drivers/ata/libahci_platform.c
drivers/ata/libata-core.c
drivers/ata/sata_mv.c
drivers/ata/sata_rcar.c
drivers/base/power/main.c
drivers/base/power/wakeup.c
drivers/block/drbd/drbd_req.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/char/lp.c
drivers/char/mem.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/random.c
drivers/clk/meson/Kconfig
drivers/clk/sunxi-ng/Kconfig
drivers/clk/sunxi-ng/ccu-sun50i-a64.h
drivers/clk/sunxi-ng/ccu-sun5i.c
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.h
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/cadence_ttc_timer.c
drivers/clocksource/timer-sun5i.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Makefile
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/kirkwood-cpufreq.c
drivers/cpuidle/dt_idle_states.c
drivers/dax/super.c
drivers/devfreq/event/exynos-nocp.c
drivers/devfreq/event/exynos-ppmu.c
drivers/dma/ep93xx_dma.c
drivers/dma/mv_xor_v2.c
drivers/dma/pl330.c
drivers/dma/sh/rcar-dmac.c
drivers/dma/sh/usb-dmac.c
drivers/edac/amd64_edac.c
drivers/firmware/dmi-id.c
drivers/firmware/dmi_scan.c
drivers/firmware/efi/efi-bgrt.c
drivers/firmware/efi/efi-pstore.c
drivers/firmware/efi/libstub/secureboot.c
drivers/firmware/google/vpd.c
drivers/firmware/ti_sci.c
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-crystalcove.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
drivers/gpu/drm/arm/hdlcd_crtc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
drivers/gpu/drm/bridge/synopsys/Kconfig
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_plane.c
drivers/gpu/drm/etnaviv/etnaviv_gem.h
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/gma500/psb_intel_lvds.c
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
drivers/gpu/drm/i915/gvt/execlist.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/render.c
drivers/gpu/drm/i915/gvt/sched_policy.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_request.c
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_guc_submission.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_pvinfo.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_vgpu.c
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_cdclk.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_aux_backlight.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_lpe_audio.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lspcon.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_psr.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_uc.h
drivers/gpu/drm/i915/selftests/i915_gem_context.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mediatek/mtk_hdmi.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/Kconfig
drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_fence.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_prime.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/mxsfb/mxsfb_crtc.c
drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_vga.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_gr.c
drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
drivers/gpu/drm/rockchip/cdn-dp-core.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.h
drivers/gpu/drm/rockchip/rockchip_vop_reg.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/gpu/host1x/Kconfig
drivers/gpu/host1x/dev.c
drivers/gpu/ipu-v3/ipu-common.c
drivers/gpu/ipu-v3/ipu-pre.c
drivers/hid/Kconfig
drivers/hid/hid-asus.c
drivers/hid/hid-core.c
drivers/hid/hid-elecom.c
drivers/hid/hid-ids.h
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_wac.c
drivers/hsi/clients/ssi_protocol.c
drivers/hwmon/Kconfig
drivers/hwmon/aspeed-pwm-tacho.c
drivers/hwmon/coretemp.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-tiny-usb.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/i2c-mux.c
drivers/i2c/muxes/i2c-mux-reg.c
drivers/iio/adc/bcm_iproc_adc.c
drivers/iio/adc/max9611.c
drivers/iio/adc/meson_saradc.c
drivers/iio/adc/mxs-lradc-adc.c
drivers/iio/adc/sun4i-gpadc-iio.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/buffer/industrialio-buffer-dma.c
drivers/iio/buffer/industrialio-buffer-dmaengine.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/industrialio-trigger.c
drivers/iio/light/ltr501.c
drivers/iio/proximity/as3935.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/netlink.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/umem.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/core/uverbs_marshall.c
drivers/infiniband/hw/bnxt_re/bnxt_re.h
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/ib_verbs.h
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/bnxt_re/qplib_fp.h
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/bnxt_re/qplib_rcfw.h
drivers/infiniband/hw/bnxt_re/qplib_res.h
drivers/infiniband/hw/bnxt_re/qplib_sp.c
drivers/infiniband/hw/bnxt_re/qplib_sp.h
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/chip_registers.h
drivers/infiniband/hw/hfi1/hfi.h
drivers/infiniband/hw/hfi1/intr.c
drivers/infiniband/hw/hfi1/pcie.c
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/hfi1/sysfs.c
drivers/infiniband/hw/i40iw/i40iw_cm.c
drivers/infiniband/hw/i40iw/i40iw_ctrl.c
drivers/infiniband/hw/i40iw/i40iw_main.c
drivers/infiniband/hw/i40iw/i40iw_osdep.h
drivers/infiniband/hw/i40iw/i40iw_type.h
drivers/infiniband/hw/i40iw/i40iw_utils.c
drivers/infiniband/hw/i40iw/i40iw_virtchnl.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/qedr_cm.c
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/qib/qib_rc.c
drivers/infiniband/sw/rxe/rxe.h
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/keyboard/tm2-touchkey.c
drivers/input/misc/axp20x-pek.c
drivers/input/misc/soc_button_array.c
drivers/input/mouse/elan_i2c_i2c.c
drivers/input/mouse/elantech.c
drivers/input/mouse/synaptics.c
drivers/input/rmi4/rmi_f03.c
drivers/input/rmi4/rmi_f54.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/silead.c
drivers/iommu/amd_iommu.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/mtk_iommu_v1.c
drivers/iommu/of_iommu.c
drivers/irqchip/irq-mbigen.c
drivers/irqchip/irq-mips-gic.c
drivers/irqchip/irq-xtensa-mx.c
drivers/irqchip/irq-xtensa-pic.c
drivers/isdn/i4l/isdn_ppp.c
drivers/isdn/mISDN/stack.c
drivers/leds/leds-bcm6328.c
drivers/leds/leds-pca955x.c
drivers/leds/trigger/ledtrig-heartbeat.c
drivers/md/bitmap.c
drivers/md/dm-bufio.c
drivers/md/dm-cache-background-tracker.c
drivers/md/dm-cache-policy-smq.c
drivers/md/dm-cache-target.c
drivers/md/dm-integrity.c
drivers/md/dm-io.c
drivers/md/dm-ioctl.c
drivers/md/dm-mpath.c
drivers/md/dm-raid.c
drivers/md/dm-raid1.c
drivers/md/dm-rq.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin.c
drivers/md/dm-verity-target.c
drivers/md/dm.c
drivers/md/md-cluster.c
drivers/md/md.c
drivers/md/md.h
drivers/md/persistent-data/dm-space-map-disk.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5-cache.c
drivers/md/raid5-log.h
drivers/md/raid5-ppl.c
drivers/md/raid5.c
drivers/media/Kconfig
drivers/media/Makefile
drivers/media/cec/Kconfig
drivers/media/cec/Makefile
drivers/media/cec/cec-adap.c
drivers/media/cec/cec-api.c
drivers/media/cec/cec-core.c
drivers/media/i2c/Kconfig
drivers/media/i2c/tc358743.c
drivers/media/platform/Kconfig
drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
drivers/media/platform/vivid/Kconfig
drivers/media/rc/rc-ir-raw.c
drivers/media/rc/sir_ir.c
drivers/media/usb/pulse8-cec/Kconfig
drivers/media/usb/rainshadow-cec/Kconfig
drivers/media/usb/rainshadow-cec/rainshadow-cec.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/memory/atmel-ebi.c
drivers/memory/omap-gpmc.c
drivers/mfd/arizona-core.c
drivers/misc/Kconfig
drivers/misc/cxl/context.c
drivers/misc/cxl/cxl.h
drivers/misc/cxl/fault.c
drivers/misc/cxl/file.c
drivers/misc/cxl/main.c
drivers/misc/cxl/native.c
drivers/misc/cxl/pci.c
drivers/misc/mei/bus.c
drivers/misc/sgi-xp/xp.h
drivers/misc/sgi-xp/xp_main.c
drivers/mmc/core/pwrseq_simple.c
drivers/mmc/host/cavium-octeon.c
drivers/mmc/host/cavium-thunderx.c
drivers/mmc/host/cavium.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/sdhci-iproc.c
drivers/mmc/host/sdhci-xenon-phy.c
drivers/mmc/host/sdhci-xenon.c
drivers/mmc/host/sdhci-xenon.h
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nand_samsung.c
drivers/mtd/nand/tango_nand.c
drivers/net/arcnet/arcnet.c
drivers/net/arcnet/capmode.c
drivers/net/arcnet/com20020-pci.c
drivers/net/arcnet/com20020.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/caif/caif_hsi.c
drivers/net/caif/caif_serial.c
drivers/net/caif/caif_spi.c
drivers/net/caif/caif_virtio.c
drivers/net/can/dev.c
drivers/net/can/peak_canfd/peak_canfd.c
drivers/net/can/slcan.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/vcan.c
drivers/net/can/vxcan.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/global2.h
drivers/net/dummy.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/amazon/ena/ena_com.c
drivers/net/ethernet/amazon/ena/ena_ethtool.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amazon/ena/ena_netdev.h
drivers/net/ethernet/amd/xgbe/xgbe-desc.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
drivers/net/ethernet/atheros/atlx/atl2.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fman/Kconfig
drivers/net/ethernet/freescale/fman/mac.c
drivers/net/ethernet/freescale/fsl_pq_mdio.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/qp.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
drivers/net/ethernet/qlogic/qed/qed_debug.c
drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/qualcomm/emac/emac-phy.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/ef10_sriov.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
drivers/net/ethernet/sun/ldmvsw.c
drivers/net/ethernet/ti/cpsw-common.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ifb.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/irda/irda-usb.c
drivers/net/loopback.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/netconsole.c
drivers/net/nlmon.c
drivers/net/phy/Kconfig
drivers/net/phy/dp83640.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-mux.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/slip/slip.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc-phonet.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/ch9200.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/smsc95xx.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vrf.c
drivers/net/vsockmon.c
drivers/net/vxlan.c
drivers/net/wan/dlci.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/lapbether.c
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
drivers/net/wireless/intel/iwlwifi/iwl-7000.c
drivers/net/wireless/intel/iwlwifi/iwl-8000.c
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.h
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
drivers/net/wireless/intersil/hostap/hostap_main.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/mwifiex/main.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/netback.c
drivers/net/xen-netfront.c
drivers/ntb/hw/intel/ntb_hw_intel.c
drivers/ntb/ntb_transport.c
drivers/ntb/test/ntb_perf.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/core.c
drivers/nvme/target/fc.c
drivers/nvme/target/fcloop.c
drivers/nvme/target/loop.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/rdma.c
drivers/of/device.c
drivers/of/fdt.c
drivers/of/of_reserved_mem.c
drivers/of/platform.c
drivers/pci/access.c
drivers/pci/dwc/pci-imx6.c
drivers/pci/endpoint/Kconfig
drivers/pci/endpoint/functions/Kconfig
drivers/pci/pci.c
drivers/pci/switch/switchtec.c
drivers/perf/arm_pmu_acpi.c
drivers/phy/phy-qcom-qmp.c
drivers/pinctrl/core.c
drivers/pinctrl/freescale/pinctrl-mxs.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/pinconf-generic.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinmux.c
drivers/pinctrl/stm32/pinctrl-stm32.c
drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
drivers/platform/goldfish/goldfish_pipe.c
drivers/platform/x86/intel_telemetry_debugfs.c
drivers/powercap/powercap_sys.c
drivers/reset/hisilicon/hi6220_reset.c
drivers/rtc/rtc-cmos.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/qdio_debug.h
drivers/s390/cio/vfio_ccw_ops.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_card.c
drivers/s390/crypto/ap_queue.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_sys.c
drivers/s390/net/qeth_l2.h
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l2_sys.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/csiostor/csio_hw.c
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/cxgbi/libcxgbi.h
drivers/scsi/cxlflash/Kconfig
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
drivers/scsi/libfc/fc_fcp.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_ct.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_disc.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mem.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_nvmet.c
drivers/scsi/lpfc/lpfc_nvmet.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h
drivers/scsi/lpfc/lpfc_version.h
drivers/scsi/pmcraid.c
drivers/scsi/qedf/qedf.h
drivers/scsi/qedf/qedf_els.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qedi/qedi.h
drivers/scsi/qedi/qedi_fw.c
drivers/scsi/qedi/qedi_iscsi.c
drivers/scsi/qedi/qedi_main.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_tmpl.c
drivers/scsi/scsi.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/ufs/ufshcd.c
drivers/soc/bcm/brcmstb/common.c
drivers/soc/imx/Kconfig
drivers/soc/ti/knav_dma.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm63xx-hsspi.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi.c
drivers/staging/android/ion/devicetree.txt [deleted file]
drivers/staging/ccree/Kconfig
drivers/staging/ccree/ssi_buffer_mgr.c
drivers/staging/ccree/ssi_request_mgr.c
drivers/staging/fsl-dpaa2/Kconfig
drivers/staging/iio/cdc/ad7152.c
drivers/staging/lustre/lustre/lov/lov_pack.c
drivers/staging/media/atomisp/i2c/Makefile
drivers/staging/media/atomisp/i2c/imx/Makefile
drivers/staging/media/atomisp/i2c/ov5693/Makefile
drivers/staging/media/atomisp/pci/atomisp2/Makefile
drivers/staging/rtl8188eu/os_dep/mon.c
drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
drivers/staging/rtl8192e/rtl819x_TSProc.c
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
drivers/staging/rtl8723bs/os_dep/os_intfs.c
drivers/staging/rtl8723bs/os_dep/osdep_service.c
drivers/staging/typec/fusb302/fusb302.c
drivers/staging/typec/pd.h
drivers/staging/typec/pd_vdo.h
drivers/staging/typec/tcpci.c
drivers/staging/typec/tcpm.c
drivers/staging/typec/tcpm.h
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_erl0.h
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_nego.c
drivers/target/target_core_internal.h
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/tee/Kconfig
drivers/thermal/broadcom/Kconfig
drivers/thermal/qoriq_thermal.c
drivers/thermal/thermal_core.c
drivers/thermal/ti-soc-thermal/ti-bandgap.c
drivers/tty/ehv_bytechan.c
drivers/tty/serdev/core.c
drivers/tty/serdev/serdev-ttyport.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/altera_jtaguart.c
drivers/tty/serial/altera_uart.c
drivers/tty/serial/efm32-uart.c
drivers/tty/serial/ifx6x60.c
drivers/tty/serial/imx.c
drivers/tty/serial/serial_core.c
drivers/tty/tty_port.c
drivers/uio/uio.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/usbmisc_imx.c
drivers/usb/core/devio.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/of.c
drivers/usb/core/urb.c
drivers/usb/dwc2/params.c
drivers/usb/dwc3/dwc3-keystone.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/u_serial.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.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/misc/chaoskey.c
drivers/usb/misc/iowarrior.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/sisusbvga/sisusb_con.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/tusb6010_omap.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/storage/ene_ub6250.c
drivers/usb/usbip/vhci_hcd.c
drivers/uwb/i1480/dfu/usb.c
drivers/video/fbdev/core/fbmon.c
drivers/video/fbdev/smscufx.c
drivers/video/fbdev/udlfb.c
drivers/video/fbdev/via/viafbdev.c
drivers/virtio/virtio_balloon.c
drivers/watchdog/Kconfig
drivers/watchdog/bcm_kona_wdt.c
drivers/watchdog/cadence_wdt.c
drivers/watchdog/iTCO_wdt.c
drivers/watchdog/pcwd_usb.c
drivers/watchdog/sama5d4_wdt.c
drivers/watchdog/wdt_pci.c
drivers/watchdog/zx2967_wdt.c
drivers/xen/privcmd.c
fs/autofs4/dev-ioctl.c
fs/block_dev.c
fs/btrfs/ctree.h
fs/btrfs/dir-item.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/hash.c
fs/btrfs/inode.c
fs/ceph/acl.c
fs/ceph/export.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/cifs/cifsacl.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/smb1ops.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/transport.c
fs/cifs/xattr.c
fs/configfs/item.c
fs/configfs/symlink.c
fs/dax.c
fs/dcache.c
fs/exec.c
fs/ext2/inode.c
fs/ext4/acl.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/f2fs/f2fs.h
fs/fuse/inode.c
fs/gfs2/log.c
fs/hugetlbfs/inode.c
fs/jbd2/transaction.c
fs/namespace.c
fs/nfs/callback_xdr.c
fs/nfs/dir.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4client.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/super.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfsxdr.c
fs/ntfs/namei.c
fs/ocfs2/dlmglue.c
fs/ocfs2/export.c
fs/ocfs2/xattr.c
fs/overlayfs/Kconfig
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/overlayfs/util.c
fs/proc/base.c
fs/proc/task_mmu.c
fs/quota/dquot.c
fs/read_write.c
fs/reiserfs/journal.c
fs/stat.c
fs/ufs/balloc.c
fs/ufs/inode.c
fs/ufs/super.c
fs/ufs/ufs_fs.h
fs/ufs/util.c
fs/ufs/util.h
fs/userfaultfd.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_refcount.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_file.c
fs/xfs/xfs_fsmap.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_iomap.c
include/acpi/acpi_bus.h
include/acpi/actbl.h
include/drm/drm_dp_helper.h
include/dt-bindings/clock/sun50i-a64-ccu.h
include/dt-bindings/clock/sun8i-h3-ccu.h
include/kvm/arm_vgic.h
include/linux/bio.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/bpf_verifier.h
include/linux/ceph/ceph_debug.h
include/linux/cgroup-defs.h
include/linux/cgroup.h
include/linux/compiler-clang.h
include/linux/configfs.h
include/linux/dax.h
include/linux/dma-iommu.h
include/linux/dmi.h
include/linux/elevator.h
include/linux/filter.h
include/linux/gfp.h
include/linux/gpio/machine.h
include/linux/hashtable.h
include/linux/if_vlan.h
include/linux/irqchip/arm-gic-v3.h
include/linux/irqchip/arm-gic.h
include/linux/jiffies.h
include/linux/key.h
include/linux/kprobes.h
include/linux/memblock.h
include/linux/mlx4/qp.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mlx5/fs.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/moduleparam.h
include/linux/netdevice.h
include/linux/netfilter/x_tables.h
include/linux/netfilter_bridge/ebtables.h
include/linux/nvme-fc-driver.h
include/linux/of_irq.h
include/linux/of_platform.h
include/linux/pci.h
include/linux/pinctrl/pinconf-generic.h
include/linux/ptrace.h
include/linux/quotaops.h
include/linux/serdev.h
include/linux/slub_def.h
include/linux/soc/renesas/rcar-rst.h
include/linux/srcu.h
include/linux/sunrpc/svc.h
include/linux/suspend.h
include/linux/timekeeper_internal.h
include/linux/tty.h
include/linux/usb/hcd.h
include/linux/usb/usbnet.h
include/media/cec-notifier.h
include/media/cec.h
include/net/dst.h
include/net/ip_fib.h
include/net/ipv6.h
include/net/netfilter/nf_conntrack_helper.h
include/net/netfilter/nf_tables.h
include/net/tc_act/tc_csum.h
include/net/tcp.h
include/net/wext.h
include/net/x25.h
include/net/xfrm.h
include/rdma/ib_sa.h
include/rdma/rdma_netlink.h
include/target/iscsi/iscsi_target_core.h
include/uapi/linux/a.out.h
include/uapi/linux/bpf.h
include/uapi/linux/ethtool.h
include/uapi/linux/if_link.h
include/uapi/linux/keyctl.h
include/uapi/linux/openvswitch.h
include/uapi/linux/usb/ch11.h
kernel/bpf/arraymap.c
kernel/bpf/lpm_trie.c
kernel/bpf/stackmap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/cgroup/cpuset.c
kernel/cpu.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/fork.c
kernel/irq/chip.c
kernel/irq/manage.c
kernel/kprobes.c
kernel/livepatch/Kconfig
kernel/livepatch/patch.c
kernel/livepatch/transition.c
kernel/locking/rtmutex.c
kernel/pid_namespace.c
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/suspend.c
kernel/printk/printk.c
kernel/ptrace.c
kernel/rcu/srcu.c
kernel/rcu/srcutiny.c
kernel/rcu/srcutree.c
kernel/sched/core.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/sched/sched.h
kernel/signal.c
kernel/time/alarmtimer.c
kernel/time/posix-cpu-timers.c
kernel/time/tick-broadcast.c
kernel/time/tick-internal.h
kernel/time/timekeeping.c
kernel/trace/blktrace.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_functions.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_stack.c
lib/cmdline.c
lib/libcrc32c.c
lib/test_bpf.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/khugepaged.c
mm/ksm.c
mm/memblock.c
mm/memory-failure.c
mm/memory.c
mm/mlock.c
mm/mmap.c
mm/page_alloc.c
mm/slub.c
mm/swap_cgroup.c
mm/util.c
mm/vmalloc.c
mm/vmpressure.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/9p/trans_xen.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/routing.c
net/batman-adv/soft-interface.c
net/bluetooth/6lowpan.c
net/bridge/br_device.c
net/bridge/br_netlink.c
net/bridge/br_stp_if.c
net/bridge/br_stp_timer.c
net/bridge/netfilter/ebt_arpreply.c
net/bridge/netfilter/ebtables.c
net/caif/caif_socket.c
net/caif/cfpkt_skbuff.c
net/caif/chnl_net.c
net/can/af_can.c
net/ceph/auth_x.c
net/ceph/ceph_common.c
net/ceph/messenger.c
net/ceph/mon_client.c
net/ceph/osdmap.c
net/core/dev.c
net/core/dev_ioctl.c
net/core/devlink.c
net/core/dst.c
net/core/fib_rules.c
net/core/filter.c
net/core/neighbour.c
net/core/net_namespace.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/dccp/ipv6.c
net/decnet/dn_route.c
net/decnet/netfilter/dn_rtmsg.c
net/dsa/dsa.c
net/dsa/dsa2.c
net/dsa/legacy.c
net/hsr/hsr_device.c
net/hsr/hsr_forward.c
net/hsr/hsr_framereg.c
net/hsr/hsr_framereg.h
net/ieee802154/6lowpan/core.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/esp4.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/ipmr.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipv4/udp_impl.h
net/ipv6/addrconf.c
net/ipv6/calipso.c
net/ipv6/datagram.c
net/ipv6/esp6_offload.c
net/ipv6/fib6_rules.c
net/ipv6/icmp.c
net/ipv6/ila/ila_xlat.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ip6mr.c
net/ipv6/output_core.c
net/ipv6/ping.c
net/ipv6/proc.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udp_offload.c
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_mode_ro.c
net/ipv6/xfrm6_mode_transport.c
net/irda/irlan/irlan_eth.c
net/key/af_key.c
net/l2tp/l2tp_eth.c
net/llc/af_llc.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/wpa.c
net/mac802154/iface.c
net/mpls/af_mpls.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_cthelper.c
net/netfilter/nft_bitwise.c
net/netfilter/nft_cmp.c
net/netfilter/nft_ct.c
net/netfilter/nft_immediate.c
net/netfilter/nft_range.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_rbtree.c
net/netfilter/x_tables.c
net/netfilter/xt_CT.c
net/netlink/af_netlink.c
net/openvswitch/conntrack.c
net/openvswitch/vport-internal_dev.c
net/packet/af_packet.c
net/phonet/pep-gprs.c
net/rxrpc/key.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/cls_matchall.c
net/sched/sch_api.c
net/sctp/associola.c
net/sctp/endpointola.c
net/sctp/input.c
net/sctp/ipv6.c
net/sctp/sctp_diag.c
net/sctp/sm_make_chunk.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/smc/Kconfig
net/smc/smc_clc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/smc/smc_ib.h
net/sunrpc/xprtrdma/backchannel.c
net/sunrpc/xprtsock.c
net/tipc/msg.c
net/tipc/socket.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/wireless/scan.c
net/wireless/util.c
net/wireless/wext-core.c
net/x25/af_x25.c
net/x25/sysctl_net_x25.c
net/xfrm/Makefile
net/xfrm/xfrm_device.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
samples/bpf/cookie_uid_helper_example.c
samples/bpf/offwaketime_user.c
samples/bpf/sampleip_user.c
samples/bpf/trace_event_user.c
samples/bpf/tracex2_user.c
samples/bpf/xdp1_user.c
samples/bpf/xdp_tx_iptunnel_user.c
scripts/Makefile.headersinst
scripts/Makefile.lib
scripts/dtc/checks.c
scripts/dtc/include-prefixes/arc [new symlink]
scripts/dtc/include-prefixes/arm [new symlink]
scripts/dtc/include-prefixes/arm64 [new symlink]
scripts/dtc/include-prefixes/c6x [new symlink]
scripts/dtc/include-prefixes/cris [new symlink]
scripts/dtc/include-prefixes/dt-bindings [new symlink]
scripts/dtc/include-prefixes/h8300 [new symlink]
scripts/dtc/include-prefixes/metag [new symlink]
scripts/dtc/include-prefixes/microblaze [new symlink]
scripts/dtc/include-prefixes/mips [new symlink]
scripts/dtc/include-prefixes/nios2 [new symlink]
scripts/dtc/include-prefixes/openrisc [new symlink]
scripts/dtc/include-prefixes/powerpc [new symlink]
scripts/dtc/include-prefixes/sh [new symlink]
scripts/dtc/include-prefixes/xtensa [new symlink]
scripts/gdb/linux/dmesg.py
scripts/genksyms/genksyms.h
scripts/kconfig/Makefile
scripts/kconfig/nconf.c
scripts/kconfig/nconf.gui.c
scripts/tags.sh
security/keys/Kconfig
security/keys/dh.c
security/keys/encrypted-keys/encrypted.c
security/keys/gc.c
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/process_keys.c
security/keys/trusted.c
security/keys/user_defined.c
security/selinux/hooks.c
sound/core/pcm_lib.c
sound/core/timer.c
sound/firewire/amdtp-stream.c
sound/firewire/amdtp-stream.h
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/atmel/atmel-classd.c
sound/soc/codecs/da7213.c
sound/soc/codecs/rt286.c
sound/soc/generic/simple-card.c
sound/soc/intel/skylake/skl-sst-ipc.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h
sound/soc/sh/rcar/adg.c
sound/soc/sh/rcar/cmd.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c
sound/soc/soc-core.c
sound/usb/mixer_us16x08.c
sound/usb/quirks.c
sound/x86/intel_hdmi_audio.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/s390/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/disabled-features.h
tools/arch/x86/include/asm/required-features.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/arch/x86/include/uapi/asm/vmx.h
tools/build/feature/test-bpf.c
tools/include/linux/filter.h
tools/include/uapi/linux/bpf.h
tools/include/uapi/linux/stat.h
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf.h
tools/objtool/builtin-check.c
tools/perf/Documentation/perf-probe.txt
tools/perf/Documentation/perf-script-perl.txt
tools/perf/Documentation/perf-script-python.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Makefile.config
tools/perf/Makefile.perf
tools/perf/arch/Build
tools/perf/arch/common.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-trace.c
tools/perf/pmu-events/Build
tools/perf/tests/Build
tools/perf/tests/bp_signal.c
tools/perf/tests/builtin-test.c
tools/perf/tests/code-reading.c
tools/perf/tests/task-exit.c
tools/perf/tests/tests.h
tools/perf/ui/hist.c
tools/perf/util/annotate.c
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/callchain.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/evsel.c
tools/perf/util/evsel_fprintf.c
tools/perf/util/header.c
tools/perf/util/machine.c
tools/perf/util/probe-event.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/srcline.c
tools/perf/util/symbol-elf.c
tools/perf/util/symbol.c
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libunwind-local.c
tools/power/acpi/.gitignore [new file with mode: 0644]
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/bpf_endian.h
tools/testing/selftests/bpf/include/uapi/linux/types.h [new file with mode: 0644]
tools/testing/selftests/bpf/test_align.c [new file with mode: 0644]
tools/testing/selftests/bpf/test_pkt_access.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc [new file with mode: 0644]
tools/testing/selftests/ntb/ntb_test.sh
tools/testing/selftests/powerpc/tm/.gitignore
tools/testing/selftests/powerpc/tm/Makefile
tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c [new file with mode: 0644]
usr/Kconfig
virt/kvm/arm/hyp/vgic-v3-sr.c
virt/kvm/arm/mmu.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-mmio-v2.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.h

index 22cb3091f29776b2acfb0df339db150393a8ad83..effe7af3a5af95d25f86efadaa7dd2b127a0dea9 100644 (file)
@@ -59,20 +59,28 @@ button driver uses the following 3 modes in order not to trigger issues.
 If the userspace hasn't been prepared to ignore the unreliable "opened"
 events and the unreliable initial state notification, Linux users can use
 the following kernel parameters to handle the possible issues:
-A. button.lid_init_state=open:
+A. button.lid_init_state=method:
+   When this option is specified, the ACPI button driver reports the
+   initial lid state using the returning value of the _LID control method
+   and whether the "opened"/"closed" events are paired fully relies on the
+   firmware implementation.
+   This option can be used to fix some platforms where the returning value
+   of the _LID control method is reliable but the initial lid state
+   notification is missing.
+   This option is the default behavior during the period the userspace
+   isn't ready to handle the buggy AML tables.
+B. button.lid_init_state=open:
    When this option is specified, the ACPI button driver always reports the
    initial lid state as "opened" and whether the "opened"/"closed" events
    are paired fully relies on the firmware implementation.
    This may fix some platforms where the returning value of the _LID
    control method is not reliable and the initial lid state notification is
    missing.
-   This option is the default behavior during the period the userspace
-   isn't ready to handle the buggy AML tables.
 
 If the userspace has been prepared to ignore the unreliable "opened" events
 and the unreliable initial state notification, Linux users should always
 use the following kernel parameter:
-B. button.lid_init_state=ignore:
+C. button.lid_init_state=ignore:
    When this option is specified, the ACPI button driver never reports the
    initial lid state and there is a compensation mechanism implemented to
    ensure that the reliable "closed" notifications can always be delievered
index 15f79c27748df1611b1643b77ca68e2a5e7cfaab..7737ab5d04b2941621df23b7fc83a4cdba36e5ba 100644 (file)
 
        dscc4.setup=    [NET]
 
+       dt_cpu_ftrs=    [PPC]
+                       Format: {"off" | "known"}
+                       Control how the dt_cpu_ftrs device-tree binding is
+                       used for CPU feature discovery and setup (if it
+                       exists).
+                       off: Do not use it, fall back to legacy cpu table.
+                       known: Do not pass through unknown features to guests
+                       or userspace, only those that the kernel is aware of.
+
        dump_apple_properties   [X86]
                        Dump name and content of EFI device properties on
                        x86 Macs.  Useful for driver authors to determine
                        expediting.  Set to zero to disable automatic
                        expediting.
 
+       stack_guard_gap=        [MM]
+                       override the default stack gap protection. The value
+                       is in page units and it defines how many pages prior
+                       to (for stacks growing down) resp. after (for stacks
+                       growing up) the main stack are reserved for no other
+                       mapping. Default value is 256 pages.
+
        stacktrace      [FTRACE]
                        Enabled the stack tracer on boot up.
 
index 289c80f7760ebb966b13d91b5627e61963e5b3aa..09aa2e9497875acec984dc68727e14139c5d23ad 100644 (file)
@@ -1,4 +1,5 @@
 .. |struct cpufreq_policy| replace:: :c:type:`struct cpufreq_policy <cpufreq_policy>`
+.. |intel_pstate| replace:: :doc:`intel_pstate <intel_pstate>`
 
 =======================
 CPU Performance Scaling
@@ -75,7 +76,7 @@ feedback registers, as that information is typically specific to the hardware
 interface it comes from and may not be easily represented in an abstract,
 platform-independent way.  For this reason, ``CPUFreq`` allows scaling drivers
 to bypass the governor layer and implement their own performance scaling
-algorithms.  That is done by the ``intel_pstate`` scaling driver.
+algorithms.  That is done by the |intel_pstate| scaling driver.
 
 
 ``CPUFreq`` Policy Objects
@@ -174,13 +175,13 @@ necessary to restart the scaling governor so that it can take the new online CPU
 into account.  That is achieved by invoking the governor's ``->stop`` and
 ``->start()`` callbacks, in this order, for the entire policy.
 
-As mentioned before, the ``intel_pstate`` scaling driver bypasses the scaling
+As mentioned before, the |intel_pstate| scaling driver bypasses the scaling
 governor layer of ``CPUFreq`` and provides its own P-state selection algorithms.
-Consequently, if ``intel_pstate`` is used, scaling governors are not attached to
+Consequently, if |intel_pstate| is used, scaling governors are not attached to
 new policy objects.  Instead, the driver's ``->setpolicy()`` callback is invoked
 to register per-CPU utilization update callbacks for each policy.  These
 callbacks are invoked by the CPU scheduler in the same way as for scaling
-governors, but in the ``intel_pstate`` case they both determine the P-state to
+governors, but in the |intel_pstate| case they both determine the P-state to
 use and change the hardware configuration accordingly in one go from scheduler
 context.
 
@@ -257,7 +258,7 @@ are the following:
 
 ``scaling_available_governors``
        List of ``CPUFreq`` scaling governors present in the kernel that can
-       be attached to this policy or (if the ``intel_pstate`` scaling driver is
+       be attached to this policy or (if the |intel_pstate| scaling driver is
        in use) list of scaling algorithms provided by the driver that can be
        applied to this policy.
 
@@ -274,7 +275,7 @@ are the following:
        the CPU is actually running at (due to hardware design and other
        limitations).
 
-       Some scaling drivers (e.g. ``intel_pstate``) attempt to provide
+       Some scaling drivers (e.g. |intel_pstate|) attempt to provide
        information more precisely reflecting the current CPU frequency through
        this attribute, but that still may not be the exact current CPU
        frequency as seen by the hardware at the moment.
@@ -284,13 +285,13 @@ are the following:
 
 ``scaling_governor``
        The scaling governor currently attached to this policy or (if the
-       ``intel_pstate`` scaling driver is in use) the scaling algorithm
+       |intel_pstate| scaling driver is in use) the scaling algorithm
        provided by the driver that is currently applied to this policy.
 
        This attribute is read-write and writing to it will cause a new scaling
        governor to be attached to this policy or a new scaling algorithm
        provided by the scaling driver to be applied to it (in the
-       ``intel_pstate`` case), as indicated by the string written to this
+       |intel_pstate| case), as indicated by the string written to this
        attribute (which must be one of the names listed by the
        ``scaling_available_governors`` attribute described above).
 
@@ -619,7 +620,7 @@ This file is located under :file:`/sys/devices/system/cpu/cpufreq/` and controls
 the "boost" setting for the whole system.  It is not present if the underlying
 scaling driver does not support the frequency boost mechanism (or supports it,
 but provides a driver-specific interface for controlling it, like
-``intel_pstate``).
+|intel_pstate|).
 
 If the value in this file is 1, the frequency boost mechanism is enabled.  This
 means that either the hardware can be put into states in which it is able to
index c80f087321fcb704e549254c70ccb927f9659b4c..7f148f76f432cbfc62ed663a6be7b9849b66b3c6 100644 (file)
@@ -6,6 +6,7 @@ Power Management
    :maxdepth: 2
 
    cpufreq
+   intel_pstate
 
 .. only::  subproject and html
 
diff --git a/Documentation/admin-guide/pm/intel_pstate.rst b/Documentation/admin-guide/pm/intel_pstate.rst
new file mode 100644 (file)
index 0000000..33d7039
--- /dev/null
@@ -0,0 +1,755 @@
+===============================================
+``intel_pstate`` CPU Performance Scaling Driver
+===============================================
+
+::
+
+ Copyright (c) 2017 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+
+General Information
+===================
+
+``intel_pstate`` is a part of the
+:doc:`CPU performance scaling subsystem <cpufreq>` in the Linux kernel
+(``CPUFreq``).  It is a scaling driver for the Sandy Bridge and later
+generations of Intel processors.  Note, however, that some of those processors
+may not be supported.  [To understand ``intel_pstate`` it is necessary to know
+how ``CPUFreq`` works in general, so this is the time to read :doc:`cpufreq` if
+you have not done that yet.]
+
+For the processors supported by ``intel_pstate``, the P-state concept is broader
+than just an operating frequency or an operating performance point (see the
+`LinuxCon Europe 2015 presentation by Kristen Accardi <LCEU2015_>`_ for more
+information about that).  For this reason, the representation of P-states used
+by ``intel_pstate`` internally follows the hardware specification (for details
+refer to `Intel® 64 and IA-32 Architectures Software Developer’s Manual
+Volume 3: System Programming Guide <SDM_>`_).  However, the ``CPUFreq`` core
+uses frequencies for identifying operating performance points of CPUs and
+frequencies are involved in the user space interface exposed by it, so
+``intel_pstate`` maps its internal representation of P-states to frequencies too
+(fortunately, that mapping is unambiguous).  At the same time, it would not be
+practical for ``intel_pstate`` to supply the ``CPUFreq`` core with a table of
+available frequencies due to the possible size of it, so the driver does not do
+that.  Some functionality of the core is limited by that.
+
+Since the hardware P-state selection interface used by ``intel_pstate`` is
+available at the logical CPU level, the driver always works with individual
+CPUs.  Consequently, if ``intel_pstate`` is in use, every ``CPUFreq`` policy
+object corresponds to one logical CPU and ``CPUFreq`` policies are effectively
+equivalent to CPUs.  In particular, this means that they become "inactive" every
+time the corresponding CPU is taken offline and need to be re-initialized when
+it goes back online.
+
+``intel_pstate`` is not modular, so it cannot be unloaded, which means that the
+only way to pass early-configuration-time parameters to it is via the kernel
+command line.  However, its configuration can be adjusted via ``sysfs`` to a
+great extent.  In some configurations it even is possible to unregister it via
+``sysfs`` which allows another ``CPUFreq`` scaling driver to be loaded and
+registered (see `below <status_attr_>`_).
+
+
+Operation Modes
+===============
+
+``intel_pstate`` can operate in three different modes: in the active mode with
+or without hardware-managed P-states support and in the passive mode.  Which of
+them will be in effect depends on what kernel command line options are used and
+on the capabilities of the processor.
+
+Active Mode
+-----------
+
+This is the default operation mode of ``intel_pstate``.  If it works in this
+mode, the ``scaling_driver`` policy attribute in ``sysfs`` for all ``CPUFreq``
+policies contains the string "intel_pstate".
+
+In this mode the driver bypasses the scaling governors layer of ``CPUFreq`` and
+provides its own scaling algorithms for P-state selection.  Those algorithms
+can be applied to ``CPUFreq`` policies in the same way as generic scaling
+governors (that is, through the ``scaling_governor`` policy attribute in
+``sysfs``).  [Note that different P-state selection algorithms may be chosen for
+different policies, but that is not recommended.]
+
+They are not generic scaling governors, but their names are the same as the
+names of some of those governors.  Moreover, confusingly enough, they generally
+do not work in the same way as the generic governors they share the names with.
+For example, the ``powersave`` P-state selection algorithm provided by
+``intel_pstate`` is not a counterpart of the generic ``powersave`` governor
+(roughly, it corresponds to the ``schedutil`` and ``ondemand`` governors).
+
+There are two P-state selection algorithms provided by ``intel_pstate`` in the
+active mode: ``powersave`` and ``performance``.  The way they both operate
+depends on whether or not the hardware-managed P-states (HWP) feature has been
+enabled in the processor and possibly on the processor model.
+
+Which of the P-state selection algorithms is used by default depends on the
+:c:macro:`CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE` kernel configuration option.
+Namely, if that option is set, the ``performance`` algorithm will be used by
+default, and the other one will be used by default if it is not set.
+
+Active Mode With HWP
+~~~~~~~~~~~~~~~~~~~~
+
+If the processor supports the HWP feature, it will be enabled during the
+processor initialization and cannot be disabled after that.  It is possible
+to avoid enabling it by passing the ``intel_pstate=no_hwp`` argument to the
+kernel in the command line.
+
+If the HWP feature has been enabled, ``intel_pstate`` relies on the processor to
+select P-states by itself, but still it can give hints to the processor's
+internal P-state selection logic.  What those hints are depends on which P-state
+selection algorithm has been applied to the given policy (or to the CPU it
+corresponds to).
+
+Even though the P-state selection is carried out by the processor automatically,
+``intel_pstate`` registers utilization update callbacks with the CPU scheduler
+in this mode.  However, they are not used for running a P-state selection
+algorithm, but for periodic updates of the current CPU frequency information to
+be made available from the ``scaling_cur_freq`` policy attribute in ``sysfs``.
+
+HWP + ``performance``
+.....................
+
+In this configuration ``intel_pstate`` will write 0 to the processor's
+Energy-Performance Preference (EPP) knob (if supported) or its
+Energy-Performance Bias (EPB) knob (otherwise), which means that the processor's
+internal P-state selection logic is expected to focus entirely on performance.
+
+This will override the EPP/EPB setting coming from the ``sysfs`` interface
+(see `Energy vs Performance Hints`_ below).
+
+Also, in this configuration the range of P-states available to the processor's
+internal P-state selection logic is always restricted to the upper boundary
+(that is, the maximum P-state that the driver is allowed to use).
+
+HWP + ``powersave``
+...................
+
+In this configuration ``intel_pstate`` will set the processor's
+Energy-Performance Preference (EPP) knob (if supported) or its
+Energy-Performance Bias (EPB) knob (otherwise) to whatever value it was
+previously set to via ``sysfs`` (or whatever default value it was
+set to by the platform firmware).  This usually causes the processor's
+internal P-state selection logic to be less performance-focused.
+
+Active Mode Without HWP
+~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the default operation mode for processors that do not support the HWP
+feature.  It also is used by default with the ``intel_pstate=no_hwp`` argument
+in the kernel command line.  However, in this mode ``intel_pstate`` may refuse
+to work with the given processor if it does not recognize it.  [Note that
+``intel_pstate`` will never refuse to work with any processor with the HWP
+feature enabled.]
+
+In this mode ``intel_pstate`` registers utilization update callbacks with the
+CPU scheduler in order to run a P-state selection algorithm, either
+``powersave`` or ``performance``, depending on the ``scaling_cur_freq`` policy
+setting in ``sysfs``.  The current CPU frequency information to be made
+available from the ``scaling_cur_freq`` policy attribute in ``sysfs`` is
+periodically updated by those utilization update callbacks too.
+
+``performance``
+...............
+
+Without HWP, this P-state selection algorithm is always the same regardless of
+the processor model and platform configuration.
+
+It selects the maximum P-state it is allowed to use, subject to limits set via
+``sysfs``, every time the P-state selection computations are carried out by the
+driver's utilization update callback for the given CPU (that does not happen
+more often than every 10 ms), but the hardware configuration will not be changed
+if the new P-state is the same as the current one.
+
+This is the default P-state selection algorithm if the
+:c:macro:`CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE` kernel configuration option
+is set.
+
+``powersave``
+.............
+
+Without HWP, this P-state selection algorithm generally depends on the
+processor model and/or the system profile setting in the ACPI tables and there
+are two variants of it.
+
+One of them is used with processors from the Atom line and (regardless of the
+processor model) on platforms with the system profile in the ACPI tables set to
+"mobile" (laptops mostly), "tablet", "appliance PC", "desktop", or
+"workstation".  It is also used with processors supporting the HWP feature if
+that feature has not been enabled (that is, with the ``intel_pstate=no_hwp``
+argument in the kernel command line).  It is similar to the algorithm
+implemented by the generic ``schedutil`` scaling governor except that the
+utilization metric used by it is based on numbers coming from feedback
+registers of the CPU.  It generally selects P-states proportional to the
+current CPU utilization, so it is referred to as the "proportional" algorithm.
+
+The second variant of the ``powersave`` P-state selection algorithm, used in all
+of the other cases (generally, on processors from the Core line, so it is
+referred to as the "Core" algorithm), is based on the values read from the APERF
+and MPERF feedback registers and the previously requested target P-state.
+It does not really take CPU utilization into account explicitly, but as a rule
+it causes the CPU P-state to ramp up very quickly in response to increased
+utilization which is generally desirable in server environments.
+
+Regardless of the variant, this algorithm is run by the driver's utilization
+update callback for the given CPU when it is invoked by the CPU scheduler, but
+not more often than every 10 ms (that can be tweaked via ``debugfs`` in `this
+particular case <Tuning Interface in debugfs_>`_).  Like in the ``performance``
+case, the hardware configuration is not touched if the new P-state turns out to
+be the same as the current one.
+
+This is the default P-state selection algorithm if the
+:c:macro:`CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE` kernel configuration option
+is not set.
+
+Passive Mode
+------------
+
+This mode is used if the ``intel_pstate=passive`` argument is passed to the
+kernel in the command line (it implies the ``intel_pstate=no_hwp`` setting too).
+Like in the active mode without HWP support, in this mode ``intel_pstate`` may
+refuse to work with the given processor if it does not recognize it.
+
+If the driver works in this mode, the ``scaling_driver`` policy attribute in
+``sysfs`` for all ``CPUFreq`` policies contains the string "intel_cpufreq".
+Then, the driver behaves like a regular ``CPUFreq`` scaling driver.  That is,
+it is invoked by generic scaling governors when necessary to talk to the
+hardware in order to change the P-state of a CPU (in particular, the
+``schedutil`` governor can invoke it directly from scheduler context).
+
+While in this mode, ``intel_pstate`` can be used with all of the (generic)
+scaling governors listed by the ``scaling_available_governors`` policy attribute
+in ``sysfs`` (and the P-state selection algorithms described above are not
+used).  Then, it is responsible for the configuration of policy objects
+corresponding to CPUs and provides the ``CPUFreq`` core (and the scaling
+governors attached to the policy objects) with accurate information on the
+maximum and minimum operating frequencies supported by the hardware (including
+the so-called "turbo" frequency ranges).  In other words, in the passive mode
+the entire range of available P-states is exposed by ``intel_pstate`` to the
+``CPUFreq`` core.  However, in this mode the driver does not register
+utilization update callbacks with the CPU scheduler and the ``scaling_cur_freq``
+information comes from the ``CPUFreq`` core (and is the last frequency selected
+by the current scaling governor for the given policy).
+
+
+.. _turbo:
+
+Turbo P-states Support
+======================
+
+In the majority of cases, the entire range of P-states available to
+``intel_pstate`` can be divided into two sub-ranges that correspond to
+different types of processor behavior, above and below a boundary that
+will be referred to as the "turbo threshold" in what follows.
+
+The P-states above the turbo threshold are referred to as "turbo P-states" and
+the whole sub-range of P-states they belong to is referred to as the "turbo
+range".  These names are related to the Turbo Boost technology allowing a
+multicore processor to opportunistically increase the P-state of one or more
+cores if there is enough power to do that and if that is not going to cause the
+thermal envelope of the processor package to be exceeded.
+
+Specifically, if software sets the P-state of a CPU core within the turbo range
+(that is, above the turbo threshold), the processor is permitted to take over
+performance scaling control for that core and put it into turbo P-states of its
+choice going forward.  However, that permission is interpreted differently by
+different processor generations.  Namely, the Sandy Bridge generation of
+processors will never use any P-states above the last one set by software for
+the given core, even if it is within the turbo range, whereas all of the later
+processor generations will take it as a license to use any P-states from the
+turbo range, even above the one set by software.  In other words, on those
+processors setting any P-state from the turbo range will enable the processor
+to put the given core into all turbo P-states up to and including the maximum
+supported one as it sees fit.
+
+One important property of turbo P-states is that they are not sustainable.  More
+precisely, there is no guarantee that any CPUs will be able to stay in any of
+those states indefinitely, because the power distribution within the processor
+package may change over time  or the thermal envelope it was designed for might
+be exceeded if a turbo P-state was used for too long.
+
+In turn, the P-states below the turbo threshold generally are sustainable.  In
+fact, if one of them is set by software, the processor is not expected to change
+it to a lower one unless in a thermal stress or a power limit violation
+situation (a higher P-state may still be used if it is set for another CPU in
+the same package at the same time, for example).
+
+Some processors allow multiple cores to be in turbo P-states at the same time,
+but the maximum P-state that can be set for them generally depends on the number
+of cores running concurrently.  The maximum turbo P-state that can be set for 3
+cores at the same time usually is lower than the analogous maximum P-state for
+2 cores, which in turn usually is lower than the maximum turbo P-state that can
+be set for 1 core.  The one-core maximum turbo P-state is thus the maximum
+supported one overall.
+
+The maximum supported turbo P-state, the turbo threshold (the maximum supported
+non-turbo P-state) and the minimum supported P-state are specific to the
+processor model and can be determined by reading the processor's model-specific
+registers (MSRs).  Moreover, some processors support the Configurable TDP
+(Thermal Design Power) feature and, when that feature is enabled, the turbo
+threshold effectively becomes a configurable value that can be set by the
+platform firmware.
+
+Unlike ``_PSS`` objects in the ACPI tables, ``intel_pstate`` always exposes
+the entire range of available P-states, including the whole turbo range, to the
+``CPUFreq`` core and (in the passive mode) to generic scaling governors.  This
+generally causes turbo P-states to be set more often when ``intel_pstate`` is
+used relative to ACPI-based CPU performance scaling (see `below <acpi-cpufreq_>`_
+for more information).
+
+Moreover, since ``intel_pstate`` always knows what the real turbo threshold is
+(even if the Configurable TDP feature is enabled in the processor), its
+``no_turbo`` attribute in ``sysfs`` (described `below <no_turbo_attr_>`_) should
+work as expected in all cases (that is, if set to disable turbo P-states, it
+always should prevent ``intel_pstate`` from using them).
+
+
+Processor Support
+=================
+
+To handle a given processor ``intel_pstate`` requires a number of different
+pieces of information on it to be known, including:
+
+ * The minimum supported P-state.
+
+ * The maximum supported `non-turbo P-state <turbo_>`_.
+
+ * Whether or not turbo P-states are supported at all.
+
+ * The maximum supported `one-core turbo P-state <turbo_>`_ (if turbo P-states
+   are supported).
+
+ * The scaling formula to translate the driver's internal representation
+   of P-states into frequencies and the other way around.
+
+Generally, ways to obtain that information are specific to the processor model
+or family.  Although it often is possible to obtain all of it from the processor
+itself (using model-specific registers), there are cases in which hardware
+manuals need to be consulted to get to it too.
+
+For this reason, there is a list of supported processors in ``intel_pstate`` and
+the driver initialization will fail if the detected processor is not in that
+list, unless it supports the `HWP feature <Active Mode_>`_.  [The interface to
+obtain all of the information listed above is the same for all of the processors
+supporting the HWP feature, which is why they all are supported by
+``intel_pstate``.]
+
+
+User Space Interface in ``sysfs``
+=================================
+
+Global Attributes
+-----------------
+
+``intel_pstate`` exposes several global attributes (files) in ``sysfs`` to
+control its functionality at the system level.  They are located in the
+``/sys/devices/system/cpu/cpufreq/intel_pstate/`` directory and affect all
+CPUs.
+
+Some of them are not present if the ``intel_pstate=per_cpu_perf_limits``
+argument is passed to the kernel in the command line.
+
+``max_perf_pct``
+       Maximum P-state the driver is allowed to set in percent of the
+       maximum supported performance level (the highest supported `turbo
+       P-state <turbo_>`_).
+
+       This attribute will not be exposed if the
+       ``intel_pstate=per_cpu_perf_limits`` argument is present in the kernel
+       command line.
+
+``min_perf_pct``
+       Minimum P-state the driver is allowed to set in percent of the
+       maximum supported performance level (the highest supported `turbo
+       P-state <turbo_>`_).
+
+       This attribute will not be exposed if the
+       ``intel_pstate=per_cpu_perf_limits`` argument is present in the kernel
+       command line.
+
+``num_pstates``
+       Number of P-states supported by the processor (between 0 and 255
+       inclusive) including both turbo and non-turbo P-states (see
+       `Turbo P-states Support`_).
+
+       The value of this attribute is not affected by the ``no_turbo``
+       setting described `below <no_turbo_attr_>`_.
+
+       This attribute is read-only.
+
+``turbo_pct``
+       Ratio of the `turbo range <turbo_>`_ size to the size of the entire
+       range of supported P-states, in percent.
+
+       This attribute is read-only.
+
+.. _no_turbo_attr:
+
+``no_turbo``
+       If set (equal to 1), the driver is not allowed to set any turbo P-states
+       (see `Turbo P-states Support`_).  If unset (equalt to 0, which is the
+       default), turbo P-states can be set by the driver.
+       [Note that ``intel_pstate`` does not support the general ``boost``
+       attribute (supported by some other scaling drivers) which is replaced
+       by this one.]
+
+       This attrubute does not affect the maximum supported frequency value
+       supplied to the ``CPUFreq`` core and exposed via the policy interface,
+       but it affects the maximum possible value of per-policy P-state limits
+       (see `Interpretation of Policy Attributes`_ below for details).
+
+.. _status_attr:
+
+``status``
+       Operation mode of the driver: "active", "passive" or "off".
+
+       "active"
+               The driver is functional and in the `active mode
+               <Active Mode_>`_.
+
+       "passive"
+               The driver is functional and in the `passive mode
+               <Passive Mode_>`_.
+
+       "off"
+               The driver is not functional (it is not registered as a scaling
+               driver with the ``CPUFreq`` core).
+
+       This attribute can be written to in order to change the driver's
+       operation mode or to unregister it.  The string written to it must be
+       one of the possible values of it and, if successful, the write will
+       cause the driver to switch over to the operation mode represented by
+       that string - or to be unregistered in the "off" case.  [Actually,
+       switching over from the active mode to the passive mode or the other
+       way around causes the driver to be unregistered and registered again
+       with a different set of callbacks, so all of its settings (the global
+       as well as the per-policy ones) are then reset to their default
+       values, possibly depending on the target operation mode.]
+
+       That only is supported in some configurations, though (for example, if
+       the `HWP feature is enabled in the processor <Active Mode With HWP_>`_,
+       the operation mode of the driver cannot be changed), and if it is not
+       supported in the current configuration, writes to this attribute with
+       fail with an appropriate error.
+
+Interpretation of Policy Attributes
+-----------------------------------
+
+The interpretation of some ``CPUFreq`` policy attributes described in
+:doc:`cpufreq` is special with ``intel_pstate`` as the current scaling driver
+and it generally depends on the driver's `operation mode <Operation Modes_>`_.
+
+First of all, the values of the ``cpuinfo_max_freq``, ``cpuinfo_min_freq`` and
+``scaling_cur_freq`` attributes are produced by applying a processor-specific
+multiplier to the internal P-state representation used by ``intel_pstate``.
+Also, the values of the ``scaling_max_freq`` and ``scaling_min_freq``
+attributes are capped by the frequency corresponding to the maximum P-state that
+the driver is allowed to set.
+
+If the ``no_turbo`` `global attribute <no_turbo_attr_>`_ is set, the driver is
+not allowed to use turbo P-states, so the maximum value of ``scaling_max_freq``
+and ``scaling_min_freq`` is limited to the maximum non-turbo P-state frequency.
+Accordingly, setting ``no_turbo`` causes ``scaling_max_freq`` and
+``scaling_min_freq`` to go down to that value if they were above it before.
+However, the old values of ``scaling_max_freq`` and ``scaling_min_freq`` will be
+restored after unsetting ``no_turbo``, unless these attributes have been written
+to after ``no_turbo`` was set.
+
+If ``no_turbo`` is not set, the maximum possible value of ``scaling_max_freq``
+and ``scaling_min_freq`` corresponds to the maximum supported turbo P-state,
+which also is the value of ``cpuinfo_max_freq`` in either case.
+
+Next, the following policy attributes have special meaning if
+``intel_pstate`` works in the `active mode <Active Mode_>`_:
+
+``scaling_available_governors``
+       List of P-state selection algorithms provided by ``intel_pstate``.
+
+``scaling_governor``
+       P-state selection algorithm provided by ``intel_pstate`` currently in
+       use with the given policy.
+
+``scaling_cur_freq``
+       Frequency of the average P-state of the CPU represented by the given
+       policy for the time interval between the last two invocations of the
+       driver's utilization update callback by the CPU scheduler for that CPU.
+
+The meaning of these attributes in the `passive mode <Passive Mode_>`_ is the
+same as for other scaling drivers.
+
+Additionally, the value of the ``scaling_driver`` attribute for ``intel_pstate``
+depends on the operation mode of the driver.  Namely, it is either
+"intel_pstate" (in the `active mode <Active Mode_>`_) or "intel_cpufreq" (in the
+`passive mode <Passive Mode_>`_).
+
+Coordination of P-State Limits
+------------------------------
+
+``intel_pstate`` allows P-state limits to be set in two ways: with the help of
+the ``max_perf_pct`` and ``min_perf_pct`` `global attributes
+<Global Attributes_>`_ or via the ``scaling_max_freq`` and ``scaling_min_freq``
+``CPUFreq`` policy attributes.  The coordination between those limits is based
+on the following rules, regardless of the current operation mode of the driver:
+
+ 1. All CPUs are affected by the global limits (that is, none of them can be
+    requested to run faster than the global maximum and none of them can be
+    requested to run slower than the global minimum).
+
+ 2. Each individual CPU is affected by its own per-policy limits (that is, it
+    cannot be requested to run faster than its own per-policy maximum and it
+    cannot be requested to run slower than its own per-policy minimum).
+
+ 3. The global and per-policy limits can be set independently.
+
+If the `HWP feature is enabled in the processor <Active Mode With HWP_>`_, the
+resulting effective values are written into its registers whenever the limits
+change in order to request its internal P-state selection logic to always set
+P-states within these limits.  Otherwise, the limits are taken into account by
+scaling governors (in the `passive mode <Passive Mode_>`_) and by the driver
+every time before setting a new P-state for a CPU.
+
+Additionally, if the ``intel_pstate=per_cpu_perf_limits`` command line argument
+is passed to the kernel, ``max_perf_pct`` and ``min_perf_pct`` are not exposed
+at all and the only way to set the limits is by using the policy attributes.
+
+
+Energy vs Performance Hints
+---------------------------
+
+If ``intel_pstate`` works in the `active mode with the HWP feature enabled
+<Active Mode With HWP_>`_ in the processor, additional attributes are present
+in every ``CPUFreq`` policy directory in ``sysfs``.  They are intended to allow
+user space to help ``intel_pstate`` to adjust the processor's internal P-state
+selection logic by focusing it on performance or on energy-efficiency, or
+somewhere between the two extremes:
+
+``energy_performance_preference``
+       Current value of the energy vs performance hint for the given policy
+       (or the CPU represented by it).
+
+       The hint can be changed by writing to this attribute.
+
+``energy_performance_available_preferences``
+       List of strings that can be written to the
+       ``energy_performance_preference`` attribute.
+
+       They represent different energy vs performance hints and should be
+       self-explanatory, except that ``default`` represents whatever hint
+       value was set by the platform firmware.
+
+Strings written to the ``energy_performance_preference`` attribute are
+internally translated to integer values written to the processor's
+Energy-Performance Preference (EPP) knob (if supported) or its
+Energy-Performance Bias (EPB) knob.
+
+[Note that tasks may by migrated from one CPU to another by the scheduler's
+load-balancing algorithm and if different energy vs performance hints are
+set for those CPUs, that may lead to undesirable outcomes.  To avoid such
+issues it is better to set the same energy vs performance hint for all CPUs
+or to pin every task potentially sensitive to them to a specific CPU.]
+
+.. _acpi-cpufreq:
+
+``intel_pstate`` vs ``acpi-cpufreq``
+====================================
+
+On the majority of systems supported by ``intel_pstate``, the ACPI tables
+provided by the platform firmware contain ``_PSS`` objects returning information
+that can be used for CPU performance scaling (refer to the `ACPI specification`_
+for details on the ``_PSS`` objects and the format of the information returned
+by them).
+
+The information returned by the ACPI ``_PSS`` objects is used by the
+``acpi-cpufreq`` scaling driver.  On systems supported by ``intel_pstate``
+the ``acpi-cpufreq`` driver uses the same hardware CPU performance scaling
+interface, but the set of P-states it can use is limited by the ``_PSS``
+output.
+
+On those systems each ``_PSS`` object returns a list of P-states supported by
+the corresponding CPU which basically is a subset of the P-states range that can
+be used by ``intel_pstate`` on the same system, with one exception: the whole
+`turbo range <turbo_>`_ is represented by one item in it (the topmost one).  By
+convention, the frequency returned by ``_PSS`` for that item is greater by 1 MHz
+than the frequency of the highest non-turbo P-state listed by it, but the
+corresponding P-state representation (following the hardware specification)
+returned for it matches the maximum supported turbo P-state (or is the
+special value 255 meaning essentially "go as high as you can get").
+
+The list of P-states returned by ``_PSS`` is reflected by the table of
+available frequencies supplied by ``acpi-cpufreq`` to the ``CPUFreq`` core and
+scaling governors and the minimum and maximum supported frequencies reported by
+it come from that list as well.  In particular, given the special representation
+of the turbo range described above, this means that the maximum supported
+frequency reported by ``acpi-cpufreq`` is higher by 1 MHz than the frequency
+of the highest supported non-turbo P-state listed by ``_PSS`` which, of course,
+affects decisions made by the scaling governors, except for ``powersave`` and
+``performance``.
+
+For example, if a given governor attempts to select a frequency proportional to
+estimated CPU load and maps the load of 100% to the maximum supported frequency
+(possibly multiplied by a constant), then it will tend to choose P-states below
+the turbo threshold if ``acpi-cpufreq`` is used as the scaling driver, because
+in that case the turbo range corresponds to a small fraction of the frequency
+band it can use (1 MHz vs 1 GHz or more).  In consequence, it will only go to
+the turbo range for the highest loads and the other loads above 50% that might
+benefit from running at turbo frequencies will be given non-turbo P-states
+instead.
+
+One more issue related to that may appear on systems supporting the
+`Configurable TDP feature <turbo_>`_ allowing the platform firmware to set the
+turbo threshold.  Namely, if that is not coordinated with the lists of P-states
+returned by ``_PSS`` properly, there may be more than one item corresponding to
+a turbo P-state in those lists and there may be a problem with avoiding the
+turbo range (if desirable or necessary).  Usually, to avoid using turbo
+P-states overall, ``acpi-cpufreq`` simply avoids using the topmost state listed
+by ``_PSS``, but that is not sufficient when there are other turbo P-states in
+the list returned by it.
+
+Apart from the above, ``acpi-cpufreq`` works like ``intel_pstate`` in the
+`passive mode <Passive Mode_>`_, except that the number of P-states it can set
+is limited to the ones listed by the ACPI ``_PSS`` objects.
+
+
+Kernel Command Line Options for ``intel_pstate``
+================================================
+
+Several kernel command line options can be used to pass early-configuration-time
+parameters to ``intel_pstate`` in order to enforce specific behavior of it.  All
+of them have to be prepended with the ``intel_pstate=`` prefix.
+
+``disable``
+       Do not register ``intel_pstate`` as the scaling driver even if the
+       processor is supported by it.
+
+``passive``
+       Register ``intel_pstate`` in the `passive mode <Passive Mode_>`_ to
+       start with.
+
+       This option implies the ``no_hwp`` one described below.
+
+``force``
+       Register ``intel_pstate`` as the scaling driver instead of
+       ``acpi-cpufreq`` even if the latter is preferred on the given system.
+
+       This may prevent some platform features (such as thermal controls and
+       power capping) that rely on the availability of ACPI P-states
+       information from functioning as expected, so it should be used with
+       caution.
+
+       This option does not work with processors that are not supported by
+       ``intel_pstate`` and on platforms where the ``pcc-cpufreq`` scaling
+       driver is used instead of ``acpi-cpufreq``.
+
+``no_hwp``
+       Do not enable the `hardware-managed P-states (HWP) feature
+       <Active Mode With HWP_>`_ even if it is supported by the processor.
+
+``hwp_only``
+       Register ``intel_pstate`` as the scaling driver only if the
+       `hardware-managed P-states (HWP) feature <Active Mode With HWP_>`_ is
+       supported by the processor.
+
+``support_acpi_ppc``
+       Take ACPI ``_PPC`` performance limits into account.
+
+       If the preferred power management profile in the FADT (Fixed ACPI
+       Description Table) is set to "Enterprise Server" or "Performance
+       Server", the ACPI ``_PPC`` limits are taken into account by default
+       and this option has no effect.
+
+``per_cpu_perf_limits``
+       Use per-logical-CPU P-State limits (see `Coordination of P-state
+       Limits`_ for details).
+
+
+Diagnostics and Tuning
+======================
+
+Trace Events
+------------
+
+There are two static trace events that can be used for ``intel_pstate``
+diagnostics.  One of them is the ``cpu_frequency`` trace event generally used
+by ``CPUFreq``, and the other one is the ``pstate_sample`` trace event specific
+to ``intel_pstate``.  Both of them are triggered by ``intel_pstate`` only if
+it works in the `active mode <Active Mode_>`_.
+
+The following sequence of shell commands can be used to enable them and see
+their output (if the kernel is generally configured to support event tracing)::
+
+ # cd /sys/kernel/debug/tracing/
+ # echo 1 > events/power/pstate_sample/enable
+ # echo 1 > events/power/cpu_frequency/enable
+ # cat trace
+ gnome-terminal--4510  [001] ..s.  1177.680733: pstate_sample: core_busy=107 scaled=94 from=26 to=26 mperf=1143818 aperf=1230607 tsc=29838618 freq=2474476
+ cat-5235  [002] ..s.  1177.681723: cpu_frequency: state=2900000 cpu_id=2
+
+If ``intel_pstate`` works in the `passive mode <Passive Mode_>`_, the
+``cpu_frequency`` trace event will be triggered either by the ``schedutil``
+scaling governor (for the policies it is attached to), or by the ``CPUFreq``
+core (for the policies with other scaling governors).
+
+``ftrace``
+----------
+
+The ``ftrace`` interface can be used for low-level diagnostics of
+``intel_pstate``.  For example, to check how often the function to set a
+P-state is called, the ``ftrace`` filter can be set to to
+:c:func:`intel_pstate_set_pstate`::
+
+ # cd /sys/kernel/debug/tracing/
+ # cat available_filter_functions | grep -i pstate
+ intel_pstate_set_pstate
+ intel_pstate_cpu_init
+ ...
+ # echo intel_pstate_set_pstate > set_ftrace_filter
+ # echo function > current_tracer
+ # cat trace | head -15
+ # tracer: function
+ #
+ # entries-in-buffer/entries-written: 80/80   #P:4
+ #
+ #                              _-----=> irqs-off
+ #                             / _----=> need-resched
+ #                            | / _---=> hardirq/softirq
+ #                            || / _--=> preempt-depth
+ #                            ||| /     delay
+ #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+ #              | |       |   ||||       |         |
+             Xorg-3129  [000] ..s.  2537.644844: intel_pstate_set_pstate <-intel_pstate_timer_func
+  gnome-terminal--4510  [002] ..s.  2537.649844: intel_pstate_set_pstate <-intel_pstate_timer_func
+      gnome-shell-3409  [001] ..s.  2537.650850: intel_pstate_set_pstate <-intel_pstate_timer_func
+           <idle>-0     [000] ..s.  2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func
+
+Tuning Interface in ``debugfs``
+-------------------------------
+
+The ``powersave`` algorithm provided by ``intel_pstate`` for `the Core line of
+processors in the active mode <powersave_>`_ is based on a `PID controller`_
+whose parameters were chosen to address a number of different use cases at the
+same time.  However, it still is possible to fine-tune it to a specific workload
+and the ``debugfs`` interface under ``/sys/kernel/debug/pstate_snb/`` is
+provided for this purpose.  [Note that the ``pstate_snb`` directory will be
+present only if the specific P-state selection algorithm matching the interface
+in it actually is in use.]
+
+The following files present in that directory can be used to modify the PID
+controller parameters at run time:
+
+| ``deadband``
+| ``d_gain_pct``
+| ``i_gain_pct``
+| ``p_gain_pct``
+| ``sample_rate_ms``
+| ``setpoint``
+
+Note, however, that achieving desirable results this way generally requires
+expert-level understanding of the power vs performance tradeoff, so extra care
+is recommended when attempting to do that.
+
+
+.. _LCEU2015: http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf
+.. _SDM: http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-system-programming-manual-325384.html
+.. _ACPI specification: http://www.uefi.org/sites/default/files/resources/ACPI_6_1.pdf
+.. _PID controller: https://en.wikipedia.org/wiki/PID_controller
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt
deleted file mode 100644 (file)
index 3fdcdfd..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-Intel P-State driver
---------------------
-
-This driver provides an interface to control the P-State selection for the
-SandyBridge+ Intel processors.
-
-The following document explains P-States:
-http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf
-As stated in the document, P-State doesn’t exactly mean a frequency. However, for
-the sake of the relationship with cpufreq, P-State and frequency are used
-interchangeably.
-
-Understanding the cpufreq core governors and policies are important before
-discussing more details about the Intel P-State driver. Based on what callbacks
-a cpufreq driver provides to the cpufreq core, it can support two types of
-drivers:
-- with target_index() callback: In this mode, the drivers using cpufreq core
-simply provide the minimum and maximum frequency limits and an additional
-interface target_index() to set the current frequency. The cpufreq subsystem
-has a number of scaling governors ("performance", "powersave", "ondemand",
-etc.). Depending on which governor is in use, cpufreq core will call for
-transitions to a specific frequency using target_index() callback.
-- setpolicy() callback: In this mode, drivers do not provide target_index()
-callback, so cpufreq core can't request a transition to a specific frequency.
-The driver provides minimum and maximum frequency limits and callbacks to set a
-policy. The policy in cpufreq sysfs is referred to as the "scaling governor".
-The cpufreq core can request the driver to operate in any of the two policies:
-"performance" and "powersave". The driver decides which frequency to use based
-on the above policy selection considering minimum and maximum frequency limits.
-
-The Intel P-State driver falls under the latter category, which implements the
-setpolicy() callback. This driver decides what P-State to use based on the
-requested policy from the cpufreq core. If the processor is capable of
-selecting its next P-State internally, then the driver will offload this
-responsibility to the processor (aka HWP: Hardware P-States). If not, the
-driver implements algorithms to select the next P-State.
-
-Since these policies are implemented in the driver, they are not same as the
-cpufreq scaling governors implementation, even if they have the same name in
-the cpufreq sysfs (scaling_governors). For example the "performance" policy is
-similar to cpufreq’s "performance" governor, but "powersave" is completely
-different than the cpufreq "powersave" governor. The strategy here is similar
-to cpufreq "ondemand", where the requested P-State is related to the system load.
-
-Sysfs Interface
-
-In addition to the frequency-controlling interfaces provided by the cpufreq
-core, the driver provides its own sysfs files to control the P-State selection.
-These files have been added to /sys/devices/system/cpu/intel_pstate/.
-Any changes made to these files are applicable to all CPUs (even in a
-multi-package system, Refer to later section on placing "Per-CPU limits").
-
-      max_perf_pct: Limits the maximum P-State that will be requested by
-      the driver. It states it as a percentage of the available performance. The
-      available (P-State) performance may be reduced by the no_turbo
-      setting described below.
-
-      min_perf_pct: Limits the minimum P-State that will be requested by
-      the driver. It states it as a percentage of the max (non-turbo)
-      performance level.
-
-      no_turbo: Limits the driver to selecting P-State below the turbo
-      frequency range.
-
-      turbo_pct: Displays the percentage of the total performance that
-      is supported by hardware that is in the turbo range. This number
-      is independent of whether turbo has been disabled or not.
-
-      num_pstates: Displays the number of P-States that are supported
-      by hardware. This number is independent of whether turbo has
-      been disabled or not.
-
-For example, if a system has these parameters:
-       Max 1 core turbo ratio: 0x21 (Max 1 core ratio is the maximum P-State)
-       Max non turbo ratio: 0x17
-       Minimum ratio : 0x08 (Here the ratio is called max efficiency ratio)
-
-Sysfs will show :
-       max_perf_pct:100, which corresponds to 1 core ratio
-       min_perf_pct:24, max_efficiency_ratio / max 1 Core ratio
-       no_turbo:0, turbo is not disabled
-       num_pstates:26 = (max 1 Core ratio - Max Efficiency Ratio + 1)
-       turbo_pct:39 = (max 1 core ratio - max non turbo ratio) / num_pstates
-
-Refer to "Intel® 64 and IA-32 Architectures Software Developer’s Manual
-Volume 3: System Programming Guide" to understand ratios.
-
-There is one more sysfs attribute in /sys/devices/system/cpu/intel_pstate/
-that can be used for controlling the operation mode of the driver:
-
-      status: Three settings are possible:
-      "off"     - The driver is not in use at this time.
-      "active"  - The driver works as a P-state governor (default).
-      "passive" - The driver works as a regular cpufreq one and collaborates
-                  with the generic cpufreq governors (it sets P-states as
-                  requested by those governors).
-      The current setting is returned by reads from this attribute.  Writing one
-      of the above strings to it changes the operation mode as indicated by that
-      string, if possible.  If HW-managed P-states (HWP) are enabled, it is not
-      possible to change the driver's operation mode and attempts to write to
-      this attribute will fail.
-
-cpufreq sysfs for Intel P-State
-
-Since this driver registers with cpufreq, cpufreq sysfs is also presented.
-There are some important differences, which need to be considered.
-
-scaling_cur_freq: This displays the real frequency which was used during
-the last sample period instead of what is requested. Some other cpufreq driver,
-like acpi-cpufreq, displays what is requested (Some changes are on the
-way to fix this for acpi-cpufreq driver). The same is true for frequencies
-displayed at /proc/cpuinfo.
-
-scaling_governor: This displays current active policy. Since each CPU has a
-cpufreq sysfs, it is possible to set a scaling governor to each CPU. But this
-is not possible with Intel P-States, as there is one common policy for all
-CPUs. Here, the last requested policy will be applicable to all CPUs. It is
-suggested that one use the cpupower utility to change policy to all CPUs at the
-same time.
-
-scaling_setspeed: This attribute can never be used with Intel P-State.
-
-scaling_max_freq/scaling_min_freq: This interface can be used similarly to
-the max_perf_pct/min_perf_pct of Intel P-State sysfs. However since frequencies
-are converted to nearest possible P-State, this is prone to rounding errors.
-This method is not preferred to limit performance.
-
-affected_cpus: Not used
-related_cpus: Not used
-
-For contemporary Intel processors, the frequency is controlled by the
-processor itself and the P-State exposed to software is related to
-performance levels.  The idea that frequency can be set to a single
-frequency is fictional for Intel Core processors. Even if the scaling
-driver selects a single P-State, the actual frequency the processor
-will run at is selected by the processor itself.
-
-Per-CPU limits
-
-The kernel command line option "intel_pstate=per_cpu_perf_limits" forces
-the intel_pstate driver to use per-CPU performance limits.  When it is set,
-the sysfs control interface described above is subject to limitations.
-- The following controls are not available for both read and write
-       /sys/devices/system/cpu/intel_pstate/max_perf_pct
-       /sys/devices/system/cpu/intel_pstate/min_perf_pct
-- The following controls can be used to set performance limits, as far as the
-architecture of the processor permits:
-       /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq
-       /sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq
-       /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
-- User can still observe turbo percent and number of P-States from
-       /sys/devices/system/cpu/intel_pstate/turbo_pct
-       /sys/devices/system/cpu/intel_pstate/num_pstates
-- User can read write system wide turbo status
-       /sys/devices/system/cpu/no_turbo
-
-Support of energy performance hints
-It is possible to provide hints to the HWP algorithms in the processor
-to be more performance centric to more energy centric. When the driver
-is using HWP, two additional cpufreq sysfs attributes are presented for
-each logical CPU.
-These attributes are:
-       - energy_performance_available_preferences
-       - energy_performance_preference
-
-To get list of supported hints:
-$ cat energy_performance_available_preferences
-    default performance balance_performance balance_power power
-
-The current preference can be read or changed via cpufreq sysfs
-attribute "energy_performance_preference". Reading from this attribute
-will display current effective setting. User can write any of the valid
-preference string to this attribute. User can always restore to power-on
-default by writing "default".
-
-Since threads can migrate to different CPUs, this is possible that the
-new CPU may have different energy performance preference than the previous
-one. To avoid such issues, either threads can be pinned to specific CPUs
-or set the same energy performance preference value to all CPUs.
-
-Tuning Intel P-State driver
-
-When the performance can be tuned using PID (Proportional Integral
-Derivative) controller, debugfs files are provided for adjusting performance.
-They are presented under:
-/sys/kernel/debug/pstate_snb/
-
-The PID tunable parameters are:
-      deadband
-      d_gain_pct
-      i_gain_pct
-      p_gain_pct
-      sample_rate_ms
-      setpoint
-
-To adjust these parameters, some understanding of driver implementation is
-necessary. There are some tweeks described here, but be very careful. Adjusting
-them requires expert level understanding of power and performance relationship.
-These limits are only useful when the "powersave" policy is active.
-
--To make the system more responsive to load changes, sample_rate_ms can
-be adjusted  (current default is 10ms).
--To make the system use higher performance, even if the load is lower, setpoint
-can be adjusted to a lower number. This will also lead to faster ramp up time
-to reach the maximum P-State.
-If there are no derivative and integral coefficients, The next P-State will be
-equal to:
-       current P-State - ((setpoint - current cpu load) * p_gain_pct)
-
-For example, if the current PID parameters are (Which are defaults for the core
-processors like SandyBridge):
-      deadband = 0
-      d_gain_pct = 0
-      i_gain_pct = 0
-      p_gain_pct = 20
-      sample_rate_ms = 10
-      setpoint = 97
-
-If the current P-State = 0x08 and current load = 100, this will result in the
-next P-State = 0x08 - ((97 - 100) * 0.2) = 8.6 (rounded to 9). Here the P-State
-goes up by only 1. If during next sample interval the current load doesn't
-change and still 100, then P-State goes up by one again. This process will
-continue as long as the load is more than the setpoint until the maximum P-State
-is reached.
-
-For the same load at setpoint = 60, this will result in the next P-State
-= 0x08 - ((60 - 100) * 0.2) = 16
-So by changing the setpoint from 97 to 60, there is an increase of the
-next P-State from 9 to 16. So this will make processor execute at higher
-P-State for the same CPU load. If the load continues to be more than the
-setpoint during next sample intervals, then P-State will go up again till the
-maximum P-State is reached. But the ramp up time to reach the maximum P-State
-will be much faster when the setpoint is 60 compared to 97.
-
-Debugging Intel P-State driver
-
-Event tracing
-To debug P-State transition, the Linux event tracing interface can be used.
-There are two specific events, which can be enabled (Provided the kernel
-configs related to event tracing are enabled).
-
-# cd /sys/kernel/debug/tracing/
-# echo 1 > events/power/pstate_sample/enable
-# echo 1 > events/power/cpu_frequency/enable
-# cat trace
-gnome-terminal--4510  [001] ..s.  1177.680733: pstate_sample: core_busy=107
-       scaled=94 from=26 to=26 mperf=1143818 aperf=1230607 tsc=29838618
-               freq=2474476
-cat-5235  [002] ..s.  1177.681723: cpu_frequency: state=2900000 cpu_id=2
-
-
-Using ftrace
-
-If function level tracing is required, the Linux ftrace interface can be used.
-For example if we want to check how often a function to set a P-State is
-called, we can set ftrace filter to intel_pstate_set_pstate.
-
-# cd /sys/kernel/debug/tracing/
-# cat available_filter_functions | grep -i pstate
-intel_pstate_set_pstate
-intel_pstate_cpu_init
-...
-
-# echo intel_pstate_set_pstate > set_ftrace_filter
-# echo function > current_tracer
-# cat trace | head -15
-# tracer: function
-#
-# entries-in-buffer/entries-written: 80/80   #P:4
-#
-#                              _-----=> irqs-off
-#                             / _----=> need-resched
-#                            | / _---=> hardirq/softirq
-#                            || / _--=> preempt-depth
-#                            ||| /     delay
-#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
-#              | |       |   ||||       |         |
-            Xorg-3129  [000] ..s.  2537.644844: intel_pstate_set_pstate <-intel_pstate_timer_func
- gnome-terminal--4510  [002] ..s.  2537.649844: intel_pstate_set_pstate <-intel_pstate_timer_func
-     gnome-shell-3409  [001] ..s.  2537.650850: intel_pstate_set_pstate <-intel_pstate_timer_func
-          <idle>-0     [000] ..s.  2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func
index e9c5a1d9834af600de55821bc0077e6235ff0bff..f465647a4dd219a7718c26c88725a42dc5106f0d 100644 (file)
@@ -22,7 +22,8 @@ Required properties :
 - #clock-cells : must contain 1
 - #reset-cells : must contain 1
 
-For the PRCM CCUs on H3/A64, one more clock is needed:
+For the PRCM CCUs on H3/A64, two more clocks are needed:
+- "pll-periph": the SoC's peripheral PLL from the main CCU
 - "iosc": the SoC's internal frequency oscillator
 
 Example for generic CCU:
@@ -39,8 +40,8 @@ Example for PRCM CCU:
 r_ccu: clock@01f01400 {
        compatible = "allwinner,sun50i-a64-r-ccu";
        reg = <0x01f01400 0x100>;
-       clocks = <&osc24M>, <&osc32k>, <&iosc>;
-       clock-names = "hosc", "losc", "iosc";
+       clocks = <&osc24M>, <&osc32k>, <&iosc>, <&ccu CLK_PLL_PERIPH0>;
+       clock-names = "hosc", "losc", "iosc", "pll-periph";
        #clock-cells = <1>;
        #reset-cells = <1>;
 };
index 42c3bb2d53e88b651a7d39efe00e278c24d9c9b3..01e331a5f3e7491fba25188b5a12e91722057e42 100644 (file)
@@ -41,9 +41,9 @@ Required properties:
 Optional properties:
 
 In order to use the GPIO lines in PWM mode, some additional optional
-properties are required. Only Armada 370 and XP support these properties.
+properties are required.
 
-- compatible: Must contain "marvell,armada-370-xp-gpio"
+- compatible: Must contain "marvell,armada-370-gpio"
 
 - reg: an additional register set is needed, for the GPIO Blink
   Counter on/off registers.
@@ -71,7 +71,7 @@ Example:
                };
 
                gpio1: gpio@18140 {
-                       compatible = "marvell,armada-370-xp-gpio";
+                       compatible = "marvell,armada-370-gpio";
                        reg = <0x18140 0x40>, <0x181c8 0x08>;
                        reg-names = "gpio", "pwm";
                        ngpios = <17>;
index 6db22103e2dd535952143a2bae9ba4c6790c6e56..025cf8c9324ac362eeee56b5d4f9df09db466180 100644 (file)
@@ -36,7 +36,7 @@ Optional properties:
                 control gpios
 
  - threshold:   allows setting the "click"-threshold in the range
-                from 20 to 80.
+                from 0 to 80.
 
  - gain:        allows setting the sensitivity in the range from 0 to
                 31. Note that lower values indicate higher
index 05485699d70e7c85cb25eb83f39b86f5be0daaca..9630ac0e4b56ef372f08a0850175be06d13cd9a7 100644 (file)
@@ -16,6 +16,11 @@ Required properties:
 - reg:                  Base address of PMIC on Hi6220 SoC.
 - interrupt-controller: Hi655x has internal IRQs (has own IRQ domain).
 - pmic-gpios:           The GPIO used by PMIC IRQ.
+- #clock-cells:                From common clock binding; shall be set to 0
+
+Optional properties:
+- clock-output-names: From common clock binding to override the
+  default output clock name
 
 Example:
        pmic: pmic@f8000000 {
@@ -24,4 +29,5 @@ Example:
                interrupt-controller;
                #interrupt-cells = <2>;
                pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+               #clock-cells = <0>;
        }
index bbd083f5600a786b23a0ec821f384e8e8a6a3553..1db6e0057a638e09a5346956a70620c31276fdf6 100644 (file)
@@ -31,7 +31,7 @@ Example:
                compatible = "st,stm32-timers";
                reg = <0x40010000 0x400>;
                clocks = <&rcc 0 160>;
-               clock-names = "clk_int";
+               clock-names = "int";
 
                pwm {
                        compatible = "st,stm32-pwm";
index e25436861867f28f75a2450ecbf28d1fd2df3921..9029b45b8a22a8d5b6a1afa3184bf389a85202f4 100644 (file)
@@ -18,6 +18,8 @@ Optional properties:
   "ext_clock" (External clock provided to the card).
 - post-power-on-delay-ms : Delay in ms after powering the card and
        de-asserting the reset-gpios (if any)
+- power-off-delay-us : Delay in us after asserting the reset-gpios (if any)
+       during power off of the card.
 
 Example:
 
index d6c6e41648d4f17814ea43775e8591a40a4c0786..8ec2ca21adeb6ca840a7fd5d660a57748919af42 100644 (file)
@@ -34,7 +34,7 @@ Required properties:
       "brcm,bcm6328-switch"
       "brcm,bcm6368-switch" and the mandatory "brcm,bcm63xx-switch"
 
-See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
 required and optional properties.
 
 Examples:
index 7ef9dbb08957a593528a4d873d1f3af29892f5c2..1d4d0f49c9d06eb66d9957fb0661cec35ddc7af9 100644 (file)
@@ -26,6 +26,10 @@ Optional properties:
 - interrupt-controller : Indicates the switch is itself an interrupt
                          controller. This is used for the PHY interrupts.
 #interrupt-cells = <2> : Controller uses two cells, number and flag
+- eeprom-length                : Set to the length of an EEPROM connected to the
+                         switch. Must be set if the switch can not detect
+                         the presence and/or size of a connected EEPROM,
+                         otherwise optional.
 - mdio                 : Container of PHY and devices on the switches MDIO
                          bus.
 - mdio?                : Container of PHYs and devices on the external MDIO
index a1e3693cca1601e47096dc2edc2a9580b8b0569a..6f55bdd52f8a99be3c0741cf6411a00554c85778 100644 (file)
@@ -15,6 +15,10 @@ Optional properties:
 - phy-reset-active-high : If present then the reset sequence using the GPIO
   specified in the "phy-reset-gpios" property is reversed (H=reset state,
   L=operation state).
+- phy-reset-post-delay : Post reset delay in milliseconds. If present then
+  a delay of phy-reset-post-delay milliseconds will be observed after the
+  phy-reset-gpios has been toggled. Can be omitted thus no delay is
+  observed. Delay is in range of 1ms to 1000ms. Other delays are invalid.
 - phy-supply : regulator that powers the Ethernet PHY.
 - phy-handle : phandle to the PHY device connected to this device.
 - fixed-link : Assume a fixed link. See fixed-link.txt in the same directory.
index 16c3a9501f5d689431451c52b91c86b8ae1395b8..acfafc8e143c4c8599510eb7d2cbcb35af7e6f9f 100644 (file)
@@ -27,6 +27,7 @@ Optional properties:
   of the device. On many systems this is wired high so the device goes
   out of reset at power-on, but if it is under program control, this
   optional GPIO can wake up in response to it.
+- vdd33a-supply, vddvario-supply : 3.3V analog and IO logic power supplies
 
 Examples:
 
index 71a3c134af1b25d58613699aa465d17cff2c23d0..f01d154090dab1b3a8a58fee6a599459392aa1f8 100644 (file)
@@ -247,7 +247,6 @@ bias-bus-hold               - latch weakly
 bias-pull-up           - pull up the pin
 bias-pull-down         - pull down the pin
 bias-pull-pin-default  - use pin-default pull state
-bi-directional         - pin supports simultaneous input/output operations
 drive-push-pull                - drive actively high and low
 drive-open-drain       - drive with open drain
 drive-open-source      - drive with open source
@@ -260,7 +259,6 @@ input-debounce              - debounce mode with debound time X
 power-source           - select between different power supplies
 low-power-enable       - enable low power mode
 low-power-disable      - disable low power mode
-output-enable          - enable output on pin regardless of output value
 output-low             - set the pin to output mode with low level
 output-high            - set the pin to output mode with high level
 slew-rate              - set the slew rate
diff --git a/Documentation/devicetree/bindings/staging/ion/hi6220-ion.txt b/Documentation/devicetree/bindings/staging/ion/hi6220-ion.txt
deleted file mode 100644 (file)
index c59e27c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Hi6220 SoC ION
-===================================================================
-Required properties:
-- compatible : "hisilicon,hi6220-ion"
-- list of the ION heaps
-       - heap name : maybe heap_sys_user@0
-       - heap id   : id should be unique in the system.
-       - heap base : base ddr address of the heap,0 means that
-       it is dynamic.
-       - heap size : memory size and 0 means it is dynamic.
-       - heap type : the heap type of the heap, please also
-       see the define in ion.h(drivers/staging/android/uapi/ion.h)
--------------------------------------------------------------------
-Example:
-       hi6220-ion {
-               compatible = "hisilicon,hi6220-ion";
-               heap_sys_user@0 {
-                       heap-name = "sys_user";
-                       heap-id   = <0x0>;
-                       heap-base = <0x0>;
-                       heap-size = <0x0>;
-                       heap-type = "ion_system";
-               };
-               heap_sys_contig@0 {
-                       heap-name = "sys_contig";
-                       heap-id   = <0x1>;
-                       heap-base = <0x0>;
-                       heap-size = <0x0>;
-                       heap-type = "ion_system_contig";
-               };
-       };
index 00bea038639e4ea341735c875040ea55a12e8be3..fcf199b64d3d3f2b703c42001d7cf7dfff5ca7bf 100644 (file)
@@ -10,6 +10,7 @@ Required properties:
   - "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc;
   - "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs;
   - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs;
+  - "amlogic,meson8-usb": The DWC2 USB controller instance in Amlogic Meson8 SoCs;
   - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs;
   - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
   - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs;
index 2032f0b7a8fa125dc3c88842dbeccb25a41a3453..1ccc94b192b7edacd8a42ff81de923b4a35a27e7 100644 (file)
@@ -15,7 +15,7 @@ It has been tested with the following devices:
 The driver allows configuration of the touch screen via a set of sysfs files:
 
 /sys/class/input/eventX/device/device/threshold:
-    allows setting the "click"-threshold in the range from 20 to 80.
+    allows setting the "click"-threshold in the range from 0 to 80.
 
 /sys/class/input/eventX/device/device/gain:
     allows setting the sensitivity in the range from 0 to 31. Note that
diff --git a/Documentation/networking/dpaa.txt b/Documentation/networking/dpaa.txt
new file mode 100644 (file)
index 0000000..76e016d
--- /dev/null
@@ -0,0 +1,194 @@
+The QorIQ DPAA Ethernet Driver
+==============================
+
+Authors:
+Madalin Bucur <madalin.bucur@nxp.com>
+Camelia Groza <camelia.groza@nxp.com>
+
+Contents
+========
+
+       - DPAA Ethernet Overview
+       - DPAA Ethernet Supported SoCs
+       - Configuring DPAA Ethernet in your kernel
+       - DPAA Ethernet Frame Processing
+       - DPAA Ethernet Features
+       - Debugging
+
+DPAA Ethernet Overview
+======================
+
+DPAA stands for Data Path Acceleration Architecture and it is a
+set of networking acceleration IPs that are available on several
+generations of SoCs, both on PowerPC and ARM64.
+
+The Freescale DPAA architecture consists of a series of hardware blocks
+that support Ethernet connectivity. The Ethernet driver depends upon the
+following drivers in the Linux kernel:
+
+ - Peripheral Access Memory Unit (PAMU) (* needed only for PPC platforms)
+    drivers/iommu/fsl_*
+ - Frame Manager (FMan)
+    drivers/net/ethernet/freescale/fman
+ - Queue Manager (QMan), Buffer Manager (BMan)
+    drivers/soc/fsl/qbman
+
+A simplified view of the dpaa_eth interfaces mapped to FMan MACs:
+
+  dpaa_eth       /eth0\     ...       /ethN\
+  driver        |      |             |      |
+  -------------   ----   -----------   ----   -------------
+       -Ports  / Tx  Rx \    ...    / Tx  Rx \
+  FMan        |          |         |          |
+       -MACs  |   MAC0   |         |   MACN   |
+             /   dtsec0   \  ...  /   dtsecN   \ (or tgec)
+            /              \     /              \(or memac)
+  ---------  --------------  ---  --------------  ---------
+      FMan, FMan Port, FMan SP, FMan MURAM drivers
+  ---------------------------------------------------------
+      FMan HW blocks: MURAM, MACs, Ports, SP
+  ---------------------------------------------------------
+
+The dpaa_eth relation to the QMan, BMan and FMan:
+              ________________________________
+  dpaa_eth   /            eth0                \
+  driver    /                                  \
+  ---------   -^-   -^-   -^-   ---    ---------
+  QMan driver / \   / \   / \  \   /  | BMan    |
+             |Rx | |Rx | |Tx | |Tx |  | driver  |
+  ---------  |Dfl| |Err| |Cnf| |FQs|  |         |
+  QMan HW    |FQ | |FQ | |FQs| |   |  |         |
+             /   \ /   \ /   \  \ /   |         |
+  ---------   ---   ---   ---   -v-    ---------
+            |        FMan QMI         |         |
+            | FMan HW       FMan BMI  | BMan HW |
+              -----------------------   --------
+
+where the acronyms used above (and in the code) are:
+DPAA = Data Path Acceleration Architecture
+FMan = DPAA Frame Manager
+QMan = DPAA Queue Manager
+BMan = DPAA Buffers Manager
+QMI = QMan interface in FMan
+BMI = BMan interface in FMan
+FMan SP = FMan Storage Profiles
+MURAM = Multi-user RAM in FMan
+FQ = QMan Frame Queue
+Rx Dfl FQ = default reception FQ
+Rx Err FQ = Rx error frames FQ
+Tx Cnf FQ = Tx confirmation FQs
+Tx FQs = transmission frame queues
+dtsec = datapath three speed Ethernet controller (10/100/1000 Mbps)
+tgec = ten gigabit Ethernet controller (10 Gbps)
+memac = multirate Ethernet MAC (10/100/1000/10000)
+
+DPAA Ethernet Supported SoCs
+============================
+
+The DPAA drivers enable the Ethernet controllers present on the following SoCs:
+
+# PPC
+P1023
+P2041
+P3041
+P4080
+P5020
+P5040
+T1023
+T1024
+T1040
+T1042
+T2080
+T4240
+B4860
+
+# ARM
+LS1043A
+LS1046A
+
+Configuring DPAA Ethernet in your kernel
+========================================
+
+To enable the DPAA Ethernet driver, the following Kconfig options are required:
+
+# common for arch/arm64 and arch/powerpc platforms
+CONFIG_FSL_DPAA=y
+CONFIG_FSL_FMAN=y
+CONFIG_FSL_DPAA_ETH=y
+CONFIG_FSL_XGMAC_MDIO=y
+
+# for arch/powerpc only
+CONFIG_FSL_PAMU=y
+
+# common options needed for the PHYs used on the RDBs
+CONFIG_VITESSE_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_AQUANTIA_PHY=y
+
+DPAA Ethernet Frame Processing
+==============================
+
+On Rx, buffers for the incoming frames are retrieved from one of the three
+existing buffers pools. The driver initializes and seeds these, each with
+buffers of different sizes: 1KB, 2KB and 4KB.
+
+On Tx, all transmitted frames are returned to the driver through Tx
+confirmation frame queues. The driver is then responsible for freeing the
+buffers. In order to do this properly, a backpointer is added to the buffer
+before transmission that points to the skb. When the buffer returns to the
+driver on a confirmation FQ, the skb can be correctly consumed.
+
+DPAA Ethernet Features
+======================
+
+Currently the DPAA Ethernet driver enables the basic features required for
+a Linux Ethernet driver. The support for advanced features will be added
+gradually.
+
+The driver has Rx and Tx checksum offloading for UDP and TCP. Currently the Rx
+checksum offload feature is enabled by default and cannot be controlled through
+ethtool.
+
+The driver has support for multiple prioritized Tx traffic classes. Priorities
+range from 0 (lowest) to 3 (highest). These are mapped to HW workqueues with
+strict priority levels. Each traffic class contains NR_CPU TX queues. By
+default, only one traffic class is enabled and the lowest priority Tx queues
+are used. Higher priority traffic classes can be enabled with the mqprio
+qdisc. For example, all four traffic classes are enabled on an interface with
+the following command. Furthermore, skb priority levels are mapped to traffic
+classes as follows:
+
+       * priorities 0 to 3 - traffic class 0 (low priority)
+       * priorities 4 to 7 - traffic class 1 (medium-low priority)
+       * priorities 8 to 11 - traffic class 2 (medium-high priority)
+       * priorities 12 to 15 - traffic class 3 (high priority)
+
+tc qdisc add dev <int> root handle 1: \
+        mqprio num_tc 4 map 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 hw 1
+
+Debugging
+=========
+
+The following statistics are exported for each interface through ethtool:
+
+       - interrupt count per CPU
+       - Rx packets count per CPU
+       - Tx packets count per CPU
+       - Tx confirmed packets count per CPU
+       - Tx S/G frames count per CPU
+       - Tx error count per CPU
+       - Rx error count per CPU
+       - Rx error count per type
+       - congestion related statistics:
+               - congestion status
+               - time spent in congestion
+               - number of time the device entered congestion
+               - dropped packets count per cause
+
+The driver also exports the following information in sysfs:
+
+       - the FQ IDs for each FQ type
+       /sys/devices/platform/dpaa-ethernet.0/net/<int>/fqids
+
+       - the IDs of the buffer pools in use
+       /sys/devices/platform/dpaa-ethernet.0/net/<int>/bpids
index 59f4db2a0c85c02df4f6cee3176ceb173333cac1..f55639d71d35b8c466252808cf9b0e58d42b7f30 100644 (file)
@@ -122,7 +122,7 @@ associated flow of the packet. The hash is either provided by hardware
 or will be computed in the stack. Capable hardware can pass the hash in
 the receive descriptor for the packet; this would usually be the same
 hash used for RSS (e.g. computed Toeplitz hash). The hash is saved in
-skb->rx_hash and can be used elsewhere in the stack as a hash of the
+skb->hash and can be used elsewhere in the stack as a hash of the
 packet’s flow.
 
 Each receive hardware queue has an associated list of CPUs to which
index bdc4c0db51e1078fb002907124fe7008ef4c0cd4..9c7139d57e5748508ce20400349cfdefd0284f74 100644 (file)
@@ -1,7 +1,7 @@
 TCP protocol
 ============
 
-Last updated: 9 February 2008
+Last updated: 3 June 2017
 
 Contents
 ========
@@ -29,18 +29,19 @@ As of 2.6.13, Linux supports pluggable congestion control algorithms.
 A congestion control mechanism can be registered through functions in
 tcp_cong.c. The functions used by the congestion control mechanism are
 registered via passing a tcp_congestion_ops struct to
-tcp_register_congestion_control. As a minimum name, ssthresh,
-cong_avoid must be valid.
+tcp_register_congestion_control. As a minimum, the congestion control
+mechanism must provide a valid name and must implement either ssthresh,
+cong_avoid and undo_cwnd hooks or the "omnipotent" cong_control hook.
 
 Private data for a congestion control mechanism is stored in tp->ca_priv.
 tcp_ca(tp) returns a pointer to this space.  This is preallocated space - it
 is important to check the size of your private data will fit this space, or
-alternatively space could be allocated elsewhere and a pointer to it could
+alternatively, space could be allocated elsewhere and a pointer to it could
 be stored here.
 
 There are three kinds of congestion control algorithms currently: The
 simplest ones are derived from TCP reno (highspeed, scalable) and just
-provide an alternative the congestion window calculation. More complex
+provide an alternative congestion window calculation. More complex
 ones like BIC try to look at other events to provide better
 heuristics.  There are also round trip time based algorithms like
 Vegas and Westwood+.
@@ -49,21 +50,15 @@ Good TCP congestion control is a complex problem because the algorithm
 needs to maintain fairness and performance. Please review current
 research and RFC's before developing new modules.
 
-The method that is used to determine which congestion control mechanism is
-determined by the setting of the sysctl net.ipv4.tcp_congestion_control.
-The default congestion control will be the last one registered (LIFO);
-so if you built everything as modules, the default will be reno. If you
-build with the defaults from Kconfig, then CUBIC will be builtin (not a
-module) and it will end up the default.
+The default congestion control mechanism is chosen based on the
+DEFAULT_TCP_CONG Kconfig parameter. If you really want a particular default
+value then you can set it using sysctl net.ipv4.tcp_congestion_control. The
+module will be autoloaded if needed and you will get the expected protocol. If
+you ask for an unknown congestion method, then the sysctl attempt will fail.
 
-If you really want a particular default value then you will need
-to set it with the sysctl.  If you use a sysctl, the module will be autoloaded
-if needed and you will get the expected protocol. If you ask for an
-unknown congestion method, then the sysctl attempt will fail.
-
-If you remove a tcp congestion control module, then you will get the next
+If you remove a TCP congestion control module, then you will get the next
 available one. Since reno cannot be built as a module, and cannot be
-deleted, it will always be available.
+removed, it will always be available.
 
 How the new TCP output machine [nyi] works.
 ===========================================
index 5338673c88d950e21dbed11f7f030544eeb7fa2e..773d2bfacc6cc6b8e714fd89c249296d647d3f1f 100644 (file)
@@ -16,6 +16,8 @@ ALC880
     6-jack in back, 2-jack in front
 6stack-digout
     6-jack with a SPDIF out
+6stack-automute
+    6-jack with headphone jack detection
 
 ALC260
 ======
@@ -62,6 +64,8 @@ lenovo-dock
     Enables docking station I/O for some Lenovos
 hp-gpio-led
     GPIO LED support on HP laptops
+hp-dock-gpio-mic1-led
+    HP dock with mic LED support
 dell-headset-multi
     Headset jack, which can also be used as mic-in
 dell-headset-dock
@@ -72,6 +76,12 @@ alc283-sense-combo
     Combo jack sensing on ALC283
 tpt440-dock
     Pin configs for Lenovo Thinkpad Dock support
+tpt440
+    Lenovo Thinkpad T440s setup
+tpt460
+    Lenovo Thinkpad T460/560 setup
+dual-codecs
+    Lenovo laptops with dual codecs
 
 ALC66x/67x/892
 ==============
@@ -97,6 +107,8 @@ inv-dmic
     Inverted internal mic workaround
 dell-headset-multi
     Headset jack, which can also be used as mic-in
+dual-codecs
+    Lenovo laptops with dual codecs
 
 ALC680
 ======
@@ -114,6 +126,8 @@ inv-dmic
     Inverted internal mic workaround
 no-primary-hp
     VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC)
+dual-codecs
+    ALC1220 dual codecs for Gaming mobos
 
 ALC861/660
 ==========
@@ -206,65 +220,47 @@ auto
 
 Conexant 5045
 =============
-laptop-hpsense
-    Laptop with HP sense (old model laptop)
-laptop-micsense
-    Laptop with Mic sense (old model fujitsu)
-laptop-hpmicsense
-    Laptop with HP and Mic senses
-benq
-    Benq R55E
-laptop-hp530
-    HP 530 laptop
-test
-    for testing/debugging purpose, almost all controls can be
-    adjusted.  Appearing only when compiled with $CONFIG_SND_DEBUG=y
+cap-mix-amp
+    Fix max input level on mixer widget
+toshiba-p105
+    Toshiba P105 quirk
+hp-530
+    HP 530 quirk
 
 Conexant 5047
 =============
-laptop
-    Basic Laptop config 
-laptop-hp
-    Laptop config for some HP models (subdevice 30A5)
-laptop-eapd
-    Laptop config with EAPD support
-test
-    for testing/debugging purpose, almost all controls can be
-    adjusted.  Appearing only when compiled with $CONFIG_SND_DEBUG=y
+cap-mix-amp
+    Fix max input level on mixer widget
 
 Conexant 5051
 =============
-laptop
-    Basic Laptop config (default)
-hp
-    HP Spartan laptop
-hp-dv6736
-    HP dv6736
-hp-f700
-    HP Compaq Presario F700
-ideapad
-    Lenovo IdeaPad laptop
-toshiba
-    Toshiba Satellite M300
+lenovo-x200
+    Lenovo X200 quirk
 
 Conexant 5066
 =============
-laptop
-    Basic Laptop config (default)
-hp-laptop
-    HP laptops, e g G60
-asus
-    Asus K52JU, Lenovo G560
-dell-laptop
-    Dell laptops
-dell-vostro
-    Dell Vostro
-olpc-xo-1_5
-    OLPC XO 1.5
-ideapad
-    Lenovo IdeaPad U150
+stereo-dmic
+    Workaround for inverted stereo digital mic
+gpio1
+    Enable GPIO1 pin
+headphone-mic-pin
+    Enable headphone mic NID 0x18 without detection
+tp410
+    Thinkpad T400 & co quirks
 thinkpad
-    Lenovo Thinkpad
+    Thinkpad mute/mic LED quirk
+lemote-a1004
+    Lemote A1004 quirk
+lemote-a1205
+    Lemote A1205 quirk
+olpc-xo
+    OLPC XO quirk
+mute-led-eapd
+    Mute LED control via EAPD
+hp-dock
+    HP dock support
+mute-led-gpio
+    Mute LED control via GPIO
 
 STAC9200
 ========
@@ -444,6 +440,8 @@ dell-eq
     Dell desktops/laptops
 alienware
     Alienware M17x
+asus-mobo
+    Pin configs for ASUS mobo with 5.1/SPDIF out
 auto
     BIOS setup (default)
 
@@ -477,6 +475,8 @@ hp-envy-ts-bass
     Pin fixup for HP Envy TS bass speaker (NID 0x10)
 hp-bnb13-eq
     Hardware equalizer setup for HP laptops
+hp-envy-ts-bass
+    HP Envy TS bass support
 auto
     BIOS setup (default)
 
@@ -496,10 +496,22 @@ auto
 
 Cirrus Logic CS4206/4207
 ========================
+mbp53
+    MacBook Pro 5,3
 mbp55
     MacBook Pro 5,5
 imac27
     IMac 27 Inch
+imac27_122
+    iMac 12,2
+apple
+    Generic Apple quirk
+mbp101
+    MacBookPro 10,1
+mbp81
+    MacBookPro 8,1
+mba42
+    MacBookAir 4,2
 auto
     BIOS setup (default)
 
@@ -509,6 +521,10 @@ mba6
     MacBook Air 6,1 and 6,2
 gpio0
     Enable GPIO 0 amp
+mbp11
+    MacBookPro 11,2
+macmini
+    MacMini 7,1
 auto
     BIOS setup (default)
 
index b67a46779de9fb7ee2d2c515718de3dab4914b37..8a7249f2ff04ca8c24e5ae9174fb1ba2a93d0461 100644 (file)
@@ -114,8 +114,7 @@ the details during registration. The class offers the following API for
 registering/unregistering cables and their plugs:
 
 .. kernel-doc:: drivers/usb/typec/typec.c
-   :functions: typec_register_cable typec_unregister_cable typec_register_plug
-   typec_unregister_plug
+   :functions: typec_register_cable typec_unregister_cable typec_register_plug typec_unregister_plug
 
 The class will provide a handle to struct typec_cable and struct typec_plug if
 the registration is successful, or NULL if it isn't.
@@ -137,8 +136,7 @@ during connection of a partner or cable, the port driver must use the following
 APIs to report it to the class:
 
 .. kernel-doc:: drivers/usb/typec/typec.c
-   :functions: typec_set_data_role typec_set_pwr_role typec_set_vconn_role
-   typec_set_pwr_opmode
+   :functions: typec_set_data_role typec_set_pwr_role typec_set_vconn_role typec_set_pwr_opmode
 
 Alternate Modes
 ~~~~~~~~~~~~~~~
index 4f7d86dd0a5d88802d85bb68ccf1f93715003a42..914518aeb972872e0fcd3057022d59070c9db282 100644 (file)
@@ -117,7 +117,7 @@ nowayout: Watchdog cannot be stopped once started
 -------------------------------------------------
 iTCO_wdt:
 heartbeat: Watchdog heartbeat in seconds.
-       (2<heartbeat<39 (TCO v1) or 613 (TCO v2), default=30)
+       (5<=heartbeat<=74 (TCO v1) or 1226 (TCO v2), default=30)
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
 -------------------------------------------------
index f7d568b8f133d9919e3823c102d7ac78f89c894a..767e9d202adf889d5ae0a746dc6dd7a9561c4a83 100644 (file)
@@ -846,7 +846,6 @@ M:  Laura Abbott <labbott@redhat.com>
 M:     Sumit Semwal <sumit.semwal@linaro.org>
 L:     devel@driverdev.osuosl.org
 S:     Supported
-F:     Documentation/devicetree/bindings/staging/ion/
 F:     drivers/staging/android/ion
 F:     drivers/staging/android/uapi/ion.h
 F:     drivers/staging/android/uapi/ion_test.h
@@ -1173,7 +1172,7 @@ N:        clps711x
 
 ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
 M:     Hartley Sweeten <hsweeten@visionengravers.com>
-M:     Ryan Mallon <rmallon@gmail.com>
+M:     Alexander Sverdlin <alexander.sverdlin@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-ep93xx/
@@ -1490,13 +1489,15 @@ M:      Gregory Clement <gregory.clement@free-electrons.com>
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     arch/arm/mach-mvebu/
-F:     drivers/rtc/rtc-armada38x.c
 F:     arch/arm/boot/dts/armada*
 F:     arch/arm/boot/dts/kirkwood*
+F:     arch/arm/configs/mvebu_*_defconfig
+F:     arch/arm/mach-mvebu/
 F:     arch/arm64/boot/dts/marvell/armada*
 F:     drivers/cpufreq/mvebu-cpufreq.c
-F:     arch/arm/configs/mvebu_*_defconfig
+F:     drivers/irqchip/irq-armada-370-xp.c
+F:     drivers/irqchip/irq-mvebu-*
+F:     drivers/rtc/rtc-armada38x.c
 
 ARM/Marvell Berlin SoC support
 M:     Jisheng Zhang <jszhang@marvell.com>
@@ -1722,7 +1723,6 @@ N:        rockchip
 ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
 M:     Kukjin Kim <kgene@kernel.org>
 M:     Krzysztof Kozlowski <krzk@kernel.org>
-R:     Javier Martinez Canillas <javier@osg.samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 Q:     https://patchwork.kernel.org/project/linux-samsung-soc/list/
@@ -1830,7 +1830,6 @@ F:        drivers/edac/altera_edac.
 ARM/STI ARCHITECTURE
 M:     Patrice Chotard <patrice.chotard@st.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L:     kernel@stlinux.com
 W:     http://www.stlinux.com
 S:     Maintained
 F:     arch/arm/mach-sti/
@@ -2965,7 +2964,7 @@ F:        sound/pci/oxygen/
 
 C6X ARCHITECTURE
 M:     Mark Salter <msalter@redhat.com>
-M:     Aurelien Jacquiot <a-jacquiot@ti.com>
+M:     Aurelien Jacquiot <jacquiot.aurelien@gmail.com>
 L:     linux-c6x-dev@linux-c6x.org
 W:     http://www.linux-c6x.org/wiki/index.php/Main_Page
 S:     Maintained
@@ -3116,6 +3115,14 @@ F:       drivers/net/ieee802154/cc2520.c
 F:     include/linux/spi/cc2520.h
 F:     Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
 
+CCREE ARM TRUSTZONE CRYPTOCELL 700 REE DRIVER
+M:     Gilad Ben-Yossef <gilad@benyossef.com>
+L:     linux-crypto@vger.kernel.org
+L:     driverdev-devel@linuxdriverproject.org
+S:     Supported
+F:     drivers/staging/ccree/
+W:     https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
+
 CEC FRAMEWORK
 M:     Hans Verkuil <hans.verkuil@cisco.com>
 L:     linux-media@vger.kernel.org
@@ -5615,7 +5622,7 @@ F:        scripts/get_maintainer.pl
 
 GENWQE (IBM Generic Workqueue Card)
 M:     Frank Haverkamp <haver@linux.vnet.ibm.com>
-M:     Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
+M:     Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
 S:     Supported
 F:     drivers/misc/genwqe/
 
@@ -5660,7 +5667,6 @@ F:        tools/testing/selftests/gpio/
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
-M:     Alexandre Courbot <gnurou@gmail.com>
 L:     linux-gpio@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
 S:     Maintained
@@ -5695,7 +5701,7 @@ M:        Alex Elder <elder@kernel.org>
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 S:     Maintained
 F:     drivers/staging/greybus/
-L:     greybus-dev@lists.linaro.org
+L:     greybus-dev@lists.linaro.org (moderated for non-subscribers)
 
 GREYBUS AUDIO PROTOCOLS DRIVERS
 M:     Vaibhav Agarwal <vaibhav.sr@gmail.com>
@@ -7136,7 +7142,7 @@ S:        Maintained
 F:     drivers/media/platform/rcar_jpu.c
 
 JSM Neo PCI based serial card
-M:     Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
+M:     Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
 L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial/jsm/
@@ -7700,7 +7706,7 @@ F:        drivers/platform/x86/hp_accel.c
 
 LIVE PATCHING
 M:     Josh Poimboeuf <jpoimboe@redhat.com>
-M:     Jessica Yu <jeyu@redhat.com>
+M:     Jessica Yu <jeyu@kernel.org>
 M:     Jiri Kosina <jikos@kernel.org>
 M:     Miroslav Benes <mbenes@suse.cz>
 R:     Petr Mladek <pmladek@suse.com>
@@ -8501,7 +8507,7 @@ S:        Odd Fixes
 F:     drivers/media/radio/radio-miropcm20*
 
 MELLANOX MLX4 core VPI driver
-M:     Yishai Hadas <yishaih@mellanox.com>
+M:     Tariq Toukan <tariqt@mellanox.com>
 L:     netdev@vger.kernel.org
 L:     linux-rdma@vger.kernel.org
 W:     http://www.mellanox.com
@@ -8509,7 +8515,6 @@ Q:        http://patchwork.ozlabs.org/project/netdev/list/
 S:     Supported
 F:     drivers/net/ethernet/mellanox/mlx4/
 F:     include/linux/mlx4/
-F:     include/uapi/rdma/mlx4-abi.h
 
 MELLANOX MLX4 IB driver
 M:     Yishai Hadas <yishaih@mellanox.com>
@@ -8519,6 +8524,7 @@ Q:        http://patchwork.kernel.org/project/linux-rdma/list/
 S:     Supported
 F:     drivers/infiniband/hw/mlx4/
 F:     include/linux/mlx4/
+F:     include/uapi/rdma/mlx4-abi.h
 
 MELLANOX MLX5 core VPI driver
 M:     Saeed Mahameed <saeedm@mellanox.com>
@@ -8531,7 +8537,6 @@ Q:        http://patchwork.ozlabs.org/project/netdev/list/
 S:     Supported
 F:     drivers/net/ethernet/mellanox/mlx5/core/
 F:     include/linux/mlx5/
-F:     include/uapi/rdma/mlx5-abi.h
 
 MELLANOX MLX5 IB driver
 M:     Matan Barak <matanb@mellanox.com>
@@ -8542,6 +8547,7 @@ Q:        http://patchwork.kernel.org/project/linux-rdma/list/
 S:     Supported
 F:     drivers/infiniband/hw/mlx5/
 F:     include/linux/mlx5/
+F:     include/uapi/rdma/mlx5-abi.h
 
 MELEXIS MLX90614 DRIVER
 M:     Crt Mori <cmo@melexis.com>
@@ -8581,7 +8587,7 @@ S:        Maintained
 F:     drivers/media/dvb-frontends/mn88473*
 
 MODULE SUPPORT
-M:     Jessica Yu <jeyu@redhat.com>
+M:     Jessica Yu <jeyu@kernel.org>
 M:     Rusty Russell <rusty@rustcorp.com.au>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux.git modules-next
 S:     Maintained
@@ -9553,10 +9559,6 @@ F:       drivers/net/wireless/intersil/orinoco/
 
 OSD LIBRARY and FILESYSTEM
 M:     Boaz Harrosh <ooo@electrozaur.com>
-M:     Benny Halevy <bhalevy@primarydata.com>
-L:     osd-dev@open-osd.org
-W:     http://open-osd.org
-T:     git git://git.open-osd.org/open-osd.git
 S:     Maintained
 F:     drivers/scsi/osd/
 F:     include/scsi/osd_*
@@ -10447,7 +10449,7 @@ S:      Orphan
 
 PXA RTC DRIVER
 M:     Robert Jarzmik <robert.jarzmik@free.fr>
-L:     rtc-linux@googlegroups.com
+L:     linux-rtc@vger.kernel.org
 S:     Maintained
 
 QAT DRIVER
@@ -10754,7 +10756,7 @@ X:      kernel/torture.c
 REAL TIME CLOCK (RTC) SUBSYSTEM
 M:     Alessandro Zummo <a.zummo@towertech.it>
 M:     Alexandre Belloni <alexandre.belloni@free-electrons.com>
-L:     rtc-linux@googlegroups.com
+L:     linux-rtc@vger.kernel.org
 Q:     http://patchwork.ozlabs.org/project/rtc-linux/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
 S:     Maintained
@@ -11265,7 +11267,6 @@ F:      drivers/media/rc/serial_ir.c
 
 STI CEC DRIVER
 M:     Benjamin Gaignard <benjamin.gaignard@linaro.org>
-L:     kernel@stlinux.com
 S:     Maintained
 F:     drivers/staging/media/st-cec/
 F:     Documentation/devicetree/bindings/media/stih-cec.txt
@@ -11775,6 +11776,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git
 S:     Supported
 F:     arch/arm/mach-davinci/
 F:     drivers/i2c/busses/i2c-davinci.c
+F:     arch/arm/boot/dts/da850*
 
 TI DAVINCI SERIES MEDIA DRIVER
 M:     "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
@@ -13858,7 +13860,7 @@ S:      Odd fixes
 F:     drivers/net/wireless/wl3501*
 
 WOLFSON MICROELECTRONICS DRIVERS
-L:     patches@opensource.wolfsonmicro.com
+L:     patches@opensource.cirrus.com
 T:     git https://github.com/CirrusLogic/linux-drivers.git
 W:     https://github.com/CirrusLogic/linux-drivers/wiki
 S:     Supported
index b400c0604facc79e86731a37e77c6620c61aa358..283c6236438e09ea62455b0bd6a19c9cbdd2f835 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 12
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION =
 NAME = Fearless Coyote
 
 # *DOCUMENTATION*
@@ -1172,7 +1172,7 @@ headers_check_all: headers_install_all
 PHONY += headers_check
 headers_check: headers_install
        $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/ $(hdr-dst) HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Kernel selftest
@@ -1437,7 +1437,7 @@ help:
        @echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
        @echo  '  make V=2   [targets] 2 => give reason for rebuild of target'
        @echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
-       @echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
+       @echo  '  make C=1   [targets] Check re-compiled c source with $$CHECK (sparse by default)'
        @echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
        @echo  '  make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections'
        @echo  '  make W=n   [targets] Enable extra gcc checks, n=1,2,3 where'
index 9ec56dc973749555019f5f0087727cc1bb97881a..ce93124a850be26520524579d30188e1ba5fcee6 100644 (file)
@@ -1201,8 +1201,10 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
        if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
                return -EFAULT;
 
-       err = 0;
-       err |= put_user(status, ustatus);
+       err = put_user(status, ustatus);
+       if (ret < 0)
+               return err ? err : ret;
+
        err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
        err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
        err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
index 6e1242da0159e274b7e161f9648e031cbddd7ef4..4104a08392146f6c479710557010135aa4774a15 100644 (file)
@@ -86,8 +86,6 @@ struct task_struct;
 #define TSK_K_BLINK(tsk)       TSK_K_REG(tsk, 4)
 #define TSK_K_FP(tsk)          TSK_K_REG(tsk, 0)
 
-#define thread_saved_pc(tsk)   TSK_K_BLINK(tsk)
-
 extern void start_thread(struct pt_regs * regs, unsigned long pc,
                         unsigned long usp);
 
index 3e25e8d6486ba258c8fa07ae52214af5e845decb..2e13683dfb24ba68363a08e88e019e4753977179 100644 (file)
@@ -65,7 +65,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index 4c1a35f1583872d2ce39db5c1cacce28be48ccb1..c0fcab6a550473859b4a2ca525cefc16624e1710 100644 (file)
@@ -1416,6 +1416,7 @@ choice
        config VMSPLIT_3G
                bool "3G/1G user/kernel split"
        config VMSPLIT_3G_OPT
+               depends on !ARM_LPAE
                bool "3G/1G user/kernel split (for full 1G low memory)"
        config VMSPLIT_2G
                bool "2G/2G user/kernel split"
index 9d5dc4fda3c16710c0443b6a5043f212230f057d..a17ca8d78656d1012910ffb8a37b3433720a8d44 100644 (file)
                @ there.
                .inst   'M' | ('Z' << 8) | (0x1310 << 16)   @ tstne r0, #0x4d000
 #else
-               mov     r0, r0
+ AR_CLASS(     mov     r0, r0          )
+  M_CLASS(     nop.w                   )
 #endif
                .endm
 
                .macro  __EFI_HEADER
 #ifdef CONFIG_EFI_STUB
-               b       __efi_start
-
                .set    start_offset, __efi_start - start
                .org    start + 0x3c
                @
index 7c711ba614173d91d8c2fd6ff4ccb13980bb3109..8a756870c238435af684215c653f54a739f4f1a5 100644 (file)
@@ -130,19 +130,22 @@ start:
                .rept   7
                __nop
                .endr
-   ARM(                mov     r0, r0          )
-   ARM(                b       1f              )
- THUMB(                badr    r12, 1f         )
- THUMB(                bx      r12             )
+#ifndef CONFIG_THUMB2_KERNEL
+               mov     r0, r0
+#else
+ AR_CLASS(     sub     pc, pc, #3      )       @ A/R: switch to Thumb2 mode
+  M_CLASS(     nop.w                   )       @ M: already in Thumb2 mode
+               .thumb
+#endif
+               W(b)    1f
 
                .word   _magic_sig      @ Magic numbers to help the loader
                .word   _magic_start    @ absolute load/run zImage address
                .word   _magic_end      @ zImage end address
                .word   0x04030201      @ endianness flag
 
- THUMB(                .thumb                  )
-1:             __EFI_HEADER
-
+               __EFI_HEADER
+1:
  ARM_BE8(      setend  be              )       @ go BE8 if compiled for BE8
  AR_CLASS(     mrs     r9, cpsr        )
 #ifdef CONFIG_ARM_VIRT_EXT
index c5d2589c55fc3ddfab5909413e7bbfe59aba50f7..fc864a8559918992401f2db3594bd5f28a7b7b28 100644 (file)
 
        mmc1_pins: pinmux_mmc1_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7)              /* spi0_cs1.gpio0_6 */
+                       AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE7)              /* uart0_rtsn.gpio1_9 */
                >;
        };
 
                        AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE7)       /* nKbdReset - gpmc_ad13.gpio1_13 */
                        AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7)       /* nDispReset - gpmc_ad14.gpio1_14 */
                        AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7)       /* USB1_enPower - gpmc_a1.gpio1_17 */
-                       /* AVR Programming - SPI Bus (bit bang) - Screen and Keyboard */
-                       AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE7)       /* Kbd/Disp/BattMOSI spi0_d0.gpio0_3 */
-                       AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE7)       /* Kbd/Disp/BattMISO spi0_d1.gpio0_4 */
-                       AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE7)       /* Kbd/Disp/BattSCLK spi0_clk.gpio0_2 */
                        /* PDI Bus - Battery system */
                        AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7)       /* nBattReset  gpmc_a0.gpio1_16 */
                        AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE7)       /* BattPDIData gpmc_ad15.gpio1_15 */
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        bus-width = <4>;
-       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+       cd-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
        vmmc-supply = <&vmmcsd_fixed>;
 };
 
index 12c981e5113489ea785d8f4d8b0a5b9f99d61beb..9a0599f711ff3382a7b908bb72e9f0392db5e1bf 100644 (file)
@@ -1,6 +1,6 @@
 / {
        aliases {
-               ethernet = &ethernet;
+               ethernet0 = &ethernet;
        };
 };
 
index 3f0a56ebcf1f64692cbdd311752ce8d1fd36a5f1..dc7ae776db5fc0ca54e91ef6369fbaee71162d22 100644 (file)
@@ -1,6 +1,6 @@
 / {
        aliases {
-               ethernet = &ethernet;
+               ethernet0 = &ethernet;
        };
 };
 
index 35cea3fcaf5c479e68e50e5d8e6606cb9735abba..9444a9a9ba1057e6b594dc8e2595ac1e5ec593fb 100644 (file)
@@ -3,6 +3,11 @@
 #include <dt-bindings/clock/bcm2835-aux.h>
 #include <dt-bindings/gpio/gpio.h>
 
+/* firmware-provided startup stubs live here, where the secondary CPUs are
+ * spinning.
+ */
+/memreserve/ 0x00000000 0x00001000;
+
 /* This include file covers the common peripherals and configuration between
  * bcm2835 and bcm2836 implementations, leaving the CPU configuration to
  * bcm2835.dtsi and bcm2836.dtsi.
                                brcm,pins = <0 1>;
                                brcm,function = <BCM2835_FSEL_ALT0>;
                        };
-                       i2c0_gpio32: i2c0_gpio32 {
-                               brcm,pins = <32 34>;
+                       i2c0_gpio28: i2c0_gpio28 {
+                               brcm,pins = <28 29>;
                                brcm,function = <BCM2835_FSEL_ALT0>;
                        };
                        i2c0_gpio44: i2c0_gpio44 {
                        /* Separate from the uart0_gpio14 group
                         * because it conflicts with spi1_gpio16, and
                         * people often run uart0 on the two pins
-                        * without flow contrl.
+                        * without flow control.
                         */
                        uart0_ctsrts_gpio16: uart0_ctsrts_gpio16 {
                                brcm,pins = <16 17>;
                                brcm,function = <BCM2835_FSEL_ALT3>;
                        };
-                       uart0_gpio30: uart0_gpio30 {
+                       uart0_ctsrts_gpio30: uart0_ctsrts_gpio30 {
                                brcm,pins = <30 31>;
                                brcm,function = <BCM2835_FSEL_ALT3>;
                        };
-                       uart0_ctsrts_gpio32: uart0_ctsrts_gpio32 {
+                       uart0_gpio32: uart0_gpio32 {
                                brcm,pins = <32 33>;
                                brcm,function = <BCM2835_FSEL_ALT3>;
                        };
+                       uart0_gpio36: uart0_gpio36 {
+                               brcm,pins = <36 37>;
+                               brcm,function = <BCM2835_FSEL_ALT2>;
+                       };
+                       uart0_ctsrts_gpio38: uart0_ctsrts_gpio38 {
+                               brcm,pins = <38 39>;
+                               brcm,function = <BCM2835_FSEL_ALT2>;
+                       };
 
                        uart1_gpio14: uart1_gpio14 {
                                brcm,pins = <14 15>;
                                brcm,pins = <30 31>;
                                brcm,function = <BCM2835_FSEL_ALT5>;
                        };
-                       uart1_gpio36: uart1_gpio36 {
-                               brcm,pins = <36 37 38 39>;
-                               brcm,function = <BCM2835_FSEL_ALT2>;
-                       };
                        uart1_gpio40: uart1_gpio40 {
                                brcm,pins = <40 41>;
                                brcm,function = <BCM2835_FSEL_ALT5>;
index 4bc4b575c99bd43da80115cf4d8ee74845f3cc22..31a9e061ddd0d0f76b115890aab09dbd2ae340d9 100644 (file)
        tps659038: tps659038@58 {
                compatible = "ti,tps659038";
                reg = <0x58>;
+               ti,palmas-override-powerhold;
+               ti,system-power-controller;
 
                tps659038_pmic {
                        compatible = "ti,tps659038-pmic";
index 57892f264ceaee19ac08e4650a01ccd3f1c9866f..e7144662af45cc98974e648f2b6e2226e214df29 100644 (file)
        coefficients = <0 2000>;
 };
 
+&cpu_crit {
+       temperature = <120000>; /* milli Celsius */
+};
+
 /include/ "dra7xx-clocks.dtsi"
index de221583237276a5b4cd57c7de724c8cbbf9ec57..4e103a905dc9c9adb112caba85f2b7cff8f8ef1d 100644 (file)
@@ -23,7 +23,7 @@
        imx53-qsrb {
                pinctrl_pmic: pmicgrp {
                        fsl,pins = <
-                               MX53_PAD_CSI0_DAT5__GPIO5_23    0x1e4 /* IRQ */
+                               MX53_PAD_CSI0_DAT5__GPIO5_23    0x1c4 /* IRQ */
                        >;
                };
        };
index 5bb8fd57e7f5a83f6cbae6c2292f33c92446c4f7..d71da30c9cff2347900f9e68715b18d65597d47a 100644 (file)
        model = "Freescale i.MX6 SoloX SDB RevB Board";
 };
 
-&cpu0 {
-       operating-points = <
-               /* kHz    uV */
-               996000  1250000
-               792000  1175000
-               396000  1175000
-               198000  1175000
-               >;
-       fsl,soc-operating-points = <
-               /* ARM kHz      SOC uV */
-               996000  1250000
-               792000  1175000
-               396000  1175000
-               198000  1175000
-       >;
-};
-
 &i2c1 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
index f18e1f1d0ce2c6aad83c08b7ad8ac4cfc41e715e..d2be8aa3370b7840e014964c147a4742d5ca87e8 100644 (file)
 
                ethphy0: ethernet-phy@2 {
                        reg = <2>;
+                       micrel,led-mode = <1>;
+                       clocks = <&clks IMX6UL_CLK_ENET_REF>;
+                       clock-names = "rmii-ref";
                };
 
                ethphy1: ethernet-phy@1 {
                        reg = <1>;
+                       micrel,led-mode = <1>;
+                       clocks = <&clks IMX6UL_CLK_ENET2_REF>;
+                       clock-names = "rmii-ref";
                };
        };
 };
diff --git a/arch/arm/boot/dts/include/arm b/arch/arm/boot/dts/include/arm
deleted file mode 120000 (symlink)
index a96aa0e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-..
\ No newline at end of file
diff --git a/arch/arm/boot/dts/include/arm64 b/arch/arm/boot/dts/include/arm64
deleted file mode 120000 (symlink)
index 074a835..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../arm64/boot/dts
\ No newline at end of file
diff --git a/arch/arm/boot/dts/include/dt-bindings b/arch/arm/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index b6f26824e83a96a88e34d33b99a0f4dace08e306..66f615a74118b9da1fe77088b63be8738c17f6c4 100644 (file)
@@ -137,8 +137,8 @@ netcp: netcp@26000000 {
        /* NetCP address range */
        ranges = <0 0x26000000 0x1000000>;
 
-       clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>, <&clkosr>;
-       clock-names = "pa_clk", "ethss_clk", "cpts", "osr_clk";
+       clocks = <&clkpa>, <&clkcpgmac>, <&chipclk12>;
+       clock-names = "pa_clk", "ethss_clk", "cpts";
        dma-coherent;
 
        ti,navigator-dmas = <&dma_gbe 0>,
index b58e7ebc091994645dd1adb35c7e7dc843fae7b0..148650406cf701cd7ffc5ac92d9054d606e97bfd 100644 (file)
                        };
                };
 
+               osr: sram@70000000 {
+                       compatible = "mmio-sram";
+                       reg = <0x70000000 0x10000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       clocks = <&clkosr>;
+               };
+
                dspgpio0: keystone_dsp_gpio@02620240 {
                        compatible = "ti,keystone-dsp-gpio";
                        gpio-controller;
index 08cce17a25a01f460fd199f5f380bb3c907e20ed..43e9364083de84383a34815c04a6bd1021b3baa0 100644 (file)
                        OMAP3_CORE1_IOPAD(0x2110, PIN_INPUT | MUX_MODE0)   /* cam_xclka.cam_xclka */
                        OMAP3_CORE1_IOPAD(0x2112, PIN_INPUT | MUX_MODE0)   /* cam_pclk.cam_pclk */
 
-                       OMAP3_CORE1_IOPAD(0x2114, PIN_INPUT | MUX_MODE0)   /* cam_d0.cam_d0 */
-                       OMAP3_CORE1_IOPAD(0x2116, PIN_INPUT | MUX_MODE0)   /* cam_d1.cam_d1 */
-                       OMAP3_CORE1_IOPAD(0x2118, PIN_INPUT | MUX_MODE0)   /* cam_d2.cam_d2 */
+                       OMAP3_CORE1_IOPAD(0x2116, PIN_INPUT | MUX_MODE0)   /* cam_d0.cam_d0 */
+                       OMAP3_CORE1_IOPAD(0x2118, PIN_INPUT | MUX_MODE0)   /* cam_d1.cam_d1 */
+                       OMAP3_CORE1_IOPAD(0x211a, PIN_INPUT | MUX_MODE0)   /* cam_d2.cam_d2 */
                        OMAP3_CORE1_IOPAD(0x211c, PIN_INPUT | MUX_MODE0)   /* cam_d3.cam_d3 */
                        OMAP3_CORE1_IOPAD(0x211e, PIN_INPUT | MUX_MODE0)   /* cam_d4.cam_d4 */
                        OMAP3_CORE1_IOPAD(0x2120, PIN_INPUT | MUX_MODE0)   /* cam_d5.cam_d5 */
index 402579ab70d2b94a21f58fd8bea2eeb1885a9072..3a9e9b6aea6892784a3379fd39fb562c0869a0ba 100644 (file)
@@ -72,6 +72,8 @@
                             <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
                             <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
                             <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clock-frequency = <13000000>;
+               arm,cpu-registers-not-fw-configured;
        };
 
        watchdog: watchdog@10007000 {
index b3a8b1f24499afe232d752ba16e15e45e4280d5b..9ec737069369672f6b52b26df840636cce768761 100644 (file)
@@ -55,7 +55,8 @@
                simple-audio-card,bitclock-master = <&telephony_link_master>;
                simple-audio-card,frame-master = <&telephony_link_master>;
                simple-audio-card,format = "i2s";
-
+               simple-audio-card,bitclock-inversion;
+               simple-audio-card,frame-inversion;
                simple-audio-card,cpu {
                        sound-dai = <&mcbsp4>;
                };
index 78d3631777629b8422deac792a6d2e6f1c655e7c..f1a6476af3716489007c12141d06f208ec2ebc94 100644 (file)
@@ -13,7 +13,7 @@
 /* Pandaboard Rev A4+ have external pullups on SCL & SDA */
 &dss_hdmi_pins {
        pinctrl-single,pins = <
-               OMAP4_IOPAD(0x09a, PIN_INPUT_PULLUP | MUX_MODE0)        /* hdmi_cec.hdmi_cec */
+               OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0)               /* hdmi_cec.hdmi_cec */
                OMAP4_IOPAD(0x09c, PIN_INPUT | MUX_MODE0)               /* hdmi_scl.hdmi_scl */
                OMAP4_IOPAD(0x09e, PIN_INPUT | MUX_MODE0)               /* hdmi_sda.hdmi_sda */
                >;
index 119f8e657edc9bae37089588968b660c9c3749da..940fe4f7c5f6e148a1e22e7b2daaadc91c627c10 100644 (file)
@@ -34,7 +34,7 @@
 /* PandaboardES has external pullups on SCL & SDA */
 &dss_hdmi_pins {
        pinctrl-single,pins = <
-               OMAP4_IOPAD(0x09a, PIN_INPUT_PULLUP | MUX_MODE0)        /* hdmi_cec.hdmi_cec */
+               OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0)               /* hdmi_cec.hdmi_cec */
                OMAP4_IOPAD(0x09c, PIN_INPUT | MUX_MODE0)               /* hdmi_scl.hdmi_scl */
                OMAP4_IOPAD(0x09e, PIN_INPUT | MUX_MODE0)               /* hdmi_sda.hdmi_sda */
                >;
index 1aeeacb3a8849b63b9c21796612f9a870084ce34..d4f600dbb7eb8dc7b5f922e9334c5dddf3528296 100644 (file)
                };
 
                r_ccu: clock@1f01400 {
-                       compatible = "allwinner,sun50i-a64-r-ccu";
+                       compatible = "allwinner,sun8i-h3-r-ccu";
                        reg = <0x01f01400 0x100>;
-                       clocks = <&osc24M>, <&osc32k>, <&iosc>;
-                       clock-names = "hosc", "losc", "iosc";
+                       clocks = <&osc24M>, <&osc32k>, <&iosc>,
+                                <&ccu 9>;
+                       clock-names = "hosc", "losc", "iosc", "pll-periph";
                        #clock-cells = <1>;
                        #reset-cells = <1>;
                };
index 33a8eb28374eaa8d3b8aca95d8801227bedd87ca..06e2331f666d45fb2a2432ac1ef5401c3c50e37d 100644 (file)
@@ -1,4 +1,4 @@
-#include <versatile-ab.dts>
+#include "versatile-ab.dts"
 
 / {
        model = "ARM Versatile PB";
index cf062472e07bcb4be470bf35ab029df3438dbc7e..2b913f17d50f5d91f50d3aa30e3a8a26c97847b9 100644 (file)
@@ -235,7 +235,7 @@ int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster)
        return ret;
 }
 
-typedef void (*phys_reset_t)(unsigned long);
+typedef typeof(cpu_reset) phys_reset_t;
 
 void mcpm_cpu_power_down(void)
 {
@@ -300,7 +300,7 @@ void mcpm_cpu_power_down(void)
         * on the CPU.
         */
        phys_reset = (phys_reset_t)(unsigned long)__pa_symbol(cpu_reset);
-       phys_reset(__pa_symbol(mcpm_entry_point));
+       phys_reset(__pa_symbol(mcpm_entry_point), false);
 
        /* should never get here */
        BUG();
@@ -389,7 +389,7 @@ static int __init nocache_trampoline(unsigned long _arg)
        __mcpm_cpu_down(cpu, cluster);
 
        phys_reset = (phys_reset_t)(unsigned long)__pa_symbol(cpu_reset);
-       phys_reset(__pa_symbol(mcpm_entry_point));
+       phys_reset(__pa_symbol(mcpm_entry_point), false);
        BUG();
 }
 
diff --git a/arch/arm/configs/gemini_defconfig b/arch/arm/configs/gemini_defconfig
new file mode 100644 (file)
index 0000000..d2d75fa
--- /dev/null
@@ -0,0 +1,68 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_USER_NS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_MULTI_V4=y
+# CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_GEMINI=y
+CONFIG_PCI=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="console=ttyS0,115200n8"
+CONFIG_KEXEC=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_GEMINI_WATCHDOG=y
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_FOTG210_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GEMINI=y
+CONFIG_DMADEVICES=y
+# CONFIG_DNOTIFY is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
index 36ec9c8f6e161d59d56caafbbe92fe0d2239d3f9..3234fe9bba6e76196d8a852db8c26d078150d989 100644 (file)
@@ -19,7 +19,8 @@ struct dev_archdata {
 #ifdef CONFIG_XEN
        const struct dma_map_ops *dev_dma_ops;
 #endif
-       bool dma_coherent;
+       unsigned int dma_coherent:1;
+       unsigned int dma_ops_setup:1;
 };
 
 struct omap_device;
index 4917c2f7e45955919509727640b9e54edd940b01..e74ab0fbab79091105dd1e5026c1e3e1e1347ead 100644 (file)
@@ -31,7 +31,8 @@ void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
 int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 
index 302240c19a5aa688e7bdab1ece506dfbeaccea4e..a0d726a47c8a272b722b0d5623021058da50e113 100644 (file)
@@ -66,6 +66,7 @@ typedef pte_t *pte_addr_t;
 #define pgprot_noncached(prot) (prot)
 #define pgprot_writecombine(prot) (prot)
 #define pgprot_dmacoherent(prot) (prot)
+#define pgprot_device(prot)    (prot)
 
 
 /*
index 32e1a9513dc70eba4787ca1af0ba3e32b9f29d7e..4e80bf7420d4e65fb30e0c68e7bef53932f765b3 100644 (file)
@@ -315,7 +315,7 @@ static void __init cacheid_init(void)
        if (arch >= CPU_ARCH_ARMv6) {
                unsigned int cachetype = read_cpuid_cachetype();
 
-               if ((arch == CPU_ARCH_ARMv7M) && !cachetype) {
+               if ((arch == CPU_ARCH_ARMv7M) && !(cachetype & 0xf000f)) {
                        cacheid = 0;
                } else if ((cachetype & (7 << 29)) == 4 << 29) {
                        /* ARMv7 register format */
index 2c14b69511e981816861e16b31ed18dce0f2360f..6d1d2e26dfe5d8cd83e1a89a106f8028eed65c8e 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/vfp.h>
 #include "../vfp/vfpinstr.h"
 
+#define CREATE_TRACE_POINTS
 #include "trace.h"
 #include "coproc.h"
 
@@ -111,12 +112,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
        return 1;
 }
 
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       kvm_inject_undefined(vcpu);
-       return 1;
-}
-
 static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
 {
        /*
@@ -284,7 +279,7 @@ static bool access_gic_sre(struct kvm_vcpu *vcpu,
  * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
  * all PM registers, which doesn't crash the guest kernel at least.
  */
-static bool pm_fake(struct kvm_vcpu *vcpu,
+static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                    const struct coproc_params *p,
                    const struct coproc_reg *r)
 {
@@ -294,19 +289,19 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
                return read_zero(vcpu, p);
 }
 
-#define access_pmcr pm_fake
-#define access_pmcntenset pm_fake
-#define access_pmcntenclr pm_fake
-#define access_pmovsr pm_fake
-#define access_pmselr pm_fake
-#define access_pmceid0 pm_fake
-#define access_pmceid1 pm_fake
-#define access_pmccntr pm_fake
-#define access_pmxevtyper pm_fake
-#define access_pmxevcntr pm_fake
-#define access_pmuserenr pm_fake
-#define access_pmintenset pm_fake
-#define access_pmintenclr pm_fake
+#define access_pmcr trap_raz_wi
+#define access_pmcntenset trap_raz_wi
+#define access_pmcntenclr trap_raz_wi
+#define access_pmovsr trap_raz_wi
+#define access_pmselr trap_raz_wi
+#define access_pmceid0 trap_raz_wi
+#define access_pmceid1 trap_raz_wi
+#define access_pmccntr trap_raz_wi
+#define access_pmxevtyper trap_raz_wi
+#define access_pmxevcntr trap_raz_wi
+#define access_pmuserenr trap_raz_wi
+#define access_pmintenset trap_raz_wi
+#define access_pmintenclr trap_raz_wi
 
 /* Architected CP15 registers.
  * CRn denotes the primary register number, but is copied to the CRm in the
@@ -532,12 +527,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu,
        return 1;
 }
 
-/**
- * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu)
 {
        struct coproc_params params;
 
@@ -551,9 +541,38 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
        params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
        params.CRm = 0;
 
+       return params;
+}
+
+/**
+ * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_64bit_hsr(vcpu);
+
        return emulate_cp15(vcpu, &params);
 }
 
+/**
+ * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_64bit_hsr(vcpu);
+
+       /* raz_wi cp14 */
+       trap_raz_wi(vcpu, &params, NULL);
+
+       /* handled */
+       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+       return 1;
+}
+
 static void reset_coproc_regs(struct kvm_vcpu *vcpu,
                              const struct coproc_reg *table, size_t num)
 {
@@ -564,12 +583,7 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu,
                        table[i].reset(vcpu, &table[i]);
 }
 
-/**
- * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
 {
        struct coproc_params params;
 
@@ -583,9 +597,37 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
        params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
        params.Rt2 = 0;
 
+       return params;
+}
+
+/**
+ * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_32bit_hsr(vcpu);
        return emulate_cp15(vcpu, &params);
 }
 
+/**
+ * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_32bit_hsr(vcpu);
+
+       /* raz_wi cp14 */
+       trap_raz_wi(vcpu, &params, NULL);
+
+       /* handled */
+       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+       return 1;
+}
+
 /******************************************************************************
  * Userspace API
  *****************************************************************************/
index 5fd7968cdae9efb4f68968eca13afebffb8c0be4..f86a9aaef462c6d861a80ae60bb26492ddb28d66 100644 (file)
@@ -95,9 +95,9 @@ static exit_handle_fn arm_exit_handlers[] = {
        [HSR_EC_WFI]            = kvm_handle_wfx,
        [HSR_EC_CP15_32]        = kvm_handle_cp15_32,
        [HSR_EC_CP15_64]        = kvm_handle_cp15_64,
-       [HSR_EC_CP14_MR]        = kvm_handle_cp14_access,
+       [HSR_EC_CP14_MR]        = kvm_handle_cp14_32,
        [HSR_EC_CP14_LS]        = kvm_handle_cp14_load_store,
-       [HSR_EC_CP14_64]        = kvm_handle_cp14_access,
+       [HSR_EC_CP14_64]        = kvm_handle_cp14_64,
        [HSR_EC_CP_0_13]        = kvm_handle_cp_0_13_access,
        [HSR_EC_CP10_ID]        = kvm_handle_cp10_id,
        [HSR_EC_HVC]            = handle_hvc,
index 3023bb530edf160ddbbe974e820227950a06ac31..8679405b0b2bb1e7a23232554bf26f71d7ae75ac 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
index 92678b7bd046d74b2cb0ad6df34978c3a9e1c112..624a510d31df4095701387da09b4b9a27bd09a17 100644 (file)
@@ -48,7 +48,9 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
        write_sysreg(HSTR_T(15), HSTR);
        write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
        val = read_sysreg(HDCR);
-       write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR);
+       val |= HDCR_TPM | HDCR_TPMCR; /* trap performance monitors */
+       val |= HDCR_TDRA | HDCR_TDOSA | HDCR_TDA; /* trap debug regs */
+       write_sysreg(val, HDCR);
 }
 
 static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
index 570ed4a9c2618ba7810f96af0b106c8cfbdfd2cc..5386528665b54fc191cdf0e456a133531c78b626 100644 (file)
@@ -104,7 +104,6 @@ __do_hyp_init:
        @  - Write permission implies XN: disabled
        @  - Instruction cache: enabled
        @  - Data/Unified cache: enabled
-       @  - Memory alignment checks: enabled
        @  - MMU: enabled (this code must be run from an identity mapping)
        mrc     p15, 4, r0, c1, c0, 0   @ HSCR
        ldr     r2, =HSCTLR_MASK
@@ -112,8 +111,8 @@ __do_hyp_init:
        mrc     p15, 0, r1, c1, c0, 0   @ SCTLR
        ldr     r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
        and     r1, r1, r2
- ARM(  ldr     r2, =(HSCTLR_M | HSCTLR_A)                      )
- THUMB(        ldr     r2, =(HSCTLR_M | HSCTLR_A | HSCTLR_TE)          )
+ ARM(  ldr     r2, =(HSCTLR_M)                                 )
+ THUMB(        ldr     r2, =(HSCTLR_M | HSCTLR_TE)                     )
        orr     r1, r1, r2
        orr     r0, r0, r1
        mcr     p15, 4, r0, c1, c0, 0   @ HSCR
index fc0943776db2d821a5b3931a9d4e217a8cf747d6..b0d10648c4864b22c4566884d252d2554e2ceeb6 100644 (file)
@@ -1,5 +1,5 @@
-#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_KVM_H
+#if !defined(_TRACE_ARM_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ARM_KVM_H
 
 #include <linux/tracepoint.h>
 
@@ -74,10 +74,10 @@ TRACE_EVENT(kvm_hvc,
                  __entry->vcpu_pc, __entry->r0, __entry->imm)
 );
 
-#endif /* _TRACE_KVM_H */
+#endif /* _TRACE_ARM_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH arch/arm/kvm
+#define TRACE_INCLUDE_PATH .
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 841e924143f90e089bae9269acacdff65ab597f9..cbd959b73654c43deb72cbe084bdb99043a22b66 100644 (file)
@@ -1,6 +1,7 @@
 menuconfig ARCH_AT91
        bool "Atmel SoCs"
        depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7
+       select ARM_CPU_SUSPEND if PM
        select COMMON_CLK_AT91
        select GPIOLIB
        select PINCTRL
index 2cd27c830ab68b3e7e340adb9bfab9d0e42a38ee..283e79ab587de91405e0b579fb16d202ca5072b7 100644 (file)
@@ -335,7 +335,7 @@ static const struct ramc_info ramc_infos[] __initconst = {
        { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
 };
 
-static const struct of_device_id const ramc_ids[] __initconst = {
+static const struct of_device_id ramc_ids[] __initconst = {
        { .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] },
        { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
        { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
index cf3f8658f0e5e9849f866e2135f76aa81c11b1cc..a55a7ecf146a277df8c55603837b67d6fdc30a03 100644 (file)
@@ -33,7 +33,7 @@ struct bcm_kona_smc_data {
        unsigned result;
 };
 
-static const struct of_device_id const bcm_kona_smc_ids[] __initconst = {
+static const struct of_device_id bcm_kona_smc_ids[] __initconst = {
        {.compatible = "brcm,kona-smc"},
        {.compatible = "bcm,kona-smc"}, /* deprecated name */
        {},
index 03da3813f1ab631a0f97be7a1d893176820f9b29..7d5a44a06648de2fd8e5e15beef19762d6925e81 100644 (file)
@@ -346,7 +346,7 @@ static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
        .power_off      = csn3xxx_usb_power_off,
 };
 
-static const struct of_dev_auxdata const cns3xxx_auxdata[] __initconst = {
+static const struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
        { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
        { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
        { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
index efb80354f3034d856ab259bb1568dab41173d3b3..b5cc05dc2cb27c9e20e5f8290b65fff2efeec8ec 100644 (file)
@@ -153,7 +153,8 @@ int __init davinci_pm_init(void)
        davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
        if (!davinci_sram_suspend) {
                pr_err("PM: cannot allocate SRAM memory\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto no_sram_mem;
        }
 
        davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
@@ -161,6 +162,10 @@ int __init davinci_pm_init(void)
 
        suspend_set_ops(&davinci_pm_ops);
 
+       return 0;
+
+no_sram_mem:
+       iounmap(pm_config.ddrpsc_reg_base);
 no_ddrpsc_mem:
        iounmap(pm_config.ddrpll_reg_base);
 no_ddrpll_mem:
index 3089d3bfa19b4a5c595e6872824c81f103d4c5e2..8cc6338fcb1288022854d7bb3347b9e000139c76 100644 (file)
@@ -266,11 +266,12 @@ extern int omap4_cpu_kill(unsigned int cpu);
 extern const struct smp_operations omap4_smp_ops;
 #endif
 
+extern u32 omap4_get_cpu1_ns_pa_addr(void);
+
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
 extern int omap4_mpuss_init(void);
 extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
-extern u32 omap4_get_cpu1_ns_pa_addr(void);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
                                        unsigned int power_state)
index 03ec6d307c8235fc907a599322991b1efd6c27bf..4cfc4f9b2c6944d935d210190a0afb99b1b0c816 100644 (file)
@@ -213,11 +213,6 @@ static void __init save_l2x0_context(void)
 {}
 #endif
 
-u32 omap4_get_cpu1_ns_pa_addr(void)
-{
-       return old_cpu1_ns_pa_addr;
-}
-
 /**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
@@ -457,6 +452,11 @@ int __init omap4_mpuss_init(void)
 
 #endif
 
+u32 omap4_get_cpu1_ns_pa_addr(void)
+{
+       return old_cpu1_ns_pa_addr;
+}
+
 /*
  * For kexec, we must set CPU1_WAKEUP_NS_PA_ADDR to point to
  * current kernel's secondary_startup() early before
index 3faf454ba4871c8f60d5e12e912a1ff9dd9af271..33e4953c61a8843b5dde41994b30ea41c52a0abf 100644 (file)
@@ -306,7 +306,6 @@ static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
 
        cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base +
                                        OMAP_AUX_CORE_BOOT_1);
-       cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
 
        /* Did the configured secondary_startup() get overwritten? */
        if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa))
@@ -316,9 +315,13 @@ static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
         * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a
         * deeper idle state in WFI and will wake to an invalid address.
         */
-       if ((soc_is_omap44xx() || soc_is_omap54xx()) &&
-           !omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
-               needs_reset = true;
+       if ((soc_is_omap44xx() || soc_is_omap54xx())) {
+               cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
+               if (!omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
+                       needs_reset = true;
+       } else {
+               cpu1_ns_pa_addr = 0;
+       }
 
        if (!needs_reset || !c->cpu1_rstctrl_va)
                return;
index 2b138b65129a5d609ff2ae02a55181c10154113b..dc11841ca334c64aa0f70a04781463737c191282 100644 (file)
@@ -711,7 +711,7 @@ static struct omap_prcm_init_data scrm_data __initdata = {
 };
 #endif
 
-static const struct of_device_id const omap_prcm_dt_match_table[] __initconst = {
+static const struct of_device_id omap_prcm_dt_match_table[] __initconst = {
 #ifdef CONFIG_SOC_AM33XX
        { .compatible = "ti,am3-prcm", .data = &am3_prm_data },
 #endif
index 2028167fff310041cf54037798f81cc8efa9efc2..d76b1e5eb8ba50ed9a09b0e1df3c56b1e2f0c6bb 100644 (file)
@@ -559,7 +559,7 @@ struct i2c_init_data {
        u8 hsscll_12;
 };
 
-static const struct i2c_init_data const omap4_i2c_timing_data[] __initconst = {
+static const struct i2c_init_data omap4_i2c_timing_data[] __initconst = {
        {
                .load = 50,
                .loadbits = 0x3,
index 4878ba90026df68bb0d06683df795c94ee20d7ec..289e036c9c3054a3e0ba3b9d9f553867c9bd09ef 100644 (file)
@@ -204,7 +204,7 @@ static void __init spear_clockevent_init(int irq)
        setup_irq(irq, &spear_timer_irq);
 }
 
-static const struct of_device_id const timer_of_match[] __initconst = {
+static const struct of_device_id timer_of_match[] __initconst = {
        { .compatible = "st,spear-timer", },
        { },
 };
index c742dfd2967bcae6057c3ea59b81979fcf60aa55..bd83c531828a7349eecf233b5c213a65388e9567 100644 (file)
@@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
 
-static void __arm_iommu_detach_device(struct device *dev)
+/**
+ * arm_iommu_detach_device
+ * @dev: valid struct device pointer
+ *
+ * Detaches the provided device from a previously attached map.
+ * This voids the dma operations (dma_map_ops pointer)
+ */
+void arm_iommu_detach_device(struct device *dev)
 {
        struct dma_iommu_mapping *mapping;
 
@@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device *dev)
        iommu_detach_device(mapping->domain, dev);
        kref_put(&mapping->kref, release_iommu_mapping);
        to_dma_iommu_mapping(dev) = NULL;
+       set_dma_ops(dev, NULL);
 
        pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
 }
-
-/**
- * arm_iommu_detach_device
- * @dev: valid struct device pointer
- *
- * Detaches the provided device from a previously attached map.
- * This voids the dma operations (dma_map_ops pointer)
- */
-void arm_iommu_detach_device(struct device *dev)
-{
-       __arm_iommu_detach_device(dev);
-       set_dma_ops(dev, NULL);
-}
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
 static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
@@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
        if (!mapping)
                return;
 
-       __arm_iommu_detach_device(dev);
+       arm_iommu_detach_device(dev);
        arm_iommu_release_mapping(mapping);
 }
 
@@ -2430,9 +2425,13 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
                dev->dma_ops = xen_dma_ops;
        }
 #endif
+       dev->archdata.dma_ops_setup = true;
 }
 
 void arch_teardown_dma_ops(struct device *dev)
 {
+       if (!dev->archdata.dma_ops_setup)
+               return;
+
        arm_teardown_iommu_dma_ops(dev);
 }
index 2239fde10b808d7985bba83f42984dda35871901..f0701d8d24df5a8edd151055402c0cdf05e8a8e3 100644 (file)
@@ -90,7 +90,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
@@ -141,7 +141,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                               (!vma || addr + len <= vma->vm_start))
+                               (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index 31af3cb59a60c56fb7b428486c7d356a2ddd22b4..e46a6a446cdd27126869bb97574d5bf51075e9e4 100644 (file)
@@ -1218,15 +1218,15 @@ void __init adjust_lowmem_bounds(void)
 
        high_memory = __va(arm_lowmem_limit - 1) + 1;
 
+       if (!memblock_limit)
+               memblock_limit = arm_lowmem_limit;
+
        /*
         * Round the memblock limit down to a pmd size.  This
         * helps to ensure that we will allocate memory from the
         * last full pmd, which should be mapped.
         */
-       if (memblock_limit)
-               memblock_limit = round_down(memblock_limit, PMD_SIZE);
-       if (!memblock_limit)
-               memblock_limit = arm_lowmem_limit;
+       memblock_limit = round_down(memblock_limit, PMD_SIZE);
 
        if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
                if (memblock_end_of_DRAM() > arm_lowmem_limit) {
index 3dcd7ec69bca8f939dba09e9087902fbd1561e8a..b2024db225a9dd116cf5d2ba49d62bc79c8e0bf8 100644 (file)
@@ -1084,10 +1084,6 @@ config SYSVIPC_COMPAT
        def_bool y
        depends on COMPAT && SYSVIPC
 
-config KEYS_COMPAT
-       def_bool y
-       depends on COMPAT && KEYS
-
 endmenu
 
 menu "Power management options"
index 4afcffcb46cbf097789eb75c2bab8711647e0285..73272f43ca012faac98c0aceed350dcd49814b28 100644 (file)
@@ -106,8 +106,13 @@ config ARCH_MVEBU
        select ARMADA_AP806_SYSCON
        select ARMADA_CP110_SYSCON
        select ARMADA_37XX_CLK
+       select GPIOLIB
+       select GPIOLIB_IRQCHIP
        select MVEBU_ODMI
        select MVEBU_PIC
+       select OF_GPIO
+       select PINCTRL
+       select PINCTRL_ARMADA_37XX
        help
          This enables support for Marvell EBU familly, including:
           - Armada 3700 SoC Family
index c7f669f5884f910c6e4be44ac1dd09a216cb97f0..166c9ef884dc6e52432e0030d06f1b7036d2c428 100644 (file)
                r_ccu: clock@1f01400 {
                        compatible = "allwinner,sun50i-a64-r-ccu";
                        reg = <0x01f01400 0x100>;
-                       clocks = <&osc24M>, <&osc32k>, <&iosc>;
-                       clock-names = "hosc", "losc", "iosc";
+                       clocks = <&osc24M>, <&osc32k>, <&iosc>,
+                                <&ccu 11>;
+                       clock-names = "hosc", "losc", "iosc", "pll-periph";
                        #clock-cells = <1>;
                        #reset-cells = <1>;
                };
index 4d314a253fd9e08bd4e0f6db6b1677c2e2e2fb05..732e2e06f503c83e42c0c4925b06295e6e47dc64 100644 (file)
@@ -40,7 +40,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "sunxi-h3-h5.dtsi"
+#include <arm/sunxi-h3-h5.dtsi>
 
 / {
        cpus {
diff --git a/arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi b/arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi
deleted file mode 120000 (symlink)
index 036f01d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../arm/boot/dts/sunxi-h3-h5.dtsi
\ No newline at end of file
index 75bce2d0b1a83fa9f953b55a75ebdcb2ff4dc526..49f6a6242cf9fa3d9cd64d4ef22f8abf74e8e885 100644 (file)
                };
        };
 
+       reg_sys_5v: regulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "SYS_5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       reg_vdd_3v3: regulator@1 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDD_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+               vin-supply = <&reg_sys_5v>;
+       };
+
+       reg_5v_hub: regulator@2 {
+               compatible = "regulator-fixed";
+               regulator-name = "5V_HUB";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               gpio = <&gpio0 7 0>;
+               regulator-always-on;
+               vin-supply = <&reg_sys_5v>;
+       };
+
+       wl1835_pwrseq: wl1835-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               /* WLAN_EN GPIO */
+               reset-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+               clocks = <&pmic>;
+               clock-names = "ext_clock";
+               power-off-delay-us = <10>;
+       };
+
        soc {
                spi0: spi@f7106000 {
                        status = "ok";
 
                /* GPIO blocks 16 thru 19 do not appear to be routed to pins */
 
+               dwmmc_0: dwmmc0@f723d000 {
+                       cap-mmc-highspeed;
+                       non-removable;
+                       bus-width = <0x8>;
+                       vmmc-supply = <&ldo19>;
+               };
+
+               dwmmc_1: dwmmc1@f723e000 {
+                       card-detect-delay = <200>;
+                       cap-sd-highspeed;
+                       sd-uhs-sdr12;
+                       sd-uhs-sdr25;
+                       sd-uhs-sdr50;
+                       vqmmc-supply = <&ldo7>;
+                       vmmc-supply = <&ldo10>;
+                       bus-width = <0x4>;
+                       disable-wp;
+                       cd-gpios = <&gpio1 0 1>;
+               };
+
                dwmmc_2: dwmmc2@f723f000 {
-                       ti,non-removable;
+                       bus-width = <0x4>;
                        non-removable;
-                       /* WL_EN */
-                       vmmc-supply = <&wlan_en_reg>;
+                       vmmc-supply = <&reg_vdd_3v3>;
+                       mmc-pwrseq = <&wl1835_pwrseq>;
 
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;
                                interrupts = <3 IRQ_TYPE_EDGE_RISING>;
                        };
                };
-
-               wlan_en_reg: regulator@1 {
-                       compatible = "regulator-fixed";
-                       regulator-name = "wlan-en-regulator";
-                       regulator-min-microvolt = <1800000>;
-                       regulator-max-microvolt = <1800000>;
-                       /* WLAN_EN GPIO */
-                       gpio = <&gpio0 5 0>;
-                       /* WLAN card specific delay */
-                       startup-delay-us = <70000>;
-                       enable-active-high;
-               };
        };
 
        leds {
        pmic: pmic@f8000000 {
                compatible = "hisilicon,hi655x-pmic";
                reg = <0x0 0xf8000000 0x0 0x1000>;
+               #clock-cells = <0>;
                interrupt-controller;
                #interrupt-cells = <2>;
                pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
index 1e5129b19280bf8195a9ac24e506ec096493b084..5013e4b2ea71930960021fff96b8528611964955 100644 (file)
                        status = "disabled";
                };
 
-               fixed_5v_hub: regulator@0 {
-                       compatible = "regulator-fixed";
-                       regulator-name = "fixed_5v_hub";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       regulator-boot-on;
-                       gpio = <&gpio0 7 0>;
-                       regulator-always-on;
-               };
-
                usb_phy: usbphy {
                        compatible = "hisilicon,hi6220-usb-phy";
                        #phy-cells = <0>;
-                       phy-supply = <&fixed_5v_hub>;
+                       phy-supply = <&reg_5v_hub>;
                        hisilicon,peripheral-syscon = <&sys_ctrl>;
                };
 
 
                dwmmc_0: dwmmc0@f723d000 {
                        compatible = "hisilicon,hi6220-dw-mshc";
-                       num-slots = <0x1>;
-                       cap-mmc-highspeed;
-                       non-removable;
                        reg = <0x0 0xf723d000 0x0 0x1000>;
                        interrupts = <0x0 0x48 0x4>;
                        clocks = <&sys_ctrl 2>, <&sys_ctrl 1>;
                        clock-names = "ciu", "biu";
                        resets = <&sys_ctrl PERIPH_RSTDIS0_MMC0>;
                        reset-names = "reset";
-                       bus-width = <0x8>;
-                       vmmc-supply = <&ldo19>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&emmc_pmx_func &emmc_clk_cfg_func
                                     &emmc_cfg_func &emmc_rst_cfg_func>;
 
                dwmmc_1: dwmmc1@f723e000 {
                        compatible = "hisilicon,hi6220-dw-mshc";
-                       num-slots = <0x1>;
-                       card-detect-delay = <200>;
                        hisilicon,peripheral-syscon = <&ao_ctrl>;
-                       cap-sd-highspeed;
-                       sd-uhs-sdr12;
-                       sd-uhs-sdr25;
-                       sd-uhs-sdr50;
                        reg = <0x0 0xf723e000 0x0 0x1000>;
                        interrupts = <0x0 0x49 0x4>;
                        #address-cells = <0x1>;
                        clock-names = "ciu", "biu";
                        resets = <&sys_ctrl PERIPH_RSTDIS0_MMC1>;
                        reset-names = "reset";
-                       vqmmc-supply = <&ldo7>;
-                       vmmc-supply = <&ldo10>;
-                       bus-width = <0x4>;
-                       disable-wp;
-                       cd-gpios = <&gpio1 0 1>;
                        pinctrl-names = "default", "idle";
                        pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
                        pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
 
                dwmmc_2: dwmmc2@f723f000 {
                        compatible = "hisilicon,hi6220-dw-mshc";
-                       num-slots = <0x1>;
                        reg = <0x0 0xf723f000 0x0 0x1000>;
                        interrupts = <0x0 0x4a 0x4>;
                        clocks = <&sys_ctrl HI6220_MMC2_CIUCLK>, <&sys_ctrl HI6220_MMC2_CLK>;
                        clock-names = "ciu", "biu";
                        resets = <&sys_ctrl PERIPH_RSTDIS0_MMC2>;
                        reset-names = "reset";
-                       bus-width = <0x4>;
-                       broken-cd;
                        pinctrl-names = "default", "idle";
                        pinctrl-0 = <&sdio_pmx_func &sdio_clk_cfg_func &sdio_cfg_func>;
                        pinctrl-1 = <&sdio_pmx_idle &sdio_clk_cfg_idle &sdio_cfg_idle>;
diff --git a/arch/arm64/boot/dts/include/arm b/arch/arm64/boot/dts/include/arm
deleted file mode 120000 (symlink)
index cf63d80..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../arm/boot/dts
\ No newline at end of file
diff --git a/arch/arm64/boot/dts/include/arm64 b/arch/arm64/boot/dts/include/arm64
deleted file mode 120000 (symlink)
index a96aa0e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-..
\ No newline at end of file
diff --git a/arch/arm64/boot/dts/include/dt-bindings b/arch/arm64/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index cef5f976bc0f2afea9a85db88827c6e5529a87c4..a89855f57091fac35d3ba4b9821fd2a902f5ed77 100644 (file)
@@ -79,6 +79,8 @@
 };
 
 &i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        status = "okay";
 
        gpio_exp: pca9555@22 {
 
 &spi0 {
        status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_quad_pins>;
 
        m25p80@0 {
                compatible = "jedec,spi-nor";
 
 /* Exported on the micro USB connector CON32 through an FTDI */
 &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart1_pins>;
        status = "okay";
 };
 
 };
 
 &eth0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
        phy-mode = "rgmii-id";
        phy = <&phy0>;
        status = "okay";
index 58ae9e095af2a2a986082143789995cd5cc348d7..4d495ec39202d0c34b46996598466ec87d116eea 100644 (file)
                                #clock-cells = <1>;
                        };
 
-                       gpio1: gpio@13800 {
-                               compatible = "marvell,mvebu-gpio-3700",
+                       pinctrl_nb: pinctrl@13800 {
+                               compatible = "marvell,armada3710-nb-pinctrl",
                                "syscon", "simple-mfd";
-                               reg = <0x13800 0x500>;
+                               reg = <0x13800 0x100>, <0x13C00 0x20>;
+                               gpionb: gpio {
+                                       #gpio-cells = <2>;
+                                       gpio-ranges = <&pinctrl_nb 0 0 36>;
+                                       gpio-controller;
+                                       interrupts =
+                                       <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+
+                               };
 
                                xtalclk: xtal-clk {
                                        compatible = "marvell,armada-3700-xtal-clock";
                                        clock-output-names = "xtal";
                                        #clock-cells = <0>;
                                };
+
+                               spi_quad_pins: spi-quad-pins {
+                                       groups = "spi_quad";
+                                       function = "spi";
+                               };
+
+                               i2c1_pins: i2c1-pins {
+                                       groups = "i2c1";
+                                       function = "i2c";
+                               };
+
+                               i2c2_pins: i2c2-pins {
+                                       groups = "i2c2";
+                                       function = "i2c";
+                               };
+
+                               uart1_pins: uart1-pins {
+                                       groups = "uart1";
+                                       function = "uart";
+                               };
+
+                               uart2_pins: uart2-pins {
+                                       groups = "uart2";
+                                       function = "uart";
+                               };
+                       };
+
+                       pinctrl_sb: pinctrl@18800 {
+                               compatible = "marvell,armada3710-sb-pinctrl",
+                               "syscon", "simple-mfd";
+                               reg = <0x18800 0x100>, <0x18C00 0x20>;
+                               gpiosb: gpio {
+                                       #gpio-cells = <2>;
+                                       gpio-ranges = <&pinctrl_sb 0 0 29>;
+                                       gpio-controller;
+                                       interrupts =
+                                       <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               rgmii_pins: mii-pins {
+                                       groups = "rgmii";
+                                       function = "mii";
+                               };
+
                        };
 
                        eth0: ethernet@30000 {
index ac8df5201cd656d70073bc03cd13436435b79c66..b4bc42ece7541154431a5855c4bbe0f984094445 100644 (file)
                        cpm_crypto: crypto@800000 {
                                compatible = "inside-secure,safexcel-eip197";
                                reg = <0x800000 0x200000>;
-                               interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING
-                               | IRQ_TYPE_LEVEL_HIGH)>,
+                               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
index 7740a75a823084d027ffab1c02d221f3083dea87..6e2058847ddcd59ca9fd0d472bfb94f5331b00cd 100644 (file)
                        cps_crypto: crypto@800000 {
                                compatible = "inside-secure,safexcel-eip197";
                                reg = <0x800000 0x200000>;
-                               interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING
-                               | IRQ_TYPE_LEVEL_HIGH)>,
+                               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
index 0ecaad4333a7690f68c019d660ee0bc75b8580b3..1c3634fa94bf4e7c6a65d85e9c76a6e240e4d14a 100644 (file)
        bus-width = <8>;
        max-frequency = <50000000>;
        cap-mmc-highspeed;
+       mediatek,hs200-cmd-int-delay=<26>;
+       mediatek,hs400-cmd-int-delay=<14>;
+       mediatek,hs400-cmd-resp-sel-rising;
        vmmc-supply = <&mt6397_vemc_3v3_reg>;
        vqmmc-supply = <&mt6397_vio18_reg>;
        non-removable;
index 658bb9dc9dfd3d2e1dbda080b3252fb2e2365390..7bd31066399b5859a053570a35281cec23d1d888 100644 (file)
@@ -44,7 +44,7 @@
 
 /dts-v1/;
 #include "rk3399-gru.dtsi"
-#include <include/dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/input/linux-event-codes.h>
 
 /*
  * Kevin-specific things
index ce072859e3b232dd95b9e4ca9227bb58a65161fd..97c123e09e45bfd80173029de0da0161dd4be0c7 100644 (file)
@@ -30,7 +30,6 @@ CONFIG_PROFILING=y
 CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_SUNXI=y
 CONFIG_ARCH_ALPINE=y
@@ -62,16 +61,16 @@ CONFIG_ARCH_XGENE=y
 CONFIG_ARCH_ZX=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_PCI=y
-CONFIG_PCI_MSI=y
 CONFIG_PCI_IOV=y
-CONFIG_PCI_AARDVARK=y
-CONFIG_PCIE_RCAR=y
-CONFIG_PCI_HOST_GENERIC=y
-CONFIG_PCI_XGENE=y
 CONFIG_PCI_LAYERSCAPE=y
 CONFIG_PCI_HISI=y
 CONFIG_PCIE_QCOM=y
 CONFIG_PCIE_ARMADA_8K=y
+CONFIG_PCI_AARDVARK=y
+CONFIG_PCIE_RCAR=y
+CONFIG_PCIE_ROCKCHIP=m
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCI_XGENE=y
 CONFIG_ARM64_VA_BITS_48=y
 CONFIG_SCHED_MC=y
 CONFIG_NUMA=y
@@ -80,12 +79,11 @@ CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CMA=y
 CONFIG_SECCOMP=y
-CONFIG_XEN=y
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
+CONFIG_XEN=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
-CONFIG_CPU_IDLE=y
 CONFIG_HIBERNATION=y
 CONFIG_ARM_CPUIDLE=y
 CONFIG_CPU_FREQ=y
@@ -155,8 +153,8 @@ CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_VIRTIO_BLK=y
-CONFIG_EEPROM_AT25=m
 CONFIG_SRAM=y
+CONFIG_EEPROM_AT25=m
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SAS_ATA=y
@@ -168,8 +166,8 @@ CONFIG_AHCI_CEVA=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_AHCI_XGENE=y
 CONFIG_AHCI_QORIQ=y
-CONFIG_SATA_RCAR=y
 CONFIG_SATA_SIL24=y
+CONFIG_SATA_RCAR=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
@@ -186,18 +184,17 @@ CONFIG_HNS_ENET=y
 CONFIG_E1000E=y
 CONFIG_IGB=y
 CONFIG_IGBVF=y
-CONFIG_MVPP2=y
 CONFIG_MVNETA=y
+CONFIG_MVPP2=y
 CONFIG_SKY2=y
 CONFIG_RAVB=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=m
-CONFIG_REALTEK_PHY=m
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
 CONFIG_MESON_GXL_PHY=m
 CONFIG_MICREL_PHY=y
-CONFIG_MDIO_BUS_MUX=y
-CONFIG_MDIO_BUS_MUX_MMIOREG=y
+CONFIG_REALTEK_PHY=m
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
@@ -212,6 +209,8 @@ CONFIG_BRCMFMAC=m
 CONFIG_WL18XX=m
 CONFIG_WLCORE_SDIO=m
 CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_ADC=m
+CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_PM8941_PWRKEY=y
@@ -230,14 +229,14 @@ CONFIG_SERIAL_8250_UNIPHIER=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MESON=y
+CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
 CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=11
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_SERIAL_MESON=y
-CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_XILINX_PS_UART=y
@@ -261,14 +260,15 @@ CONFIG_I2C_UNIPHIER_F=y
 CONFIG_I2C_RCAR=y
 CONFIG_I2C_CROS_EC_TUNNEL=y
 CONFIG_SPI=y
-CONFIG_SPI_MESON_SPIFC=m
 CONFIG_SPI_BCM2835=m
 CONFIG_SPI_BCM2835AUX=m
+CONFIG_SPI_MESON_SPIFC=m
 CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_QUP=y
-CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_ROCKCHIP=y
 CONFIG_SPI_S3C64XX=y
+CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_PINCTRL_MAX77620=y
@@ -286,33 +286,33 @@ CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_MAX77620=y
 CONFIG_POWER_RESET_MSM=y
-CONFIG_BATTERY_BQ27XXX=y
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
+CONFIG_BATTERY_BQ27XXX=y
+CONFIG_SENSORS_ARM_SCPI=y
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_INA2XX=m
-CONFIG_SENSORS_ARM_SCPI=y
-CONFIG_THERMAL=y
-CONFIG_THERMAL_EMULATION=y
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
 CONFIG_CPU_THERMAL=y
-CONFIG_BCM2835_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
 CONFIG_EXYNOS_THERMAL=y
+CONFIG_ROCKCHIP_THERMAL=m
 CONFIG_WATCHDOG=y
-CONFIG_BCM2835_WDT=y
-CONFIG_RENESAS_WDT=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MESON_GXBB_WATCHDOG=m
 CONFIG_MESON_WATCHDOG=m
+CONFIG_RENESAS_WDT=y
+CONFIG_BCM2835_WDT=y
+CONFIG_MFD_CROS_EC=y
+CONFIG_MFD_CROS_EC_I2C=y
+CONFIG_MFD_CROS_EC_SPI=y
 CONFIG_MFD_EXYNOS_LPASS=m
+CONFIG_MFD_HI655X_PMIC=y
 CONFIG_MFD_MAX77620=y
-CONFIG_MFD_RK808=y
 CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_RK808=y
 CONFIG_MFD_SEC_CORE=y
-CONFIG_MFD_HI655X_PMIC=y
-CONFIG_REGULATOR=y
-CONFIG_MFD_CROS_EC=y
-CONFIG_MFD_CROS_EC_I2C=y
+CONFIG_REGULATOR_FAN53555=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_HI655X=y
@@ -345,13 +345,12 @@ CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_EXYNOS_MIC=y
 CONFIG_DRM_RCAR_DU=m
-CONFIG_DRM_RCAR_HDMI=y
 CONFIG_DRM_RCAR_LVDS=y
 CONFIG_DRM_RCAR_VSP=y
 CONFIG_DRM_TEGRA=m
-CONFIG_DRM_VC4=m
 CONFIG_DRM_PANEL_SIMPLE=m
 CONFIG_DRM_I2C_ADV7511=m
+CONFIG_DRM_VC4=m
 CONFIG_DRM_HISI_KIRIN=m
 CONFIG_DRM_MESON=m
 CONFIG_FB=y
@@ -366,39 +365,37 @@ CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_BCM2835_SOC_I2S=m
-CONFIG_SND_SOC_RCAR=y
 CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_RCAR=y
 CONFIG_SND_SOC_AK4613=y
 CONFIG_USB=y
 CONFIG_USB_OTG=y
 CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_PLATFORM=y
-CONFIG_USB_XHCI_RCAR=y
-CONFIG_USB_EHCI_EXYNOS=y
 CONFIG_USB_XHCI_TEGRA=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_EXYNOS=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_EXYNOS=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_RENESAS_USBHS=m
 CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC2=y
 CONFIG_USB_DWC3=y
+CONFIG_USB_DWC2=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_ISP1760=y
 CONFIG_USB_HSIC_USB3503=y
 CONFIG_USB_MSM_OTG=y
+CONFIG_USB_QCOM_8X16_PHY=y
 CONFIG_USB_ULPI=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_ARMMMCI=y
-CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ACPI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -406,6 +403,7 @@ CONFIG_MMC_SDHCI_OF_ARASAN=y
 CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_MMC_SDHCI_CADENCE=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_SPI=y
 CONFIG_MMC_SDHI=y
@@ -414,32 +412,31 @@ CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_K3=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SUNXI=y
-CONFIG_MMC_SDHCI_XENON=y
 CONFIG_MMC_BCM2835=y
+CONFIG_MMC_SDHCI_XENON=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_PWM=y
 CONFIG_LEDS_SYSCON=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MAX77686=y
+CONFIG_RTC_DRV_RK808=m
 CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_EFI=y
+CONFIG_RTC_DRV_S3C=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_SUN6I=y
-CONFIG_RTC_DRV_RK808=m
 CONFIG_RTC_DRV_TEGRA=y
 CONFIG_RTC_DRV_XGENE=y
-CONFIG_RTC_DRV_S3C=y
 CONFIG_DMADEVICES=y
+CONFIG_DMA_BCM2835=m
 CONFIG_MV_XOR_V2=y
 CONFIG_PL330_DMA=y
-CONFIG_DMA_BCM2835=m
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_QCOM_HIDMA_MGMT=y
@@ -452,52 +449,56 @@ CONFIG_VIRTIO_BALLOON=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_XEN_GNTDEV=y
 CONFIG_XEN_GRANT_DEV_ALLOC=y
+CONFIG_COMMON_CLK_RK808=y
 CONFIG_COMMON_CLK_SCPI=y
 CONFIG_COMMON_CLK_CS2000_CP=y
 CONFIG_COMMON_CLK_S2MPS11=y
-CONFIG_COMMON_CLK_PWM=y
-CONFIG_COMMON_CLK_RK808=y
 CONFIG_CLK_QORIQ=y
+CONFIG_COMMON_CLK_PWM=y
 CONFIG_COMMON_CLK_QCOM=y
+CONFIG_QCOM_CLK_SMD_RPM=y
 CONFIG_MSM_GCC_8916=y
 CONFIG_MSM_GCC_8994=y
 CONFIG_MSM_MMCC_8996=y
 CONFIG_HWSPINLOCK_QCOM=y
-CONFIG_MAILBOX=y
 CONFIG_ARM_MHU=y
 CONFIG_PLATFORM_MHU=y
 CONFIG_BCM2835_MBOX=y
 CONFIG_HI6220_MBOX=y
 CONFIG_ARM_SMMU=y
 CONFIG_ARM_SMMU_V3=y
+CONFIG_RPMSG_QCOM_SMD=y
 CONFIG_RASPBERRYPI_POWER=y
 CONFIG_QCOM_SMEM=y
-CONFIG_QCOM_SMD=y
 CONFIG_QCOM_SMD_RPM=y
+CONFIG_QCOM_SMP2P=y
+CONFIG_QCOM_SMSM=y
 CONFIG_ROCKCHIP_PM_DOMAINS=y
 CONFIG_ARCH_TEGRA_132_SOC=y
 CONFIG_ARCH_TEGRA_210_SOC=y
 CONFIG_ARCH_TEGRA_186_SOC=y
 CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_EXYNOS_ADC=y
+CONFIG_ROCKCHIP_SARADC=m
 CONFIG_PWM=y
 CONFIG_PWM_BCM2835=m
+CONFIG_PWM_CROS_EC=m
+CONFIG_PWM_MESON=m
 CONFIG_PWM_ROCKCHIP=y
+CONFIG_PWM_SAMSUNG=y
 CONFIG_PWM_TEGRA=m
-CONFIG_PWM_MESON=m
-CONFIG_COMMON_RESET_HI6220=y
 CONFIG_PHY_RCAR_GEN3_USB2=y
 CONFIG_PHY_HI6220_USB=y
+CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
 CONFIG_PHY_ROCKCHIP_EMMC=y
-CONFIG_PHY_SUN4I_USB=y
+CONFIG_PHY_ROCKCHIP_PCIE=m
 CONFIG_PHY_XGENE=y
 CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_ARM_SCPI_PROTOCOL=y
-CONFIG_ACPI=y
-CONFIG_IIO=y
-CONFIG_EXYNOS_ADC=y
-CONFIG_PWM_SAMSUNG=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_ACPI=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -511,7 +512,6 @@ CONFIG_FUSE_FS=m
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
 CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_EFIVAR_FS=y
@@ -539,11 +539,9 @@ CONFIG_MEMTEST=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_ECHAINIV=y
 CONFIG_CRYPTO_ANSI_CPRNG=y
-CONFIG_CRYPTO_DEV_SAFEXCEL=m
 CONFIG_ARM64_CRYPTO=y
 CONFIG_CRYPTO_SHA1_ARM64_CE=y
 CONFIG_CRYPTO_SHA2_ARM64_CE=y
 CONFIG_CRYPTO_GHASH_ARM64_CE=y
 CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
 CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
-# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set
index 0e99978da3f05013d145132950ad204a92e3e4b0..59cca1d6ec547270adbd56a4e2265b9f9fc34375 100644 (file)
@@ -23,9 +23,9 @@
 #define ACPI_MADT_GICC_LENGTH  \
        (acpi_gbl_FADT.header.revision < 6 ? 76 : 80)
 
-#define BAD_MADT_GICC_ENTRY(entry, end)                                                \
-       (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) ||       \
-        (entry)->header.length != ACPI_MADT_GICC_LENGTH)
+#define BAD_MADT_GICC_ENTRY(entry, end)                                        \
+       (!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH || \
+       (unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end))
 
 /* Basic configuration for ACPI */
 #ifdef CONFIG_ACPI
index f819fdcff1accf694cc0ec7428096fe41aef7f89..f5a2d09afb3841bd5ac7d40764ef48b2e108de0d 100644 (file)
@@ -264,7 +264,6 @@ __LL_SC_PREFIX(__cmpxchg_case_##name(volatile void *ptr,            \
        "       st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n"     \
        "       cbnz    %w[tmp], 1b\n"                                  \
        "       " #mb "\n"                                              \
-       "       mov     %" #w "[oldval], %" #w "[old]\n"                \
        "2:"                                                            \
        : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval),                   \
          [v] "+Q" (*(unsigned long *)ptr)                              \
index e7f84a7b44658d2f93d642e06e013300693d6a82..428ee1f2468c55959d52cf1cffde922399387b9f 100644 (file)
@@ -115,6 +115,7 @@ struct arm64_cpu_capabilities {
 
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
+extern struct static_key_false arm64_const_caps_ready;
 
 bool this_cpu_has_cap(unsigned int cap);
 
@@ -124,7 +125,7 @@ static inline bool cpu_have_feature(unsigned int num)
 }
 
 /* System capability check for constant caps */
-static inline bool cpus_have_const_cap(int num)
+static inline bool __cpus_have_const_cap(int num)
 {
        if (num >= ARM64_NCAPS)
                return false;
@@ -138,6 +139,14 @@ static inline bool cpus_have_cap(unsigned int num)
        return test_bit(num, cpu_hwcaps);
 }
 
+static inline bool cpus_have_const_cap(int num)
+{
+       if (static_branch_likely(&arm64_const_caps_ready))
+               return __cpus_have_const_cap(num);
+       else
+               return cpus_have_cap(num);
+}
+
 static inline void cpus_set_cap(unsigned int num)
 {
        if (num >= ARM64_NCAPS) {
@@ -145,7 +154,6 @@ static inline void cpus_set_cap(unsigned int num)
                        num, ARM64_NCAPS);
        } else {
                __set_bit(num, cpu_hwcaps);
-               static_branch_enable(&cpu_hwcap_keys[num]);
        }
 }
 
index 5e19165c5fa8b86002f0308812a0c49199a91b44..1f252a95bc02979cc8c6f01425e26e44f34c1990 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/types.h>
 #include <linux/kvm_types.h>
+#include <asm/cpufeature.h>
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
@@ -355,9 +356,12 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
                                       unsigned long vector_ptr)
 {
        /*
-        * Call initialization code, and switch to the full blown
-        * HYP code.
+        * Call initialization code, and switch to the full blown HYP code.
+        * If the cpucaps haven't been finalized yet, something has gone very
+        * wrong, and hyp will crash and burn when it uses any
+        * cpus_have_const_cap() wrapper.
         */
+       BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
        __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
 }
 
index 15c142ce991cd9180172f0ecb8ddf399e8e31c60..b4d13d9267ff8b56c95aa981928bb3b7ed950a88 100644 (file)
 #define SCTLR_ELx_A    (1 << 1)
 #define SCTLR_ELx_M    1
 
+#define SCTLR_EL2_RES1 ((1 << 4)  | (1 << 5)  | (1 << 11) | (1 << 16) | \
+                        (1 << 16) | (1 << 18) | (1 << 22) | (1 << 23) | \
+                        (1 << 28) | (1 << 29))
+
 #define SCTLR_ELx_FLAGS        (SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
                         SCTLR_ELx_SA | SCTLR_ELx_I)
 
index 94b8f7fc33100f85db825a372bf36d6f597934ac..817ce3365e200dfb5f7ff205dadabe72c3490e43 100644 (file)
@@ -985,8 +985,16 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
  */
 void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
-       for (; caps->matches; caps++)
-               if (caps->enable && cpus_have_cap(caps->capability))
+       for (; caps->matches; caps++) {
+               unsigned int num = caps->capability;
+
+               if (!cpus_have_cap(num))
+                       continue;
+
+               /* Ensure cpus_have_const_cap(num) works */
+               static_branch_enable(&cpu_hwcap_keys[num]);
+
+               if (caps->enable) {
                        /*
                         * Use stop_machine() as it schedules the work allowing
                         * us to modify PSTATE, instead of on_each_cpu() which
@@ -994,6 +1002,8 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
                         * we return.
                         */
                        stop_machine(caps->enable, NULL, cpu_online_mask);
+               }
+       }
 }
 
 /*
@@ -1096,6 +1106,14 @@ static void __init setup_feature_capabilities(void)
        enable_cpu_capabilities(arm64_features);
 }
 
+DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
+EXPORT_SYMBOL(arm64_const_caps_ready);
+
+static void __init mark_const_caps_ready(void)
+{
+       static_branch_enable(&arm64_const_caps_ready);
+}
+
 /*
  * Check if the current CPU has a given feature capability.
  * Should be called from non-preemptible context.
@@ -1131,6 +1149,7 @@ void __init setup_cpu_features(void)
        /* Set the CPU feature capabilies */
        setup_feature_capabilities();
        enable_errata_workarounds();
+       mark_const_caps_ready();
        setup_elf_hwcaps(arm64_elf_hwcaps);
 
        if (system_supports_32bit_el0())
index 4f0e3ebfea4b4f6496a783bd172abc05e7ec1d4a..c7e3e6387a4910a6377d78e10caf98cc1c20243b 100644 (file)
@@ -191,8 +191,10 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
                return NULL;
 
        root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node);
-       if (!root_ops)
+       if (!root_ops) {
+               kfree(ri);
                return NULL;
+       }
 
        ri->cfg = pci_acpi_setup_ecam_mapping(root);
        if (!ri->cfg) {
index bcc79471b38e24cff24b5702a182752ef26583cc..83a1b1ad189f51536af8c4c8dd8c509cb70f9a95 100644 (file)
@@ -877,15 +877,24 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
 
        if (attr->exclude_idle)
                return -EPERM;
-       if (is_kernel_in_hyp_mode() &&
-           attr->exclude_kernel != attr->exclude_hv)
-               return -EINVAL;
+
+       /*
+        * If we're running in hyp mode, then we *are* the hypervisor.
+        * Therefore we ignore exclude_hv in this configuration, since
+        * there's no hypervisor to sample anyway. This is consistent
+        * with other architectures (x86 and Power).
+        */
+       if (is_kernel_in_hyp_mode()) {
+               if (!attr->exclude_kernel)
+                       config_base |= ARMV8_PMU_INCLUDE_EL2;
+       } else {
+               if (attr->exclude_kernel)
+                       config_base |= ARMV8_PMU_EXCLUDE_EL1;
+               if (!attr->exclude_hv)
+                       config_base |= ARMV8_PMU_INCLUDE_EL2;
+       }
        if (attr->exclude_user)
                config_base |= ARMV8_PMU_EXCLUDE_EL0;
-       if (!is_kernel_in_hyp_mode() && attr->exclude_kernel)
-               config_base |= ARMV8_PMU_EXCLUDE_EL1;
-       if (!attr->exclude_hv)
-               config_base |= ARMV8_PMU_INCLUDE_EL2;
 
        /*
         * Install the filter into config_base as this is used to
index 41b6e31f8f556f4d4af8ecdafd3867e540a8ed10..d0cb007fa4823791be514b8a5ac65d8d408f099d 100644 (file)
@@ -221,10 +221,11 @@ void update_vsyscall(struct timekeeper *tk)
                /* tkr_mono.cycle_last == tkr_raw.cycle_last */
                vdso_data->cs_cycle_last        = tk->tkr_mono.cycle_last;
                vdso_data->raw_time_sec         = tk->raw_time.tv_sec;
-               vdso_data->raw_time_nsec        = tk->raw_time.tv_nsec;
+               vdso_data->raw_time_nsec        = (tk->raw_time.tv_nsec <<
+                                                  tk->tkr_raw.shift) +
+                                                 tk->tkr_raw.xtime_nsec;
                vdso_data->xtime_clock_sec      = tk->xtime_sec;
                vdso_data->xtime_clock_nsec     = tk->tkr_mono.xtime_nsec;
-               /* tkr_raw.xtime_nsec == 0 */
                vdso_data->cs_mono_mult         = tk->tkr_mono.mult;
                vdso_data->cs_raw_mult          = tk->tkr_raw.mult;
                /* tkr_mono.shift == tkr_raw.shift */
index e00b4671bd7c4af5516b95da00409c7296df1963..76320e9209651fd307659dcbab8092ff7c1c09e2 100644 (file)
@@ -256,7 +256,6 @@ monotonic_raw:
        seqcnt_check fail=monotonic_raw
 
        /* All computations are done with left-shifted nsecs. */
-       lsl     x14, x14, x12
        get_nsec_per_sec res=x9
        lsl     x9, x9, x12
 
index 839425c24b1c7078c7397470aa811286eb119f49..3f9615582377661a88fab8be6a12365d625d830a 100644 (file)
@@ -106,10 +106,13 @@ __do_hyp_init:
        tlbi    alle2
        dsb     sy
 
-       mrs     x4, sctlr_el2
-       and     x4, x4, #SCTLR_ELx_EE   // preserve endianness of EL2
-       ldr     x5, =SCTLR_ELx_FLAGS
-       orr     x4, x4, x5
+       /*
+        * Preserve all the RES1 bits while setting the default flags,
+        * as well as the EE bit on BE. Drop the A flag since the compiler
+        * is allowed to generate unaligned accesses.
+        */
+       ldr     x4, =(SCTLR_EL2_RES1 | (SCTLR_ELx_FLAGS & ~SCTLR_ELx_A))
+CPU_BE(        orr     x4, x4, #SCTLR_ELx_EE)
        msr     sctlr_el2, x4
        isb
 
index aaf42ae8d8c31395d63590289e55798073bc99a4..14c4e3b14bcb6f59a6de55db07de9cc8457be8ec 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
index 79f37e37d367c88b2bd76a9a93a91a587ee6347a..6260b69e5622930b87d100e0dfbdf8fda249deee 100644 (file)
@@ -65,8 +65,8 @@ static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
                 * Here set VMCR.CTLR in ICC_CTLR_EL1 layout.
                 * The vgic_set_vmcr() will convert to ICH_VMCR layout.
                 */
-               vmcr.ctlr = val & ICC_CTLR_EL1_CBPR_MASK;
-               vmcr.ctlr |= val & ICC_CTLR_EL1_EOImode_MASK;
+               vmcr.cbpr = (val & ICC_CTLR_EL1_CBPR_MASK) >> ICC_CTLR_EL1_CBPR_SHIFT;
+               vmcr.eoim = (val & ICC_CTLR_EL1_EOImode_MASK) >> ICC_CTLR_EL1_EOImode_SHIFT;
                vgic_set_vmcr(vcpu, &vmcr);
        } else {
                val = 0;
@@ -83,8 +83,8 @@ static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
                 * The VMCR.CTLR value is in ICC_CTLR_EL1 layout.
                 * Extract it directly using ICC_CTLR_EL1 reg definitions.
                 */
-               val |= vmcr.ctlr & ICC_CTLR_EL1_CBPR_MASK;
-               val |= vmcr.ctlr & ICC_CTLR_EL1_EOImode_MASK;
+               val |= (vmcr.cbpr << ICC_CTLR_EL1_CBPR_SHIFT) & ICC_CTLR_EL1_CBPR_MASK;
+               val |= (vmcr.eoim << ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK;
 
                p->regval = val;
        }
@@ -135,7 +135,7 @@ static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
                p->regval = 0;
 
        vgic_get_vmcr(vcpu, &vmcr);
-       if (!((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT)) {
+       if (!vmcr.cbpr) {
                if (p->is_write) {
                        vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >>
                                     ICC_BPR1_EL1_SHIFT;
index c6e53580aefe9148f6d865a9a89e611a6d1c542e..c870d6f01ac217e0dc80bf4ee0d3549e6fa1c658 100644 (file)
@@ -36,6 +36,7 @@ int bpf_jit_enable __read_mostly;
 #define TMP_REG_1 (MAX_BPF_JIT_REG + 0)
 #define TMP_REG_2 (MAX_BPF_JIT_REG + 1)
 #define TCALL_CNT (MAX_BPF_JIT_REG + 2)
+#define TMP_REG_3 (MAX_BPF_JIT_REG + 3)
 
 /* Map BPF registers to A64 registers */
 static const int bpf2a64[] = {
@@ -57,6 +58,7 @@ static const int bpf2a64[] = {
        /* temporary registers for internal BPF JIT */
        [TMP_REG_1] = A64_R(10),
        [TMP_REG_2] = A64_R(11),
+       [TMP_REG_3] = A64_R(12),
        /* tail_call_cnt */
        [TCALL_CNT] = A64_R(26),
        /* temporary register for blinding constants */
@@ -253,8 +255,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
         */
        off = offsetof(struct bpf_array, ptrs);
        emit_a64_mov_i64(tmp, off, ctx);
-       emit(A64_LDR64(tmp, r2, tmp), ctx);
-       emit(A64_LDR64(prg, tmp, r3), ctx);
+       emit(A64_ADD(1, tmp, r2, tmp), ctx);
+       emit(A64_LSL(1, prg, r3, 3), ctx);
+       emit(A64_LDR64(prg, tmp, prg), ctx);
        emit(A64_CBZ(1, prg, jmp_offset), ctx);
 
        /* goto *(prog->bpf_func + prologue_size); */
@@ -318,6 +321,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
        const u8 src = bpf2a64[insn->src_reg];
        const u8 tmp = bpf2a64[TMP_REG_1];
        const u8 tmp2 = bpf2a64[TMP_REG_2];
+       const u8 tmp3 = bpf2a64[TMP_REG_3];
        const s16 off = insn->off;
        const s32 imm = insn->imm;
        const int i = insn - ctx->prog->insnsi;
@@ -688,10 +692,10 @@ emit_cond_jmp:
                emit(A64_PRFM(tmp, PST, L1, STRM), ctx);
                emit(A64_LDXR(isdw, tmp2, tmp), ctx);
                emit(A64_ADD(isdw, tmp2, tmp2, src), ctx);
-               emit(A64_STXR(isdw, tmp2, tmp, tmp2), ctx);
+               emit(A64_STXR(isdw, tmp2, tmp, tmp3), ctx);
                jmp_offset = -3;
                check_imm19(jmp_offset);
-               emit(A64_CBNZ(0, tmp2, jmp_offset), ctx);
+               emit(A64_CBNZ(0, tmp3, jmp_offset), ctx);
                break;
 
        /* R0 = ntohx(*(size *)(((struct sk_buff *)R6)->data + imm)) */
index 85d4af97c986aee4a7eff90b4347aca444ee1ed9..dbdbb8a558df4acb548b71dbc52f63b3e7373d7f 100644 (file)
@@ -75,11 +75,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/*
- * Return saved PC of a blocked thread.
- */
-#define thread_saved_pc(tsk)   (tsk->thread.pc)
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)                                                   \
index b9eb3da7f278dac858bfb2191094f9fc837ac5c8..7c87b5be53b5b74c76fbe03829034b1e96ac3c7c 100644 (file)
@@ -95,11 +95,6 @@ static inline void release_thread(struct task_struct *dead_task)
 #define copy_segments(tsk, mm)         do { } while (0)
 #define release_segments(mm)           do { } while (0)
 
-/*
- * saved PC of a blocked thread.
- */
-#define thread_saved_pc(tsk) (task_pt_regs(tsk)->pc)
-
 /*
  * saved kernel SP and DP of a blocked thread.
  */
index e299d30105b53bf5ad0e8b8df7f036f39267ad66..a2cdb1521aca4db4069d449f56094ee822e0313d 100644 (file)
@@ -69,14 +69,6 @@ void hard_reset_now (void)
        while(1) /* waiting for RETRIBUTION! */ ;
 }
 
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *t)
-{
-       return task_pt_regs(t)->irp;
-}
-
 /* setup the child's kernel stack with a pt_regs and switch_stack on it.
  * it will be un-nested during _resume and _ret_from_sys_call when the
  * new thread is scheduled.
index c530a8fa87ceb751a0c275885e34852dbcd5b6c2..fe87b383fbf3fc45522d8ce74a122c8469347993 100644 (file)
@@ -84,14 +84,6 @@ hard_reset_now(void)
                ; /* Wait for reset. */
 }
 
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *t)
-{
-       return task_pt_regs(t)->erp;
-}
-
 /*
  * Setup the child's kernel stack with a pt_regs and call switch_stack() on it.
  * It will be unnested during _resume and _ret_from_sys_call when the new thread
diff --git a/arch/cris/boot/dts/include/dt-bindings b/arch/cris/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index 15b815df29c165809c4e6e229ede6a077d9e8e71..bc2729e4b2c97e89b5a9dd3daf30df555dee1e0f 100644 (file)
@@ -52,8 +52,6 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_ESP(tsk)   ((tsk) == current ? rdusp() : (tsk)->thread.usp)
 
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
 /* Free all resources held by a thread. */
 static inline void release_thread(struct task_struct *dead_task)
 {
index ddaeb9cc9143333d8f00de60291298f6dce5530c..e4d08d74ed9f8dc4f81140fcf60442378f02cf58 100644 (file)
@@ -96,11 +96,6 @@ extern asmlinkage void *restore_user_regs(const struct user_context *target, ...
 #define release_segments(mm)           do { } while (0)
 #define forget_segments()              do { } while (0)
 
-/*
- * Return saved PC of a blocked thread.
- */
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)   ((tsk)->thread.frame0->pc)
index a89bddefdacf9194373a201c6c6c4cf8c4ac87c0..139093fab3260debefb4da2fbd33e37778784298 100644 (file)
@@ -16,5 +16,11 @@ static inline cycles_t get_cycles(void)
 #define vxtime_lock()          do {} while (0)
 #define vxtime_unlock()                do {} while (0)
 
+/* This attribute is used in include/linux/jiffies.h alongside with
+ * __cacheline_aligned_in_smp. It is assumed that __cacheline_aligned_in_smp
+ * for frv does not contain another section specification.
+ */
+#define __jiffy_arch_data      __attribute__((__section__(".data")))
+
 #endif
 
index 5a4c92abc99ec320b54ef80841bc6f3333a9d3dd..a957b374e3a66b28a30bf5d30b623bfccbc2fb0a 100644 (file)
@@ -198,15 +198,6 @@ unsigned long get_wchan(struct task_struct *p)
        return 0;
 }
 
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       /* Check whether the thread is blocked in resume() */
-       if (in_sched_functions(tsk->thread.pc))
-               return ((unsigned long *)tsk->thread.fp)[2];
-       else
-               return tsk->thread.pc;
-}
-
 int elf_check_arch(const struct elf32_hdr *hdr)
 {
        unsigned long hsr0 = __get_HSR(0);
index da82c25301e7774bcbe3058129b574c7496efba8..46aa289c5102baf8a1b841e693316538ee901f8b 100644 (file)
@@ -75,7 +75,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
                addr = PAGE_ALIGN(addr);
                vma = find_vma(current->mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        goto success;
        }
 
index 65132d7ae9e5b66fb484014f7930fd91f75cc944..afa53147e66a82e24d8d9e100b4706a9ce2ee760 100644 (file)
@@ -110,10 +110,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk);
 unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)   \
index 0f5db5bb561b75cb30bb2871ffa7c00545f84539..d1ddcabbbe8383fc6160db3946a334286676b5ae 100644 (file)
@@ -129,11 +129,6 @@ int copy_thread(unsigned long clone_flags,
        return 0;
 }
 
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       return ((struct pt_regs *)tsk->thread.esp0)->pc;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
index 45a825402f634ee4b650a08a60efc5c60d50e261..ce67940860a536dce66bea9b59daeab1fcaa103e 100644 (file)
@@ -33,9 +33,6 @@
 /*  task_struct, defined elsewhere, is the "process descriptor" */
 struct task_struct;
 
-/*  this is defined in arch/process.c  */
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
 extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
 
 /*
index de715bab7956c7e38df0b8ab689d11cca8fceb16..656050c2e6a06ab7f60ad6c1a65351dfd29f544f 100644 (file)
@@ -60,14 +60,6 @@ void arch_cpu_idle(void)
        local_irq_enable();
 }
 
-/*
- *  Return saved PC of a blocked thread
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       return 0;
-}
-
 /*
  * Copy architecture-specific thread state
  */
index ec90afdb3ad084e999e6980077aff846564f7b7c..c599eb126c9e7be9a3324744297f562ad743e97a 100644 (file)
@@ -37,15 +37,14 @@ __kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count)
        long uncleared;
 
        while (count > PAGE_SIZE) {
-               uncleared = __copy_to_user_hexagon(dest, &empty_zero_page,
-                                               PAGE_SIZE);
+               uncleared = raw_copy_to_user(dest, &empty_zero_page, PAGE_SIZE);
                if (uncleared)
                        return count - (PAGE_SIZE - uncleared);
                count -= PAGE_SIZE;
                dest += PAGE_SIZE;
        }
        if (count)
-               count = __copy_to_user_hexagon(dest, &empty_zero_page, count);
+               count = raw_copy_to_user(dest, &empty_zero_page, count);
 
        return count;
 }
index 26a63d69c599addab0486c2fa08d548dd229ccf9..ab982f07ea681253d42f351c230c976a83258f95 100644 (file)
@@ -601,23 +601,6 @@ ia64_set_unat (__u64 *unat, void *spill_addr, unsigned long nat)
        *unat = (*unat & ~mask) | (nat << bit);
 }
 
-/*
- * Return saved PC of a blocked thread.
- * Note that the only way T can block is through a call to schedule() -> switch_to().
- */
-static inline unsigned long
-thread_saved_pc (struct task_struct *t)
-{
-       struct unw_frame_info info;
-       unsigned long ip;
-
-       unw_init_from_blocked_task(&info, t);
-       if (unw_unwind(&info) < 0)
-               return 0;
-       unw_get_ip(&info, &ip);
-       return ip;
-}
-
 /*
  * Get the current instruction/program counter value.
  */
index 5767367550c69637a0b51c7a037b7a5e0c4fbfb4..657874eeeccc262c11268094e0f0ba530e05dd92 100644 (file)
@@ -122,8 +122,6 @@ extern void release_thread(struct task_struct *);
 extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
 extern void release_segments(struct mm_struct * mm);
 
-extern unsigned long thread_saved_pc(struct task_struct *);
-
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)  do { } while (0)
 #define release_segments(mm)  do { } while (0)
index d8ffcfec599cb6a10a6eb649f15d628a97a377f9..8cd7e03f4370c06a633d2a12b5db70299ffa41ae 100644 (file)
 
 #include <linux/err.h>
 
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       return tsk->thread.lr;
-}
-
 void (*pm_power_off)(void) = NULL;
 EXPORT_SYMBOL(pm_power_off);
 
index 77239e81379b16b52e39cff979d1da4ceb2e1965..94c36030440cc825c4688244a0b973ba60be3863 100644 (file)
@@ -130,8 +130,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)   \
index e475c945c8b2bf199e6147a16fcf42c2d7c0d714..7df92f8b0781dd2651096f83f8c45185a26be803 100644 (file)
 asmlinkage void ret_from_fork(void);
 asmlinkage void ret_from_kernel_thread(void);
 
-
-/*
- * Return saved PC from a blocked thread
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
-       /* Check whether the thread is blocked in resume() */
-       if (in_sched_functions(sw->retpc))
-               return ((unsigned long *)sw->a6)[1];
-       else
-               return sw->retpc;
-}
-
 void arch_cpu_idle(void)
 {
 #if defined(MACH_ATARI_ONLY)
diff --git a/arch/metag/boot/dts/include/dt-bindings b/arch/metag/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index 37ef196e45191adb481450c8648e9e9acbb05106..330d556860ba7a8211b767cd4ac03275adcab9f0 100644 (file)
@@ -69,8 +69,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern unsigned long thread_saved_pc(struct task_struct *t);
-
 extern unsigned long get_wchan(struct task_struct *p);
 
 # define KSTK_EIP(tsk) (0)
@@ -121,10 +119,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/* Return saved (kernel) PC of a blocked thread.  */
-#  define thread_saved_pc(tsk) \
-       ((tsk)->thread.regs ? (tsk)->thread.regs->r15 : 0)
-
 unsigned long get_wchan(struct task_struct *p);
 
 /* The size allocated for kernel stacks. This _must_ be a power of two! */
index e92a817e645fac7bf8782e782b2525429572d5b3..6527ec22f158f16acef89a0b78310c518866ae73 100644 (file)
@@ -119,23 +119,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-#ifndef CONFIG_MMU
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       struct cpu_context *ctx =
-               &(((struct thread_info *)(tsk->stack))->cpu_context);
-
-       /* Check whether the thread is blocked in resume() */
-       if (in_sched_functions(ctx->r15))
-               return (unsigned long)ctx->r15;
-       else
-               return ctx->r14;
-}
-#endif
-
 unsigned long get_wchan(struct task_struct *p)
 {
 /* TBD (used by procfs) */
index 2728a9a9c7c5bc4f822ab6788e1f889cb39c0a51..145b5ce8eb7e660dda67f6a53aa472f74a413af0 100644 (file)
@@ -128,19 +128,19 @@ quiet_cmd_cpp_its_S = ITS     $@
                        -DADDR_BITS=$(ADDR_BITS) \
                        -DADDR_CELLS=$(itb_addr_cells)
 
-$(obj)/vmlinux.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
+$(obj)/vmlinux.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
        $(call if_changed_dep,cpp_its_S,none,vmlinux.bin)
 
-$(obj)/vmlinux.gz.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
+$(obj)/vmlinux.gz.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
        $(call if_changed_dep,cpp_its_S,gzip,vmlinux.bin.gz)
 
-$(obj)/vmlinux.bz2.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
+$(obj)/vmlinux.bz2.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX)  FORCE
        $(call if_changed_dep,cpp_its_S,bzip2,vmlinux.bin.bz2)
 
-$(obj)/vmlinux.lzma.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
+$(obj)/vmlinux.lzma.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
        $(call if_changed_dep,cpp_its_S,lzma,vmlinux.bin.lzma)
 
-$(obj)/vmlinux.lzo.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
+$(obj)/vmlinux.lzo.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
        $(call if_changed_dep,cpp_its_S,lzo,vmlinux.bin.lzo)
 
 quiet_cmd_itb-image = ITB     $@
diff --git a/arch/mips/boot/dts/include/dt-bindings b/arch/mips/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index d34536e7653f6a29fe85b5b1e15b67c19a8c9b3e..279b6d14ffeb7c5af5b54152292b70dd5581d88c 100644 (file)
@@ -35,7 +35,12 @@ extern pte_t *pkmap_page_table;
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#define LAST_PKMAP 512
+#else
 #define LAST_PKMAP 1024
+#endif
+
 #define LAST_PKMAP_MASK (LAST_PKMAP-1)
 #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
index 291846d9ba8346ca915879ff6b7c1162cde67df8..ad1a99948f2795c0608c32e3dc213c46e171d162 100644 (file)
@@ -43,7 +43,8 @@ typedef union mips_instruction kprobe_opcode_t;
 
 #define flush_insn_slot(p)                                             \
 do {                                                                   \
-       flush_icache_range((unsigned long)p->addr,                      \
+       if (p->addr)                                                    \
+               flush_icache_range((unsigned long)p->addr,              \
                           (unsigned long)p->addr +                     \
                           (MAX_INSN_SIZE * sizeof(kprobe_opcode_t)));  \
 } while (0)
index 6f94bed571c4416b917a52fe364172243a3a9fe6..74afe8c76bdd01a9a0351208ab05f54f4d43160a 100644 (file)
 #define __ARCH_USE_5LEVEL_HACK
 #include <asm-generic/pgtable-nopmd.h>
 
+#ifdef CONFIG_HIGHMEM
+#include <asm/highmem.h>
+#endif
+
 extern int temp_tlb_entry;
 
 /*
@@ -62,7 +66,8 @@ extern int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
 
 #define VMALLOC_START    MAP_BASE
 
-#define PKMAP_BASE             (0xfe000000UL)
+#define PKMAP_END      ((FIXADDR_START) & ~((LAST_PKMAP << PAGE_SHIFT)-1))
+#define PKMAP_BASE     (PKMAP_END - PAGE_SIZE * LAST_PKMAP)
 
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END   (PKMAP_BASE-2*PAGE_SIZE)
index b11facd11c9d05dfae733094359da713c948ad84..f702a459a830060f6aa77fe09eda28c03a3d4f4c 100644 (file)
@@ -804,8 +804,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
                        break;
                }
                /* Compact branch: BNEZC || JIALC */
-               if (insn.i_format.rs)
+               if (!insn.i_format.rs) {
+                       /* JIALC: set $31/ra */
                        regs->regs[31] = epc + 4;
+               }
                regs->cp0_epc += 8;
                break;
 #endif
index 8d83fc2a96b7196b47367fe8bfb6a39b0f67730e..38a302919e6b5ae8aa07303065bd561529fe828e 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/asm.h>
 #include <asm/asmmacro.h>
 #include <asm/compiler.h>
+#include <asm/irqflags.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
@@ -119,6 +120,7 @@ work_pending:
        andi    t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
        beqz    t0, work_notifysig
 work_resched:
+       TRACE_IRQS_OFF
        jal     schedule
 
        local_irq_disable               # make sure need_resched and
@@ -155,6 +157,7 @@ syscall_exit_work:
        beqz    t0, work_pending        # trace bit set?
        local_irq_enable                # could let syscall_trace_leave()
                                        # call schedule() instead
+       TRACE_IRQS_ON
        move    a0, sp
        jal     syscall_trace_leave
        b       resume_userspace
index 30a3b75e88eb6a3310808d8c743739efa3f98fb7..9d9b8fbae2022a426f0bcd9c7e134c4c33b67034 100644 (file)
@@ -38,20 +38,6 @@ void arch_ftrace_update_code(int command)
 
 #endif
 
-/*
- * Check if the address is in kernel space
- *
- * Clone core_kernel_text() from kernel/extable.c, but doesn't call
- * init_kernel_text() for Ftrace doesn't trace functions in init sections.
- */
-static inline int in_kernel_space(unsigned long ip)
-{
-       if (ip >= (unsigned long)_stext &&
-           ip <= (unsigned long)_etext)
-               return 1;
-       return 0;
-}
-
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 #define JAL 0x0c000000         /* jump & link: ip --> ra, jump to target */
@@ -198,7 +184,7 @@ int ftrace_make_nop(struct module *mod,
         * If ip is in kernel space, no long call, otherwise, long call is
         * needed.
         */
-       new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;
+       new = core_kernel_text(ip) ? INSN_NOP : INSN_B_1F;
 #ifdef CONFIG_64BIT
        return ftrace_modify_code(ip, new);
 #else
@@ -218,12 +204,12 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
        unsigned int new;
        unsigned long ip = rec->ip;
 
-       new = in_kernel_space(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
+       new = core_kernel_text(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
 
 #ifdef CONFIG_64BIT
        return ftrace_modify_code(ip, new);
 #else
-       return ftrace_modify_code_2r(ip, new, in_kernel_space(ip) ?
+       return ftrace_modify_code_2r(ip, new, core_kernel_text(ip) ?
                                                INSN_NOP : insn_la_mcount[1]);
 #endif
 }
@@ -289,7 +275,7 @@ unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long
         * instruction "lui v1, hi_16bit_of_mcount"(offset is 24), but for
         * kernel, move after the instruction "move ra, at"(offset is 16)
         */
-       ip = self_ra - (in_kernel_space(self_ra) ? 16 : 24);
+       ip = self_ra - (core_kernel_text(self_ra) ? 16 : 24);
 
        /*
         * search the text until finding the non-store instruction or "s{d,w}
@@ -394,7 +380,7 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
         * entries configured through the tracing/set_graph_function interface.
         */
 
-       insns = in_kernel_space(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
+       insns = core_kernel_text(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
        trace.func = self_ra - (MCOUNT_INSN_SIZE * insns);
 
        /* Only trace if the calling function expects to */
index cf052204eb0ae50460de00055994cc229694d854..d1bb506adc1044d6b72585ae5972fd200e224a89 100644 (file)
@@ -106,8 +106,8 @@ NESTED(kernel_entry, 16, sp)                        # kernel entry point
        beq             t0, t1, dtb_found
 #endif
        li              t1, -2
-       beq             a0, t1, dtb_found
        move            t2, a1
+       beq             a0, t1, dtb_found
 
        li              t2, 0
 dtb_found:
index 313a88b2973f673f0fac0998c36517fd2139504b..f3e301f95aef7edb160e122fa722d8cb6840a9a7 100644 (file)
@@ -1597,7 +1597,6 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
                break;
        case CPU_P5600:
        case CPU_P6600:
-       case CPU_I6400:
                /* 8-bit event numbers */
                raw_id = config & 0x1ff;
                base_id = raw_id & 0xff;
@@ -1610,6 +1609,11 @@ static const struct mips_perf_event *mipsxx_pmu_map_raw_event(u64 config)
                raw_event.range = P;
 #endif
                break;
+       case CPU_I6400:
+               /* 8-bit event numbers */
+               base_id = config & 0xff;
+               raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
+               break;
        case CPU_1004K:
                if (IS_BOTH_COUNTERS_1004K_EVENT(base_id))
                        raw_event.cntr_mask = CNTR_EVEN | CNTR_ODD;
index 5f928c34c1489c1b054b105a37296f72d863d6f7..d99416094ba964a356bfdf83946ac945f9d600d5 100644 (file)
@@ -56,7 +56,6 @@ DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT);
  * state. Actually per-core rather than per-CPU.
  */
 static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
-static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc);
 
 /* Indicates online CPUs coupled with the current CPU */
 static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
@@ -642,7 +641,6 @@ static int cps_pm_online_cpu(unsigned int cpu)
 {
        enum cps_pm_state state;
        unsigned core = cpu_data[cpu].core;
-       unsigned dlinesz = cpu_data[cpu].dcache.linesz;
        void *entry_fn, *core_rc;
 
        for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
@@ -662,16 +660,11 @@ static int cps_pm_online_cpu(unsigned int cpu)
        }
 
        if (!per_cpu(ready_count, core)) {
-               core_rc = kmalloc(dlinesz * 2, GFP_KERNEL);
+               core_rc = kmalloc(sizeof(u32), GFP_KERNEL);
                if (!core_rc) {
                        pr_err("Failed allocate core %u ready_count\n", core);
                        return -ENOMEM;
                }
-               per_cpu(ready_count_alloc, core) = core_rc;
-
-               /* Ensure ready_count is aligned to a cacheline boundary */
-               core_rc += dlinesz - 1;
-               core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1));
                per_cpu(ready_count, core) = core_rc;
        }
 
index 918d4c73e951d7815fc4063322c9ed8e493afb9f..5351e1f3950d158aaa5ff2590c32734862a79834 100644 (file)
@@ -120,7 +120,6 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
        struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs, *regs = current_pt_regs();
        unsigned long childksp;
-       p->set_child_tid = p->clear_child_tid = NULL;
 
        childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
 
index 9681b5877140112393f414356f110ea74a53a6a1..38dfa27730ff158768f69380c3fdcb75e4865488 100644 (file)
@@ -201,6 +201,8 @@ void show_stack(struct task_struct *task, unsigned long *sp)
 {
        struct pt_regs regs;
        mm_segment_t old_fs = get_fs();
+
+       regs.cp0_status = KSU_KERNEL;
        if (sp) {
                regs.regs[29] = (unsigned long)sp;
                regs.regs[31] = 0;
index 7c6336dd2638ce9c12c4ff8be566ff6acb856137..7cd92166a0b9a9bf3c14fe1df33442442ac668ac 100644 (file)
@@ -166,7 +166,11 @@ static int _kvm_mips_host_tlb_inv(unsigned long entryhi)
 int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va,
                          bool user, bool kernel)
 {
-       int idx_user, idx_kernel;
+       /*
+        * Initialize idx_user and idx_kernel to workaround bogus
+        * maybe-initialized warning when using GCC 6.
+        */
+       int idx_user = 0, idx_kernel = 0;
        unsigned long flags, old_entryhi;
 
        local_irq_save(flags);
index 4a2d03c72959cb5f1fb67da81e9f11b143086256..caa62f20a888d120dc22ec187aa5693470b9ec22 100644 (file)
@@ -54,7 +54,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
                return ieee754dp_nanxcpt(z);
        case IEEE754_CLASS_DNORM:
                DPDNORMZ;
-       /* QNAN is handled separately below */
+       /* QNAN and ZERO cases are handled separately below */
        }
 
        switch (CLPAIR(xc, yc)) {
@@ -210,6 +210,9 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
        }
        assert(rm & (DP_HIDDEN_BIT << 3));
 
+       if (zc == IEEE754_CLASS_ZERO)
+               return ieee754dp_format(rs, re, rm);
+
        /* And now the addition */
        assert(zm & DP_HIDDEN_BIT);
 
index a8cd8b4f235eb810db8c0472dea29c82dc2cd173..c91d5e5d9b5fa8293312e074350d10add7648a85 100644 (file)
@@ -54,7 +54,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
                return ieee754sp_nanxcpt(z);
        case IEEE754_CLASS_DNORM:
                SPDNORMZ;
-       /* QNAN is handled separately below */
+       /* QNAN and ZERO cases are handled separately below */
        }
 
        switch (CLPAIR(xc, yc)) {
@@ -203,6 +203,9 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
        }
        assert(rm & (SP_HIDDEN_BIT << 3));
 
+       if (zc == IEEE754_CLASS_ZERO)
+               return ieee754sp_format(rs, re, rm);
+
        /* And now the addition */
 
        assert(zm & SP_HIDDEN_BIT);
index fe8df14b616984a702416dcdb442e5a2c2f3761d..e08598c70b3e72d3c579462d9b82cbe340256ac9 100644 (file)
@@ -68,12 +68,25 @@ static inline struct page *dma_addr_to_page(struct device *dev,
  * systems and only the R10000 and R12000 are used in such systems, the
  * SGI IP28 Indigo² rsp. SGI IP32 aka O2.
  */
-static inline int cpu_needs_post_dma_flush(struct device *dev)
+static inline bool cpu_needs_post_dma_flush(struct device *dev)
 {
-       return !plat_device_is_coherent(dev) &&
-              (boot_cpu_type() == CPU_R10000 ||
-               boot_cpu_type() == CPU_R12000 ||
-               boot_cpu_type() == CPU_BMIPS5000);
+       if (plat_device_is_coherent(dev))
+               return false;
+
+       switch (boot_cpu_type()) {
+       case CPU_R10000:
+       case CPU_R12000:
+       case CPU_BMIPS5000:
+               return true;
+
+       default:
+               /*
+                * Presence of MAARs suggests that the CPU supports
+                * speculatively prefetching data, and therefore requires
+                * the post-DMA flush/invalidate.
+                */
+               return cpu_has_maar;
+       }
 }
 
 static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
index 64dd8bdd92c3390ba0c5df29e57e955293dbac9a..28adeabe851ff22dbea2da9d701208dadcc4925d 100644 (file)
@@ -93,7 +93,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
 
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index adc6911ba748915bda5b2575fc03b76891f1fb21..b19a3c506b1e9d203cbacb0da71513d8f21868b1 100644 (file)
@@ -51,15 +51,15 @@ void __init pagetable_init(void)
        /*
         * Fixed mappings:
         */
-       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       fixrange_init(vaddr, vaddr + FIXADDR_SIZE, pgd_base);
+       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
+       fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, pgd_base);
 
 #ifdef CONFIG_HIGHMEM
        /*
         * Permanent kmaps:
         */
        vaddr = PKMAP_BASE;
-       fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+       fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
 
        pgd = swapper_pg_dir + __pgd_offset(vaddr);
        pud = pud_offset(pgd, vaddr);
index 18e17abf7664e51c807e3d5649b0585bfd89a3be..3ae479117b42efd07d719282ee1dd287abecb1a4 100644 (file)
@@ -132,11 +132,6 @@ static inline void start_thread(struct pt_regs *regs,
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/*
- * Return saved PC of a blocked thread.
- */
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define task_pt_regs(task) ((task)->thread.uregs)
index c9fa42619c6a9aa4f5fa3244b3ce45efdfaeea11..89e8027e07fb327d39de0170c0da61af177c7160 100644 (file)
 #include <asm/gdb-stub.h>
 #include "internal.h"
 
-/*
- * return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       return ((unsigned long *) tsk->thread.sp)[3];
-}
-
 /*
  * power off function, if any
  */
index 3bbbc3d798e5f4738548690eb8511834050baa76..4944e2e1d8b0677d48c30ebba98629d43db90933 100644 (file)
@@ -75,9 +75,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-/* Return saved PC of a blocked thread. */
-#define thread_saved_pc(tsk)   ((tsk)->thread.kregs->ea)
-
 extern unsigned long get_wchan(struct task_struct *p);
 
 #define task_pt_regs(p) \
index a908e6c30a001e14860fe70f174f1451c6e4ae09..396d8f306c21b6c24f872780b9500cb8ebc1b963 100644 (file)
@@ -84,11 +84,6 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
 void release_thread(struct task_struct *);
 unsigned long get_wchan(struct task_struct *p);
 
-/*
- * Return saved PC of a blocked thread. For now, this is the "user" PC
- */
-extern unsigned long thread_saved_pc(struct task_struct *t);
-
 #define init_stack      (init_thread_union.stack)
 
 #define cpu_relax()     barrier()
index f8da545854f979c33a7b3116d26d822caa46c494..f9b77003f1138ce42dff841814cb280d562481e0 100644 (file)
@@ -110,11 +110,6 @@ void show_regs(struct pt_regs *regs)
        show_registers(regs);
 }
 
-unsigned long thread_saved_pc(struct task_struct *t)
-{
-       return (unsigned long)user_regs(t->stack)->pc;
-}
-
 void release_thread(struct task_struct *dead_task)
 {
 }
@@ -167,8 +162,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 
        top_of_kernel_stack = sp;
 
-       p->set_child_tid = p->clear_child_tid = NULL;
-
        /* Locate userspace context on stack... */
        sp -= STACK_FRAME_OVERHEAD;     /* redzone */
        sp -= sizeof(struct pt_regs);
index a3661ee6b060c1d258ab740e5468cfffb665f8d5..4c6694b4e77e0dd12ef6aed95508ea035ccdb10c 100644 (file)
@@ -163,12 +163,7 @@ struct thread_struct {
        .flags          = 0 \
        }
 
-/*
- * Return saved PC of a blocked thread.  This is used by ps mostly.
- */
-
 struct task_struct;
-unsigned long thread_saved_pc(struct task_struct *t);
 void show_trace(struct task_struct *task, unsigned long *stack);
 
 /*
index 4516a5b53f38ef651c038e4231effa00fd6db19d..b64d7d21646ed50c4a5c1f046b0f8ca758abfcc6 100644 (file)
@@ -239,11 +239,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-unsigned long thread_saved_pc(struct task_struct *t)
-{
-       return t->thread.regs.kpc;
-}
-
 unsigned long
 get_wchan(struct task_struct *p)
 {
index e5288638a1d9ad713c03fa4fc0d439efd012c470..378a754ca1867fb17d48625150a707dd95675b87 100644 (file)
@@ -90,7 +90,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                unsigned long len, unsigned long pgoff, unsigned long flags)
 {
        struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
+       struct vm_area_struct *vma, *prev;
        unsigned long task_size = TASK_SIZE;
        int do_color_align, last_mmap;
        struct vm_unmapped_area_info info;
@@ -117,9 +117,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                else
                        addr = PAGE_ALIGN(addr);
 
-               vma = find_vma(mm, addr);
+               vma = find_vma_prev(mm, addr, &prev);
                if (task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)) &&
+                   (!prev || addr >= vm_end_gap(prev)))
                        goto found_addr;
        }
 
@@ -143,7 +144,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                          const unsigned long len, const unsigned long pgoff,
                          const unsigned long flags)
 {
-       struct vm_area_struct *vma;
+       struct vm_area_struct *vma, *prev;
        struct mm_struct *mm = current->mm;
        unsigned long addr = addr0;
        int do_color_align, last_mmap;
@@ -177,9 +178,11 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                        addr = COLOR_ALIGN(addr, last_mmap, pgoff);
                else
                        addr = PAGE_ALIGN(addr);
-               vma = find_vma(mm, addr);
+
+               vma = find_vma_prev(mm, addr, &prev);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)) &&
+                   (!prev || addr >= vm_end_gap(prev)))
                        goto found_addr;
        }
 
index f7c8f9972f618109209e4892512ed903f6b865f3..bf4391d189233847a7cc82a5623fa5fd3bf30a31 100644 (file)
@@ -380,22 +380,6 @@ source "arch/powerpc/platforms/Kconfig"
 
 menu "Kernel options"
 
-config PPC_DT_CPU_FTRS
-       bool "Device-tree based CPU feature discovery & setup"
-       depends on PPC_BOOK3S_64
-       default n
-       help
-         This enables code to use a new device tree binding for describing CPU
-         compatibility and features. Saying Y here will attempt to use the new
-         binding if the firmware provides it. Currently only the skiboot
-         firmware provides this binding.
-         If you're not sure say Y.
-
-config PPC_CPUFEATURES_ENABLE_UNKNOWN
-       bool "cpufeatures pass through unknown features to guest/userspace"
-       depends on PPC_DT_CPU_FTRS
-       default y
-
 config HIGHMEM
        bool "High memory support"
        depends on PPC32
@@ -1215,11 +1199,6 @@ source "arch/powerpc/Kconfig.debug"
 
 source "security/Kconfig"
 
-config KEYS_COMPAT
-       bool
-       depends on COMPAT && KEYS
-       default y
-
 source "crypto/Kconfig"
 
 config PPC_LIB_RHEAP
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index b4b5e6b671ca4dedc27fc35d59b30d4ad488e1c3..0c4e470571ca0faa74d3e9fa38fa57a384cab4bf 100644 (file)
@@ -8,7 +8,7 @@
 #define H_PTE_INDEX_SIZE  9
 #define H_PMD_INDEX_SIZE  7
 #define H_PUD_INDEX_SIZE  9
-#define H_PGD_INDEX_SIZE  12
+#define H_PGD_INDEX_SIZE  9
 
 #ifndef __ASSEMBLY__
 #define H_PTE_TABLE_SIZE       (sizeof(pte_t) << H_PTE_INDEX_SIZE)
index f2c562a0a427dda2c774acb1e13c7eda8514e21e..0151af6c2a505a77c512110271e73f0c9c3fcd6e 100644 (file)
                "1:     "PPC_TLNEI"     %4,0\n"                 \
                _EMIT_BUG_ENTRY                                 \
                : : "i" (__FILE__), "i" (__LINE__),             \
-                 "i" (BUGFLAG_TAINT(TAINT_WARN)),              \
+                 "i" (BUGFLAG_WARNING|BUGFLAG_TAINT(TAINT_WARN)),\
                  "i" (sizeof(struct bug_entry)),               \
                  "r" (__ret_warn_on));                         \
        }                                                       \
index c2d509584a98070accd6be62519fa992e5bc1f3f..d02ad93bf70892f8d342b9d8890a4e1b8065eed6 100644 (file)
@@ -214,7 +214,6 @@ enum {
 #define CPU_FTR_DAWR                   LONG_ASM_CONST(0x0400000000000000)
 #define CPU_FTR_DABRX                  LONG_ASM_CONST(0x0800000000000000)
 #define CPU_FTR_PMAO_BUG               LONG_ASM_CONST(0x1000000000000000)
-#define CPU_FTR_SUBCORE                        LONG_ASM_CONST(0x2000000000000000)
 #define CPU_FTR_POWER9_DD1             LONG_ASM_CONST(0x4000000000000000)
 
 #ifndef __ASSEMBLY__
@@ -463,7 +462,7 @@ enum {
            CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
            CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
            CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
-           CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_SUBCORE)
+           CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP)
 #define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG)
 #define CPU_FTRS_POWER8_DD1 (CPU_FTRS_POWER8 & ~CPU_FTR_DBELL)
 #define CPU_FTRS_POWER9 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
index a83821f33ea36f8c005dab8e80dfdfcfd26a7058..8814a7249cebe29852dd8b4588a61052decac88c 100644 (file)
@@ -103,6 +103,7 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 extern int kprobe_handler(struct pt_regs *regs);
 extern int kprobe_post_handler(struct pt_regs *regs);
+extern int is_current_kprobe_addr(unsigned long addr);
 #ifdef CONFIG_KPROBES_ON_FTRACE
 extern int skip_singlestep(struct kprobe *p, struct pt_regs *regs,
                           struct kprobe_ctlblk *kcb);
index 53885512b8d31b12acec28dc3ba6688e57fb9615..6c0132c7212f8ea484805c9a9f72b682b79f6a39 100644 (file)
 #include <asm-generic/module.h>
 
 
+#ifdef CC_USING_MPROFILE_KERNEL
+#define MODULE_ARCH_VERMAGIC   "mprofile-kernel"
+#endif
+
 #ifndef __powerpc64__
 /*
  * Thanks to Paul M for explaining this.
index 2a32483c7b6cd5db8bab609891a5fbb3ad1f7844..8da5d4c1cab2b6d52a297117c6e6b27221d941c6 100644 (file)
@@ -132,7 +132,19 @@ extern long long virt_phys_offset;
 #define virt_to_pfn(kaddr)     (__pa(kaddr) >> PAGE_SHIFT)
 #define virt_to_page(kaddr)    pfn_to_page(virt_to_pfn(kaddr))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
+
+#ifdef CONFIG_PPC_BOOK3S_64
+/*
+ * On hash the vmalloc and other regions alias to the kernel region when passed
+ * through __pa(), which virt_to_pfn() uses. That means virt_addr_valid() can
+ * return true for some vmalloc addresses, which is incorrect. So explicitly
+ * check that the address is in the kernel region.
+ */
+#define virt_addr_valid(kaddr) (REGION_ID(kaddr) == KERNEL_REGION_ID && \
+                               pfn_valid(virt_to_pfn(kaddr)))
+#else
 #define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
+#endif
 
 /*
  * On Book-E parts we need __va to parse the device tree and we can't
index a2123f291ab0c5c8dc13cc9364c3a12848a4bb2c..1189d04f3bd1ce6db0f6ed5da3414f25dc3f4c38 100644 (file)
@@ -110,13 +110,18 @@ void release_thread(struct task_struct *);
 #define TASK_SIZE_128TB (0x0000800000000000UL)
 #define TASK_SIZE_512TB (0x0002000000000000UL)
 
-#ifdef CONFIG_PPC_BOOK3S_64
+/*
+ * For now 512TB is only supported with book3s and 64K linux page size.
+ */
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_64K_PAGES)
 /*
  * Max value currently used:
  */
-#define TASK_SIZE_USER64       TASK_SIZE_512TB
+#define TASK_SIZE_USER64               TASK_SIZE_512TB
+#define DEFAULT_MAP_WINDOW_USER64      TASK_SIZE_128TB
 #else
-#define TASK_SIZE_USER64       TASK_SIZE_64TB
+#define TASK_SIZE_USER64               TASK_SIZE_64TB
+#define DEFAULT_MAP_WINDOW_USER64      TASK_SIZE_64TB
 #endif
 
 /*
@@ -132,7 +137,7 @@ void release_thread(struct task_struct *);
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
-#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_128TB / 4))
+#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(DEFAULT_MAP_WINDOW_USER64 / 4))
 
 #define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \
                TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
@@ -143,21 +148,15 @@ void release_thread(struct task_struct *);
  * with 128TB and conditionally enable upto 512TB
  */
 #ifdef CONFIG_PPC_BOOK3S_64
-#define DEFAULT_MAP_WINDOW     ((is_32bit_task()) ? \
-                                TASK_SIZE_USER32 : TASK_SIZE_128TB)
+#define DEFAULT_MAP_WINDOW     ((is_32bit_task()) ?                    \
+                                TASK_SIZE_USER32 : DEFAULT_MAP_WINDOW_USER64)
 #else
 #define DEFAULT_MAP_WINDOW     TASK_SIZE
 #endif
 
 #ifdef __powerpc64__
 
-#ifdef CONFIG_PPC_BOOK3S_64
-/* Limit stack to 128TB */
-#define STACK_TOP_USER64 TASK_SIZE_128TB
-#else
-#define STACK_TOP_USER64 TASK_SIZE_USER64
-#endif
-
+#define STACK_TOP_USER64 DEFAULT_MAP_WINDOW_USER64
 #define STACK_TOP_USER32 TASK_SIZE_USER32
 
 #define STACK_TOP (is_32bit_task() ? \
@@ -379,12 +378,6 @@ struct thread_struct {
 }
 #endif
 
-/*
- * Return saved PC of a blocked thread. For now, this is the "user" PC
- */
-#define thread_saved_pc(tsk)    \
-        ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
-
 #define task_pt_regs(tsk)      ((struct pt_regs *)(tsk)->thread.regs)
 
 unsigned long get_wchan(struct task_struct *p);
index 8b3b46b7b0f2795b6195eb95ee649d3dece6dc9a..329771559cbbb16048d67d27450865703a248c90 100644 (file)
@@ -44,8 +44,22 @@ extern void __init dump_numa_cpu_topology(void);
 extern int sysfs_add_device_to_node(struct device *dev, int nid);
 extern void sysfs_remove_device_from_node(struct device *dev, int nid);
 
+static inline int early_cpu_to_node(int cpu)
+{
+       int nid;
+
+       nid = numa_cpu_lookup_table[cpu];
+
+       /*
+        * Fall back to node 0 if nid is unset (it should be, except bugs).
+        * This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)).
+        */
+       return (nid < 0) ? 0 : nid;
+}
 #else
 
+static inline int early_cpu_to_node(int cpu) { return 0; }
+
 static inline void dump_numa_cpu_topology(void) {}
 
 static inline int sysfs_add_device_to_node(struct device *dev, int nid)
index 5c0d8a8cdae5b588ac1254882c90787f81c40052..41e88d3ce36bfbbe0b4e2ffdc614194c3b797449 100644 (file)
@@ -267,13 +267,7 @@ do {                                                               \
 extern unsigned long __copy_tofrom_user(void __user *to,
                const void __user *from, unsigned long size);
 
-#ifndef __powerpc64__
-
-#define INLINE_COPY_FROM_USER
-#define INLINE_COPY_TO_USER
-
-#else /* __powerpc64__ */
-
+#ifdef __powerpc64__
 static inline unsigned long
 raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
 {
index c8a822acf962ab95d3ef36c37abe70cc82f1c76e..c23ff4389ca236c43994fe4279b7f151e80fe5e7 100644 (file)
@@ -94,11 +94,13 @@ struct xive_q {
  * store at 0 and some ESBs support doing a trigger via a
  * separate trigger page.
  */
-#define XIVE_ESB_GET           0x800
-#define XIVE_ESB_SET_PQ_00     0xc00
-#define XIVE_ESB_SET_PQ_01     0xd00
-#define XIVE_ESB_SET_PQ_10     0xe00
-#define XIVE_ESB_SET_PQ_11     0xf00
+#define XIVE_ESB_STORE_EOI     0x400 /* Store */
+#define XIVE_ESB_LOAD_EOI      0x000 /* Load */
+#define XIVE_ESB_GET           0x800 /* Load */
+#define XIVE_ESB_SET_PQ_00     0xc00 /* Load */
+#define XIVE_ESB_SET_PQ_01     0xd00 /* Load */
+#define XIVE_ESB_SET_PQ_10     0xe00 /* Load */
+#define XIVE_ESB_SET_PQ_11     0xf00 /* Load */
 
 #define XIVE_ESB_VAL_P         0x2
 #define XIVE_ESB_VAL_Q         0x1
index 3e7ce86d5c1330986289a72b0c38ea2686f6d6e6..4d877144f3773b3aa4dcefd9deeb12b13bcfe136 100644 (file)
@@ -46,6 +46,8 @@
 #define PPC_FEATURE2_HTM_NOSC          0x01000000
 #define PPC_FEATURE2_ARCH_3_00         0x00800000 /* ISA 3.00 */
 #define PPC_FEATURE2_HAS_IEEE128       0x00400000 /* VSX IEEE Binary Float 128-bit */
+#define PPC_FEATURE2_DARN              0x00200000 /* darn random number insn */
+#define PPC_FEATURE2_SCV               0x00100000 /* scv syscall */
 
 /*
  * IMPORTANT!
index 9b3e88b1a9c83b041d9bd84ce9d17fdc87aaeaf7..6f849832a66914f520d59c38a3c6c28f405de904 100644 (file)
@@ -124,7 +124,8 @@ extern void __restore_cpu_e6500(void);
 #define COMMON_USER_POWER9     COMMON_USER_POWER8
 #define COMMON_USER2_POWER9    (COMMON_USER2_POWER8 | \
                                 PPC_FEATURE2_ARCH_3_00 | \
-                                PPC_FEATURE2_HAS_IEEE128)
+                                PPC_FEATURE2_HAS_IEEE128 | \
+                                PPC_FEATURE2_DARN )
 
 #ifdef CONFIG_PPC_BOOK3E_64
 #define COMMON_USER_BOOKE      (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE)
index fcc7588a96d694265899935eae34521eda29690d..4c7656dc4e04f09bed8b9bbc8d8f979876237202 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/jump_label.h>
+#include <linux/libfdt.h>
 #include <linux/memblock.h>
 #include <linux/printk.h>
 #include <linux/sched.h>
@@ -642,7 +643,6 @@ static struct dt_cpu_feature_match __initdata
        {"processor-control-facility", feat_enable_dbell, CPU_FTR_DBELL},
        {"processor-control-facility-v3", feat_enable_dbell, CPU_FTR_DBELL},
        {"processor-utilization-of-resources-register", feat_enable_purr, 0},
-       {"subcore", feat_enable, CPU_FTR_SUBCORE},
        {"no-execute", feat_enable, 0},
        {"strong-access-ordering", feat_enable, CPU_FTR_SAO},
        {"cache-inhibited-large-page", feat_enable_large_ci, 0},
@@ -671,12 +671,24 @@ static struct dt_cpu_feature_match __initdata
        {"wait-v3", feat_enable, 0},
 };
 
-/* XXX: how to configure this? Default + boot time? */
-#ifdef CONFIG_PPC_CPUFEATURES_ENABLE_UNKNOWN
-#define CPU_FEATURE_ENABLE_UNKNOWN 1
-#else
-#define CPU_FEATURE_ENABLE_UNKNOWN 0
-#endif
+static bool __initdata using_dt_cpu_ftrs;
+static bool __initdata enable_unknown = true;
+
+static int __init dt_cpu_ftrs_parse(char *str)
+{
+       if (!str)
+               return 0;
+
+       if (!strcmp(str, "off"))
+               using_dt_cpu_ftrs = false;
+       else if (!strcmp(str, "known"))
+               enable_unknown = false;
+       else
+               return 1;
+
+       return 0;
+}
+early_param("dt_cpu_ftrs", dt_cpu_ftrs_parse);
 
 static void __init cpufeatures_setup_start(u32 isa)
 {
@@ -707,7 +719,7 @@ static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
                }
        }
 
-       if (!known && CPU_FEATURE_ENABLE_UNKNOWN) {
+       if (!known && enable_unknown) {
                if (!feat_try_enable_unknown(f)) {
                        pr_info("not enabling: %s (unknown and unsupported by kernel)\n",
                                f->name);
@@ -756,6 +768,26 @@ static void __init cpufeatures_setup_finished(void)
                cur_cpu_spec->cpu_features, cur_cpu_spec->mmu_features);
 }
 
+static int __init disabled_on_cmdline(void)
+{
+       unsigned long root, chosen;
+       const char *p;
+
+       root = of_get_flat_dt_root();
+       chosen = of_get_flat_dt_subnode_by_name(root, "chosen");
+       if (chosen == -FDT_ERR_NOTFOUND)
+               return false;
+
+       p = of_get_flat_dt_prop(chosen, "bootargs", NULL);
+       if (!p)
+               return false;
+
+       if (strstr(p, "dt_cpu_ftrs=off"))
+               return true;
+
+       return false;
+}
+
 static int __init fdt_find_cpu_features(unsigned long node, const char *uname,
                                        int depth, void *data)
 {
@@ -766,8 +798,6 @@ static int __init fdt_find_cpu_features(unsigned long node, const char *uname,
        return 0;
 }
 
-static bool __initdata using_dt_cpu_ftrs = false;
-
 bool __init dt_cpu_ftrs_in_use(void)
 {
        return using_dt_cpu_ftrs;
@@ -775,6 +805,8 @@ bool __init dt_cpu_ftrs_in_use(void)
 
 bool __init dt_cpu_ftrs_init(void *fdt)
 {
+       using_dt_cpu_ftrs = false;
+
        /* Setup and verify the FDT, if it fails we just bail */
        if (!early_init_dt_verify(fdt))
                return false;
@@ -782,6 +814,9 @@ bool __init dt_cpu_ftrs_init(void *fdt)
        if (!of_scan_flat_dt(fdt_find_cpu_features, NULL))
                return false;
 
+       if (disabled_on_cmdline())
+               return false;
+
        cpufeatures_setup_cpu();
 
        using_dt_cpu_ftrs = true;
@@ -1027,5 +1062,8 @@ static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
 
 void __init dt_cpu_ftrs_scan(void)
 {
+       if (!using_dt_cpu_ftrs)
+               return;
+
        of_scan_flat_dt(dt_cpu_ftrs_scan_callback, NULL);
 }
index ae418b85c17c4bce805227a82350d322259cf06e..b886795060fd2dba727c54d8c7b5e2b47a888f8d 100644 (file)
@@ -1411,10 +1411,8 @@ USE_TEXT_SECTION()
        .balign IFETCH_ALIGN_BYTES
 do_hash_page:
 #ifdef CONFIG_PPC_STD_MMU_64
-       andis.  r0,r4,0xa410            /* weird error? */
+       andis.  r0,r4,0xa450            /* weird error? */
        bne-    handle_page_fault       /* if not, try to insert a HPTE */
-       andis.  r0,r4,DSISR_DABRMATCH@h
-       bne-    handle_dabr_fault
        CURRENT_THREAD_INFO(r11, r1)
        lwz     r0,TI_PREEMPT(r11)      /* If we're in an "NMI" */
        andis.  r0,r0,NMI_MASK@h        /* (i.e. an irq when soft-disabled) */
@@ -1438,11 +1436,16 @@ do_hash_page:
 
        /* Error */
        blt-    13f
+
+       /* Reload DSISR into r4 for the DABR check below */
+       ld      r4,_DSISR(r1)
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
 /* Here we have a page fault that hash_page can't handle. */
 handle_page_fault:
-11:    ld      r4,_DAR(r1)
+11:    andis.  r0,r4,DSISR_DABRMATCH@h
+       bne-    handle_dabr_fault
+       ld      r4,_DAR(r1)
        ld      r5,_DSISR(r1)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      do_page_fault
index 07d4e0ad60db5b1a1f2cd5da08763a3acea7ea3b..4898d676dcaef1d02600c5c75ef13ceca1fc8c69 100644 (file)
@@ -416,7 +416,7 @@ power9_dd1_recover_paca:
         * which needs to be restored from the stack.
         */
        li      r3, 1
-       stb     r0,PACA_NAPSTATELOST(r13)
+       stb     r3,PACA_NAPSTATELOST(r13)
        blr
 
 /*
index 160ae0fa7d0d15152011b111134784107287e7bb..01addfb0ed0a42216d64c7692c3fea4694c528fb 100644 (file)
@@ -43,6 +43,12 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
 
+int is_current_kprobe_addr(unsigned long addr)
+{
+       struct kprobe *p = kprobe_running();
+       return (p && (unsigned long)p->addr == addr) ? 1 : 0;
+}
+
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
        return  (addr >= (unsigned long)__kprobes_text_start &&
@@ -305,16 +311,17 @@ int kprobe_handler(struct pt_regs *regs)
                        save_previous_kprobe(kcb);
                        set_current_kprobe(p, regs, kcb);
                        kprobes_inc_nmissed_count(p);
-                       prepare_singlestep(p, regs);
                        kcb->kprobe_status = KPROBE_REENTER;
                        if (p->ainsn.boostable >= 0) {
                                ret = try_to_emulate(p, regs);
 
                                if (ret > 0) {
                                        restore_previous_kprobe(kcb);
+                                       preempt_enable_no_resched();
                                        return 1;
                                }
                        }
+                       prepare_singlestep(p, regs);
                        return 1;
                } else {
                        if (*addr != BREAKPOINT_INSTRUCTION) {
@@ -616,6 +623,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc);
 #endif
 
+       /*
+        * jprobes use jprobe_return() which skips the normal return
+        * path of the function, and this messes up the accounting of the
+        * function graph tracer.
+        *
+        * Pause function graph tracing while performing the jprobe function.
+        */
+       pause_graph_tracing();
+
        return 1;
 }
 NOKPROBE_SYMBOL(setjmp_pre_handler);
@@ -641,6 +657,8 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
         * saved regs...
         */
        memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
+       /* It's OK to start function graph tracing again */
+       unpause_graph_tracing();
        preempt_enable_no_resched();
        return 1;
 }
index d645da302bf22f46c046bcb3912bbdd51186c416..2ad725ef4368a3e525681b0ce4a56ef8e960bf48 100644 (file)
@@ -864,6 +864,25 @@ static void tm_reclaim_thread(struct thread_struct *thr,
        if (!MSR_TM_SUSPENDED(mfmsr()))
                return;
 
+       /*
+        * If we are in a transaction and FP is off then we can't have
+        * used FP inside that transaction. Hence the checkpointed
+        * state is the same as the live state. We need to copy the
+        * live state to the checkpointed state so that when the
+        * transaction is restored, the checkpointed state is correct
+        * and the aborted transaction sees the correct state. We use
+        * ckpt_regs.msr here as that's what tm_reclaim will use to
+        * determine if it's going to write the checkpointed state or
+        * not. So either this will write the checkpointed registers,
+        * or reclaim will. Similarly for VMX.
+        */
+       if ((thr->ckpt_regs.msr & MSR_FP) == 0)
+               memcpy(&thr->ckfp_state, &thr->fp_state,
+                      sizeof(struct thread_fp_state));
+       if ((thr->ckpt_regs.msr & MSR_VEC) == 0)
+               memcpy(&thr->ckvr_state, &thr->vr_state,
+                      sizeof(struct thread_vr_state));
+
        giveup_all(container_of(thr, struct task_struct, thread));
 
        tm_reclaim(thr, thr->ckpt_regs.msr, cause);
@@ -1647,6 +1666,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
 #ifdef CONFIG_VSX
        current->thread.used_vsr = 0;
 #endif
+       current->thread.load_fp = 0;
        memset(&current->thread.fp_state, 0, sizeof(current->thread.fp_state));
        current->thread.fp_save_area = NULL;
 #ifdef CONFIG_ALTIVEC
@@ -1655,6 +1675,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
        current->thread.vr_save_area = NULL;
        current->thread.vrsave = 0;
        current->thread.used_vr = 0;
+       current->thread.load_vec = 0;
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_SPE
        memset(current->thread.evr, 0, sizeof(current->thread.evr));
@@ -1666,6 +1687,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
        current->thread.tm_tfhar = 0;
        current->thread.tm_texasr = 0;
        current->thread.tm_tfiar = 0;
+       current->thread.load_tm = 0;
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 }
 EXPORT_SYMBOL(start_thread);
index 40c4887c27b613d73bc420b4aca34cee406325a8..f830562974417bfd0f338766b59a6ffd7a09a176 100644 (file)
@@ -161,7 +161,9 @@ static struct ibm_pa_feature {
        { .pabyte = 0,  .pabit = 3, .cpu_features  = CPU_FTR_CTRL },
        { .pabyte = 0,  .pabit = 6, .cpu_features  = CPU_FTR_NOEXECUTE },
        { .pabyte = 1,  .pabit = 2, .mmu_features  = MMU_FTR_CI_LARGE_PAGE },
+#ifdef CONFIG_PPC_RADIX_MMU
        { .pabyte = 40, .pabit = 0, .mmu_features  = MMU_FTR_TYPE_RADIX },
+#endif
        { .pabyte = 1,  .pabit = 1, .invert = 1, .cpu_features = CPU_FTR_NODSISRALIGN },
        { .pabyte = 5,  .pabit = 0, .cpu_features  = CPU_FTR_REAL_LE,
                                    .cpu_user_ftrs = PPC_FEATURE_TRUE_LE },
index 71dcda91755d51a2e5705f29308239e7e9c7e506..857129acf960a1bf93c0c5791a6de1d84585caa3 100644 (file)
@@ -928,7 +928,7 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_PPC_MM_SLICES
 #ifdef CONFIG_PPC64
-       init_mm.context.addr_limit = TASK_SIZE_128TB;
+       init_mm.context.addr_limit = DEFAULT_MAP_WINDOW_USER64;
 #else
 #error "context.addr_limit not initialized."
 #endif
index f35ff9dea4fb4607459c10d42a29c47f2984e613..4640f6d64f8b406a636d60c4ea2263658dde5be6 100644 (file)
@@ -615,6 +615,24 @@ void __init exc_lvl_early_init(void)
 }
 #endif
 
+/*
+ * Emergency stacks are used for a range of things, from asynchronous
+ * NMIs (system reset, machine check) to synchronous, process context.
+ * We set preempt_count to zero, even though that isn't necessarily correct. To
+ * get the right value we'd need to copy it from the previous thread_info, but
+ * doing that might fault causing more problems.
+ * TODO: what to do with accounting?
+ */
+static void emerg_stack_init_thread_info(struct thread_info *ti, int cpu)
+{
+       ti->task = NULL;
+       ti->cpu = cpu;
+       ti->preempt_count = 0;
+       ti->local_flags = 0;
+       ti->flags = 0;
+       klp_init_thread_info(ti);
+}
+
 /*
  * Stack space used when we detect a bad kernel stack pointer, and
  * early in SMP boots before relocation is enabled. Exclusive emergency
@@ -633,24 +651,31 @@ void __init emergency_stack_init(void)
         * Since we use these as temporary stacks during secondary CPU
         * bringup, we need to get at them in real mode. This means they
         * must also be within the RMO region.
+        *
+        * The IRQ stacks allocated elsewhere in this file are zeroed and
+        * initialized in kernel/irq.c. These are initialized here in order
+        * to have emergency stacks available as early as possible.
         */
        limit = min(safe_stack_limit(), ppc64_rma_size);
 
        for_each_possible_cpu(i) {
                struct thread_info *ti;
                ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
-               klp_init_thread_info(ti);
+               memset(ti, 0, THREAD_SIZE);
+               emerg_stack_init_thread_info(ti, i);
                paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
 
 #ifdef CONFIG_PPC_BOOK3S_64
                /* emergency stack for NMI exception handling. */
                ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
-               klp_init_thread_info(ti);
+               memset(ti, 0, THREAD_SIZE);
+               emerg_stack_init_thread_info(ti, i);
                paca[i].nmi_emergency_sp = (void *)ti + THREAD_SIZE;
 
                /* emergency stack for machine check exception handling. */
                ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
-               klp_init_thread_info(ti);
+               memset(ti, 0, THREAD_SIZE);
+               emerg_stack_init_thread_info(ti, i);
                paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
 #endif
        }
@@ -661,7 +686,7 @@ void __init emergency_stack_init(void)
 
 static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
 {
-       return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align,
+       return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align,
                                    __pa(MAX_DMA_ADDRESS));
 }
 
@@ -672,7 +697,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size)
 
 static int pcpu_cpu_distance(unsigned int from, unsigned int to)
 {
-       if (cpu_to_node(from) == cpu_to_node(to))
+       if (early_cpu_to_node(from) == early_cpu_to_node(to))
                return LOCAL_DISTANCE;
        else
                return REMOTE_DISTANCE;
index 7c933a99f5d578bdfd1408b16d4e7fe33e95e4a9..c98e90b4ea7b1f15a2dd7157300376e370774cf2 100644 (file)
@@ -45,10 +45,14 @@ _GLOBAL(ftrace_caller)
        stdu    r1,-SWITCH_FRAME_SIZE(r1)
 
        /* Save all gprs to pt_regs */
-       SAVE_8GPRS(0,r1)
-       SAVE_8GPRS(8,r1)
-       SAVE_8GPRS(16,r1)
-       SAVE_8GPRS(24,r1)
+       SAVE_GPR(0, r1)
+       SAVE_10GPRS(2, r1)
+       SAVE_10GPRS(12, r1)
+       SAVE_10GPRS(22, r1)
+
+       /* Save previous stack pointer (r1) */
+       addi    r8, r1, SWITCH_FRAME_SIZE
+       std     r8, GPR1(r1)
 
        /* Load special regs for save below */
        mfmsr   r8
@@ -95,18 +99,44 @@ ftrace_call:
        bl      ftrace_stub
        nop
 
-       /* Load ctr with the possibly modified NIP */
-       ld      r3, _NIP(r1)
-       mtctr   r3
+       /* Load the possibly modified NIP */
+       ld      r15, _NIP(r1)
+
 #ifdef CONFIG_LIVEPATCH
-       cmpd    r14,r3          /* has NIP been altered? */
+       cmpd    r14, r15        /* has NIP been altered? */
+#endif
+
+#if defined(CONFIG_LIVEPATCH) && defined(CONFIG_KPROBES_ON_FTRACE)
+       /* NIP has not been altered, skip over further checks */
+       beq     1f
+
+       /* Check if there is an active kprobe on us */
+       subi    r3, r14, 4
+       bl      is_current_kprobe_addr
+       nop
+
+       /*
+        * If r3 == 1, then this is a kprobe/jprobe.
+        * else, this is livepatched function.
+        *
+        * The conditional branch for livepatch_handler below will use the
+        * result of this comparison. For kprobe/jprobe, we just need to branch to
+        * the new NIP, not call livepatch_handler. The branch below is bne, so we
+        * want CR0[EQ] to be true if this is a kprobe/jprobe. Which means we want
+        * CR0[EQ] = (r3 == 1).
+        */
+       cmpdi   r3, 1
+1:
 #endif
 
+       /* Load CTR with the possibly modified NIP */
+       mtctr   r15
+
        /* Restore gprs */
-       REST_8GPRS(0,r1)
-       REST_8GPRS(8,r1)
-       REST_8GPRS(16,r1)
-       REST_8GPRS(24,r1)
+       REST_GPR(0,r1)
+       REST_10GPRS(2,r1)
+       REST_10GPRS(12,r1)
+       REST_10GPRS(22,r1)
 
        /* Restore possibly modified LR */
        ld      r0, _LINK(r1)
@@ -119,7 +149,10 @@ ftrace_call:
        addi r1, r1, SWITCH_FRAME_SIZE
 
 #ifdef CONFIG_LIVEPATCH
-        /* Based on the cmpd above, if the NIP was altered handle livepatch */
+        /*
+        * Based on the cmpd or cmpdi above, if the NIP was altered and we're
+        * not on a kprobe/jprobe, then handle livepatch.
+        */
        bne-    livepatch_handler
 #endif
 
index 24de532c17369c1d8fb9498c50447cc6c6b21528..0c52cb5d43f52bdba5008ccade5edfd2b4fee5f4 100644 (file)
@@ -67,7 +67,7 @@ config KVM_BOOK3S_64
        select KVM_BOOK3S_64_HANDLER
        select KVM
        select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE
-       select SPAPR_TCE_IOMMU if IOMMU_SUPPORT
+       select SPAPR_TCE_IOMMU if IOMMU_SUPPORT && (PPC_SERIES || PPC_POWERNV)
        ---help---
          Support running unmodified book3s_64 and book3s_32 guest kernels
          in virtual machines on book3s_64 host processors.
index d91a2604c49637c009f6a8ef42b69821dcbc445d..381a6ec0ff3b72ab085834fc14a35e853b237fc6 100644 (file)
@@ -46,7 +46,7 @@ kvm-e500mc-objs := \
        e500_emulate.o
 kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)
 
-kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \
+kvm-book3s_64-builtin-objs-$(CONFIG_SPAPR_TCE_IOMMU) := \
        book3s_64_vio_hv.o
 
 kvm-pr-y := \
@@ -90,11 +90,11 @@ kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
        book3s_xics.o
 
 kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o
+kvm-book3s_64-objs-$(CONFIG_SPAPR_TCE_IOMMU) += book3s_64_vio.o
 
 kvm-book3s_64-module-objs := \
        $(common-objs-y) \
        book3s.o \
-       book3s_64_vio.o \
        book3s_rtas.o \
        $(kvm-book3s_64-objs-y)
 
index eda0a8f6fae8eba29b5b04c28fe49e7f9d605d45..3adfd2f5301c686762007e496717d453c258d37c 100644 (file)
@@ -301,6 +301,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
        /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
        /*          liobn, ioba, tce); */
 
+       /* For radix, we might be in virtual mode, so punt */
+       if (kvm_is_radix(vcpu->kvm))
+               return H_TOO_HARD;
+
        stt = kvmppc_find_table(vcpu->kvm, liobn);
        if (!stt)
                return H_TOO_HARD;
@@ -381,6 +385,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
        bool prereg = false;
        struct kvmppc_spapr_tce_iommu_table *stit;
 
+       /* For radix, we might be in virtual mode, so punt */
+       if (kvm_is_radix(vcpu->kvm))
+               return H_TOO_HARD;
+
        stt = kvmppc_find_table(vcpu->kvm, liobn);
        if (!stt)
                return H_TOO_HARD;
@@ -491,6 +499,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
        long i, ret;
        struct kvmppc_spapr_tce_iommu_table *stit;
 
+       /* For radix, we might be in virtual mode, so punt */
+       if (kvm_is_radix(vcpu->kvm))
+               return H_TOO_HARD;
+
        stt = kvmppc_find_table(vcpu->kvm, liobn);
        if (!stt)
                return H_TOO_HARD;
@@ -527,6 +539,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
        return H_SUCCESS;
 }
 
+/* This can be called in either virtual mode or real mode */
 long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                      unsigned long ioba)
 {
index 42b7a4fd57d9a557f8278a9f9a8c228f2758a1e8..8d1a365b8edc45fa9f655b77789a0d8602b462fd 100644 (file)
@@ -1486,6 +1486,14 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
                r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len);
                break;
        case KVM_REG_PPC_TB_OFFSET:
+               /*
+                * POWER9 DD1 has an erratum where writing TBU40 causes
+                * the timebase to lose ticks.  So we don't let the
+                * timebase offset be changed on P9 DD1.  (It is
+                * initialized to zero.)
+                */
+               if (cpu_has_feature(CPU_FTR_POWER9_DD1))
+                       break;
                /* round up to multiple of 2^24 */
                vcpu->arch.vcore->tb_offset =
                        ALIGN(set_reg_val(id, *val), 1UL << 24);
@@ -2907,12 +2915,36 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
 {
        int r;
        int srcu_idx;
+       unsigned long ebb_regs[3] = {}; /* shut up GCC */
+       unsigned long user_tar = 0;
+       unsigned int user_vrsave;
 
        if (!vcpu->arch.sane) {
                run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                return -EINVAL;
        }
 
+       /*
+        * Don't allow entry with a suspended transaction, because
+        * the guest entry/exit code will lose it.
+        * If the guest has TM enabled, save away their TM-related SPRs
+        * (they will get restored by the TM unavailable interrupt).
+        */
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs &&
+           (current->thread.regs->msr & MSR_TM)) {
+               if (MSR_TM_ACTIVE(current->thread.regs->msr)) {
+                       run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+                       run->fail_entry.hardware_entry_failure_reason = 0;
+                       return -EINVAL;
+               }
+               current->thread.tm_tfhar = mfspr(SPRN_TFHAR);
+               current->thread.tm_tfiar = mfspr(SPRN_TFIAR);
+               current->thread.tm_texasr = mfspr(SPRN_TEXASR);
+               current->thread.regs->msr &= ~MSR_TM;
+       }
+#endif
+
        kvmppc_core_prepare_to_enter(vcpu);
 
        /* No need to go into the guest when all we'll do is come back out */
@@ -2934,6 +2966,15 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
 
        flush_all_to_thread(current);
 
+       /* Save userspace EBB and other register values */
+       if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+               ebb_regs[0] = mfspr(SPRN_EBBHR);
+               ebb_regs[1] = mfspr(SPRN_EBBRR);
+               ebb_regs[2] = mfspr(SPRN_BESCR);
+               user_tar = mfspr(SPRN_TAR);
+       }
+       user_vrsave = mfspr(SPRN_VRSAVE);
+
        vcpu->arch.wqp = &vcpu->arch.vcore->wq;
        vcpu->arch.pgdir = current->mm->pgd;
        vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
@@ -2960,6 +3001,16 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
                }
        } while (is_kvmppc_resume_guest(r));
 
+       /* Restore userspace EBB and other register values */
+       if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+               mtspr(SPRN_EBBHR, ebb_regs[0]);
+               mtspr(SPRN_EBBRR, ebb_regs[1]);
+               mtspr(SPRN_BESCR, ebb_regs[2]);
+               mtspr(SPRN_TAR, user_tar);
+               mtspr(SPRN_FSCR, current->thread.fscr);
+       }
+       mtspr(SPRN_VRSAVE, user_vrsave);
+
  out:
        vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
        atomic_dec(&vcpu->kvm->arch.vcpus_running);
index 88a65923c6495750db570890954f65416e359d25..ee4c2558c3058717da1f6299fd6a0e0aebc75360 100644 (file)
@@ -207,7 +207,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
 
 long kvmppc_h_random(struct kvm_vcpu *vcpu)
 {
-       if (powernv_get_random_real_mode(&vcpu->arch.gpr[4]))
+       int r;
+
+       /* Only need to do the expensive mfmsr() on radix */
+       if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
+               r = powernv_get_random_long(&vcpu->arch.gpr[4]);
+       else
+               r = powernv_get_random_real_mode(&vcpu->arch.gpr[4]);
+       if (r)
                return H_SUCCESS;
 
        return H_HARDWARE;
index 0fdc4a28970b3c53d821088dae8eec5e2282dca4..404deb512844424d07bba8ead5bd77e70aee82af 100644 (file)
@@ -121,10 +121,20 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
         * Put whatever is in the decrementer into the
         * hypervisor decrementer.
         */
+BEGIN_FTR_SECTION
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       ld      r6, VCORE_KVM(r5)
+       ld      r9, KVM_HOST_LPCR(r6)
+       andis.  r9, r9, LPCR_LD@h
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        mfspr   r8,SPRN_DEC
        mftb    r7
-       mtspr   SPRN_HDEC,r8
+BEGIN_FTR_SECTION
+       /* On POWER9, don't sign-extend if host LPCR[LD] bit is set */
+       bne     32f
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        extsw   r8,r8
+32:    mtspr   SPRN_HDEC,r8
        add     r8,r8,r7
        std     r8,HSTATE_DECEXP(r13)
 
index bdb3f76ceb6b9ff0e25e5b3b56c3be48dd6f65cc..4888dd494604f101a194a51ff168c44d85c4354d 100644 (file)
 #include <asm/opal.h>
 #include <asm/xive-regs.h>
 
+/* Sign-extend HDEC if not on POWER9 */
+#define EXTEND_HDEC(reg)                       \
+BEGIN_FTR_SECTION;                             \
+       extsw   reg, reg;                       \
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
+
 #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
 
 /* Values in HSTATE_NAPPING(r13) */
 #define NAPPING_CEDE   1
 #define NAPPING_NOVCPU 2
 
+/* Stack frame offsets for kvmppc_hv_entry */
+#define SFS                    144
+#define STACK_SLOT_TRAP                (SFS-4)
+#define STACK_SLOT_TID         (SFS-16)
+#define STACK_SLOT_PSSCR       (SFS-24)
+#define STACK_SLOT_PID         (SFS-32)
+#define STACK_SLOT_IAMR                (SFS-40)
+#define STACK_SLOT_CIABR       (SFS-48)
+#define STACK_SLOT_DAWR                (SFS-56)
+#define STACK_SLOT_DAWRX       (SFS-64)
+
 /*
  * Call kvmppc_hv_entry in real mode.
  * Must be called with interrupts hard-disabled.
@@ -214,6 +231,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 kvmppc_primary_no_guest:
        /* We handle this much like a ceded vcpu */
        /* put the HDEC into the DEC, since HDEC interrupts don't wake us */
+       /* HDEC may be larger than DEC for arch >= v3.00, but since the */
+       /* HDEC value came from DEC in the first place, it will fit */
        mfspr   r3, SPRN_HDEC
        mtspr   SPRN_DEC, r3
        /*
@@ -295,8 +314,9 @@ kvm_novcpu_wakeup:
 
        /* See if our timeslice has expired (HDEC is negative) */
        mfspr   r0, SPRN_HDEC
+       EXTEND_HDEC(r0)
        li      r12, BOOK3S_INTERRUPT_HV_DECREMENTER
-       cmpwi   r0, 0
+       cmpdi   r0, 0
        blt     kvm_novcpu_exit
 
        /* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */
@@ -319,10 +339,10 @@ kvm_novcpu_exit:
        bl      kvmhv_accumulate_time
 #endif
 13:    mr      r3, r12
-       stw     r12, 112-4(r1)
+       stw     r12, STACK_SLOT_TRAP(r1)
        bl      kvmhv_commence_exit
        nop
-       lwz     r12, 112-4(r1)
+       lwz     r12, STACK_SLOT_TRAP(r1)
        b       kvmhv_switch_to_host
 
 /*
@@ -390,8 +410,8 @@ kvm_secondary_got_guest:
        lbz     r4, HSTATE_PTID(r13)
        cmpwi   r4, 0
        bne     63f
-       lis     r6, 0x7fff
-       ori     r6, r6, 0xffff
+       LOAD_REG_ADDR(r6, decrementer_max)
+       ld      r6, 0(r6)
        mtspr   SPRN_HDEC, r6
        /* and set per-LPAR registers, if doing dynamic micro-threading */
        ld      r6, HSTATE_SPLIT_MODE(r13)
@@ -545,11 +565,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
  *                                                                            *
  *****************************************************************************/
 
-/* Stack frame offsets */
-#define STACK_SLOT_TID         (112-16)
-#define STACK_SLOT_PSSCR       (112-24)
-#define STACK_SLOT_PID         (112-32)
-
 .global kvmppc_hv_entry
 kvmppc_hv_entry:
 
@@ -565,7 +580,7 @@ kvmppc_hv_entry:
         */
        mflr    r0
        std     r0, PPC_LR_STKOFF(r1)
-       stdu    r1, -112(r1)
+       stdu    r1, -SFS(r1)
 
        /* Save R1 in the PACA */
        std     r1, HSTATE_HOST_R1(r13)
@@ -749,10 +764,20 @@ BEGIN_FTR_SECTION
        mfspr   r5, SPRN_TIDR
        mfspr   r6, SPRN_PSSCR
        mfspr   r7, SPRN_PID
+       mfspr   r8, SPRN_IAMR
        std     r5, STACK_SLOT_TID(r1)
        std     r6, STACK_SLOT_PSSCR(r1)
        std     r7, STACK_SLOT_PID(r1)
+       std     r8, STACK_SLOT_IAMR(r1)
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+BEGIN_FTR_SECTION
+       mfspr   r5, SPRN_CIABR
+       mfspr   r6, SPRN_DAWR
+       mfspr   r7, SPRN_DAWRX
+       std     r5, STACK_SLOT_CIABR(r1)
+       std     r6, STACK_SLOT_DAWR(r1)
+       std     r7, STACK_SLOT_DAWRX(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 
 BEGIN_FTR_SECTION
        /* Set partition DABR */
@@ -968,7 +993,8 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 
        /* Check if HDEC expires soon */
        mfspr   r3, SPRN_HDEC
-       cmpwi   r3, 512         /* 1 microsecond */
+       EXTEND_HDEC(r3)
+       cmpdi   r3, 512         /* 1 microsecond */
        blt     hdec_soon
 
 #ifdef CONFIG_KVM_XICS
@@ -1505,11 +1531,10 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
         * set by the guest could disrupt the host.
         */
        li      r0, 0
-       mtspr   SPRN_IAMR, r0
-       mtspr   SPRN_CIABR, r0
-       mtspr   SPRN_DAWRX, r0
+       mtspr   SPRN_PSPB, r0
        mtspr   SPRN_WORT, r0
 BEGIN_FTR_SECTION
+       mtspr   SPRN_IAMR, r0
        mtspr   SPRN_TCSCR, r0
        /* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
        li      r0, 1
@@ -1525,6 +1550,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
        std     r6,VCPU_UAMOR(r9)
        li      r6,0
        mtspr   SPRN_AMR,r6
+       mtspr   SPRN_UAMOR, r6
 
        /* Switch DSCR back to host value */
        mfspr   r8, SPRN_DSCR
@@ -1669,13 +1695,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        ptesync
 
        /* Restore host values of some registers */
+BEGIN_FTR_SECTION
+       ld      r5, STACK_SLOT_CIABR(r1)
+       ld      r6, STACK_SLOT_DAWR(r1)
+       ld      r7, STACK_SLOT_DAWRX(r1)
+       mtspr   SPRN_CIABR, r5
+       mtspr   SPRN_DAWR, r6
+       mtspr   SPRN_DAWRX, r7
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 BEGIN_FTR_SECTION
        ld      r5, STACK_SLOT_TID(r1)
        ld      r6, STACK_SLOT_PSSCR(r1)
        ld      r7, STACK_SLOT_PID(r1)
+       ld      r8, STACK_SLOT_IAMR(r1)
        mtspr   SPRN_TIDR, r5
        mtspr   SPRN_PSSCR, r6
        mtspr   SPRN_PID, r7
+       mtspr   SPRN_IAMR, r8
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 BEGIN_FTR_SECTION
        PPC_INVALIDATE_ERAT
@@ -1819,8 +1855,8 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
        li      r0, KVM_GUEST_MODE_NONE
        stb     r0, HSTATE_IN_GUEST(r13)
 
-       ld      r0, 112+PPC_LR_STKOFF(r1)
-       addi    r1, r1, 112
+       ld      r0, SFS+PPC_LR_STKOFF(r1)
+       addi    r1, r1, SFS
        mtlr    r0
        blr
 
@@ -2366,12 +2402,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
        mfspr   r3, SPRN_DEC
        mfspr   r4, SPRN_HDEC
        mftb    r5
-       cmpw    r3, r4
+       extsw   r3, r3
+       EXTEND_HDEC(r4)
+       cmpd    r3, r4
        ble     67f
        mtspr   SPRN_DEC, r4
 67:
        /* save expiry time of guest decrementer */
-       extsw   r3, r3
        add     r3, r3, r5
        ld      r4, HSTATE_KVM_VCPU(r13)
        ld      r5, HSTATE_KVM_VCORE(r13)
index bcbeeb62dd13e9eafb9d0b8e4c6ece982627db85..8a4205fa774fe552a8a7f72b90b9c28dfb1ed0e5 100644 (file)
@@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
        pteg_addr = get_pteg_addr(vcpu, pte_index);
 
        mutex_lock(&vcpu->kvm->arch.hpt_mutex);
-       copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
+       ret = H_FUNCTION;
+       if (copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)))
+               goto done;
        hpte = pteg;
 
        ret = H_PTEG_FULL;
@@ -71,7 +73,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
        hpte[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
        hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
        pteg_addr += i * HPTE_SIZE;
-       copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE);
+       ret = H_FUNCTION;
+       if (copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE))
+               goto done;
        kvmppc_set_gpr(vcpu, 4, pte_index | i);
        ret = H_SUCCESS;
 
@@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
 
        pteg = get_pteg_addr(vcpu, pte_index);
        mutex_lock(&vcpu->kvm->arch.hpt_mutex);
-       copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+       ret = H_FUNCTION;
+       if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
+               goto done;
        pte[0] = be64_to_cpu((__force __be64)pte[0]);
        pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
@@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
            ((flags & H_ANDCOND) && (pte[0] & avpn) != 0))
                goto done;
 
-       copy_to_user((void __user *)pteg, &v, sizeof(v));
+       ret = H_FUNCTION;
+       if (copy_to_user((void __user *)pteg, &v, sizeof(v)))
+               goto done;
 
        rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
        vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
@@ -171,7 +179,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
                }
 
                pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
-               copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+               if (copy_from_user(pte, (void __user *)pteg, sizeof(pte))) {
+                       ret = H_FUNCTION;
+                       break;
+               }
                pte[0] = be64_to_cpu((__force __be64)pte[0]);
                pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
@@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
                        tsh |= H_BULK_REMOVE_NOT_FOUND;
                } else {
                        /* Splat the pteg in (userland) hpt */
-                       copy_to_user((void __user *)pteg, &v, sizeof(v));
+                       if (copy_to_user((void __user *)pteg, &v, sizeof(v))) {
+                               ret = H_FUNCTION;
+                               break;
+                       }
 
                        rb = compute_tlbie_rb(pte[0], pte[1],
                                              tsh & H_BULK_REMOVE_PTEX);
@@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
 
        pteg = get_pteg_addr(vcpu, pte_index);
        mutex_lock(&vcpu->kvm->arch.hpt_mutex);
-       copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+       ret = H_FUNCTION;
+       if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
+               goto done;
        pte[0] = be64_to_cpu((__force __be64)pte[0]);
        pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
@@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
        vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
        pte[0] = (__force u64)cpu_to_be64(pte[0]);
        pte[1] = (__force u64)cpu_to_be64(pte[1]);
-       copy_to_user((void __user *)pteg, pte, sizeof(pte));
+       ret = H_FUNCTION;
+       if (copy_to_user((void __user *)pteg, pte, sizeof(pte)))
+               goto done;
        ret = H_SUCCESS;
 
  done:
@@ -244,36 +262,37 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
-static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
+static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
 {
-       unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
-       unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
-       unsigned long tce = kvmppc_get_gpr(vcpu, 6);
        long rc;
 
-       rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
+       rc = kvmppc_h_logical_ci_load(vcpu);
        if (rc == H_TOO_HARD)
                return EMULATE_FAIL;
        kvmppc_set_gpr(vcpu, 3, rc);
        return EMULATE_DONE;
 }
 
-static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
+static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
 {
        long rc;
 
-       rc = kvmppc_h_logical_ci_load(vcpu);
+       rc = kvmppc_h_logical_ci_store(vcpu);
        if (rc == H_TOO_HARD)
                return EMULATE_FAIL;
        kvmppc_set_gpr(vcpu, 3, rc);
        return EMULATE_DONE;
 }
 
-static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
 {
+       unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
+       unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
+       unsigned long tce = kvmppc_get_gpr(vcpu, 6);
        long rc;
 
-       rc = kvmppc_h_logical_ci_store(vcpu);
+       rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
        if (rc == H_TOO_HARD)
                return EMULATE_FAIL;
        kvmppc_set_gpr(vcpu, 3, rc);
@@ -311,6 +330,23 @@ static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
+#else /* CONFIG_SPAPR_TCE_IOMMU */
+static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
+{
+       return EMULATE_FAIL;
+}
+
+static int kvmppc_h_pr_put_tce_indirect(struct kvm_vcpu *vcpu)
+{
+       return EMULATE_FAIL;
+}
+
+static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
+{
+       return EMULATE_FAIL;
+}
+#endif /* CONFIG_SPAPR_TCE_IOMMU */
+
 static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
 {
        long rc = kvmppc_xics_hcall(vcpu, cmd);
index 023a31133c37ce0714fc4457a5ff73062ce8abbc..4636ca6e7d383b7d3ce26b18df01152b8087a8ec 100644 (file)
@@ -69,7 +69,7 @@ static void GLUE(X_PFX,source_eoi)(u32 hw_irq, struct xive_irq_data *xd)
 {
        /* If the XIVE supports the new "store EOI facility, use it */
        if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI)
-               __x_writeq(0, __x_eoi_page(xd));
+               __x_writeq(0, __x_eoi_page(xd) + XIVE_ESB_STORE_EOI);
        else if (hw_irq && xd->flags & XIVE_IRQ_FLAG_EOI_FW) {
                opal_int_eoi(hw_irq);
        } else {
@@ -89,7 +89,7 @@ static void GLUE(X_PFX,source_eoi)(u32 hw_irq, struct xive_irq_data *xd)
                 * properly.
                 */
                if (xd->flags & XIVE_IRQ_FLAG_LSI)
-                       __x_readq(__x_eoi_page(xd));
+                       __x_readq(__x_eoi_page(xd) + XIVE_ESB_LOAD_EOI);
                else {
                        eoi_val = GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_00);
 
index f7cf2cd564efe53a072b91cb3705e69a0ffa6e02..7f71ab5fcad1bbc20abaa43627c1220c3ff4e17b 100644 (file)
@@ -1749,7 +1749,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = kvm_vm_ioctl_enable_cap(kvm, &cap);
                break;
        }
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_SPAPR_TCE_IOMMU
        case KVM_CREATE_SPAPR_TCE_64: {
                struct kvm_create_spapr_tce_64 create_tce_64;
 
@@ -1780,6 +1780,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64);
                goto out;
        }
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
        case KVM_PPC_GET_SMMU_INFO: {
                struct kvm_ppc_smmu_info info;
                struct kvm *kvm = filp->private_data;
index d659345a98d66c03a2cab1ceed3526af95551cc6..44fe4833910f64bcd014a2e3843ecd8c3077fc26 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/debugfs.h>
 #include <linux/fs.h>
+#include <linux/hugetlb.h>
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
@@ -391,7 +392,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
 
        for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
                addr = start + i * PMD_SIZE;
-               if (!pmd_none(*pmd))
+               if (!pmd_none(*pmd) && !pmd_huge(*pmd))
                        /* pmd exists */
                        walk_pte(st, pmd, addr);
                else
@@ -407,7 +408,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
 
        for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
                addr = start + i * PUD_SIZE;
-               if (!pud_none(*pud))
+               if (!pud_none(*pud) && !pud_huge(*pud))
                        /* pud exists */
                        walk_pmd(st, pud, addr);
                else
@@ -427,7 +428,7 @@ static void walk_pagetables(struct pg_state *st)
         */
        for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
                addr = KERN_VIRT_START + i * PGDIR_SIZE;
-               if (!pgd_none(*pgd))
+               if (!pgd_none(*pgd) && !pgd_huge(*pgd))
                        /* pgd exists */
                        walk_pud(st, pgd, addr);
                else
index 6575b9aabef4df3f0e8903417d121b47c1f2f2a4..a12e86395025f9c7fcdb8a12c76ae642a1ef7cb8 100644 (file)
@@ -68,7 +68,7 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (mm->task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
        /*
index 9dbd2a733d6b12401ee9157cd6309cd835b2b87b..0ee6be4f1ba44e231da18c7e38d217610ac4bcd5 100644 (file)
@@ -112,7 +112,7 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (mm->task_size - len >= addr && addr >= mmap_min_addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
@@ -157,7 +157,7 @@ radix__arch_get_unmapped_area_topdown(struct file *filp,
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (mm->task_size - len >= addr && addr >= mmap_min_addr &&
-                               (!vma || addr + len <= vma->vm_start))
+                               (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index c6dca2ae78ef9f1225dd6a13e0997034132315a4..a3edf813d4556c547e5b00155c5f9a0dc411872d 100644 (file)
@@ -99,7 +99,7 @@ static int hash__init_new_context(struct mm_struct *mm)
         * mm->context.addr_limit. Default to max task size so that we copy the
         * default values to paca which will help us to handle slb miss early.
         */
-       mm->context.addr_limit = TASK_SIZE_128TB;
+       mm->context.addr_limit = DEFAULT_MAP_WINDOW_USER64;
 
        /*
         * The old code would re-promote on fork, we don't do that when using
index 966b9fccfa66b4268c5421252364bf2af6d6253f..45f6740dd407dae752c25a19ad2ae4a804a19858 100644 (file)
@@ -99,7 +99,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr,
        if ((mm->task_size - len) < addr)
                return 0;
        vma = find_vma(mm, addr);
-       return (!vma || (addr + len) <= vma->vm_start);
+       return (!vma || (addr + len) <= vm_start_gap(vma));
 }
 
 static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice)
index cbd82fde57702e2a210608dc2e1800ae574465e0..09ceea6175ba9dc1d99b8b56eadae1367138b166 100644 (file)
@@ -101,5 +101,6 @@ void perf_get_regs_user(struct perf_regs *regs_user,
                        struct pt_regs *regs_user_copy)
 {
        regs_user->regs = task_pt_regs(current);
-       regs_user->abi  = perf_reg_abi(current);
+       regs_user->abi = (regs_user->regs) ? perf_reg_abi(current) :
+                        PERF_SAMPLE_REGS_ABI_NONE;
 }
index 018f8e90ac35fd19bf37bdbb99438f970621634a..bb28e1a412576ea15492be658a5bf78ee75950a5 100644 (file)
@@ -402,7 +402,7 @@ static struct power_pmu power9_isa207_pmu = {
        .name                   = "POWER9",
        .n_counter              = MAX_PMU_COUNTERS,
        .add_fields             = ISA207_ADD_FIELDS,
-       .test_adder             = ISA207_TEST_ADDER,
+       .test_adder             = P9_DD1_TEST_ADDER,
        .compute_mmcr           = isa207_compute_mmcr,
        .config_bhrb            = power9_config_bhrb,
        .bhrb_filter_map        = power9_bhrb_filter_map,
@@ -421,7 +421,7 @@ static struct power_pmu power9_pmu = {
        .name                   = "POWER9",
        .n_counter              = MAX_PMU_COUNTERS,
        .add_fields             = ISA207_ADD_FIELDS,
-       .test_adder             = P9_DD1_TEST_ADDER,
+       .test_adder             = ISA207_TEST_ADDER,
        .compute_mmcr           = isa207_compute_mmcr,
        .config_bhrb            = power9_config_bhrb,
        .bhrb_filter_map        = power9_bhrb_filter_map,
index 33244e3d9375eae3ccd1224b7dbac87b3822f92a..4fd64d3f5c4429206b8c838ca99387e6668aee11 100644 (file)
@@ -59,6 +59,17 @@ config PPC_OF_BOOT_TRAMPOLINE
 
          In case of doubt, say Y
 
+config PPC_DT_CPU_FTRS
+       bool "Device-tree based CPU feature discovery & setup"
+       depends on PPC_BOOK3S_64
+       default y
+       help
+         This enables code to use a new device tree binding for describing CPU
+         compatibility and features. Saying Y here will attempt to use the new
+         binding if the firmware provides it. Currently only the skiboot
+         firmware provides this binding.
+         If you're not sure say Y.
+
 config UDBG_RTAS_CONSOLE
        bool "RTAS based debug console"
        depends on PPC_RTAS
index 96c2b8a406303194737962905330c0a7a3900944..0c45cdbac4cfc80bcb79e287486d5a8a85fefdef 100644 (file)
@@ -197,7 +197,9 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
            (REGION_ID(ea) != USER_REGION_ID)) {
 
                spin_unlock(&spu->register_lock);
-               ret = hash_page(ea, _PAGE_PRESENT | _PAGE_READ, 0x300, dsisr);
+               ret = hash_page(ea,
+                               _PAGE_PRESENT | _PAGE_READ | _PAGE_PRIVILEGED,
+                               0x300, dsisr);
                spin_lock(&spu->register_lock);
 
                if (!ret) {
index e5a891ae80ee5e6881bd10be148c04519d3dffd0..84b7ac926ce65682e83781ec6ab4ac97b6d0727f 100644 (file)
@@ -175,6 +175,8 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
        skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
        if (!dump_skip(cprm, skip))
                goto Eio;
+
+       rc = 0;
 out:
        free_page((unsigned long)buf);
        return rc;
index 067defeea6911303e7fd59206e239fa7d6d770eb..b5d960d6db3d0b18d33273b31ac67e03caebd02b 100644 (file)
@@ -75,7 +75,8 @@ struct pci_dev *pnv_pci_get_npu_dev(struct pci_dev *gpdev, int index)
        if (WARN_ON(!gpdev))
                return NULL;
 
-       if (WARN_ON(!gpdev->dev.of_node))
+       /* Not all PCI devices have device-tree nodes */
+       if (!gpdev->dev.of_node)
                return NULL;
 
        /* Get assoicated PCI device */
@@ -448,7 +449,7 @@ static int mmio_launch_invalidate(struct npu *npu, unsigned long launch,
        return mmio_atsd_reg;
 }
 
-static int mmio_invalidate_pid(struct npu *npu, unsigned long pid)
+static int mmio_invalidate_pid(struct npu *npu, unsigned long pid, bool flush)
 {
        unsigned long launch;
 
@@ -464,12 +465,15 @@ static int mmio_invalidate_pid(struct npu *npu, unsigned long pid)
        /* PID */
        launch |= pid << PPC_BITLSHIFT(38);
 
+       /* No flush */
+       launch |= !flush << PPC_BITLSHIFT(39);
+
        /* Invalidating the entire process doesn't use a va */
        return mmio_launch_invalidate(npu, launch, 0);
 }
 
 static int mmio_invalidate_va(struct npu *npu, unsigned long va,
-                       unsigned long pid)
+                       unsigned long pid, bool flush)
 {
        unsigned long launch;
 
@@ -485,26 +489,60 @@ static int mmio_invalidate_va(struct npu *npu, unsigned long va,
        /* PID */
        launch |= pid << PPC_BITLSHIFT(38);
 
+       /* No flush */
+       launch |= !flush << PPC_BITLSHIFT(39);
+
        return mmio_launch_invalidate(npu, launch, va);
 }
 
 #define mn_to_npu_context(x) container_of(x, struct npu_context, mn)
 
+struct mmio_atsd_reg {
+       struct npu *npu;
+       int reg;
+};
+
+static void mmio_invalidate_wait(
+       struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], bool flush)
+{
+       struct npu *npu;
+       int i, reg;
+
+       /* Wait for all invalidations to complete */
+       for (i = 0; i <= max_npu2_index; i++) {
+               if (mmio_atsd_reg[i].reg < 0)
+                       continue;
+
+               /* Wait for completion */
+               npu = mmio_atsd_reg[i].npu;
+               reg = mmio_atsd_reg[i].reg;
+               while (__raw_readq(npu->mmio_atsd_regs[reg] + XTS_ATSD_STAT))
+                       cpu_relax();
+
+               put_mmio_atsd_reg(npu, reg);
+
+               /*
+                * The GPU requires two flush ATSDs to ensure all entries have
+                * been flushed. We use PID 0 as it will never be used for a
+                * process on the GPU.
+                */
+               if (flush)
+                       mmio_invalidate_pid(npu, 0, true);
+       }
+}
+
 /*
  * Invalidate either a single address or an entire PID depending on
  * the value of va.
  */
 static void mmio_invalidate(struct npu_context *npu_context, int va,
-                       unsigned long address)
+                       unsigned long address, bool flush)
 {
-       int i, j, reg;
+       int i, j;
        struct npu *npu;
        struct pnv_phb *nphb;
        struct pci_dev *npdev;
-       struct {
-               struct npu *npu;
-               int reg;
-       } mmio_atsd_reg[NV_MAX_NPUS];
+       struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS];
        unsigned long pid = npu_context->mm->context.id;
 
        /*
@@ -524,10 +562,11 @@ static void mmio_invalidate(struct npu_context *npu_context, int va,
 
                        if (va)
                                mmio_atsd_reg[i].reg =
-                                       mmio_invalidate_va(npu, address, pid);
+                                       mmio_invalidate_va(npu, address, pid,
+                                                       flush);
                        else
                                mmio_atsd_reg[i].reg =
-                                       mmio_invalidate_pid(npu, pid);
+                                       mmio_invalidate_pid(npu, pid, flush);
 
                        /*
                         * The NPU hardware forwards the shootdown to all GPUs
@@ -543,18 +582,10 @@ static void mmio_invalidate(struct npu_context *npu_context, int va,
         */
        flush_tlb_mm(npu_context->mm);
 
-       /* Wait for all invalidations to complete */
-       for (i = 0; i <= max_npu2_index; i++) {
-               if (mmio_atsd_reg[i].reg < 0)
-                       continue;
-
-               /* Wait for completion */
-               npu = mmio_atsd_reg[i].npu;
-               reg = mmio_atsd_reg[i].reg;
-               while (__raw_readq(npu->mmio_atsd_regs[reg] + XTS_ATSD_STAT))
-                       cpu_relax();
-               put_mmio_atsd_reg(npu, reg);
-       }
+       mmio_invalidate_wait(mmio_atsd_reg, flush);
+       if (flush)
+               /* Wait for the flush to complete */
+               mmio_invalidate_wait(mmio_atsd_reg, false);
 }
 
 static void pnv_npu2_mn_release(struct mmu_notifier *mn,
@@ -570,7 +601,7 @@ static void pnv_npu2_mn_release(struct mmu_notifier *mn,
         * There should be no more translation requests for this PID, but we
         * need to ensure any entries for it are removed from the TLB.
         */
-       mmio_invalidate(npu_context, 0, 0);
+       mmio_invalidate(npu_context, 0, 0, true);
 }
 
 static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn,
@@ -580,7 +611,7 @@ static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn,
 {
        struct npu_context *npu_context = mn_to_npu_context(mn);
 
-       mmio_invalidate(npu_context, 1, address);
+       mmio_invalidate(npu_context, 1, address, true);
 }
 
 static void pnv_npu2_mn_invalidate_page(struct mmu_notifier *mn,
@@ -589,7 +620,7 @@ static void pnv_npu2_mn_invalidate_page(struct mmu_notifier *mn,
 {
        struct npu_context *npu_context = mn_to_npu_context(mn);
 
-       mmio_invalidate(npu_context, 1, address);
+       mmio_invalidate(npu_context, 1, address, true);
 }
 
 static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn,
@@ -599,8 +630,11 @@ static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn,
        struct npu_context *npu_context = mn_to_npu_context(mn);
        unsigned long address;
 
-       for (address = start; address <= end; address += PAGE_SIZE)
-               mmio_invalidate(npu_context, 1, address);
+       for (address = start; address < end; address += PAGE_SIZE)
+               mmio_invalidate(npu_context, 1, address, false);
+
+       /* Do the flush only on the final addess == end */
+       mmio_invalidate(npu_context, 1, address, true);
 }
 
 static const struct mmu_notifier_ops nv_nmmu_notifier_ops = {
@@ -650,8 +684,11 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
                /* No nvlink associated with this GPU device */
                return ERR_PTR(-ENODEV);
 
-       if (!mm) {
-               /* kernel thread contexts are not supported */
+       if (!mm || mm->context.id == 0) {
+               /*
+                * Kernel thread contexts are not supported and context id 0 is
+                * reserved on the GPU.
+                */
                return ERR_PTR(-EINVAL);
        }
 
@@ -714,7 +751,7 @@ static void pnv_npu2_release_context(struct kref *kref)
 void pnv_npu2_destroy_context(struct npu_context *npu_context,
                        struct pci_dev *gpdev)
 {
-       struct pnv_phb *nphb, *phb;
+       struct pnv_phb *nphb;
        struct npu *npu;
        struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
        struct device_node *nvlink_dn;
@@ -728,13 +765,12 @@ void pnv_npu2_destroy_context(struct npu_context *npu_context,
 
        nphb = pci_bus_to_host(npdev->bus)->private_data;
        npu = &nphb->npu;
-       phb = pci_bus_to_host(gpdev->bus)->private_data;
        nvlink_dn = of_parse_phandle(npdev->dev.of_node, "ibm,nvlink", 0);
        if (WARN_ON(of_property_read_u32(nvlink_dn, "ibm,npu-link-index",
                                                        &nvlink_index)))
                return;
        npu_context->npdev[npu->index][nvlink_index] = NULL;
-       opal_npu_destroy_context(phb->opal_id, npu_context->mm->context.id,
+       opal_npu_destroy_context(nphb->opal_id, npu_context->mm->context.id,
                                PCI_DEVID(gpdev->bus->number, gpdev->devfn));
        kref_put(&npu_context->kref, pnv_npu2_release_context);
 }
index 0babef11136fc8daba7f2666fed3f3b649cc2bd8..8c6119280c1306afd399d2c86ce88381882ab5df 100644 (file)
@@ -407,7 +407,13 @@ static DEVICE_ATTR(subcores_per_core, 0644,
 
 static int subcore_init(void)
 {
-       if (!cpu_has_feature(CPU_FTR_SUBCORE))
+       unsigned pvr_ver;
+
+       pvr_ver = PVR_VER(mfspr(SPRN_PVR));
+
+       if (pvr_ver != PVR_POWER8 &&
+           pvr_ver != PVR_POWER8E &&
+           pvr_ver != PVR_POWER8NVL)
                return 0;
 
        /*
index e104c71ea44ab5bf715fa5720c0a1ed47c6221c7..1fb162ba9d1c6aaa730123d07258a3923b3d245d 100644 (file)
@@ -124,6 +124,7 @@ static struct property *dlpar_clone_drconf_property(struct device_node *dn)
        for (i = 0; i < num_lmbs; i++) {
                lmbs[i].base_addr = be64_to_cpu(lmbs[i].base_addr);
                lmbs[i].drc_index = be32_to_cpu(lmbs[i].drc_index);
+               lmbs[i].aa_index = be32_to_cpu(lmbs[i].aa_index);
                lmbs[i].flags = be32_to_cpu(lmbs[i].flags);
        }
 
@@ -147,6 +148,7 @@ static void dlpar_update_drconf_property(struct device_node *dn,
        for (i = 0; i < num_lmbs; i++) {
                lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
                lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
+               lmbs[i].aa_index = cpu_to_be32(lmbs[i].aa_index);
                lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
        }
 
index ef470b470b04ae85488d1a9ffcbe27519884a4db..6afddae2fb4796dc61de3258f683bcc158b15a2e 100644 (file)
@@ -75,7 +75,8 @@ static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 
 static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
 {
-       struct u8_gpio_chip *u8_gc = gpiochip_get_data(&mm_gc->gc);
+       struct u8_gpio_chip *u8_gc =
+               container_of(mm_gc, struct u8_gpio_chip, mm_gc);
 
        u8_gc->data = in_8(mm_gc->regs);
 }
index 913825086b8df675f68f69a0b993934c3b607104..8f5e3035483bc3fac3b552f793ac358344774661 100644 (file)
@@ -297,7 +297,7 @@ void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd)
 {
        /* If the XIVE supports the new "store EOI facility, use it */
        if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI)
-               out_be64(xd->eoi_mmio, 0);
+               out_be64(xd->eoi_mmio + XIVE_ESB_STORE_EOI, 0);
        else if (hw_irq && xd->flags & XIVE_IRQ_FLAG_EOI_FW) {
                /*
                 * The FW told us to call it. This happens for some
index e161fafb495b746f94d84a172b27708a1ce77816..6967addc6a8940630bf3038abdad18d37d8bda39 100644 (file)
@@ -363,9 +363,6 @@ config COMPAT
 config SYSVIPC_COMPAT
        def_bool y if COMPAT && SYSVIPC
 
-config KEYS_COMPAT
-       def_bool y if COMPAT && KEYS
-
 config SMP
        def_bool y
        prompt "Symmetric multi-processing support"
index a5039fa8931442a5c5b35c77fbee22fe86e78131..282072206df7076e732b8fcd121ca49b1693634a 100644 (file)
@@ -30,6 +30,7 @@ CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
+# CONFIG_SYSFS_SYSCALL is not set
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
@@ -44,7 +45,10 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_WBT_SQ=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
@@ -90,6 +94,8 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
+CONFIG_SMC=m
+CONFIG_SMC_DIAG=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -359,6 +365,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_DNS_RESOLVER=y
+CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
@@ -367,16 +374,19 @@ CONFIG_DEVTMPFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
+CONFIG_ZRAM=m
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_OSD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_ATA_OVER_ETH=m
+CONFIG_BLK_DEV_RAM_DAX=y
 CONFIG_VIRTIO_BLK=y
+CONFIG_BLK_DEV_RBD=m
 CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_GENWQE=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -442,6 +452,8 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
+CONFIG_MLX5_CORE=m
+CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -452,7 +464,6 @@ CONFIG_PPTP=m
 CONFIG_PPPOL2TP=m
 CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
@@ -471,6 +482,7 @@ CONFIG_DIAG288_WATCHDOG=m
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_MLX4_INFINIBAND=m
+CONFIG_MLX5_INFINIBAND=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -487,12 +499,18 @@ CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
 CONFIG_XFS_DEBUG=y
 CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
 CONFIG_OCFS2_FS=m
 CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_BTRFS_DEBUG=y
 CONFIG_NILFS2_FS=m
+CONFIG_FS_DAX=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
 CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_DEBUG=y
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
 CONFIG_AUTOFS4_FS=m
@@ -558,6 +576,7 @@ CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DEBUG_RODATA_TEST=y
 CONFIG_DEBUG_OBJECTS=y
 CONFIG_DEBUG_OBJECTS_SELFTEST=y
 CONFIG_DEBUG_OBJECTS_FREE=y
@@ -580,7 +599,6 @@ 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
 CONFIG_PROVE_LOCKING=y
@@ -595,6 +613,7 @@ CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
 CONFIG_NOTIFIER_ERROR_INJECTION=m
 CONFIG_PM_NOTIFIER_ERROR_INJECT=m
+CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
 CONFIG_FAILSLAB=y
 CONFIG_FAIL_PAGE_ALLOC=y
@@ -616,13 +635,12 @@ CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
+CONFIG_TEST_SORT=y
 CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_RBTREE_TEST=y
 CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
-CONFIG_TEST_STRING_HELPERS=y
-CONFIG_TEST_KSTRTOX=y
 CONFIG_DMA_API_DEBUG=y
 CONFIG_TEST_BPF=m
 CONFIG_BUG_ON_DATA_CORRUPTION=y
@@ -630,6 +648,7 @@ CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
+CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
@@ -640,7 +659,9 @@ CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_DH=m
 CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_PCRYPT=m
 CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
@@ -648,6 +669,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_CMAC=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -657,8 +679,10 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES_TI=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -674,6 +698,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
@@ -685,6 +710,7 @@ CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_PAES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_ASYMMETRIC_KEY_TYPE=y
@@ -692,6 +718,7 @@ CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
+CONFIG_RANDOM32_SELFTEST=y
 CONFIG_CORDIC=m
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
index 83970b5afb2bc32f8ca86545c6eea31ece2d0001..3c6b78189fbcc805225b9b2e05d5812c5a5f9b67 100644 (file)
@@ -31,6 +31,7 @@ CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
+# CONFIG_SYSFS_SYSCALL is not set
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
@@ -46,7 +47,10 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_WBT_SQ=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
@@ -88,6 +92,8 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
+CONFIG_SMC=m
+CONFIG_SMC_DIAG=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -356,6 +362,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_DNS_RESOLVER=y
+CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
@@ -364,16 +371,18 @@ CONFIG_DEVTMPFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
+CONFIG_ZRAM=m
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_OSD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_ATA_OVER_ETH=m
+CONFIG_BLK_DEV_RAM_DAX=y
 CONFIG_VIRTIO_BLK=y
 CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_GENWQE=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -439,6 +448,8 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
+CONFIG_MLX5_CORE=m
+CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -449,7 +460,6 @@ CONFIG_PPTP=m
 CONFIG_PPPOL2TP=m
 CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
@@ -468,6 +478,7 @@ CONFIG_DIAG288_WATCHDOG=m
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_MLX4_INFINIBAND=m
+CONFIG_MLX5_INFINIBAND=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -483,11 +494,15 @@ CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
 CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
 CONFIG_OCFS2_FS=m
 CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
+CONFIG_FS_DAX=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
 CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
@@ -553,7 +568,6 @@ CONFIG_UNUSED_SYMBOLS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
-CONFIG_TIMER_STATS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
@@ -576,6 +590,7 @@ CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
+CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
@@ -599,6 +614,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_CMAC=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -611,6 +627,7 @@ CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES_TI=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -626,16 +643,19 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
+CONFIG_PKEY=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_PAES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CRC7=m
index fbc6542aaf5955bdeb839fbf03496d2b39113688..653d72bcc007db3b2e39aa7225b447c18c9d9cb2 100644 (file)
@@ -31,6 +31,7 @@ CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
+# CONFIG_SYSFS_SYSCALL is not set
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
@@ -44,7 +45,10 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_WBT_SQ=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
@@ -86,6 +90,8 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
+CONFIG_SMC=m
+CONFIG_SMC_DIAG=m
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
@@ -354,6 +360,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_DNS_RESOLVER=y
+CONFIG_NETLINK_DIAG=m
 CONFIG_CGROUP_NET_PRIO=y
 CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
@@ -362,16 +369,18 @@ CONFIG_DEVTMPFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
+CONFIG_ZRAM=m
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_OSD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_ATA_OVER_ETH=m
+CONFIG_BLK_DEV_RAM_DAX=y
 CONFIG_VIRTIO_BLK=y
 CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_GENWQE=m
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -437,6 +446,8 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
+CONFIG_MLX5_CORE=m
+CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 CONFIG_PPP=m
 CONFIG_PPP_BSDCOMP=m
@@ -447,7 +458,6 @@ CONFIG_PPTP=m
 CONFIG_PPPOL2TP=m
 CONFIG_PPP_ASYNC=m
 CONFIG_PPP_SYNC_TTY=m
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
@@ -466,6 +476,7 @@ CONFIG_DIAG288_WATCHDOG=m
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_MLX4_INFINIBAND=m
+CONFIG_MLX5_INFINIBAND=m
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -481,11 +492,15 @@ CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_XFS_RT=y
 CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
 CONFIG_OCFS2_FS=m
 CONFIG_BTRFS_FS=y
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
+CONFIG_FS_DAX=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
 CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
@@ -551,7 +566,6 @@ CONFIG_UNUSED_SYMBOLS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
-CONFIG_TIMER_STATS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
@@ -574,6 +588,7 @@ CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
+CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
@@ -597,6 +612,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_CMAC=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -609,6 +625,7 @@ CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_AES_TI=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAMELLIA=m
@@ -624,6 +641,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
@@ -635,6 +653,7 @@ CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_PAES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
 CONFIG_CRC7=m
index e23d97c13735b94e43bb965341b93766413a5502..afa46a7406eaeddbbf70bbaf384f49ffa0535874 100644 (file)
@@ -12,8 +12,10 @@ CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=2
 # CONFIG_HOTPLUG_CPU is not set
 CONFIG_HZ_100=y
+# CONFIG_ARCH_RANDOM is not set
 # CONFIG_COMPACTION is not set
 # CONFIG_MIGRATION is not set
+# CONFIG_BOUNCE is not set
 # CONFIG_CHECK_STACK is not set
 # CONFIG_CHSC_SCH is not set
 # CONFIG_SCM_BUS is not set
@@ -36,11 +38,11 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_ZFCP=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_HVC_IUCV is not set
+# CONFIG_HW_RANDOM_S390 is not set
 CONFIG_RAW_DRIVER=y
 # CONFIG_SCLP_ASYNC is not set
 # CONFIG_HMC_DRV is not set
@@ -54,9 +56,9 @@ CONFIG_RAW_DRIVER=y
 # CONFIG_INOTIFY_USER is not set
 CONFIG_CONFIGFS_FS=y
 # CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
index 97189dbaf34b2a36dade0738a64eb65bae38aafc..20244a38c88698f887e002bce2423afeb199ace3 100644 (file)
@@ -28,6 +28,7 @@ CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
+# CONFIG_SYSFS_SYSCALL is not set
 CONFIG_BPF_SYSCALL=y
 CONFIG_USERFAULTFD=y
 # CONFIG_COMPAT_BRK is not set
@@ -108,7 +109,6 @@ CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=y
 CONFIG_MD=y
 CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
@@ -131,6 +131,7 @@ CONFIG_TUN=m
 CONFIG_VIRTIO_NET=y
 # CONFIG_NET_VENDOR_ALACRITECH is not set
 # CONFIG_NET_VENDOR_SOLARFLARE is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 CONFIG_DEVKMEM=y
@@ -162,7 +163,6 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_PANIC_ON_OOPS=y
-CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
@@ -172,14 +172,12 @@ CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
-CONFIG_RCU_TRACE=y
 CONFIG_LATENCYTOP=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_EVENTS=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_KPROBES_SANITY_TEST=y
@@ -190,7 +188,6 @@ CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_XTS=m
@@ -230,6 +227,7 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
 CONFIG_CRYPTO_USER_API_RNG=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
+CONFIG_CRYPTO_PAES_S390=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
 CONFIG_CRYPTO_SHA512_S390=m
index 0206c805232878c95a6588dbb9909ecb4268d5d0..df7b54ea956daeb6c9a1091518e73417e688e504 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
+#include <linux/refcount.h>
 #include <uapi/asm/debug.h>
 
 #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
@@ -31,7 +32,7 @@ struct debug_view;
 typedef struct debug_info {    
        struct debug_info* next;
        struct debug_info* prev;
-       atomic_t ref_count;
+       refcount_t ref_count;
        spinlock_t lock;                        
        int level;
        int nr_areas;
index 60323c21938bb5d97407e9f0cb35c6fcdd335597..37f617dfbeded0de8edb9f9f4e1a263c46bd0635 100644 (file)
@@ -40,6 +40,8 @@ static inline int insn_length(unsigned char code)
        return ((((int) code + 64) >> 7) + 1) << 1;
 }
 
+struct pt_regs;
+
 void show_code(struct pt_regs *regs);
 void print_fn_code(unsigned char *code, unsigned long len);
 int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len);
index 1293c4066cfc806f96f06bec93743f7d051f2973..28792ef82c837a2f2c11a5765098434018d02598 100644 (file)
  * 2005-Dec    Used as a template for s390 by Mike Grundy
  *             <grundym@us.ibm.com>
  */
+#include <linux/types.h>
 #include <asm-generic/kprobes.h>
 
 #define BREAKPOINT_INSTRUCTION 0x0002
 
+#define FIXUP_PSW_NORMAL       0x08
+#define FIXUP_BRANCH_NOT_TAKEN 0x04
+#define FIXUP_RETURN_REGISTER  0x02
+#define FIXUP_NOT_REQUIRED     0x01
+
+int probe_is_prohibited_opcode(u16 *insn);
+int probe_get_fixup_type(u16 *insn);
+int probe_is_insn_relative_long(u16 *insn);
+
 #ifdef CONFIG_KPROBES
-#include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
 #include <linux/sched/task_stack.h>
@@ -56,11 +65,6 @@ typedef u16 kprobe_opcode_t;
 
 #define KPROBE_SWAP_INST       0x10
 
-#define FIXUP_PSW_NORMAL       0x08
-#define FIXUP_BRANCH_NOT_TAKEN 0x04
-#define FIXUP_RETURN_REGISTER  0x02
-#define FIXUP_NOT_REQUIRED     0x01
-
 /* Architecture specific copy of original instruction */
 struct arch_specific_insn {
        /* copy of original instruction */
@@ -90,10 +94,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 int kprobe_exceptions_notify(struct notifier_block *self,
        unsigned long val, void *data);
 
-int probe_is_prohibited_opcode(u16 *insn);
-int probe_get_fixup_type(u16 *insn);
-int probe_is_insn_relative_long(u16 *insn);
-
 #define flush_insn_slot(p)     do { } while (0)
 
 #endif /* CONFIG_KPROBES */
index 426614a882a9b12a71c96f06607f30e6b345cd0d..65d07ac34647001ad45052a18d97e49e151c4b20 100644 (file)
@@ -541,7 +541,6 @@ struct kvm_s390_float_interrupt {
        struct mutex ais_lock;
        u8 simm;
        u8 nimm;
-       int ais_enabled;
 };
 
 struct kvm_hw_wp_info_arch {
index 60d395fdc86438e55f49ddf853dca7b6f99582b3..aeac013968f2a00fd0050e772d50a8959dd57e04 100644 (file)
@@ -221,11 +221,6 @@ extern void release_thread(struct task_struct *);
 /* Free guarded storage control block for current */
 void exit_thread_gs(void);
 
-/*
- * Return saved PC of a blocked thread.
- */
-extern unsigned long thread_saved_pc(struct task_struct *t);
-
 unsigned long get_wchan(struct task_struct *p);
 #define task_pt_regs(tsk) ((struct pt_regs *) \
         (task_stack_page(tsk) + THREAD_SIZE) - 1)
index 73bff45ced55268c7f06e52a98be46f7eaa2ea54..e784bed6ed7ffb24cabb02eb92a1d90494e3b7e1 100644 (file)
@@ -146,7 +146,7 @@ extern int topology_max_mnest;
  * Returns the maximum nesting level supported by the cpu topology code.
  * The current maximum level is 4 which is the drawer level.
  */
-static inline int topology_mnest_limit(void)
+static inline unsigned char topology_mnest_limit(void)
 {
        return min(topology_max_mnest, 4);
 }
index 530226b6cb19a2ed5bb011ab61215f69e243d4c5..86b3e74f569eb7823ba6c4b0c4ec7baeb456e2f1 100644 (file)
@@ -277,7 +277,7 @@ debug_info_alloc(const char *name, int pages_per_area, int nr_areas,
        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
        memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
                sizeof(struct dentry*));
-       atomic_set(&(rc->ref_count), 0);
+       refcount_set(&(rc->ref_count), 0);
 
        return rc;
 
@@ -361,7 +361,7 @@ debug_info_create(const char *name, int pages_per_area, int nr_areas,
         debug_area_last = rc;
         rc->next = NULL;
 
-       debug_info_get(rc);
+       refcount_set(&rc->ref_count, 1);
 out:
        return rc;
 }
@@ -416,7 +416,7 @@ static void
 debug_info_get(debug_info_t * db_info)
 {
        if (db_info)
-               atomic_inc(&db_info->ref_count);
+               refcount_inc(&db_info->ref_count);
 }
 
 /*
@@ -431,7 +431,7 @@ debug_info_put(debug_info_t *db_info)
 
        if (!db_info)
                return;
-       if (atomic_dec_and_test(&db_info->ref_count)) {
+       if (refcount_dec_and_test(&db_info->ref_count)) {
                for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
                        if (!db_info->views[i])
                                continue;
index a5f5d3bb3dbc516d23c98082d0f3abe186fc95c1..6315037335ba9365a198859de579c6fdcfb683cf 100644 (file)
@@ -231,12 +231,17 @@ ENTRY(sie64a)
        lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
 .Lsie_done:
 # some program checks are suppressing. C code (e.g. do_protection_exception)
-# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other
-# instructions between sie64a and .Lsie_done should not cause program
-# interrupts. So lets use a nop (47 00 00 00) as a landing pad.
+# will rewind the PSW by the ILC, which is often 4 bytes in case of SIE. There
+# are some corner cases (e.g. runtime instrumentation) where ILC is unpredictable.
+# Other instructions between sie64a and .Lsie_done should not cause program
+# interrupts. So lets use 3 nops as a landing pad for all possible rewinds.
 # See also .Lcleanup_sie
-.Lrewind_pad:
-       nop     0
+.Lrewind_pad6:
+       nopr    7
+.Lrewind_pad4:
+       nopr    7
+.Lrewind_pad2:
+       nopr    7
        .globl sie_exit
 sie_exit:
        lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
@@ -249,7 +254,9 @@ sie_exit:
        stg     %r14,__SF_EMPTY+16(%r15)        # set exit reason code
        j       sie_exit
 
-       EX_TABLE(.Lrewind_pad,.Lsie_fault)
+       EX_TABLE(.Lrewind_pad6,.Lsie_fault)
+       EX_TABLE(.Lrewind_pad4,.Lsie_fault)
+       EX_TABLE(.Lrewind_pad2,.Lsie_fault)
        EX_TABLE(sie_exit,.Lsie_fault)
 EXPORT_SYMBOL(sie64a)
 EXPORT_SYMBOL(sie_exit)
@@ -312,6 +319,7 @@ ENTRY(system_call)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lsysc_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -623,6 +631,7 @@ ENTRY(io_int_handler)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lio_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -1174,15 +1183,23 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_sysc_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_sysc_restore_insn)
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+       cghi    %r11,__LC_SAVE_AREA_ASYNC
        je      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_sysc_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_sysc_restore_insn:
+       .quad   .Lsysc_exit_timer
        .quad   .Lsysc_done - 4
 
 .Lcleanup_io_tif:
@@ -1190,15 +1207,20 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_io_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_io_restore_insn)
-       je      0f
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_io_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved r11 pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_io_restore_insn:
+       .quad   .Lio_exit_timer
        .quad   .Lio_done - 4
 
 .Lcleanup_idle:
index 27477f34cc0a9844a7391eef1e40ab28e3b1dcf1..d03a6d12c4bdc4118c3c10e0c80e90822cac6a03 100644 (file)
@@ -173,6 +173,8 @@ int __init ftrace_dyn_arch_init(void)
        return 0;
 }
 
+#ifdef CONFIG_MODULES
+
 static int __init ftrace_plt_init(void)
 {
        unsigned int *ip;
@@ -191,6 +193,8 @@ static int __init ftrace_plt_init(void)
 }
 device_initcall(ftrace_plt_init);
 
+#endif /* CONFIG_MODULES */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Hook the return address and push it in the stack of return addresses
index e545ffe5155ab0179327cfe4f9f66e677c604041..8e622bb52f7a95fd59c2f89aec95f04c616633cf 100644 (file)
@@ -564,8 +564,6 @@ static struct kset *ipl_kset;
 
 static void __ipl_run(void *unused)
 {
-       if (MACHINE_IS_LPAR && ipl_info.type == IPL_TYPE_CCW)
-               diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
        diag308(DIAG308_LOAD_CLEAR, NULL);
        if (MACHINE_IS_VM)
                __cpcmd("IPL", NULL, 0, NULL);
@@ -1088,10 +1086,7 @@ static void __reipl_run(void *unused)
                break;
        case REIPL_METHOD_CCW_DIAG:
                diag308(DIAG308_SET, reipl_block_ccw);
-               if (MACHINE_IS_LPAR)
-                       diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
-               else
-                       diag308(DIAG308_LOAD_CLEAR, NULL);
+               diag308(DIAG308_LOAD_CLEAR, NULL);
                break;
        case REIPL_METHOD_FCP_RW_DIAG:
                diag308(DIAG308_SET, reipl_block_fcp);
index 999d7154bbdcd0891f6e2d5e6c55ea4ab62d0554..bb32b8618bf61836888d383c5b3fe1c9a352c0d2 100644 (file)
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
 
-/*
- * Return saved PC of a blocked thread. used in kernel/sched.
- * resume in entry.S does not create a new stack frame, it
- * just stores the registers %r6-%r15 to the frame given by
- * schedule. We want to return the address of the caller of
- * schedule, so we have to walk the backchain one time to
- * find the frame schedule() store its return address.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       struct stack_frame *sf, *low, *high;
-
-       if (!tsk || !task_stack_page(tsk))
-               return 0;
-       low = task_stack_page(tsk);
-       high = (struct stack_frame *) task_pt_regs(tsk);
-       sf = (struct stack_frame *) tsk->thread.ksp;
-       if (sf <= low || sf > high)
-               return 0;
-       sf = (struct stack_frame *) sf->back_chain;
-       if (sf <= low || sf > high)
-               return 0;
-       return sf->gprs[8];
-}
-
 extern void kernel_thread_starter(void);
 
 /*
index 72307f108c40387fd718e9ca1e07ee5cb6ef9cb8..6e2c42bd1c3badbc4837176aeb1e266d86890bcf 100644 (file)
@@ -31,8 +31,14 @@ SECTIONS
 {
        . = 0x00000000;
        .text : {
-       _text = .;              /* Text and read-only data */
+               /* Text and read-only data */
                HEAD_TEXT
+               /*
+                * E.g. perf doesn't like symbols starting at address zero,
+                * therefore skip the initial PSW and channel program located
+                * at address zero and let _text start at 0x200.
+                */
+       _text = 0x200;
                TEXT_TEXT
                SCHED_TEXT
                CPUIDLE_TEXT
index 9da243d94cc3286c5e1dabcfae5e563f991326a0..3b297fa3aa67c59be7fdb2fd2953f431adfbc1d4 100644 (file)
@@ -977,11 +977,12 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
        ptr = asce.origin * 4096;
        if (asce.r) {
                *fake = 1;
+               ptr = 0;
                asce.dt = ASCE_TYPE_REGION1;
        }
        switch (asce.dt) {
        case ASCE_TYPE_REGION1:
-               if (vaddr.rfx01 > asce.tl && !asce.r)
+               if (vaddr.rfx01 > asce.tl && !*fake)
                        return PGM_REGION_FIRST_TRANS;
                break;
        case ASCE_TYPE_REGION2:
@@ -1009,8 +1010,7 @@ static int kvm_s390_shadow_tables(struct gmap *sg, unsigned long saddr,
                union region1_table_entry rfte;
 
                if (*fake) {
-                       /* offset in 16EB guest memory block */
-                       ptr = ptr + ((unsigned long) vaddr.rsx << 53UL);
+                       ptr += (unsigned long) vaddr.rfx << 53;
                        rfte.val = ptr;
                        goto shadow_r2t;
                }
@@ -1036,8 +1036,7 @@ shadow_r2t:
                union region2_table_entry rste;
 
                if (*fake) {
-                       /* offset in 8PB guest memory block */
-                       ptr = ptr + ((unsigned long) vaddr.rtx << 42UL);
+                       ptr += (unsigned long) vaddr.rsx << 42;
                        rste.val = ptr;
                        goto shadow_r3t;
                }
@@ -1064,8 +1063,7 @@ shadow_r3t:
                union region3_table_entry rtte;
 
                if (*fake) {
-                       /* offset in 4TB guest memory block */
-                       ptr = ptr + ((unsigned long) vaddr.sx << 31UL);
+                       ptr += (unsigned long) vaddr.rtx << 31;
                        rtte.val = ptr;
                        goto shadow_sgt;
                }
@@ -1101,8 +1099,7 @@ shadow_sgt:
                union segment_table_entry ste;
 
                if (*fake) {
-                       /* offset in 2G guest memory block */
-                       ptr = ptr + ((unsigned long) vaddr.sx << 20UL);
+                       ptr += (unsigned long) vaddr.sx << 20;
                        ste.val = ptr;
                        goto shadow_pgt;
                }
index caf15c8a8948e76c1bf7cfb5d5a109df6cee9b3e..2d120fef7d90d915e33d7f19cb0ba39e9a6a264e 100644 (file)
@@ -2160,7 +2160,7 @@ static int modify_ais_mode(struct kvm *kvm, struct kvm_device_attr *attr)
        struct kvm_s390_ais_req req;
        int ret = 0;
 
-       if (!fi->ais_enabled)
+       if (!test_kvm_facility(kvm, 72))
                return -ENOTSUPP;
 
        if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
@@ -2204,7 +2204,7 @@ static int kvm_s390_inject_airq(struct kvm *kvm,
        };
        int ret = 0;
 
-       if (!fi->ais_enabled || !adapter->suppressible)
+       if (!test_kvm_facility(kvm, 72) || !adapter->suppressible)
                return kvm_s390_inject_vm(kvm, &s390int);
 
        mutex_lock(&fi->ais_lock);
index 689ac48361c697318ba6192962c7790d027a3199..f28e2e776931e7fdcddb2ad285ddf35b1e85500e 100644 (file)
@@ -558,7 +558,6 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
                } else {
                        set_kvm_facility(kvm->arch.model.fac_mask, 72);
                        set_kvm_facility(kvm->arch.model.fac_list, 72);
-                       kvm->arch.float_int.ais_enabled = 1;
                        r = 0;
                }
                mutex_unlock(&kvm->lock);
@@ -1533,7 +1532,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        mutex_init(&kvm->arch.float_int.ais_lock);
        kvm->arch.float_int.simm = 0;
        kvm->arch.float_int.nimm = 0;
-       kvm->arch.float_int.ais_enabled = 0;
        spin_lock_init(&kvm->arch.float_int.lock);
        for (i = 0; i < FIRQ_LIST_COUNT; i++)
                INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
index ae90e1ae3607052c6ac4403f815d33061fcaf604..1963ddbf4ab385898160ce1d75881201b9c848c8 100644 (file)
@@ -4,6 +4,7 @@
  *    Copyright IBM Corp. 2014
  */
 
+#include <linux/errno.h>
 #include <asm/kprobes.h>
 #include <asm/dis.h>
 
index 1e5bb2b86c423fefee7987ec45483077748e8ca8..b3bd3f23b8e851c7f67e46cb527e20603512e7f5 100644 (file)
@@ -337,8 +337,8 @@ long __strncpy_from_user(char *dst, const char __user *src, long size)
                return 0;
        done = 0;
        do {
-               offset = (size_t)src & ~PAGE_MASK;
-               len = min(size - done, PAGE_SIZE - offset);
+               offset = (size_t)src & (L1_CACHE_BYTES - 1);
+               len = min(size - done, L1_CACHE_BYTES - offset);
                if (copy_from_user(dst, src, len))
                        return -EFAULT;
                len_str = strnlen(dst, len);
index b017daed6887847c8eb025e146ae22b37dedfb2c..b854b1da281a3bd4473e9b62bbad03197b540ff3 100644 (file)
@@ -101,7 +101,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        goto check_asce_limit;
        }
 
@@ -151,7 +151,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-                               (!vma || addr + len <= vma->vm_start))
+                               (!vma || addr + len <= vm_start_gap(vma)))
                        goto check_asce_limit;
        }
 
index d9a922d8711b2155a2225699e5958236dbb70adb..299274581968d1c850f56341615d81bddae19003 100644 (file)
@@ -13,7 +13,6 @@ struct task_struct;
  */
 extern void (*cpu_wait)(void);
 
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
 extern void start_thread(struct pt_regs *regs,
                        unsigned long pc, unsigned long sp);
 extern unsigned long get_wchan(struct task_struct *p);
index eb64d7a677cb9525afc874a1cb3a21872ad4bddb..6e20241a1ed45c428d7f5bfe9e76c55ecd5e0d07 100644 (file)
@@ -101,11 +101,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
        return 1;
 }
 
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       return task_pt_regs(tsk)->cp0_epc;
-}
-
 unsigned long get_wchan(struct task_struct *task)
 {
        if (!task || task == current || task->state == TASK_RUNNING)
index 08e7af0be4a77b021ebc1b9736a93748cb2c5b5d..6a1a1297baaeee75ded9e04bc89a402f5c2ef2f0 100644 (file)
@@ -64,7 +64,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
 
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
@@ -114,7 +114,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index 58243b0d21c006cfea9c47723221a33b7673fae9..5639c9fe5b5522d6e7b7d05ac17a6f07d579cc0c 100644 (file)
@@ -192,9 +192,9 @@ config NR_CPUS
        int "Maximum number of CPUs"
        depends on SMP
        range 2 32 if SPARC32
-       range 2 1024 if SPARC64
+       range 2 4096 if SPARC64
        default 32 if SPARC32
-       default 64 if SPARC64
+       default 4096 if SPARC64
 
 source kernel/Kconfig.hz
 
@@ -295,9 +295,13 @@ config NUMA
        depends on SPARC64 && SMP
 
 config NODES_SHIFT
-       int
-       default "4"
+       int "Maximum NUMA Nodes (as a power of 2)"
+       range 4 5 if SPARC64
+       default "5"
        depends on NEED_MULTIPLE_NODES
+       help
+         Specify the maximum number of NUMA Nodes available on the target
+         system.  Increases memory reserved to accommodate various tables.
 
 # Some NUMA nodes have memory ranges that span
 # other nodes.  Even though a pfn is valid and
@@ -573,9 +577,6 @@ config SYSVIPC_COMPAT
        depends on COMPAT && SYSVIPC
        default y
 
-config KEYS_COMPAT
-       def_bool y if COMPAT && KEYS
-
 endmenu
 
 source "net/Kconfig"
index dcbf985ab243201250222a824fc1146320522e65..d1f837dc77a4d0c975f94e5bbd315b347001d01a 100644 (file)
@@ -24,9 +24,11 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
 static inline int prepare_hugepage_range(struct file *file,
                        unsigned long addr, unsigned long len)
 {
-       if (len & ~HPAGE_MASK)
+       struct hstate *h = hstate_file(file);
+
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
-       if (addr & ~HPAGE_MASK)
+       if (addr & ~huge_page_mask(h))
                return -EINVAL;
        return 0;
 }
index f7de0dbc38af2dd36c9f34df53e6e951f6729825..83b36a5371ffc62e80fa694e077867f4f8b1f49f 100644 (file)
@@ -52,7 +52,7 @@
 #define CTX_NR_MASK            TAG_CONTEXT_BITS
 #define CTX_HW_MASK            (CTX_NR_MASK | CTX_PGSZ_MASK)
 
-#define CTX_FIRST_VERSION      ((_AC(1,UL) << CTX_VERSION_SHIFT) + _AC(1,UL))
+#define CTX_FIRST_VERSION      BIT(CTX_VERSION_SHIFT)
 #define CTX_VALID(__ctx)       \
         (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
 #define CTX_HWBITS(__ctx)      ((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
index 22fede6eba116020cf7049e2f45a57545a6d55cb..2cddcda4f85f7555dced053b1fc82fd991e19943 100644 (file)
@@ -19,13 +19,8 @@ extern spinlock_t ctx_alloc_lock;
 extern unsigned long tlb_context_cache;
 extern unsigned long mmu_context_bmap[];
 
+DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm);
 void get_new_mmu_context(struct mm_struct *mm);
-#ifdef CONFIG_SMP
-void smp_new_mmu_context_version(void);
-#else
-#define smp_new_mmu_context_version() do { } while (0)
-#endif
-
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 void destroy_context(struct mm_struct *mm);
 
@@ -76,8 +71,9 @@ void __flush_tlb_mm(unsigned long, unsigned long);
 static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
 {
        unsigned long ctx_valid, flags;
-       int cpu;
+       int cpu = smp_processor_id();
 
+       per_cpu(per_cpu_secondary_mm, cpu) = mm;
        if (unlikely(mm == &init_mm))
                return;
 
@@ -123,7 +119,6 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
         * for the first time, we must flush that context out of the
         * local TLB.
         */
-       cpu = smp_processor_id();
        if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) {
                cpumask_set_cpu(cpu, mm_cpumask(mm));
                __flush_tlb_mm(CTX_HWBITS(mm->context),
@@ -133,26 +128,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
 }
 
 #define deactivate_mm(tsk,mm)  do { } while (0)
-
-/* Activate a new MM instance for the current task. */
-static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
-{
-       unsigned long flags;
-       int cpu;
-
-       spin_lock_irqsave(&mm->context.lock, flags);
-       if (!CTX_VALID(mm->context))
-               get_new_mmu_context(mm);
-       cpu = smp_processor_id();
-       if (!cpumask_test_cpu(cpu, mm_cpumask(mm)))
-               cpumask_set_cpu(cpu, mm_cpumask(mm));
-
-       load_secondary_context(mm);
-       __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT);
-       tsb_context_switch(mm);
-       spin_unlock_irqrestore(&mm->context.lock, flags);
-}
-
+#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, NULL)
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_MMU_CONTEXT_H) */
index ce6f56980aefd2902bfae849eb90a993295976eb..cf190728360bbfb43621d23a7fb3a22c443a7399 100644 (file)
@@ -91,9 +91,9 @@ extern unsigned long pfn_base;
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern unsigned long empty_zero_page;
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
-#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
 /*
  * In general all page table modifications should use the V8 atomic
index 2669370305465d7a4d1c2f9c5a7c9eae2f66474d..522b43db2ed336a5d34dee17b4e8c3b593e6ee5d 100644 (file)
@@ -20,7 +20,6 @@
 #define PIL_SMP_CALL_FUNC      1
 #define PIL_SMP_RECEIVE_SIGNAL 2
 #define PIL_SMP_CAPTURE                3
-#define PIL_SMP_CTX_NEW_VERSION        4
 #define PIL_DEVICE_IRQ         5
 #define PIL_SMP_CALL_FUNC_SNGL 6
 #define PIL_DEFERRED_PCR_WORK  7
index dd27159819ebedce4d0479ec800e91d56706311f..b395e5620c0b986ec808675ccf3062e9a534ae43 100644 (file)
@@ -67,9 +67,6 @@ struct thread_struct {
        .current_ds = KERNEL_DS, \
 }
 
-/* Return saved PC of a blocked thread. */
-unsigned long thread_saved_pc(struct task_struct *t);
-
 /* Do necessary setup to start up a newly executed thread. */
 static inline void start_thread(struct pt_regs * regs, unsigned long pc,
                                    unsigned long sp)
index b58ee90184334224b756360e769c47a0d10e088a..f04dc5a4306245ffc0b53b3c88707332b8a25a0f 100644 (file)
@@ -89,9 +89,7 @@ struct thread_struct {
 #include <linux/types.h>
 #include <asm/fpumacro.h>
 
-/* Return saved PC of a blocked thread. */
 struct task_struct;
-unsigned long thread_saved_pc(struct task_struct *);
 
 /* On Uniprocessor, even in RMO processes see TSO semantics */
 #ifdef CONFIG_SMP
index 478bf6bb4598b345dd7f590beee86f43893e7645..3fae200dd251f094bad756ef145ec39882470d8e 100644 (file)
@@ -16,7 +16,7 @@ extern char reboot_command[];
  */
 extern unsigned char boot_cpu_id;
 
-extern unsigned long empty_zero_page;
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 extern int serial_console;
 static inline int con_is_present(void)
index 8174f6cdbbbbd87af5bdbcb923352ddadb4e237e..9dca7a892978a49d234a2b9325228b2c900d1276 100644 (file)
@@ -327,6 +327,7 @@ struct vio_dev {
        int                     compat_len;
 
        u64                     dev_no;
+       u64                     id;
 
        unsigned long           channel_id;
 
index b542cc7c8d94d8fc75319091f91ba5dc25251fd9..f87265afb1759e16b735e95067044f827dff27e7 100644 (file)
@@ -909,7 +909,7 @@ static int register_services(struct ds_info *dp)
                pbuf.req.handle = cp->handle;
                pbuf.req.major = 1;
                pbuf.req.minor = 0;
-               strcpy(pbuf.req.svc_id, cp->service_id);
+               strcpy(pbuf.id_buf, cp->service_id);
 
                err = __ds_send(lp, &pbuf, msg_len);
                if (err > 0)
index 6bcff698069bf1fa57c1d84df180c1cb67f18a65..cec54dc4ab817e7c9c54c2d9b0532f0fd49bc7d8 100644 (file)
@@ -130,17 +130,16 @@ unsigned long prepare_ftrace_return(unsigned long parent,
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return parent + 8UL;
 
-       if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
-                                    frame_pointer, NULL) == -EBUSY)
-               return parent + 8UL;
-
        trace.func = self_addr;
+       trace.depth = current->curr_ret_stack + 1;
 
        /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
+       if (!ftrace_graph_entry(&trace))
+               return parent + 8UL;
+
+       if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
+                                    frame_pointer, NULL) == -EBUSY)
                return parent + 8UL;
-       }
 
        return return_hooker;
 }
index 4d0248aa0928695597161d93f325a49311b43e2c..99dd133a029f06528f78b2b811d81c97fc7cf9f4 100644 (file)
@@ -1034,17 +1034,26 @@ static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
 {
 #ifdef CONFIG_SMP
        unsigned long page;
+       void *mondo, *p;
 
-       BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
+       BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > PAGE_SIZE);
+
+       /* Make sure mondo block is 64byte aligned */
+       p = kzalloc(127, GFP_KERNEL);
+       if (!p) {
+               prom_printf("SUN4V: Error, cannot allocate mondo block.\n");
+               prom_halt();
+       }
+       mondo = (void *)(((unsigned long)p + 63) & ~0x3f);
+       tb->cpu_mondo_block_pa = __pa(mondo);
 
        page = get_zeroed_page(GFP_KERNEL);
        if (!page) {
-               prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
+               prom_printf("SUN4V: Error, cannot allocate cpu list page.\n");
                prom_halt();
        }
 
-       tb->cpu_mondo_block_pa = __pa(page);
-       tb->cpu_list_pa = __pa(page + 64);
+       tb->cpu_list_pa = __pa(page);
 #endif
 }
 
index c9804551262cc2832ea35b0d1285dc3051319fd4..6ae1e77be0bfde27696595a1f33e939935d83321 100644 (file)
@@ -37,7 +37,6 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
 /* smp_64.c */
 void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs);
 void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs);
-void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs);
 void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs);
 void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs);
 
index b6dac8e980f07183f9ea300abcfb033d0251b5c0..9245f93398c76a59a073963253609c1fc54bfeec 100644 (file)
@@ -176,14 +176,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
        printk("\n");
 }
 
-/*
- * Note: sparc64 has a pretty intricated thread_saved_pc, check it out.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       return task_thread_info(tsk)->kpc;
-}
-
 /*
  * Free current thread data structures etc..
  */
index 1badc493e62ee71c2e538758aec3c446780ea671..b96104da5bd6116b119872eaa79e013636aa328c 100644 (file)
@@ -400,25 +400,6 @@ core_initcall(sparc_sysrq_init);
 
 #endif
 
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       struct thread_info *ti = task_thread_info(tsk);
-       unsigned long ret = 0xdeadbeefUL;
-       
-       if (ti && ti->ksp) {
-               unsigned long *sp;
-               sp = (unsigned long *)(ti->ksp + STACK_BIAS);
-               if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
-                   sp[14]) {
-                       unsigned long *fp;
-                       fp = (unsigned long *)(sp[14] + STACK_BIAS);
-                       if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
-                               ret = fp[15];
-               }
-       }
-       return ret;
-}
-
 /* Free current thread data structures etc.. */
 void exit_thread(struct task_struct *tsk)
 {
index b3bc0ac757cc11c0c77e106a447817b89d821cae..fdf31040a7dc5cc460de6d60c9724a60933b38dc 100644 (file)
@@ -964,37 +964,6 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
        preempt_enable();
 }
 
-void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
-{
-       struct mm_struct *mm;
-       unsigned long flags;
-
-       clear_softint(1 << irq);
-
-       /* See if we need to allocate a new TLB context because
-        * the version of the one we are using is now out of date.
-        */
-       mm = current->active_mm;
-       if (unlikely(!mm || (mm == &init_mm)))
-               return;
-
-       spin_lock_irqsave(&mm->context.lock, flags);
-
-       if (unlikely(!CTX_VALID(mm->context)))
-               get_new_mmu_context(mm);
-
-       spin_unlock_irqrestore(&mm->context.lock, flags);
-
-       load_secondary_context(mm);
-       __flush_tlb_mm(CTX_HWBITS(mm->context),
-                      SECONDARY_CONTEXT);
-}
-
-void smp_new_mmu_context_version(void)
-{
-       smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
-}
-
 #ifdef CONFIG_KGDB
 void kgdb_roundup_cpus(unsigned long flags)
 {
index ef4520efc8130c1aeef8a36d4de24fdecf78c883..043544d0cda3f000ffca1a1c1f2f00680218d8d9 100644 (file)
@@ -120,7 +120,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
 
                vma = find_vma(mm, addr);
                if (task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
@@ -183,7 +183,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 
                vma = find_vma(mm, addr);
                if (task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index 10689cfd0ad40e6b12ae6b148f99ac2f5c7deb64..07c0df92496034efd1262dd2b40e56ffd5486c0c 100644 (file)
@@ -455,13 +455,16 @@ __tsb_context_switch:
        .type   copy_tsb,#function
 copy_tsb:              /* %o0=old_tsb_base, %o1=old_tsb_size
                         * %o2=new_tsb_base, %o3=new_tsb_size
+                        * %o4=page_size_shift
                         */
        sethi           %uhi(TSB_PASS_BITS), %g7
        srlx            %o3, 4, %o3
-       add             %o0, %o1, %g1   /* end of old tsb */
+       add             %o0, %o1, %o1   /* end of old tsb */
        sllx            %g7, 32, %g7
        sub             %o3, 1, %o3     /* %o3 == new tsb hash mask */
 
+       mov             %o4, %g1        /* page_size_shift */
+
 661:   prefetcha       [%o0] ASI_N, #one_read
        .section        .tsb_phys_patch, "ax"
        .word           661b
@@ -486,9 +489,9 @@ copy_tsb:           /* %o0=old_tsb_base, %o1=old_tsb_size
        /* This can definitely be computed faster... */
        srlx            %o0, 4, %o5     /* Build index */
        and             %o5, 511, %o5   /* Mask index */
-       sllx            %o5, PAGE_SHIFT, %o5 /* Put into vaddr position */
+       sllx            %o5, %g1, %o5   /* Put into vaddr position */
        or              %o4, %o5, %o4   /* Full VADDR. */
-       srlx            %o4, PAGE_SHIFT, %o4 /* Shift down to create index */
+       srlx            %o4, %g1, %o4   /* Shift down to create index */
        and             %o4, %o3, %o4   /* Mask with new_tsb_nents-1 */
        sllx            %o4, 4, %o4     /* Shift back up into tsb ent offset */
        TSB_STORE(%o2 + %o4, %g2)       /* Store TAG */
@@ -496,7 +499,7 @@ copy_tsb:           /* %o0=old_tsb_base, %o1=old_tsb_size
        TSB_STORE(%o2 + %o4, %g3)       /* Store TTE */
 
 80:    add             %o0, 16, %o0
-       cmp             %o0, %g1
+       cmp             %o0, %o1
        bne,pt          %xcc, 90b
         nop
 
index 7bd8f6556352d91cdc30e18d590e7421ffba6465..efe93ab4a9c0654143d52569c7157f9117e7ae37 100644 (file)
@@ -50,7 +50,7 @@ tl0_resv03e:  BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
 tl0_irq1:      TRAP_IRQ(smp_call_function_client, 1)
 tl0_irq2:      TRAP_IRQ(smp_receive_signal_client, 2)
 tl0_irq3:      TRAP_IRQ(smp_penguin_jailcell, 3)
-tl0_irq4:      TRAP_IRQ(smp_new_mmu_context_version_client, 4)
+tl0_irq4:       BTRAP(0x44)
 #else
 tl0_irq1:      BTRAP(0x41)
 tl0_irq2:      BTRAP(0x42)
index f6bb857254fcfa170155d4cd8dc8cb717c5bfb97..075d38980dee394fdb32f86e130d0b3ec37ebfeb 100644 (file)
@@ -302,13 +302,16 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
        if (!id) {
                dev_set_name(&vdev->dev, "%s", bus_id_name);
                vdev->dev_no = ~(u64)0;
+               vdev->id = ~(u64)0;
        } else if (!cfg_handle) {
                dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id);
                vdev->dev_no = *id;
+               vdev->id = ~(u64)0;
        } else {
                dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name,
                             *cfg_handle, *id);
                vdev->dev_no = *cfg_handle;
+               vdev->id = *id;
        }
 
        vdev->dev.parent = parent;
@@ -351,27 +354,84 @@ static void vio_add(struct mdesc_handle *hp, u64 node)
        (void) vio_create_one(hp, node, &root_vdev->dev);
 }
 
+struct vio_md_node_query {
+       const char *type;
+       u64 dev_no;
+       u64 id;
+};
+
 static int vio_md_node_match(struct device *dev, void *arg)
 {
+       struct vio_md_node_query *query = (struct vio_md_node_query *) arg;
        struct vio_dev *vdev = to_vio_dev(dev);
 
-       if (vdev->mp == (u64) arg)
-               return 1;
+       if (vdev->dev_no != query->dev_no)
+               return 0;
+       if (vdev->id != query->id)
+               return 0;
+       if (strcmp(vdev->type, query->type))
+               return 0;
 
-       return 0;
+       return 1;
 }
 
 static void vio_remove(struct mdesc_handle *hp, u64 node)
 {
+       const char *type;
+       const u64 *id, *cfg_handle;
+       u64 a;
+       struct vio_md_node_query query;
        struct device *dev;
 
-       dev = device_find_child(&root_vdev->dev, (void *) node,
+       type = mdesc_get_property(hp, node, "device-type", NULL);
+       if (!type) {
+               type = mdesc_get_property(hp, node, "name", NULL);
+               if (!type)
+                       type = mdesc_node_name(hp, node);
+       }
+
+       query.type = type;
+
+       id = mdesc_get_property(hp, node, "id", NULL);
+       cfg_handle = NULL;
+       mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
+               u64 target;
+
+               target = mdesc_arc_target(hp, a);
+               cfg_handle = mdesc_get_property(hp, target,
+                                               "cfg-handle", NULL);
+               if (cfg_handle)
+                       break;
+       }
+
+       if (!id) {
+               query.dev_no = ~(u64)0;
+               query.id = ~(u64)0;
+       } else if (!cfg_handle) {
+               query.dev_no = *id;
+               query.id = ~(u64)0;
+       } else {
+               query.dev_no = *cfg_handle;
+               query.id = *id;
+       }
+
+       dev = device_find_child(&root_vdev->dev, &query,
                                vio_md_node_match);
        if (dev) {
                printk(KERN_INFO "VIO: Removing device %s\n", dev_name(dev));
 
                device_unregister(dev);
                put_device(dev);
+       } else {
+               if (!id)
+                       printk(KERN_ERR "VIO: Removed unknown %s node.\n",
+                              type);
+               else if (!cfg_handle)
+                       printk(KERN_ERR "VIO: Removed unknown %s node %llu.\n",
+                              type, *id);
+               else
+                       printk(KERN_ERR "VIO: Removed unknown %s node %llu-%llu.\n",
+                              type, *cfg_handle, *id);
        }
 }
 
index 69912d2f8b54e903ef040b346371cc27204b9d15..07c03e72d81248cebe9c3d48bbc93e1e2de455b7 100644 (file)
@@ -15,6 +15,7 @@ lib-$(CONFIG_SPARC32) += copy_user.o locks.o
 lib-$(CONFIG_SPARC64) += atomic_64.o
 lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
 lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
+lib-$(CONFIG_SPARC64) += multi3.o
 
 lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o
 lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o
diff --git a/arch/sparc/lib/multi3.S b/arch/sparc/lib/multi3.S
new file mode 100644 (file)
index 0000000..d6b6c97
--- /dev/null
@@ -0,0 +1,35 @@
+#include <linux/linkage.h>
+#include <asm/export.h>
+
+       .text
+       .align  4
+ENTRY(__multi3) /* %o0 = u, %o1 = v */
+       mov     %o1, %g1
+       srl     %o3, 0, %g4
+       mulx    %g4, %g1, %o1
+       srlx    %g1, 0x20, %g3
+       mulx    %g3, %g4, %g5
+       sllx    %g5, 0x20, %o5
+       srl     %g1, 0, %g4
+       sub     %o1, %o5, %o5
+       srlx    %o5, 0x20, %o5
+       addcc   %g5, %o5, %g5
+       srlx    %o3, 0x20, %o5
+       mulx    %g4, %o5, %g4
+       mulx    %g3, %o5, %o5
+       sethi   %hi(0x80000000), %g3
+       addcc   %g5, %g4, %g5
+       srlx    %g5, 0x20, %g5
+       add     %g3, %g3, %g3
+       movcc   %xcc, %g0, %g3
+       addcc   %o5, %g5, %o5
+       sllx    %g4, 0x20, %g4
+       add     %o1, %g4, %o1
+       add     %o5, %g3, %g2
+       mulx    %g1, %o2, %g1
+       add     %g1, %g2, %g1
+       mulx    %o0, %o3, %o0
+       retl
+        add    %g1, %o0, %o0
+ENDPROC(__multi3)
+EXPORT_SYMBOL(__multi3)
index 7c29d38e6b99c68c5ac746eb3d3a3fe1da8394a5..88855e383b34c16a8960b1ff89ae207a1ad50b07 100644 (file)
@@ -120,7 +120,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (task_size - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
        if (mm->get_unmapped_area == arch_get_unmapped_area)
index c6afe98de4d9aba5ebad292031735988afd8180d..3bd0d513bddbde7f95275be6e3ae94bd26729c6f 100644 (file)
@@ -290,7 +290,7 @@ void __init mem_init(void)
 
 
        /* Saves us work later. */
-       memset((void *)&empty_zero_page, 0, PAGE_SIZE);
+       memset((void *)empty_zero_page, 0, PAGE_SIZE);
 
        i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
        i += 1;
index 0cda653ae007645fa01f05b4c40518332159a6ac..3c40ebd50f928cbbbfe69c65c35810a78b30c53d 100644 (file)
@@ -358,7 +358,8 @@ static int __init setup_hugepagesz(char *string)
        }
 
        if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U) {
-               pr_warn("hugepagesz=%llu not supported by MMU.\n",
+               hugetlb_bad_size();
+               pr_err("hugepagesz=%llu not supported by MMU.\n",
                        hugepage_size);
                goto out;
        }
@@ -706,10 +707,58 @@ EXPORT_SYMBOL(__flush_dcache_range);
 
 /* get_new_mmu_context() uses "cache + 1".  */
 DEFINE_SPINLOCK(ctx_alloc_lock);
-unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
+unsigned long tlb_context_cache = CTX_FIRST_VERSION;
 #define MAX_CTX_NR     (1UL << CTX_NR_BITS)
 #define CTX_BMAP_SLOTS BITS_TO_LONGS(MAX_CTX_NR)
 DECLARE_BITMAP(mmu_context_bmap, MAX_CTX_NR);
+DEFINE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm) = {0};
+
+static void mmu_context_wrap(void)
+{
+       unsigned long old_ver = tlb_context_cache & CTX_VERSION_MASK;
+       unsigned long new_ver, new_ctx, old_ctx;
+       struct mm_struct *mm;
+       int cpu;
+
+       bitmap_zero(mmu_context_bmap, 1 << CTX_NR_BITS);
+
+       /* Reserve kernel context */
+       set_bit(0, mmu_context_bmap);
+
+       new_ver = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
+       if (unlikely(new_ver == 0))
+               new_ver = CTX_FIRST_VERSION;
+       tlb_context_cache = new_ver;
+
+       /*
+        * Make sure that any new mm that are added into per_cpu_secondary_mm,
+        * are going to go through get_new_mmu_context() path.
+        */
+       mb();
+
+       /*
+        * Updated versions to current on those CPUs that had valid secondary
+        * contexts
+        */
+       for_each_online_cpu(cpu) {
+               /*
+                * If a new mm is stored after we took this mm from the array,
+                * it will go into get_new_mmu_context() path, because we
+                * already bumped the version in tlb_context_cache.
+                */
+               mm = per_cpu(per_cpu_secondary_mm, cpu);
+
+               if (unlikely(!mm || mm == &init_mm))
+                       continue;
+
+               old_ctx = mm->context.sparc64_ctx_val;
+               if (likely((old_ctx & CTX_VERSION_MASK) == old_ver)) {
+                       new_ctx = (old_ctx & ~CTX_VERSION_MASK) | new_ver;
+                       set_bit(new_ctx & CTX_NR_MASK, mmu_context_bmap);
+                       mm->context.sparc64_ctx_val = new_ctx;
+               }
+       }
+}
 
 /* Caller does TLB context flushing on local CPU if necessary.
  * The caller also ensures that CTX_VALID(mm->context) is false.
@@ -725,48 +774,30 @@ void get_new_mmu_context(struct mm_struct *mm)
 {
        unsigned long ctx, new_ctx;
        unsigned long orig_pgsz_bits;
-       int new_version;
 
        spin_lock(&ctx_alloc_lock);
+retry:
+       /* wrap might have happened, test again if our context became valid */
+       if (unlikely(CTX_VALID(mm->context)))
+               goto out;
        orig_pgsz_bits = (mm->context.sparc64_ctx_val & CTX_PGSZ_MASK);
        ctx = (tlb_context_cache + 1) & CTX_NR_MASK;
        new_ctx = find_next_zero_bit(mmu_context_bmap, 1 << CTX_NR_BITS, ctx);
-       new_version = 0;
        if (new_ctx >= (1 << CTX_NR_BITS)) {
                new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
                if (new_ctx >= ctx) {
-                       int i;
-                       new_ctx = (tlb_context_cache & CTX_VERSION_MASK) +
-                               CTX_FIRST_VERSION;
-                       if (new_ctx == 1)
-                               new_ctx = CTX_FIRST_VERSION;
-
-                       /* Don't call memset, for 16 entries that's just
-                        * plain silly...
-                        */
-                       mmu_context_bmap[0] = 3;
-                       mmu_context_bmap[1] = 0;
-                       mmu_context_bmap[2] = 0;
-                       mmu_context_bmap[3] = 0;
-                       for (i = 4; i < CTX_BMAP_SLOTS; i += 4) {
-                               mmu_context_bmap[i + 0] = 0;
-                               mmu_context_bmap[i + 1] = 0;
-                               mmu_context_bmap[i + 2] = 0;
-                               mmu_context_bmap[i + 3] = 0;
-                       }
-                       new_version = 1;
-                       goto out;
+                       mmu_context_wrap();
+                       goto retry;
                }
        }
+       if (mm->context.sparc64_ctx_val)
+               cpumask_clear(mm_cpumask(mm));
        mmu_context_bmap[new_ctx>>6] |= (1UL << (new_ctx & 63));
        new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
-out:
        tlb_context_cache = new_ctx;
        mm->context.sparc64_ctx_val = new_ctx | orig_pgsz_bits;
+out:
        spin_unlock(&ctx_alloc_lock);
-
-       if (unlikely(new_version))
-               smp_new_mmu_context_version();
 }
 
 static int numa_enabled = 1;
index bedf08b22a4773c5a104b56f7de8b44c461630c1..0d4b998c7d7b74a9e930f12d735591f14769befd 100644 (file)
@@ -496,7 +496,8 @@ retry_tsb_alloc:
                extern void copy_tsb(unsigned long old_tsb_base,
                                     unsigned long old_tsb_size,
                                     unsigned long new_tsb_base,
-                                    unsigned long new_tsb_size);
+                                    unsigned long new_tsb_size,
+                                    unsigned long page_size_shift);
                unsigned long old_tsb_base = (unsigned long) old_tsb;
                unsigned long new_tsb_base = (unsigned long) new_tsb;
 
@@ -504,7 +505,9 @@ retry_tsb_alloc:
                        old_tsb_base = __pa(old_tsb_base);
                        new_tsb_base = __pa(new_tsb_base);
                }
-               copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size);
+               copy_tsb(old_tsb_base, old_size, new_tsb_base, new_size,
+                       tsb_index == MM_TSB_BASE ?
+                       PAGE_SHIFT : REAL_HPAGE_SHIFT);
        }
 
        mm->context.tsb_block[tsb_index].tsb = new_tsb;
index 5d2fd6cd31896b87a3373a59cbfc3130808c6908..fcf4d27a38fb47af30d026079022d07bb803e323 100644 (file)
@@ -971,11 +971,6 @@ xcall_capture:
        wr              %g0, (1 << PIL_SMP_CAPTURE), %set_softint
        retry
 
-       .globl          xcall_new_mmu_context_version
-xcall_new_mmu_context_version:
-       wr              %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
-       retry
-
 #ifdef CONFIG_KGDB
        .globl          xcall_kgdb_capture
 xcall_kgdb_capture:
index 0bc9968b97a19296a48d4dfb215cd3464b69f9a6..f71e5206650bf91578677720a7701a3d766d0436 100644 (file)
@@ -214,13 +214,6 @@ static inline void release_thread(struct task_struct *dead_task)
 
 extern void prepare_exit_to_usermode(struct pt_regs *regs, u32 flags);
 
-
-/*
- * Return saved (kernel) PC of a blocked thread.
- * Only used in a printk() in kernel/sched/core.c, so don't work too hard.
- */
-#define thread_saved_pc(t)   ((t)->thread.pc)
-
 unsigned long get_wchan(struct task_struct *p);
 
 /* Return initial ksp value for given task. */
index cb10153b5c9fb4307b92359a8118be91895715db..03e5cc4e76e4e67548c8ea396012d66d8ab89752 100644 (file)
@@ -233,7 +233,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
        if (current->mm->get_unmapped_area == arch_get_unmapped_area)
index 2d1e0dd5bb0bf55a7e543f9f7f9e0eefd6ab4cac..f6d1a3f747a9b58b3f33ce0ee25c3bf889985c0b 100644 (file)
@@ -58,8 +58,6 @@ static inline void release_thread(struct task_struct *task)
 {
 }
 
-extern unsigned long thread_saved_pc(struct task_struct *t);
-
 static inline void mm_copy_segments(struct mm_struct *from_mm,
                                    struct mm_struct *new_mm)
 {
index 64a1fd06f3fde02d964c4fedcb9e73328085c94d..7b56401173250e1dbb61208106c35c58e324812b 100644 (file)
@@ -56,12 +56,6 @@ union thread_union cpu0_irqstack
        __attribute__((__section__(".data..init_irqstack"))) =
                { INIT_THREAD_INFO(init_task) };
 
-unsigned long thread_saved_pc(struct task_struct *task)
-{
-       /* FIXME: Need to look up userspace_pid by cpu */
-       return os_process_pc(userspace_pid[0]);
-}
-
 /* Changed in setup_arch, which is called in early boot */
 static char host_info[(__NEW_UTS_LEN + 1) * 5];
 
index cd18994a9555ab7ec628da2bdc909dd445fef1a2..0efb4c9497bce7e491665688840c4ced8e2c66c6 100644 (file)
@@ -360,7 +360,7 @@ config SMP
          Management" code will be disabled if you say Y here.
 
          See also <file:Documentation/x86/i386/IO-APIC.txt>,
-         <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+         <file:Documentation/lockup-watchdogs.txt> and the SMP-HOWTO available at
          <http://www.tldp.org/docs.html#howto>.
 
          If you don't know what to do here, say N.
@@ -2776,10 +2776,6 @@ config COMPAT_FOR_U64_ALIGNMENT
 config SYSVIPC_COMPAT
        def_bool y
        depends on SYSVIPC
-
-config KEYS_COMPAT
-       def_bool y
-       depends on KEYS
 endif
 
 endmenu
index 5851411e60fb9fd008f0035ac92932bd03eb519b..bf240b9204738598e78ece3f99e85d8f21385ea4 100644 (file)
@@ -159,7 +159,7 @@ ifdef CONFIG_FUNCTION_GRAPH_TRACER
        # If '-Os' is enabled, disable it and print a warning.
         ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
           undefine CONFIG_CC_OPTIMIZE_FOR_SIZE
-         $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE.  Your compiler does not have -mfentry so you cannot optimize for size with CONFIG_FUNCTION_GRAPH_TRACER.)
+          $(warning Disabling CONFIG_CC_OPTIMIZE_FOR_SIZE.  Your compiler does not have -mfentry so you cannot optimize for size with CONFIG_FUNCTION_GRAPH_TRACER.)
         endif
 
     endif
index 44163e8c3868ec4dda58fed54f38411134224089..2c860ad4fe0686a9cf796cd9a5b4453b8199223f 100644 (file)
@@ -94,7 +94,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
 quiet_cmd_check_data_rel = DATAREL $@
 define cmd_check_data_rel
        for obj in $(filter %.o,$^); do \
-               readelf -S $$obj | grep -qF .rel.local && { \
+               ${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
                        echo "error: $$obj has data relocations!" >&2; \
                        exit 1; \
                } || true; \
index 54c24f0a43d36c02f3e016961c4d5f7cc4ffd029..56a7e9201741033526443f1e14968ba362c492eb 100644 (file)
@@ -564,9 +564,6 @@ void choose_random_location(unsigned long input,
 {
        unsigned long random_addr, min_addr;
 
-       /* By default, keep output position unchanged. */
-       *virt_addr = *output;
-
        if (cmdline_find_option_bool("nokaslr")) {
                warn("KASLR disabled: 'nokaslr' on cmdline.");
                return;
index b3c5a5f030ced9e6610aeb84889561a3a0f7500e..00241c81552448c9a3877a16eb0183e2d81438ea 100644 (file)
@@ -338,7 +338,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
                                  unsigned long output_len)
 {
        const unsigned long kernel_total_size = VO__end - VO__text;
-       unsigned long virt_addr = (unsigned long)output;
+       unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
 
        /* Retain x86 boot parameters pointer passed from startup_32/64. */
        boot_params = rmode;
@@ -390,6 +390,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 #ifdef CONFIG_X86_64
        if (heap > 0x3fffffffffffUL)
                error("Destination address too large");
+       if (virt_addr + max(output_len, kernel_total_size) > KERNEL_IMAGE_SIZE)
+               error("Destination virtual address is beyond the kernel mapping area");
 #else
        if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
                error("Destination address too large");
@@ -397,7 +399,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 #ifndef CONFIG_RELOCATABLE
        if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
                error("Destination address does not match LOAD_PHYSICAL_ADDR");
-       if ((unsigned long)output != virt_addr)
+       if (virt_addr != LOAD_PHYSICAL_ADDR)
                error("Destination virtual address changed when not relocatable");
 #endif
 
index 1c8355eadbd199027fd12da0347f5f3f5f2dcf43..766a5211f82768303087818c8da4ef280e688dd0 100644 (file)
@@ -81,8 +81,6 @@ static inline void choose_random_location(unsigned long input,
                                          unsigned long output_size,
                                          unsigned long *virt_addr)
 {
-       /* No change from existing output location. */
-       *virt_addr = *output;
 }
 #endif
 
index 50bc26949e9edf75cc5978f8a08a4273bf489aec..48ef7bb32c4269331ceb2332b8e6bf5faffcb3de 100644 (file)
@@ -251,6 +251,23 @@ ENTRY(__switch_to_asm)
        jmp     __switch_to
 END(__switch_to_asm)
 
+/*
+ * The unwinder expects the last frame on the stack to always be at the same
+ * offset from the end of the page, which allows it to validate the stack.
+ * Calling schedule_tail() directly would break that convention because its an
+ * asmlinkage function so its argument has to be pushed on the stack.  This
+ * wrapper creates a proper "end of stack" frame header before the call.
+ */
+ENTRY(schedule_tail_wrapper)
+       FRAME_BEGIN
+
+       pushl   %eax
+       call    schedule_tail
+       popl    %eax
+
+       FRAME_END
+       ret
+ENDPROC(schedule_tail_wrapper)
 /*
  * A newly forked process directly context switches into this address.
  *
@@ -259,24 +276,15 @@ END(__switch_to_asm)
  * edi: kernel thread arg
  */
 ENTRY(ret_from_fork)
-       FRAME_BEGIN             /* help unwinder find end of stack */
-
-       /*
-        * schedule_tail() is asmlinkage so we have to put its 'prev' argument
-        * on the stack.
-        */
-       pushl   %eax
-       call    schedule_tail
-       popl    %eax
+       call    schedule_tail_wrapper
 
        testl   %ebx, %ebx
        jnz     1f              /* kernel threads are uncommon */
 
 2:
        /* When we fork, we trace the syscall return in the child, too. */
-       leal    FRAME_OFFSET(%esp), %eax
+       movl    %esp, %eax
        call    syscall_return_slowpath
-       FRAME_END
        jmp     restore_all
 
        /* kernel thread */
index 607d72c4a485cf25a3e582804cea0b7c031e1d32..4a4c0834f9659bd9b4855e23801d47103e644f09 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/smap.h>
 #include <asm/pgtable_types.h>
 #include <asm/export.h>
-#include <asm/frame.h>
 #include <linux/err.h>
 
 .code64
@@ -406,19 +405,17 @@ END(__switch_to_asm)
  * r12: kernel thread arg
  */
 ENTRY(ret_from_fork)
-       FRAME_BEGIN                     /* help unwinder find end of stack */
        movq    %rax, %rdi
-       call    schedule_tail           /* rdi: 'prev' task parameter */
+       call    schedule_tail                   /* rdi: 'prev' task parameter */
 
-       testq   %rbx, %rbx              /* from kernel_thread? */
-       jnz     1f                      /* kernel threads are uncommon */
+       testq   %rbx, %rbx                      /* from kernel_thread? */
+       jnz     1f                              /* kernel threads are uncommon */
 
 2:
-       leaq    FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */
+       movq    %rsp, %rdi
        call    syscall_return_slowpath /* returns with IRQs disabled */
        TRACE_IRQS_ON                   /* user mode is traced as IRQS on */
        SWAPGS
-       FRAME_END
        jmp     restore_regs_and_iret
 
 1:
index a6d91d4e37a1f1dadae588a1c084e31e65d08f5d..110ce8238466f7e404d8312dd8d9297fa09355c9 100644 (file)
@@ -431,11 +431,11 @@ static __initconst const u64 skl_hw_cache_event_ids
  [ C(DTLB) ] = {
        [ C(OP_READ) ] = {
                [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_INST_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x608,   /* DTLB_LOAD_MISSES.WALK_COMPLETED */
+               [ C(RESULT_MISS)   ] = 0xe08,   /* DTLB_LOAD_MISSES.WALK_COMPLETED */
        },
        [ C(OP_WRITE) ] = {
                [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_INST_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x649,   /* DTLB_STORE_MISSES.WALK_COMPLETED */
+               [ C(RESULT_MISS)   ] = 0xe49,   /* DTLB_STORE_MISSES.WALK_COMPLETED */
        },
        [ C(OP_PREFETCH) ] = {
                [ C(RESULT_ACCESS) ] = 0x0,
index 758c1aa5009d2414f3165a31abb6044b6ccf0409..44ec523287f670dff8eee3e3c9eb1bb1606489b6 100644 (file)
@@ -1170,7 +1170,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
                pmu = type->pmus;
                for (i = 0; i < type->num_boxes; i++, pmu++) {
                        box = pmu->boxes[pkg];
-                       if (!box && atomic_inc_return(&box->refcnt) == 1)
+                       if (box && atomic_inc_return(&box->refcnt) == 1)
                                uncore_box_init(box);
                }
        }
index b8ad261d11dce0d5f196efdc71e9f2b5e837d4bf..c66d19e3c23e8c6e31630c5c06f8a90539025695 100644 (file)
@@ -29,6 +29,7 @@ struct pt_regs;
        } while (0)
 
 extern int fixup_exception(struct pt_regs *regs, int trapnr);
+extern int fixup_bug(struct pt_regs *regs, int trapnr);
 extern bool ex_has_fault_handler(unsigned long ip);
 extern void early_fixup_exception(struct pt_regs *regs, int trapnr);
 
index 05596261577937d65afcad75574bab676a7effe9..722d0e56886342a3a9f65d7f419d0e240a9cc6ab 100644 (file)
@@ -296,6 +296,7 @@ struct x86_emulate_ctxt {
 
        bool perm_ok; /* do not check permissions if true */
        bool ud;        /* inject an #UD if host doesn't support insn */
+       bool tf;        /* TF value before instruction (after for syscall/sysret) */
 
        bool have_exception;
        struct x86_exception exception;
index 9c761fea0c982e6dfd6acb949d7c8f738a50fd67..695605eb1dfbd941b591564fef723bd030c3316f 100644 (file)
@@ -43,7 +43,7 @@
 #define KVM_PRIVATE_MEM_SLOTS 3
 #define KVM_MEM_SLOTS_NUM (KVM_USER_MEM_SLOTS + KVM_PRIVATE_MEM_SLOTS)
 
-#define KVM_HALT_POLL_NS_DEFAULT 400000
+#define KVM_HALT_POLL_NS_DEFAULT 200000
 
 #define KVM_IRQCHIP_NUM_PINS  KVM_IOAPIC_NUM_PINS
 
index 4fd5195deed01836a092dccf680baf6b3e150713..3f9a3d2a52095af1f100e72bc3c24b4fc8d1b397 100644 (file)
@@ -266,6 +266,7 @@ static inline int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *s
 #endif
 
 int mce_available(struct cpuinfo_x86 *c);
+bool mce_is_memory_error(struct mce *m);
 
 DECLARE_PER_CPU(unsigned, mce_exception_count);
 DECLARE_PER_CPU(unsigned, mce_poll_count);
index fba1007139243b21081b6bfa114bed588e6f4e8e..d5acc27ed1cc79ab7bc621ae0d85ad4076cbc4cc 100644 (file)
@@ -2,8 +2,7 @@
 #define _ASM_X86_MSHYPER_H
 
 #include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/clocksource.h>
+#include <linux/atomic.h>
 #include <asm/hyperv.h>
 
 /*
index 3cada998a402a7893ffd2fc709916f4fcbc3f970..a28b671f15499590d3b7243eb7909436aa27b814 100644 (file)
@@ -860,8 +860,6 @@ extern unsigned long KSTK_ESP(struct task_struct *task);
 
 #endif /* CONFIG_X86_64 */
 
-extern unsigned long thread_saved_pc(struct task_struct *tsk);
-
 extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
                                               unsigned long new_sp);
 
index 68766b276d9eea540ef6aad3f43d4b52e6b8bf54..a059aac9e9377d26555c0dee3898b75e54ece194 100644 (file)
@@ -319,10 +319,10 @@ do {                                                                      \
 #define __get_user_asm_u64(x, ptr, retval, errret)                     \
 ({                                                                     \
        __typeof__(ptr) __ptr = (ptr);                                  \
-       asm volatile(ASM_STAC "\n"                                      \
+       asm volatile("\n"                                       \
                     "1:        movl %2,%%eax\n"                        \
                     "2:        movl %3,%%edx\n"                        \
-                    "3: " ASM_CLAC "\n"                                \
+                    "3:\n"                             \
                     ".section .fixup,\"ax\"\n"                         \
                     "4:        mov %4,%0\n"                            \
                     "  xorl %%eax,%%eax\n"                             \
@@ -331,7 +331,7 @@ do {                                                                        \
                     ".previous\n"                                      \
                     _ASM_EXTABLE(1b, 4b)                               \
                     _ASM_EXTABLE(2b, 4b)                               \
-                    : "=r" (retval), "=A"(x)                           \
+                    : "=r" (retval), "=&A"(x)                          \
                     : "m" (__m(__ptr)), "m" __m(((u32 *)(__ptr)) + 1), \
                       "i" (errret), "0" (retval));                     \
 })
@@ -703,14 +703,15 @@ extern struct movsl_mask {
 #define unsafe_put_user(x, ptr, err_label)                                     \
 do {                                                                           \
        int __pu_err;                                                           \
-       __put_user_size((x), (ptr), sizeof(*(ptr)), __pu_err, -EFAULT);         \
+       __typeof__(*(ptr)) __pu_val = (x);                                      \
+       __put_user_size(__pu_val, (ptr), sizeof(*(ptr)), __pu_err, -EFAULT);    \
        if (unlikely(__pu_err)) goto err_label;                                 \
 } while (0)
 
 #define unsafe_get_user(x, ptr, err_label)                                     \
 do {                                                                           \
        int __gu_err;                                                           \
-       unsigned long __gu_val;                                                 \
+       __inttype(*(ptr)) __gu_val;                                             \
        __get_user_size(__gu_val, (ptr), sizeof(*(ptr)), __gu_err, -EFAULT);    \
        (x) = (__force __typeof__(*(ptr)))__gu_val;                             \
        if (unlikely(__gu_err)) goto err_label;                                 \
index c5b8f760473c32f090c430693c5b2e8a61cc196f..32e14d13741670efa680c3c9e9facd1ffc0415a5 100644 (file)
@@ -409,8 +409,13 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
                memcpy(insnbuf, replacement, a->replacementlen);
                insnbuf_sz = a->replacementlen;
 
-               /* 0xe8 is a relative jump; fix the offset. */
-               if (*insnbuf == 0xe8 && a->replacementlen == 5) {
+               /*
+                * 0xe8 is a relative jump; fix the offset.
+                *
+                * Instruction length is checked before the opcode to avoid
+                * accessing uninitialized bytes for zero-length replacements.
+                */
+               if (a->replacementlen == 5 && *insnbuf == 0xe8) {
                        *(s32 *)(insnbuf + 1) += replacement - instr;
                        DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx",
                                *(s32 *)(insnbuf + 1),
index a70fd61095f8a73baa5eb7c486afd6ff19cd4fd1..6f077445647a6840b8318cba2584e1259e1a4db1 100644 (file)
@@ -255,6 +255,7 @@ static void init_cyrix(struct cpuinfo_x86 *c)
                break;
 
        case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */
+       case 11: /* GX1 with inverted Device ID */
 #ifdef CONFIG_PCI
        {
                u32 vendor, device;
index f5af0cc7eb0d18bc9f52177c182d73500e7f3e7f..9257bd9dc6640bd2b1eff8e6cfb7021139332530 100644 (file)
@@ -856,11 +856,13 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type,
        dentry = kernfs_mount(fs_type, flags, rdt_root,
                              RDTGROUP_SUPER_MAGIC, NULL);
        if (IS_ERR(dentry))
-               goto out_cdp;
+               goto out_destroy;
 
        static_branch_enable(&rdt_enable_key);
        goto out;
 
+out_destroy:
+       kernfs_remove(kn_info);
 out_cdp:
        cdp_disable();
 out:
index 5abd4bf73d6e6805d033c361e4671087bb7be076..5cfbaeb6529a04bcba6cb6ba7b09610d0f2fa88c 100644 (file)
@@ -499,16 +499,14 @@ static int mce_usable_address(struct mce *m)
        return 1;
 }
 
-static bool memory_error(struct mce *m)
+bool mce_is_memory_error(struct mce *m)
 {
-       struct cpuinfo_x86 *c = &boot_cpu_data;
-
-       if (c->x86_vendor == X86_VENDOR_AMD) {
+       if (m->cpuvendor == X86_VENDOR_AMD) {
                /* ErrCodeExt[20:16] */
                u8 xec = (m->status >> 16) & 0x1f;
 
                return (xec == 0x0 || xec == 0x8);
-       } else if (c->x86_vendor == X86_VENDOR_INTEL) {
+       } else if (m->cpuvendor == X86_VENDOR_INTEL) {
                /*
                 * Intel SDM Volume 3B - 15.9.2 Compound Error Codes
                 *
@@ -529,6 +527,7 @@ static bool memory_error(struct mce *m)
 
        return false;
 }
+EXPORT_SYMBOL_GPL(mce_is_memory_error);
 
 static bool cec_add_mce(struct mce *m)
 {
@@ -536,7 +535,7 @@ static bool cec_add_mce(struct mce *m)
                return false;
 
        /* We eat only correctable DRAM errors with usable addresses. */
-       if (memory_error(m) &&
+       if (mce_is_memory_error(m) &&
            !(m->status & MCI_STATUS_UC) &&
            mce_usable_address(m))
                if (!cec_add_elem(m->addr >> PAGE_SHIFT))
@@ -713,7 +712,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 
                severity = mce_severity(&m, mca_cfg.tolerant, NULL, false);
 
-               if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m))
+               if (severity == MCE_DEFERRED_SEVERITY && mce_is_memory_error(&m))
                        if (m.status & MCI_STATUS_ADDRV)
                                m.severity = severity;
 
index 45db4d2ebd0118e666c205185b9162d13e33316e..e9f4d762aa5b5cabde501f95045fad6c43fef54b 100644 (file)
@@ -320,7 +320,7 @@ void load_ucode_amd_ap(unsigned int cpuid_1_eax)
 }
 
 static enum ucode_state
-load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
+load_microcode_amd(bool save, u8 family, const u8 *data, size_t size);
 
 int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
 {
@@ -338,8 +338,7 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
        if (!desc.mc)
                return -EINVAL;
 
-       ret = load_microcode_amd(smp_processor_id(), x86_family(cpuid_1_eax),
-                                desc.data, desc.size);
+       ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size);
        if (ret != UCODE_OK)
                return -EINVAL;
 
@@ -675,7 +674,7 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
 }
 
 static enum ucode_state
-load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
+load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
 {
        enum ucode_state ret;
 
@@ -689,8 +688,8 @@ load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
 
 #ifdef CONFIG_X86_32
        /* save BSP's matching patch for early load */
-       if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
-               struct ucode_patch *p = find_patch(cpu);
+       if (save) {
+               struct ucode_patch *p = find_patch(0);
                if (p) {
                        memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
                        memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
@@ -722,11 +721,12 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
 {
        char fw_name[36] = "amd-ucode/microcode_amd.bin";
        struct cpuinfo_x86 *c = &cpu_data(cpu);
+       bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
        enum ucode_state ret = UCODE_NFOUND;
        const struct firmware *fw;
 
        /* reload ucode container only on the boot cpu */
-       if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index)
+       if (!refresh_fw || !bsp)
                return UCODE_OK;
 
        if (c->x86 >= 0x15)
@@ -743,7 +743,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
                goto fw_release;
        }
 
-       ret = load_microcode_amd(cpu, c->x86, fw->data, fw->size);
+       ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);
 
  fw_release:
        release_firmware(fw);
index afdfd237b59fd7722f4b595dbde17a940096ca81..f522415bf9e53690733250b31120d9d62d63a872 100644 (file)
@@ -619,6 +619,9 @@ int __init save_microcode_in_initrd_intel(void)
 
        show_saved_mc();
 
+       /* initrd is going away, clear patch ptr. */
+       intel_ucode_patch = NULL;
+
        return 0;
 }
 
index c2f8dde3255ca706f613ff662d313ef1f06aa97d..d5d44c452624c88e3abb5c75e68d00b55fee6019 100644 (file)
@@ -90,6 +90,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
  * Boot time FPU feature detection code:
  */
 unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
+EXPORT_SYMBOL_GPL(mxcsr_feature_mask);
 
 static void __init fpu__init_system_mxcsr(void)
 {
index 0651e974dcb3a88211db1711a5969434d3163e5a..9bef1bbeba63885e3ba584960b97e8c190b4c5a8 100644 (file)
@@ -689,8 +689,12 @@ static inline void *alloc_tramp(unsigned long size)
 {
        return module_alloc(size);
 }
-static inline void tramp_free(void *tramp)
+static inline void tramp_free(void *tramp, int size)
 {
+       int npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+       set_memory_nx((unsigned long)tramp, npages);
+       set_memory_rw((unsigned long)tramp, npages);
        module_memfree(tramp);
 }
 #else
@@ -699,7 +703,7 @@ static inline void *alloc_tramp(unsigned long size)
 {
        return NULL;
 }
-static inline void tramp_free(void *tramp) { }
+static inline void tramp_free(void *tramp, int size) { }
 #endif
 
 /* Defined as markers to the end of the ftrace default trampolines */
@@ -771,7 +775,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
        /* Copy ftrace_caller onto the trampoline memory */
        ret = probe_kernel_read(trampoline, (void *)start_offset, size);
        if (WARN_ON(ret < 0)) {
-               tramp_free(trampoline);
+               tramp_free(trampoline, *tramp_size);
                return 0;
        }
 
@@ -797,7 +801,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
        /* Are we pointing to the reference? */
        if (WARN_ON(memcmp(op_ptr.op, op_ref, 3) != 0)) {
-               tramp_free(trampoline);
+               tramp_free(trampoline, *tramp_size);
                return 0;
        }
 
@@ -839,7 +843,7 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops)
        unsigned long offset;
        unsigned long ip;
        unsigned int size;
-       int ret;
+       int ret, npages;
 
        if (ops->trampoline) {
                /*
@@ -848,11 +852,14 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops)
                 */
                if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP))
                        return;
+               npages = PAGE_ALIGN(ops->trampoline_size) >> PAGE_SHIFT;
+               set_memory_rw(ops->trampoline, npages);
        } else {
                ops->trampoline = create_trampoline(ops, &size);
                if (!ops->trampoline)
                        return;
                ops->trampoline_size = size;
+               npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
        }
 
        offset = calc_trampoline_call_offset(ops->flags & FTRACE_OPS_FL_SAVE_REGS);
@@ -863,6 +870,7 @@ void arch_ftrace_update_trampoline(struct ftrace_ops *ops)
        /* Do a safe modify in case the trampoline is executing */
        new = ftrace_call_replace(ip, (unsigned long)func);
        ret = update_ftrace_func(ip, new);
+       set_memory_ro(ops->trampoline, npages);
 
        /* The update should never fail */
        WARN_ON(ret);
@@ -939,7 +947,7 @@ void arch_ftrace_trampoline_free(struct ftrace_ops *ops)
        if (!ops || !(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP))
                return;
 
-       tramp_free((void *)ops->trampoline);
+       tramp_free((void *)ops->trampoline, ops->trampoline_size);
        ops->trampoline = 0;
 }
 
index 5b2bbfbb371284942b2ce95a3b2495eb9ecc8981..6b877807598b9028527a2357fef630431021c383 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/ftrace.h>
 #include <linux/frame.h>
 #include <linux/kasan.h>
+#include <linux/moduleloader.h>
 
 #include <asm/text-patching.h>
 #include <asm/cacheflush.h>
@@ -417,6 +418,14 @@ static void prepare_boost(struct kprobe *p, struct insn *insn)
        }
 }
 
+/* Recover page to RW mode before releasing it */
+void free_insn_page(void *page)
+{
+       set_memory_nx((unsigned long)page & PAGE_MASK, 1);
+       set_memory_rw((unsigned long)page & PAGE_MASK, 1);
+       module_memfree(page);
+}
+
 static int arch_copy_kprobe(struct kprobe *p)
 {
        struct insn insn;
index da5c0978998488c612b1495a3659742b57b55071..43e10d6fdbeda3002dcd9e2063a723ded4ca5972 100644 (file)
@@ -161,8 +161,8 @@ void kvm_async_pf_task_wait(u32 token)
                         */
                        rcu_irq_exit();
                        native_safe_halt();
-                       rcu_irq_enter();
                        local_irq_disable();
+                       rcu_irq_enter();
                }
        }
        if (!n.halted)
index 0bb88428cbf2697c89a60311051cc5351ea55fde..3ca198080ea9294486ae9a1121e7815dfba7cb19 100644 (file)
@@ -544,17 +544,6 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
        return randomize_page(mm->brk, 0x02000000);
 }
 
-/*
- * Return saved PC of a blocked thread.
- * What is this good for? it will be always the scheduler or ret_from_fork.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-       struct inactive_task_frame *frame =
-               (struct inactive_task_frame *) READ_ONCE(tsk->thread.sp);
-       return READ_ONCE_NOCHECK(frame->ret_addr);
-}
-
 /*
  * Called from fs/proc with a reference on @p to find the function
  * which called into schedule(). This needs to be done carefully
index ff40e74c9181f0e009b51909a0e76ce25c1c2cf3..ffeae818aa7a95ffd0395ae9af5fcedd9b599981 100644 (file)
@@ -78,7 +78,7 @@ void __show_regs(struct pt_regs *regs, int all)
 
        printk(KERN_DEFAULT "EIP: %pS\n", (void *)regs->ip);
        printk(KERN_DEFAULT "EFLAGS: %08lx CPU: %d\n", regs->flags,
-               smp_processor_id());
+               raw_smp_processor_id());
 
        printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
                regs->ax, regs->bx, regs->cx, regs->dx);
index 0b4d3c686b1ef94463c8caabce01e38404d1b8c1..f818236950140fa0e3ccfc013e31857676db4f77 100644 (file)
@@ -980,8 +980,6 @@ void __init setup_arch(char **cmdline_p)
         */
        x86_configure_nx();
 
-       simple_udelay_calibration();
-
        parse_early_param();
 
 #ifdef CONFIG_MEMORY_HOTPLUG
@@ -1041,6 +1039,8 @@ void __init setup_arch(char **cmdline_p)
         */
        init_hypervisor_platform();
 
+       simple_udelay_calibration();
+
        x86_init.resources.probe_roms();
 
        /* after parse_early_param, so could debug it */
index 207b8f2582c75b7c80a882ffc92a720071c8277e..213ddf3e937d800577514a3677f742813298555e 100644 (file)
@@ -144,7 +144,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (end - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
@@ -187,7 +187,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                addr = PAGE_ALIGN(addr);
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                               (!vma || addr + len <= vma->vm_start))
+                               (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index 4b17240599093a6ec34c45e053ae665050d18e14..a4eb27918cebf99dc2415f7eec49c4838d6f9f41 100644 (file)
@@ -514,7 +514,7 @@ int tboot_force_iommu(void)
        if (!tboot_enabled())
                return 0;
 
-       if (!intel_iommu_tboot_noforce)
+       if (intel_iommu_tboot_noforce)
                return 1;
 
        if (no_iommu || swiotlb || dmar_disabled)
index 3995d3a777d49c569e3ba79e3eca5d2206ab1b0a..bf54309b85da279147d6dbae5bff34381fa789a8 100644 (file)
@@ -182,7 +182,7 @@ int is_valid_bugaddr(unsigned long addr)
        return ud == INSN_UD0 || ud == INSN_UD2;
 }
 
-static int fixup_bug(struct pt_regs *regs, int trapnr)
+int fixup_bug(struct pt_regs *regs, int trapnr)
 {
        if (trapnr != X86_TRAP_UD)
                return 0;
index 82c6d7f1fd73e64debd566d0846f3b9a62ab8959..b9389d72b2f784887e14acc89a6346a78c13c1b4 100644 (file)
@@ -104,6 +104,11 @@ static inline unsigned long *last_frame(struct unwind_state *state)
        return (unsigned long *)task_pt_regs(state->task) - 2;
 }
 
+static bool is_last_frame(struct unwind_state *state)
+{
+       return state->bp == last_frame(state);
+}
+
 #ifdef CONFIG_X86_32
 #define GCC_REALIGN_WORDS 3
 #else
@@ -115,16 +120,15 @@ static inline unsigned long *last_aligned_frame(struct unwind_state *state)
        return last_frame(state) - GCC_REALIGN_WORDS;
 }
 
-static bool is_last_task_frame(struct unwind_state *state)
+static bool is_last_aligned_frame(struct unwind_state *state)
 {
        unsigned long *last_bp = last_frame(state);
        unsigned long *aligned_bp = last_aligned_frame(state);
 
        /*
-        * We have to check for the last task frame at two different locations
-        * because gcc can occasionally decide to realign the stack pointer and
-        * change the offset of the stack frame in the prologue of a function
-        * called by head/entry code.  Examples:
+        * GCC can occasionally decide to realign the stack pointer and change
+        * the offset of the stack frame in the prologue of a function called
+        * by head/entry code.  Examples:
         *
         * <start_secondary>:
         *      push   %edi
@@ -141,11 +145,38 @@ static bool is_last_task_frame(struct unwind_state *state)
         *      push   %rbp
         *      mov    %rsp,%rbp
         *
-        * Note that after aligning the stack, it pushes a duplicate copy of
-        * the return address before pushing the frame pointer.
+        * After aligning the stack, it pushes a duplicate copy of the return
+        * address before pushing the frame pointer.
+        */
+       return (state->bp == aligned_bp && *(aligned_bp + 1) == *(last_bp + 1));
+}
+
+static bool is_last_ftrace_frame(struct unwind_state *state)
+{
+       unsigned long *last_bp = last_frame(state);
+       unsigned long *last_ftrace_bp = last_bp - 3;
+
+       /*
+        * When unwinding from an ftrace handler of a function called by entry
+        * code, the stack layout of the last frame is:
+        *
+        *   bp
+        *   parent ret addr
+        *   bp
+        *   function ret addr
+        *   parent ret addr
+        *   pt_regs
+        *   -----------------
         */
-       return (state->bp == last_bp ||
-               (state->bp == aligned_bp && *(aligned_bp+1) == *(last_bp+1)));
+       return (state->bp == last_ftrace_bp &&
+               *state->bp == *(state->bp + 2) &&
+               *(state->bp + 1) == *(state->bp + 4));
+}
+
+static bool is_last_task_frame(struct unwind_state *state)
+{
+       return is_last_frame(state) || is_last_aligned_frame(state) ||
+              is_last_ftrace_frame(state);
 }
 
 /*
index a181ae76c71ce102f88f6a4ee9cc3233677c55e2..59ca2eea522c466937287c3e660b8f38e49c12aa 100644 (file)
@@ -780,18 +780,20 @@ out:
 static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
 {
        struct kvm_cpuid_entry2 *e = &vcpu->arch.cpuid_entries[i];
-       int j, nent = vcpu->arch.cpuid_nent;
+       struct kvm_cpuid_entry2 *ej;
+       int j = i;
+       int nent = vcpu->arch.cpuid_nent;
 
        e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
        /* when no next entry is found, the current entry[i] is reselected */
-       for (j = i + 1; ; j = (j + 1) % nent) {
-               struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j];
-               if (ej->function == e->function) {
-                       ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
-                       return j;
-               }
-       }
-       return 0; /* silence gcc, even though control never reaches here */
+       do {
+               j = (j + 1) % nent;
+               ej = &vcpu->arch.cpuid_entries[j];
+       } while (ej->function != e->function);
+
+       ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
+
+       return j;
 }
 
 /* find an entry with matching function, matching index (if needed), and that
index c25cfaf584e7285c10d23ee8d9240f22b7c94628..80890dee66cebf370a3815e28f7bd7c34025b0d4 100644 (file)
@@ -2742,6 +2742,7 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
                ctxt->eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_IF);
        }
 
+       ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0;
        return X86EMUL_CONTINUE;
 }
 
@@ -4173,7 +4174,7 @@ static int check_dr_write(struct x86_emulate_ctxt *ctxt)
 
 static int check_svme(struct x86_emulate_ctxt *ctxt)
 {
-       u64 efer;
+       u64 efer = 0;
 
        ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
 
index c329d28949056e2d6ad4688e411c5644b81e4d68..d24c8742d9b0aa6df35d5e479e627ff008ea221f 100644 (file)
@@ -1495,8 +1495,10 @@ EXPORT_SYMBOL_GPL(kvm_lapic_hv_timer_in_use);
 
 static void cancel_hv_timer(struct kvm_lapic *apic)
 {
+       preempt_disable();
        kvm_x86_ops->cancel_hv_timer(apic->vcpu);
        apic->lapic_timer.hv_timer_in_use = false;
+       preempt_enable();
 }
 
 static bool start_hv_timer(struct kvm_lapic *apic)
@@ -1934,7 +1936,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
        for (i = 0; i < KVM_APIC_LVT_NUM; i++)
                kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
        apic_update_lvtt(apic);
-       if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED))
+       if (kvm_vcpu_is_reset_bsp(vcpu) &&
+           kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED))
                kvm_lapic_set_reg(apic, APIC_LVT0,
                             SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT));
        apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
index 5d3376f677949067f39c5e29fca2f3aceb7880bc..cb8225969255ec006fbff5eab76471f341d92b77 100644 (file)
@@ -3698,12 +3698,15 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn)
        return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
 }
 
-static bool can_do_async_pf(struct kvm_vcpu *vcpu)
+bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu)
 {
        if (unlikely(!lapic_in_kernel(vcpu) ||
                     kvm_event_needs_reinjection(vcpu)))
                return false;
 
+       if (is_guest_mode(vcpu))
+               return false;
+
        return kvm_x86_ops->interrupt_allowed(vcpu);
 }
 
@@ -3719,7 +3722,7 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
        if (!async)
                return false; /* *pfn has correct page already */
 
-       if (!prefault && can_do_async_pf(vcpu)) {
+       if (!prefault && kvm_can_do_async_pf(vcpu)) {
                trace_kvm_try_async_get_page(gva, gfn);
                if (kvm_find_async_pf_gfn(vcpu, gfn)) {
                        trace_kvm_async_pf_doublefault(gva, gfn);
index 27975807cc64fcae7bccbb53eecab35c3f0c64e2..330bf3a811fb07271de382b598be402c871f6496 100644 (file)
@@ -76,6 +76,7 @@ int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct);
 void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu);
 void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
                             bool accessed_dirty);
+bool kvm_can_do_async_pf(struct kvm_vcpu *vcpu);
 
 static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
 {
index 56241746abbd71cae280621ec4b84d13b48bc81f..b0454c7e4cffe6c99e9619892a82afcd5d7ab70e 100644 (file)
@@ -283,11 +283,13 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
        pt_element_t pte;
        pt_element_t __user *uninitialized_var(ptep_user);
        gfn_t table_gfn;
-       unsigned index, pt_access, pte_access, accessed_dirty, pte_pkey;
+       u64 pt_access, pte_access;
+       unsigned index, accessed_dirty, pte_pkey;
        unsigned nested_access;
        gpa_t pte_gpa;
        bool have_ad;
        int offset;
+       u64 walk_nx_mask = 0;
        const int write_fault = access & PFERR_WRITE_MASK;
        const int user_fault  = access & PFERR_USER_MASK;
        const int fetch_fault = access & PFERR_FETCH_MASK;
@@ -302,6 +304,7 @@ retry_walk:
        have_ad       = PT_HAVE_ACCESSED_DIRTY(mmu);
 
 #if PTTYPE == 64
+       walk_nx_mask = 1ULL << PT64_NX_SHIFT;
        if (walker->level == PT32E_ROOT_LEVEL) {
                pte = mmu->get_pdptr(vcpu, (addr >> 30) & 3);
                trace_kvm_mmu_paging_element(pte, walker->level);
@@ -313,8 +316,6 @@ retry_walk:
        walker->max_level = walker->level;
        ASSERT(!(is_long_mode(vcpu) && !is_pae(vcpu)));
 
-       accessed_dirty = have_ad ? PT_GUEST_ACCESSED_MASK : 0;
-
        /*
         * FIXME: on Intel processors, loads of the PDPTE registers for PAE paging
         * by the MOV to CR instruction are treated as reads and do not cause the
@@ -322,14 +323,14 @@ retry_walk:
         */
        nested_access = (have_ad ? PFERR_WRITE_MASK : 0) | PFERR_USER_MASK;
 
-       pt_access = pte_access = ACC_ALL;
+       pte_access = ~0;
        ++walker->level;
 
        do {
                gfn_t real_gfn;
                unsigned long host_addr;
 
-               pt_access &= pte_access;
+               pt_access = pte_access;
                --walker->level;
 
                index = PT_INDEX(addr, walker->level);
@@ -371,6 +372,12 @@ retry_walk:
 
                trace_kvm_mmu_paging_element(pte, walker->level);
 
+               /*
+                * Inverting the NX it lets us AND it like other
+                * permission bits.
+                */
+               pte_access = pt_access & (pte ^ walk_nx_mask);
+
                if (unlikely(!FNAME(is_present_gpte)(pte)))
                        goto error;
 
@@ -379,14 +386,16 @@ retry_walk:
                        goto error;
                }
 
-               accessed_dirty &= pte;
-               pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);
-
                walker->ptes[walker->level - 1] = pte;
        } while (!is_last_gpte(mmu, walker->level, pte));
 
        pte_pkey = FNAME(gpte_pkeys)(vcpu, pte);
-       errcode = permission_fault(vcpu, mmu, pte_access, pte_pkey, access);
+       accessed_dirty = have_ad ? pte_access & PT_GUEST_ACCESSED_MASK : 0;
+
+       /* Convert to ACC_*_MASK flags for struct guest_walker.  */
+       walker->pt_access = FNAME(gpte_access)(vcpu, pt_access ^ walk_nx_mask);
+       walker->pte_access = FNAME(gpte_access)(vcpu, pte_access ^ walk_nx_mask);
+       errcode = permission_fault(vcpu, mmu, walker->pte_access, pte_pkey, access);
        if (unlikely(errcode))
                goto error;
 
@@ -403,7 +412,7 @@ retry_walk:
        walker->gfn = real_gpa >> PAGE_SHIFT;
 
        if (!write_fault)
-               FNAME(protect_clean_gpte)(mmu, &pte_access, pte);
+               FNAME(protect_clean_gpte)(mmu, &walker->pte_access, pte);
        else
                /*
                 * On a write fault, fold the dirty bit into accessed_dirty.
@@ -421,10 +430,8 @@ retry_walk:
                        goto retry_walk;
        }
 
-       walker->pt_access = pt_access;
-       walker->pte_access = pte_access;
        pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
-                __func__, (u64)pte, pte_access, pt_access);
+                __func__, (u64)pte, walker->pte_access, walker->pt_access);
        return 1;
 
 error:
@@ -452,7 +459,7 @@ error:
         */
        if (!(errcode & PFERR_RSVD_MASK)) {
                vcpu->arch.exit_qualification &= 0x187;
-               vcpu->arch.exit_qualification |= ((pt_access & pte) & 0x7) << 3;
+               vcpu->arch.exit_qualification |= (pte_access & 0x7) << 3;
        }
 #endif
        walker->fault.address = addr;
index 9d4a8504a95a3ba687a5bd34b8ef3c58d4a5f2db..5ab4a364348e3c10987c33203be4ff6fa97e1e73 100644 (file)
@@ -294,7 +294,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
                        ((u64)1 << edx.split.bit_width_fixed) - 1;
        }
 
-       pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+       pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
                (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
        pmu->global_ctrl_mask = ~pmu->global_ctrl;
 
index c27ac6923a18463751d153626f54413f9615201e..ba9891ac5c568f1798555bfa9dcbc421fff5ae2a 100644 (file)
@@ -1272,7 +1272,8 @@ static void init_vmcb(struct vcpu_svm *svm)
 
 }
 
-static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu, int index)
+static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
+                                      unsigned int index)
 {
        u64 *avic_physical_id_table;
        struct kvm_arch *vm_data = &vcpu->kvm->arch;
@@ -1806,7 +1807,7 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
         * AMD's VMCB does not have an explicit unusable field, so emulate it
         * for cross vendor migration purposes by "not present"
         */
-       var->unusable = !var->present || (var->type == 0);
+       var->unusable = !var->present;
 
        switch (seg) {
        case VCPU_SREG_TR:
@@ -1839,6 +1840,7 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
                 */
                if (var->unusable)
                        var->db = 0;
+               /* This is symmetric with svm_set_segment() */
                var->dpl = to_svm(vcpu)->vmcb->save.cpl;
                break;
        }
@@ -1979,18 +1981,14 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
        s->base = var->base;
        s->limit = var->limit;
        s->selector = var->selector;
-       if (var->unusable)
-               s->attrib = 0;
-       else {
-               s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
-               s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
-               s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
-               s->attrib |= (var->present & 1) << SVM_SELECTOR_P_SHIFT;
-               s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
-               s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
-               s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
-               s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
-       }
+       s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
+       s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
+       s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
+       s->attrib |= ((var->present & 1) && !var->unusable) << SVM_SELECTOR_P_SHIFT;
+       s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
+       s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
+       s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
+       s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
 
        /*
         * This is always accurate, except if SYSRET returned to a segment
@@ -1999,7 +1997,8 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
         * would entail passing the CPL to userspace and back.
         */
        if (seg == VCPU_SREG_SS)
-               svm->vmcb->save.cpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
+               /* This is symmetric with svm_get_segment() */
+               svm->vmcb->save.cpl = (var->dpl & 3);
 
        mark_dirty(svm->vmcb, VMCB_SEG);
 }
index c6f4ad44aa95cc8f1a9013ad4fc54d22d5b2a5f7..ca5d2b93385c66e3531caefae4c06614ce6b2d45 100644 (file)
@@ -2425,7 +2425,7 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned nr)
        if (!(vmcs12->exception_bitmap & (1u << nr)))
                return 0;
 
-       nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason,
+       nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
                          vmcs_read32(VM_EXIT_INTR_INFO),
                          vmcs_readl(EXIT_QUALIFICATION));
        return 1;
@@ -6504,7 +6504,7 @@ static __init int hardware_setup(void)
                enable_ept_ad_bits = 0;
        }
 
-       if (!cpu_has_vmx_ept_ad_bits())
+       if (!cpu_has_vmx_ept_ad_bits() || !enable_ept)
                enable_ept_ad_bits = 0;
 
        if (!cpu_has_vmx_unrestricted_guest())
@@ -6914,97 +6914,21 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-/*
- * This function performs the various checks including
- * - if it's 4KB aligned
- * - No bits beyond the physical address width are set
- * - Returns 0 on success or else 1
- * (Intel SDM Section 30.3)
- */
-static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
-                                 gpa_t *vmpointer)
+static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer)
 {
        gva_t gva;
-       gpa_t vmptr;
        struct x86_exception e;
-       struct page *page;
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       int maxphyaddr = cpuid_maxphyaddr(vcpu);
 
        if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
                        vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
                return 1;
 
-       if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
-                               sizeof(vmptr), &e)) {
+       if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, vmpointer,
+                               sizeof(*vmpointer), &e)) {
                kvm_inject_page_fault(vcpu, &e);
                return 1;
        }
 
-       switch (exit_reason) {
-       case EXIT_REASON_VMON:
-               /*
-                * SDM 3: 24.11.5
-                * The first 4 bytes of VMXON region contain the supported
-                * VMCS revision identifier
-                *
-                * Note - IA32_VMX_BASIC[48] will never be 1
-                * for the nested case;
-                * which replaces physical address width with 32
-                *
-                */
-               if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
-                       nested_vmx_failInvalid(vcpu);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-
-               page = nested_get_page(vcpu, vmptr);
-               if (page == NULL) {
-                       nested_vmx_failInvalid(vcpu);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-               if (*(u32 *)kmap(page) != VMCS12_REVISION) {
-                       kunmap(page);
-                       nested_release_page_clean(page);
-                       nested_vmx_failInvalid(vcpu);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-               kunmap(page);
-               nested_release_page_clean(page);
-               vmx->nested.vmxon_ptr = vmptr;
-               break;
-       case EXIT_REASON_VMCLEAR:
-               if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
-                       nested_vmx_failValid(vcpu,
-                                            VMXERR_VMCLEAR_INVALID_ADDRESS);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-
-               if (vmptr == vmx->nested.vmxon_ptr) {
-                       nested_vmx_failValid(vcpu,
-                                            VMXERR_VMCLEAR_VMXON_POINTER);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-               break;
-       case EXIT_REASON_VMPTRLD:
-               if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
-                       nested_vmx_failValid(vcpu,
-                                            VMXERR_VMPTRLD_INVALID_ADDRESS);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-
-               if (vmptr == vmx->nested.vmxon_ptr) {
-                       nested_vmx_failValid(vcpu,
-                                            VMXERR_VMPTRLD_VMXON_POINTER);
-                       return kvm_skip_emulated_instruction(vcpu);
-               }
-               break;
-       default:
-               return 1; /* shouldn't happen */
-       }
-
-       if (vmpointer)
-               *vmpointer = vmptr;
        return 0;
 }
 
@@ -7066,6 +6990,8 @@ out_msr_bitmap:
 static int handle_vmon(struct kvm_vcpu *vcpu)
 {
        int ret;
+       gpa_t vmptr;
+       struct page *page;
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
                | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
@@ -7095,9 +7021,37 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
                return 1;
        }
 
-       if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMON, NULL))
+       if (nested_vmx_get_vmptr(vcpu, &vmptr))
                return 1;
+
+       /*
+        * SDM 3: 24.11.5
+        * The first 4 bytes of VMXON region contain the supported
+        * VMCS revision identifier
+        *
+        * Note - IA32_VMX_BASIC[48] will never be 1 for the nested case;
+        * which replaces physical address width with 32
+        */
+       if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
+               nested_vmx_failInvalid(vcpu);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+
+       page = nested_get_page(vcpu, vmptr);
+       if (page == NULL) {
+               nested_vmx_failInvalid(vcpu);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+       if (*(u32 *)kmap(page) != VMCS12_REVISION) {
+               kunmap(page);
+               nested_release_page_clean(page);
+               nested_vmx_failInvalid(vcpu);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+       kunmap(page);
+       nested_release_page_clean(page);
+
+       vmx->nested.vmxon_ptr = vmptr;
        ret = enter_vmx_operation(vcpu);
        if (ret)
                return ret;
@@ -7213,9 +7167,19 @@ static int handle_vmclear(struct kvm_vcpu *vcpu)
        if (!nested_vmx_check_permission(vcpu))
                return 1;
 
-       if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMCLEAR, &vmptr))
+       if (nested_vmx_get_vmptr(vcpu, &vmptr))
                return 1;
 
+       if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
+               nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+
+       if (vmptr == vmx->nested.vmxon_ptr) {
+               nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_VMXON_POINTER);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+
        if (vmptr == vmx->nested.current_vmptr)
                nested_release_vmcs12(vmx);
 
@@ -7545,9 +7509,19 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
        if (!nested_vmx_check_permission(vcpu))
                return 1;
 
-       if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMPTRLD, &vmptr))
+       if (nested_vmx_get_vmptr(vcpu, &vmptr))
                return 1;
 
+       if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
+               nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+
+       if (vmptr == vmx->nested.vmxon_ptr) {
+               nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_VMXON_POINTER);
+               return kvm_skip_emulated_instruction(vcpu);
+       }
+
        if (vmx->nested.current_vmptr != vmptr) {
                struct vmcs12 *new_vmcs12;
                struct page *page;
@@ -7913,11 +7887,13 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
 {
        unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
        int cr = exit_qualification & 15;
-       int reg = (exit_qualification >> 8) & 15;
-       unsigned long val = kvm_register_readl(vcpu, reg);
+       int reg;
+       unsigned long val;
 
        switch ((exit_qualification >> 4) & 3) {
        case 0: /* mov to cr */
+               reg = (exit_qualification >> 8) & 15;
+               val = kvm_register_readl(vcpu, reg);
                switch (cr) {
                case 0:
                        if (vmcs12->cr0_guest_host_mask &
@@ -7972,6 +7948,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
                 * lmsw can change bits 1..3 of cr0, and only set bit 0 of
                 * cr0. Other attempted changes are ignored, with no exit.
                 */
+               val = (exit_qualification >> LMSW_SOURCE_DATA_SHIFT) & 0x0f;
                if (vmcs12->cr0_guest_host_mask & 0xe &
                    (val ^ vmcs12->cr0_read_shadow))
                        return true;
@@ -11213,7 +11190,7 @@ static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
                if (!nested_cpu_has_pml(vmcs12))
                        return 0;
 
-               if (vmcs12->guest_pml_index > PML_ENTITY_NUM) {
+               if (vmcs12->guest_pml_index >= PML_ENTITY_NUM) {
                        vmx->nested.pml_full = true;
                        return 1;
                }
index 464da936c53dd96b2f9e89f1f0ef715bac3eafe2..0e846f0cb83bb214811d0a12d2f700cc96a455f9 100644 (file)
@@ -1763,6 +1763,7 @@ u64 get_kvmclock_ns(struct kvm *kvm)
 {
        struct kvm_arch *ka = &kvm->arch;
        struct pvclock_vcpu_time_info hv_clock;
+       u64 ret;
 
        spin_lock(&ka->pvclock_gtod_sync_lock);
        if (!ka->use_master_clock) {
@@ -1774,10 +1775,17 @@ u64 get_kvmclock_ns(struct kvm *kvm)
        hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
        spin_unlock(&ka->pvclock_gtod_sync_lock);
 
+       /* both __this_cpu_read() and rdtsc() should be on the same cpu */
+       get_cpu();
+
        kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL,
                           &hv_clock.tsc_shift,
                           &hv_clock.tsc_to_system_mul);
-       return __pvclock_read_cycles(&hv_clock, rdtsc());
+       ret = __pvclock_read_cycles(&hv_clock, rdtsc());
+
+       put_cpu();
+
+       return ret;
 }
 
 static void kvm_setup_pvclock_page(struct kvm_vcpu *v)
@@ -3288,11 +3296,14 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
        }
 }
 
+#define XSAVE_MXCSR_OFFSET 24
+
 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
                                        struct kvm_xsave *guest_xsave)
 {
        u64 xstate_bv =
                *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)];
+       u32 mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)];
 
        if (boot_cpu_has(X86_FEATURE_XSAVE)) {
                /*
@@ -3300,11 +3311,13 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
                 * CPUID leaf 0xD, index 0, EDX:EAX.  This is for compatibility
                 * with old userspace.
                 */
-               if (xstate_bv & ~kvm_supported_xcr0())
+               if (xstate_bv & ~kvm_supported_xcr0() ||
+                       mxcsr & ~mxcsr_feature_mask)
                        return -EINVAL;
                load_xsave(vcpu, (u8 *)guest_xsave->region);
        } else {
-               if (xstate_bv & ~XFEATURE_MASK_FPSSE)
+               if (xstate_bv & ~XFEATURE_MASK_FPSSE ||
+                       mxcsr & ~mxcsr_feature_mask)
                        return -EINVAL;
                memcpy(&vcpu->arch.guest_fpu.state.fxsave,
                        guest_xsave->region, sizeof(struct fxregs_state));
@@ -4818,16 +4831,20 @@ emul_write:
 
 static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
 {
-       /* TODO: String I/O for in kernel device */
-       int r;
+       int r = 0, i;
 
-       if (vcpu->arch.pio.in)
-               r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
-                                   vcpu->arch.pio.size, pd);
-       else
-               r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
-                                    vcpu->arch.pio.port, vcpu->arch.pio.size,
-                                    pd);
+       for (i = 0; i < vcpu->arch.pio.count; i++) {
+               if (vcpu->arch.pio.in)
+                       r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
+                                           vcpu->arch.pio.size, pd);
+               else
+                       r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
+                                            vcpu->arch.pio.port, vcpu->arch.pio.size,
+                                            pd);
+               if (r)
+                       break;
+               pd += vcpu->arch.pio.size;
+       }
        return r;
 }
 
@@ -4865,6 +4882,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt,
        if (vcpu->arch.pio.count)
                goto data_avail;
 
+       memset(vcpu->arch.pio_data, 0, size * count);
+
        ret = emulator_pio_in_out(vcpu, size, port, val, count, true);
        if (ret) {
 data_avail:
@@ -5048,6 +5067,8 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector,
 
        if (var.unusable) {
                memset(desc, 0, sizeof(*desc));
+               if (base3)
+                       *base3 = 0;
                return false;
        }
 
@@ -5292,6 +5313,8 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
        kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
        ctxt->eflags = kvm_get_rflags(vcpu);
+       ctxt->tf = (ctxt->eflags & X86_EFLAGS_TF) != 0;
+
        ctxt->eip = kvm_rip_read(vcpu);
        ctxt->mode = (!is_protmode(vcpu))               ? X86EMUL_MODE_REAL :
                     (ctxt->eflags & X86_EFLAGS_VM)     ? X86EMUL_MODE_VM86 :
@@ -5507,36 +5530,25 @@ static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7,
        return dr6;
 }
 
-static void kvm_vcpu_check_singlestep(struct kvm_vcpu *vcpu, unsigned long rflags, int *r)
+static void kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu, int *r)
 {
        struct kvm_run *kvm_run = vcpu->run;
 
-       /*
-        * rflags is the old, "raw" value of the flags.  The new value has
-        * not been saved yet.
-        *
-        * This is correct even for TF set by the guest, because "the
-        * processor will not generate this exception after the instruction
-        * that sets the TF flag".
-        */
-       if (unlikely(rflags & X86_EFLAGS_TF)) {
-               if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
-                       kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 |
-                                                 DR6_RTM;
-                       kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip;
-                       kvm_run->debug.arch.exception = DB_VECTOR;
-                       kvm_run->exit_reason = KVM_EXIT_DEBUG;
-                       *r = EMULATE_USER_EXIT;
-               } else {
-                       /*
-                        * "Certain debug exceptions may clear bit 0-3.  The
-                        * remaining contents of the DR6 register are never
-                        * cleared by the processor".
-                        */
-                       vcpu->arch.dr6 &= ~15;
-                       vcpu->arch.dr6 |= DR6_BS | DR6_RTM;
-                       kvm_queue_exception(vcpu, DB_VECTOR);
-               }
+       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
+               kvm_run->debug.arch.dr6 = DR6_BS | DR6_FIXED_1 | DR6_RTM;
+               kvm_run->debug.arch.pc = vcpu->arch.singlestep_rip;
+               kvm_run->debug.arch.exception = DB_VECTOR;
+               kvm_run->exit_reason = KVM_EXIT_DEBUG;
+               *r = EMULATE_USER_EXIT;
+       } else {
+               /*
+                * "Certain debug exceptions may clear bit 0-3.  The
+                * remaining contents of the DR6 register are never
+                * cleared by the processor".
+                */
+               vcpu->arch.dr6 &= ~15;
+               vcpu->arch.dr6 |= DR6_BS | DR6_RTM;
+               kvm_queue_exception(vcpu, DB_VECTOR);
        }
 }
 
@@ -5546,7 +5558,17 @@ int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
        int r = EMULATE_DONE;
 
        kvm_x86_ops->skip_emulated_instruction(vcpu);
-       kvm_vcpu_check_singlestep(vcpu, rflags, &r);
+
+       /*
+        * rflags is the old, "raw" value of the flags.  The new value has
+        * not been saved yet.
+        *
+        * This is correct even for TF set by the guest, because "the
+        * processor will not generate this exception after the instruction
+        * that sets the TF flag".
+        */
+       if (unlikely(rflags & X86_EFLAGS_TF))
+               kvm_vcpu_do_singlestep(vcpu, &r);
        return r == EMULATE_DONE;
 }
 EXPORT_SYMBOL_GPL(kvm_skip_emulated_instruction);
@@ -5705,8 +5727,9 @@ restart:
                toggle_interruptibility(vcpu, ctxt->interruptibility);
                vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
                kvm_rip_write(vcpu, ctxt->eip);
-               if (r == EMULATE_DONE)
-                       kvm_vcpu_check_singlestep(vcpu, rflags, &r);
+               if (r == EMULATE_DONE &&
+                   (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
+                       kvm_vcpu_do_singlestep(vcpu, &r);
                if (!ctxt->have_exception ||
                    exception_type(ctxt->exception.vector) == EXCPT_TRAP)
                        __kvm_set_rflags(vcpu, ctxt->eflags);
@@ -8373,10 +8396,13 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
        if (vcpu->arch.pv.pv_unhalted)
                return true;
 
-       if (atomic_read(&vcpu->arch.nmi_queued))
+       if (kvm_test_request(KVM_REQ_NMI, vcpu) ||
+           (vcpu->arch.nmi_pending &&
+            kvm_x86_ops->nmi_allowed(vcpu)))
                return true;
 
-       if (kvm_test_request(KVM_REQ_SMI, vcpu))
+       if (kvm_test_request(KVM_REQ_SMI, vcpu) ||
+           (vcpu->arch.smi_pending && !is_smm(vcpu)))
                return true;
 
        if (kvm_arch_interrupt_allowed(vcpu) &&
@@ -8583,8 +8609,7 @@ bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
        if (!(vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED))
                return true;
        else
-               return !kvm_event_needs_reinjection(vcpu) &&
-                       kvm_x86_ops->interrupt_allowed(vcpu);
+               return kvm_can_do_async_pf(vcpu);
 }
 
 void kvm_arch_start_assignment(struct kvm *kvm)
index 35ea061010a1a51f743bda3ca7cfe1be468670e1..0ea8afcb929c031fdac01681ac277dcf74887e4e 100644 (file)
@@ -162,6 +162,9 @@ void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
        if (fixup_exception(regs, trapnr))
                return;
 
+       if (fixup_bug(regs, trapnr))
+               return;
+
 fail:
        early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n",
                     (unsigned)trapnr, (unsigned long)regs->cs, regs->ip,
index 302f43fd9c28c6d14652981d672569d57e3dea35..adad702b39cd473218d373e7d1b452b96d9816be 100644 (file)
@@ -148,7 +148,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
        if (mm->get_unmapped_area == arch_get_unmapped_area)
index cbc87ea9875109b79b70a17ea6c130d8803ff207..9b3f9fa5b283acb12ba38a42824e1b872a9560b9 100644 (file)
@@ -161,16 +161,16 @@ static int page_size_mask;
 
 static void __init probe_page_size_mask(void)
 {
-#if !defined(CONFIG_KMEMCHECK)
        /*
         * For CONFIG_KMEMCHECK or pagealloc debugging, identity mapping will
         * use small pages.
         * This will simplify cpa(), which otherwise needs to support splitting
         * large pages into small in interrupt context, etc.
         */
-       if (boot_cpu_has(X86_FEATURE_PSE) && !debug_pagealloc_enabled())
+       if (boot_cpu_has(X86_FEATURE_PSE) && !debug_pagealloc_enabled() && !IS_ENABLED(CONFIG_KMEMCHECK))
                page_size_mask |= 1 << PG_LEVEL_2M;
-#endif
+       else
+               direct_gbpages = 0;
 
        /* Enable PSE if available */
        if (boot_cpu_has(X86_FEATURE_PSE))
index 95651dc58e0900d3717a462d4cfe05efffc9374e..0a59daf799f8ed95ad6cef315ff23818e1a110ea 100644 (file)
@@ -990,7 +990,13 @@ remove_p4d_table(p4d_t *p4d_start, unsigned long addr, unsigned long end,
 
                pud_base = pud_offset(p4d, 0);
                remove_pud_table(pud_base, addr, next, direct);
-               free_pud_table(pud_base, p4d);
+               /*
+                * For 4-level page tables we do not want to free PUDs, but in the
+                * 5-level case we should free them. This code will have to change
+                * to adapt for boot-time switching between 4 and 5 level page tables.
+                */
+               if (CONFIG_PGTABLE_LEVELS == 5)
+                       free_pud_table(pud_base, p4d);
        }
 
        if (direct)
index 1dcd2be4cce44aabd5659b531962f918da1b8dd3..c8520b2c62d252f774f7c6b9df83eefa6a5925c2 100644 (file)
@@ -186,7 +186,7 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache)
        unsigned int i, level;
        unsigned long addr;
 
-       BUG_ON(irqs_disabled());
+       BUG_ON(irqs_disabled() && !early_boot_irqs_disabled);
        WARN_ON(PAGE_ALIGN(start) != start);
 
        on_each_cpu(__cpa_flush_range, NULL, 1);
index 7e76a4d8304bc5add30e5f86d16e4f5b423a24f6..43b96f5f78ba8c9c323c5ae6090c19f3ae290ad0 100644 (file)
@@ -828,9 +828,11 @@ static void __init kexec_enter_virtual_mode(void)
 
        /*
         * We don't do virtual mode, since we don't do runtime services, on
-        * non-native EFI
+        * non-native EFI. With efi=old_map, we don't do runtime services in
+        * kexec kernel because in the initial boot something else might
+        * have been mapped at these virtual addresses.
         */
-       if (!efi_is_native()) {
+       if (!efi_is_native() || efi_enabled(EFI_OLD_MEMMAP)) {
                efi_memmap_unmap();
                clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
                return;
index c488625c9712de4fe150d01df5c260e650967265..eb8dff15a7f63721d0f07845263da1af75670771 100644 (file)
@@ -71,11 +71,13 @@ static void __init early_code_mapping_set_exec(int executable)
 
 pgd_t * __init efi_call_phys_prolog(void)
 {
-       unsigned long vaddress;
-       pgd_t *save_pgd;
+       unsigned long vaddr, addr_pgd, addr_p4d, addr_pud;
+       pgd_t *save_pgd, *pgd_k, *pgd_efi;
+       p4d_t *p4d, *p4d_k, *p4d_efi;
+       pud_t *pud;
 
        int pgd;
-       int n_pgds;
+       int n_pgds, i, j;
 
        if (!efi_enabled(EFI_OLD_MEMMAP)) {
                save_pgd = (pgd_t *)read_cr3();
@@ -88,10 +90,49 @@ pgd_t * __init efi_call_phys_prolog(void)
        n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
        save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL);
 
+       /*
+        * Build 1:1 identity mapping for efi=old_map usage. Note that
+        * PAGE_OFFSET is PGDIR_SIZE aligned when KASLR is disabled, while
+        * it is PUD_SIZE ALIGNED with KASLR enabled. So for a given physical
+        * address X, the pud_index(X) != pud_index(__va(X)), we can only copy
+        * PUD entry of __va(X) to fill in pud entry of X to build 1:1 mapping.
+        * This means here we can only reuse the PMD tables of the direct mapping.
+        */
        for (pgd = 0; pgd < n_pgds; pgd++) {
-               save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE);
-               vaddress = (unsigned long)__va(pgd * PGDIR_SIZE);
-               set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress));
+               addr_pgd = (unsigned long)(pgd * PGDIR_SIZE);
+               vaddr = (unsigned long)__va(pgd * PGDIR_SIZE);
+               pgd_efi = pgd_offset_k(addr_pgd);
+               save_pgd[pgd] = *pgd_efi;
+
+               p4d = p4d_alloc(&init_mm, pgd_efi, addr_pgd);
+               if (!p4d) {
+                       pr_err("Failed to allocate p4d table!\n");
+                       goto out;
+               }
+
+               for (i = 0; i < PTRS_PER_P4D; i++) {
+                       addr_p4d = addr_pgd + i * P4D_SIZE;
+                       p4d_efi = p4d + p4d_index(addr_p4d);
+
+                       pud = pud_alloc(&init_mm, p4d_efi, addr_p4d);
+                       if (!pud) {
+                               pr_err("Failed to allocate pud table!\n");
+                               goto out;
+                       }
+
+                       for (j = 0; j < PTRS_PER_PUD; j++) {
+                               addr_pud = addr_p4d + j * PUD_SIZE;
+
+                               if (addr_pud > (max_pfn << PAGE_SHIFT))
+                                       break;
+
+                               vaddr = (unsigned long)__va(addr_pud);
+
+                               pgd_k = pgd_offset_k(vaddr);
+                               p4d_k = p4d_offset(pgd_k, vaddr);
+                               pud[j] = *pud_offset(p4d_k, vaddr);
+                       }
+               }
        }
 out:
        __flush_tlb_all();
@@ -104,8 +145,11 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
        /*
         * After the lock is released, the original page table is restored.
         */
-       int pgd_idx;
+       int pgd_idx, i;
        int nr_pgds;
+       pgd_t *pgd;
+       p4d_t *p4d;
+       pud_t *pud;
 
        if (!efi_enabled(EFI_OLD_MEMMAP)) {
                write_cr3((unsigned long)save_pgd);
@@ -115,9 +159,28 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd)
 
        nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
 
-       for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++)
+       for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) {
+               pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE);
                set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]);
 
+               if (!(pgd_val(*pgd) & _PAGE_PRESENT))
+                       continue;
+
+               for (i = 0; i < PTRS_PER_P4D; i++) {
+                       p4d = p4d_offset(pgd,
+                                        pgd_idx * PGDIR_SIZE + i * P4D_SIZE);
+
+                       if (!(p4d_val(*p4d) & _PAGE_PRESENT))
+                               continue;
+
+                       pud = (pud_t *)p4d_page_vaddr(*p4d);
+                       pud_free(&init_mm, pud);
+               }
+
+               p4d = (p4d_t *)pgd_page_vaddr(*pgd);
+               p4d_free(&init_mm, p4d);
+       }
+
        kfree(save_pgd);
 
        __flush_tlb_all();
index 26615991d69cc8b024470c921aca227c2756e439..e0cf95a83f3fab918eb73715d188e631e02a1425 100644 (file)
@@ -360,6 +360,9 @@ void __init efi_free_boot_services(void)
                free_bootmem_late(start, size);
        }
 
+       if (!num_entries)
+               return;
+
        new_size = efi.memmap.desc_size * num_entries;
        new_phys = efi_memmap_alloc(num_entries);
        if (!new_phys) {
index 7cd442690f9dd6dc7af94d35f883becea31768bb..f33eef4ebd12b55645365732135638855ef313cd 100644 (file)
@@ -142,9 +142,7 @@ static void __init xen_banner(void)
        struct xen_extraversion extra;
        HYPERVISOR_xen_version(XENVER_extraversion, &extra);
 
-       pr_info("Booting paravirtualized kernel %son %s\n",
-               xen_feature(XENFEAT_auto_translated_physmap) ?
-                       "with PVH extensions " : "", pv_info.name);
+       pr_info("Booting paravirtualized kernel on %s\n", pv_info.name);
        printk(KERN_INFO "Xen version: %d.%d%s%s\n",
               version >> 16, version & 0xffff, extra.extraversion,
               xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
@@ -957,15 +955,10 @@ static void xen_write_msr(unsigned int msr, unsigned low, unsigned high)
 
 void xen_setup_shared_info(void)
 {
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               set_fixmap(FIX_PARAVIRT_BOOTMAP,
-                          xen_start_info->shared_info);
+       set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info);
 
-               HYPERVISOR_shared_info =
-                       (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
-       } else
-               HYPERVISOR_shared_info =
-                       (struct shared_info *)__va(xen_start_info->shared_info);
+       HYPERVISOR_shared_info =
+               (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
 
 #ifndef CONFIG_SMP
        /* In UP this is as good a place as any to set up shared info */
index 5e375a5e815fb2b90535429373c129c6aaa8862b..3be06f3caf3c1e25aa318fb2fd0ae8706cc0a717 100644 (file)
@@ -42,7 +42,7 @@ xmaddr_t arbitrary_virt_to_machine(void *vaddr)
 }
 EXPORT_SYMBOL_GPL(arbitrary_virt_to_machine);
 
-void xen_flush_tlb_all(void)
+static void xen_flush_tlb_all(void)
 {
        struct mmuext_op *op;
        struct multicall_space mcs;
index 7397d8b8459d65213967066a5eed7dc1d7b6cdfb..1f386d7fdf708489bf09b40c04ed338281c3e3c2 100644 (file)
@@ -355,10 +355,8 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
                pteval_t flags = val & PTE_FLAGS_MASK;
                unsigned long mfn;
 
-               if (!xen_feature(XENFEAT_auto_translated_physmap))
-                       mfn = __pfn_to_mfn(pfn);
-               else
-                       mfn = pfn;
+               mfn = __pfn_to_mfn(pfn);
+
                /*
                 * If there's no mfn for the pfn, then just create an
                 * empty non-present pte.  Unfortunately this loses
@@ -647,9 +645,6 @@ static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd,
        limit--;
        BUG_ON(limit >= FIXADDR_TOP);
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return 0;
-
        /*
         * 64-bit has a great big hole in the middle of the address
         * space, which contains the Xen mappings.  On 32-bit these
@@ -1289,9 +1284,6 @@ static void __init xen_pagetable_cleanhighmap(void)
 
 static void __init xen_pagetable_p2m_setup(void)
 {
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        xen_vmalloc_p2m_tree();
 
 #ifdef CONFIG_X86_64
@@ -1314,8 +1306,7 @@ static void __init xen_pagetable_init(void)
        xen_build_mfn_list_list();
 
        /* Remap memory freed due to conflicts with E820 map */
-       if (!xen_feature(XENFEAT_auto_translated_physmap))
-               xen_remap_memory();
+       xen_remap_memory();
 
        xen_setup_shared_info();
 }
@@ -1925,21 +1916,20 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
        /* Zap identity mapping */
        init_level4_pgt[0] = __pgd(0);
 
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               /* Pre-constructed entries are in pfn, so convert to mfn */
-               /* L4[272] -> level3_ident_pgt
-                * L4[511] -> level3_kernel_pgt */
-               convert_pfn_mfn(init_level4_pgt);
+       /* Pre-constructed entries are in pfn, so convert to mfn */
+       /* L4[272] -> level3_ident_pgt  */
+       /* L4[511] -> level3_kernel_pgt */
+       convert_pfn_mfn(init_level4_pgt);
 
-               /* L3_i[0] -> level2_ident_pgt */
-               convert_pfn_mfn(level3_ident_pgt);
-               /* L3_k[510] -> level2_kernel_pgt
-                * L3_k[511] -> level2_fixmap_pgt */
-               convert_pfn_mfn(level3_kernel_pgt);
+       /* L3_i[0] -> level2_ident_pgt */
+       convert_pfn_mfn(level3_ident_pgt);
+       /* L3_k[510] -> level2_kernel_pgt */
+       /* L3_k[511] -> level2_fixmap_pgt */
+       convert_pfn_mfn(level3_kernel_pgt);
+
+       /* L3_k[511][506] -> level1_fixmap_pgt */
+       convert_pfn_mfn(level2_fixmap_pgt);
 
-               /* L3_k[511][506] -> level1_fixmap_pgt */
-               convert_pfn_mfn(level2_fixmap_pgt);
-       }
        /* We get [511][511] and have Xen's version of level2_kernel_pgt */
        l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
        l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
@@ -1962,34 +1952,30 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
        if (i && i < pgd_index(__START_KERNEL_map))
                init_level4_pgt[i] = ((pgd_t *)xen_start_info->pt_base)[i];
 
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               /* Make pagetable pieces RO */
-               set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
-               set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
-
-               /* Pin down new L4 */
-               pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
-                                 PFN_DOWN(__pa_symbol(init_level4_pgt)));
-
-               /* Unpin Xen-provided one */
-               pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
+       /* Make pagetable pieces RO */
+       set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
+       set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
+
+       /* Pin down new L4 */
+       pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
+                         PFN_DOWN(__pa_symbol(init_level4_pgt)));
+
+       /* Unpin Xen-provided one */
+       pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
-               /*
-                * At this stage there can be no user pgd, and no page
-                * structure to attach it to, so make sure we just set kernel
-                * pgd.
-                */
-               xen_mc_batch();
-               __xen_write_cr3(true, __pa(init_level4_pgt));
-               xen_mc_issue(PARAVIRT_LAZY_CPU);
-       } else
-               native_write_cr3(__pa(init_level4_pgt));
+       /*
+        * At this stage there can be no user pgd, and no page structure to
+        * attach it to, so make sure we just set kernel pgd.
+        */
+       xen_mc_batch();
+       __xen_write_cr3(true, __pa(init_level4_pgt));
+       xen_mc_issue(PARAVIRT_LAZY_CPU);
 
        /* We can't that easily rip out L3 and L2, as the Xen pagetables are
         * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ...  for
@@ -2403,9 +2389,6 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 
 static void __init xen_post_allocator_init(void)
 {
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        pv_mmu_ops.set_pte = xen_set_pte;
        pv_mmu_ops.set_pmd = xen_set_pmd;
        pv_mmu_ops.set_pud = xen_set_pud;
@@ -2511,9 +2494,6 @@ void __init xen_init_mmu_ops(void)
 {
        x86_init.paging.pagetable_init = xen_pagetable_init;
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        pv_mmu_ops = xen_mmu_ops;
 
        memset(dummy_mapping, 0xff, PAGE_SIZE);
@@ -2650,9 +2630,6 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
         * this function are redundant and can be ignored.
         */
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return 0;
-
        if (unlikely(order > MAX_CONTIG_ORDER))
                return -ENOMEM;
 
@@ -2689,9 +2666,6 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
        int success;
        unsigned long vstart;
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        if (unlikely(order > MAX_CONTIG_ORDER))
                return;
 
index f71f88ea7646dcc798067e984dddefa8a659037d..19707db966f1393017bcf9528ff64d2951089d20 100644 (file)
@@ -29,7 +29,8 @@ static inline void variant_irq_disable(unsigned int irq) { }
 # define PLATFORM_NR_IRQS 0
 #endif
 #define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
-#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS)
+#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS + 1)
+#define XTENSA_PIC_LINUX_IRQ(hwirq) ((hwirq) + 1)
 
 #if VARIANT_NR_IRQS == 0
 static inline void variant_init_irq(void) { }
index 003eeee3fbc636d91aed849aaa39bb0c24370227..30ee8c608853d4fb4b238a01319589d38ce018b7 100644 (file)
@@ -213,8 +213,6 @@ struct mm_struct;
 #define release_segments(mm)   do { } while(0)
 #define forget_segments()      do { } while (0)
 
-#define thread_saved_pc(tsk)   (task_pt_regs(tsk)->pc)
-
 extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)          (task_pt_regs(tsk)->pc)
index a265edd6ac37b423e7227f095201fcd8e1685538..99341028cc77c5d24f10ee1ec6b1cb534137cc84 100644 (file)
@@ -34,11 +34,6 @@ asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
 {
        int irq = irq_find_mapping(NULL, hwirq);
 
-       if (hwirq >= NR_IRQS) {
-               printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
-                               __func__, hwirq);
-       }
-
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
        /* Debugging check for stack overflow: is there less than 1KB free? */
        {
index 394ef08300b6a3188b196155e0863bf2360fef93..33bfa5270d95440cd44c95674073608797e1d131 100644 (file)
@@ -593,8 +593,7 @@ c_show(struct seq_file *f, void *slot)
                      (ccount_freq/10000) % 100,
                      loops_per_jiffy/(500000/HZ),
                      (loops_per_jiffy/(5000/HZ)) % 100);
-
-       seq_printf(f,"flags\t\t: "
+       seq_puts(f, "flags\t\t: "
 #if XCHAL_HAVE_NMI
                     "nmi "
 #endif
index 06937928cb72dc1ac66d1bb18543d49daaf511ec..74afbf02d07e8b3a7539235eeb2d5cfabe791230 100644 (file)
@@ -88,7 +88,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
                /* At this point:  (!vmm || addr < vmm->vm_end). */
                if (TASK_SIZE - len < addr)
                        return -ENOMEM;
-               if (!vmm || addr + len <= vmm->vm_start)
+               if (!vmm || addr + len <= vm_start_gap(vmm))
                        return addr;
                addr = vmm->vm_end;
                if (flags & MAP_SHARED)
index 30d9fc21e0763c4115f7f5c74b78aba46ead1109..162c77e53ca845bf26ba9ab40ce4cd606f5a7060 100644 (file)
@@ -118,7 +118,7 @@ SECTIONS
   SECTION_VECTOR (.KernelExceptionVector.text, KERNEL_VECTOR_VADDR)
   SECTION_VECTOR (.UserExceptionVector.literal, USER_VECTOR_VADDR - 4)
   SECTION_VECTOR (.UserExceptionVector.text, USER_VECTOR_VADDR)
-  SECTION_VECTOR (.DoubleExceptionVector.literal, DOUBLEEXC_VECTOR_VADDR - 48)
+  SECTION_VECTOR (.DoubleExceptionVector.literal, DOUBLEEXC_VECTOR_VADDR - 20)
   SECTION_VECTOR (.DoubleExceptionVector.text, DOUBLEEXC_VECTOR_VADDR)
 #endif
 
@@ -306,13 +306,13 @@ SECTIONS
                  .UserExceptionVector.literal)
   SECTION_VECTOR (_DoubleExceptionVector_literal,
                  .DoubleExceptionVector.literal,
-                 DOUBLEEXC_VECTOR_VADDR - 48,
+                 DOUBLEEXC_VECTOR_VADDR - 20,
                  SIZEOF(.UserExceptionVector.text),
                  .UserExceptionVector.text)
   SECTION_VECTOR (_DoubleExceptionVector_text,
                  .DoubleExceptionVector.text,
                  DOUBLEEXC_VECTOR_VADDR,
-                 48,
+                 20,
                  .DoubleExceptionVector.literal)
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
index 02e94bb3ad3e088e65eef692873cf86447eccf16..c45b90bb93393bf58c20ab279bc8e63981b7dc02 100644 (file)
@@ -317,8 +317,7 @@ static int __init simdisk_init(void)
        if (simdisk_count > MAX_SIMDISK_COUNT)
                simdisk_count = MAX_SIMDISK_COUNT;
 
-       sddev = kmalloc(simdisk_count * sizeof(struct simdisk),
-                       GFP_KERNEL);
+       sddev = kmalloc_array(simdisk_count, sizeof(*sddev), GFP_KERNEL);
        if (sddev == NULL)
                goto out_unregister;
 
index dbeea2b440a1b50bd3e6a1eea85dcb7626244a91..1fda7e20dfcbff79849e5aae29ac8a6529c43e39 100644 (file)
 
 /* Interrupt configuration. */
 
-#define PLATFORM_NR_IRQS       10
+#define PLATFORM_NR_IRQS       0
 
 /* Default assignment of LX60 devices to external interrupts. */
 
 #ifdef CONFIG_XTENSA_MX
 #define DUART16552_INTNUM      XCHAL_EXTINT3_NUM
 #define OETH_IRQ               XCHAL_EXTINT4_NUM
+#define C67X00_IRQ             XCHAL_EXTINT8_NUM
 #else
 #define DUART16552_INTNUM      XCHAL_EXTINT0_NUM
 #define OETH_IRQ               XCHAL_EXTINT1_NUM
+#define C67X00_IRQ             XCHAL_EXTINT5_NUM
 #endif
 
 /*
@@ -63,5 +65,5 @@
 
 #define C67X00_PADDR           (XCHAL_KIO_PADDR + 0x0D0D0000)
 #define C67X00_SIZE            0x10
-#define C67X00_IRQ             5
+
 #endif /* __XTENSA_XTAVNET_HARDWARE_H */
index 779be723eb2bdd4fa03c6b30abd553e948df9991..42285f35d3135a0a6d58b5b9e2eea7f5fcaa4019 100644 (file)
@@ -175,8 +175,8 @@ static struct resource ethoc_res[] = {
                .flags = IORESOURCE_MEM,
        },
        [2] = { /* IRQ number */
-               .start = OETH_IRQ,
-               .end   = OETH_IRQ,
+               .start = XTENSA_PIC_LINUX_IRQ(OETH_IRQ),
+               .end   = XTENSA_PIC_LINUX_IRQ(OETH_IRQ),
                .flags = IORESOURCE_IRQ,
        },
 };
@@ -213,8 +213,8 @@ static struct resource c67x00_res[] = {
                .flags = IORESOURCE_MEM,
        },
        [1] = { /* IRQ number */
-               .start = C67X00_IRQ,
-               .end   = C67X00_IRQ,
+               .start = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ),
+               .end   = XTENSA_PIC_LINUX_IRQ(C67X00_IRQ),
                .flags = IORESOURCE_IRQ,
        },
 };
@@ -247,7 +247,7 @@ static struct resource serial_resource = {
 static struct plat_serial8250_port serial_platform_data[] = {
        [0] = {
                .mapbase        = DUART16552_PADDR,
-               .irq            = DUART16552_INTNUM,
+               .irq            = XTENSA_PIC_LINUX_IRQ(DUART16552_INTNUM),
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
                                  UPF_IOREMAP,
                .iotype         = XCHAL_HAVE_BE ? UPIO_MEM32BE : UPIO_MEM32,
index c8a32fb345cf5db7bac8d1a7b6a6c5e2b1d1a0fe..78b2e0db4fb2c0adba7f0b7ec089cf61f0f311c8 100644 (file)
@@ -52,7 +52,7 @@ BFQG_FLAG_FNS(idling)
 BFQG_FLAG_FNS(empty)
 #undef BFQG_FLAG_FNS
 
-/* This should be called with the queue_lock held. */
+/* This should be called with the scheduler lock held. */
 static void bfqg_stats_update_group_wait_time(struct bfqg_stats *stats)
 {
        unsigned long long now;
@@ -67,7 +67,7 @@ static void bfqg_stats_update_group_wait_time(struct bfqg_stats *stats)
        bfqg_stats_clear_waiting(stats);
 }
 
-/* This should be called with the queue_lock held. */
+/* This should be called with the scheduler lock held. */
 static void bfqg_stats_set_start_group_wait_time(struct bfq_group *bfqg,
                                                 struct bfq_group *curr_bfqg)
 {
@@ -81,7 +81,7 @@ static void bfqg_stats_set_start_group_wait_time(struct bfq_group *bfqg,
        bfqg_stats_mark_waiting(stats);
 }
 
-/* This should be called with the queue_lock held. */
+/* This should be called with the scheduler lock held. */
 static void bfqg_stats_end_empty_time(struct bfqg_stats *stats)
 {
        unsigned long long now;
@@ -203,12 +203,30 @@ struct bfq_group *bfqq_group(struct bfq_queue *bfqq)
 
 static void bfqg_get(struct bfq_group *bfqg)
 {
-       return blkg_get(bfqg_to_blkg(bfqg));
+       bfqg->ref++;
 }
 
 void bfqg_put(struct bfq_group *bfqg)
 {
-       return blkg_put(bfqg_to_blkg(bfqg));
+       bfqg->ref--;
+
+       if (bfqg->ref == 0)
+               kfree(bfqg);
+}
+
+static void bfqg_and_blkg_get(struct bfq_group *bfqg)
+{
+       /* see comments in bfq_bic_update_cgroup for why refcounting bfqg */
+       bfqg_get(bfqg);
+
+       blkg_get(bfqg_to_blkg(bfqg));
+}
+
+void bfqg_and_blkg_put(struct bfq_group *bfqg)
+{
+       bfqg_put(bfqg);
+
+       blkg_put(bfqg_to_blkg(bfqg));
 }
 
 void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
@@ -312,7 +330,11 @@ void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg)
        if (bfqq) {
                bfqq->ioprio = bfqq->new_ioprio;
                bfqq->ioprio_class = bfqq->new_ioprio_class;
-               bfqg_get(bfqg);
+               /*
+                * Make sure that bfqg and its associated blkg do not
+                * disappear before entity.
+                */
+               bfqg_and_blkg_get(bfqg);
        }
        entity->parent = bfqg->my_entity; /* NULL for root group */
        entity->sched_data = &bfqg->sched_data;
@@ -399,6 +421,8 @@ struct blkg_policy_data *bfq_pd_alloc(gfp_t gfp, int node)
                return NULL;
        }
 
+       /* see comments in bfq_bic_update_cgroup for why refcounting */
+       bfqg_get(bfqg);
        return &bfqg->pd;
 }
 
@@ -426,7 +450,7 @@ void bfq_pd_free(struct blkg_policy_data *pd)
        struct bfq_group *bfqg = pd_to_bfqg(pd);
 
        bfqg_stats_exit(&bfqg->stats);
-       return kfree(bfqg);
+       bfqg_put(bfqg);
 }
 
 void bfq_pd_reset_stats(struct blkg_policy_data *pd)
@@ -496,9 +520,10 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd,
  * Move @bfqq to @bfqg, deactivating it from its old group and reactivating
  * it on the new one.  Avoid putting the entity on the old group idle tree.
  *
- * Must be called under the queue lock; the cgroup owning @bfqg must
- * not disappear (by now this just means that we are called under
- * rcu_read_lock()).
+ * Must be called under the scheduler lock, to make sure that the blkg
+ * owning @bfqg does not disappear (see comments in
+ * bfq_bic_update_cgroup on guaranteeing the consistency of blkg
+ * objects).
  */
 void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                   struct bfq_group *bfqg)
@@ -519,16 +544,12 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                bfq_deactivate_bfqq(bfqd, bfqq, false, false);
        else if (entity->on_st)
                bfq_put_idle_entity(bfq_entity_service_tree(entity), entity);
-       bfqg_put(bfqq_group(bfqq));
+       bfqg_and_blkg_put(bfqq_group(bfqq));
 
-       /*
-        * Here we use a reference to bfqg.  We don't need a refcounter
-        * as the cgroup reference will not be dropped, so that its
-        * destroy() callback will not be invoked.
-        */
        entity->parent = bfqg->my_entity;
        entity->sched_data = &bfqg->sched_data;
-       bfqg_get(bfqg);
+       /* pin down bfqg and its associated blkg  */
+       bfqg_and_blkg_get(bfqg);
 
        if (bfq_bfqq_busy(bfqq)) {
                bfq_pos_tree_add_move(bfqd, bfqq);
@@ -545,8 +566,9 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
  * @bic: the bic to move.
  * @blkcg: the blk-cgroup to move to.
  *
- * Move bic to blkcg, assuming that bfqd->queue is locked; the caller
- * has to make sure that the reference to cgroup is valid across the call.
+ * Move bic to blkcg, assuming that bfqd->lock is held; which makes
+ * sure that the reference to cgroup is valid across the call (see
+ * comments in bfq_bic_update_cgroup on this issue)
  *
  * NOTE: an alternative approach might have been to store the current
  * cgroup in bfqq and getting a reference to it, reducing the lookup
@@ -604,6 +626,57 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
                goto out;
 
        bfqg = __bfq_bic_change_cgroup(bfqd, bic, bio_blkcg(bio));
+       /*
+        * Update blkg_path for bfq_log_* functions. We cache this
+        * path, and update it here, for the following
+        * reasons. Operations on blkg objects in blk-cgroup are
+        * protected with the request_queue lock, and not with the
+        * lock that protects the instances of this scheduler
+        * (bfqd->lock). This exposes BFQ to the following sort of
+        * race.
+        *
+        * The blkg_lookup performed in bfq_get_queue, protected
+        * through rcu, may happen to return the address of a copy of
+        * the original blkg. If this is the case, then the
+        * bfqg_and_blkg_get performed in bfq_get_queue, to pin down
+        * the blkg, is useless: it does not prevent blk-cgroup code
+        * from destroying both the original blkg and all objects
+        * directly or indirectly referred by the copy of the
+        * blkg.
+        *
+        * On the bright side, destroy operations on a blkg invoke, as
+        * a first step, hooks of the scheduler associated with the
+        * blkg. And these hooks are executed with bfqd->lock held for
+        * BFQ. As a consequence, for any blkg associated with the
+        * request queue this instance of the scheduler is attached
+        * to, we are guaranteed that such a blkg is not destroyed, and
+        * that all the pointers it contains are consistent, while we
+        * are holding bfqd->lock. A blkg_lookup performed with
+        * bfqd->lock held then returns a fully consistent blkg, which
+        * remains consistent until this lock is held.
+        *
+        * Thanks to the last fact, and to the fact that: (1) bfqg has
+        * been obtained through a blkg_lookup in the above
+        * assignment, and (2) bfqd->lock is being held, here we can
+        * safely use the policy data for the involved blkg (i.e., the
+        * field bfqg->pd) to get to the blkg associated with bfqg,
+        * and then we can safely use any field of blkg. After we
+        * release bfqd->lock, even just getting blkg through this
+        * bfqg may cause dangling references to be traversed, as
+        * bfqg->pd may not exist any more.
+        *
+        * In view of the above facts, here we cache, in the bfqg, any
+        * blkg data we may need for this bic, and for its associated
+        * bfq_queue. As of now, we need to cache only the path of the
+        * blkg, which is used in the bfq_log_* functions.
+        *
+        * Finally, note that bfqg itself needs to be protected from
+        * destruction on the blkg_free of the original blkg (which
+        * invokes bfq_pd_free). We use an additional private
+        * refcounter for bfqg, to let it disappear only after no
+        * bfq_queue refers to it any longer.
+        */
+       blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path));
        bic->blkcg_serial_nr = serial_nr;
 out:
        rcu_read_unlock();
@@ -640,8 +713,6 @@ static void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
  * @bfqd: the device data structure with the root group.
  * @bfqg: the group to move from.
  * @st: the service tree with the entities.
- *
- * Needs queue_lock to be taken and reference to be valid over the call.
  */
 static void bfq_reparent_active_entities(struct bfq_data *bfqd,
                                         struct bfq_group *bfqg,
@@ -692,8 +763,7 @@ void bfq_pd_offline(struct blkg_policy_data *pd)
                /*
                 * The idle tree may still contain bfq_queues belonging
                 * to exited task because they never migrated to a different
-                * cgroup from the one being destroyed now.  No one else
-                * can access them so it's safe to act without any lock.
+                * cgroup from the one being destroyed now.
                 */
                bfq_flush_idle_tree(st);
 
index 08ce45096350561896fb6c8959c5c04603e98555..ed93da2462abbc94ab75c10a0d9c7ce251f3f0fb 100644 (file)
@@ -3665,7 +3665,7 @@ void bfq_put_queue(struct bfq_queue *bfqq)
 
        kmem_cache_free(bfq_pool, bfqq);
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
-       bfqg_put(bfqg);
+       bfqg_and_blkg_put(bfqg);
 #endif
 }
 
index ae783c06dfd9ca73c9a3832e41e5617c510bdaf5..5c3bf986149215b3d98f753548cba9b4880f6e62 100644 (file)
@@ -759,6 +759,12 @@ struct bfq_group {
        /* must be the first member */
        struct blkg_policy_data pd;
 
+       /* cached path for this blkg (see comments in bfq_bic_update_cgroup) */
+       char blkg_path[128];
+
+       /* reference counter (see comments in bfq_bic_update_cgroup) */
+       int ref;
+
        struct bfq_entity entity;
        struct bfq_sched_data sched_data;
 
@@ -838,7 +844,7 @@ struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd,
 struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg);
 struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
 struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node);
-void bfqg_put(struct bfq_group *bfqg);
+void bfqg_and_blkg_put(struct bfq_group *bfqg);
 
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
 extern struct cftype bfq_blkcg_legacy_files[];
@@ -910,20 +916,13 @@ void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq);
 struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
 
 #define bfq_log_bfqq(bfqd, bfqq, fmt, args...) do {                    \
-       char __pbuf[128];                                               \
-                                                                       \
-       blkg_path(bfqg_to_blkg(bfqq_group(bfqq)), __pbuf, sizeof(__pbuf)); \
-       blk_add_trace_msg((bfqd)->queue, "bfq%d%c %s " fmt, (bfqq)->pid, \
+       blk_add_trace_msg((bfqd)->queue, "bfq%d%c %s " fmt, (bfqq)->pid,\
                        bfq_bfqq_sync((bfqq)) ? 'S' : 'A',              \
-                         __pbuf, ##args);                              \
+                       bfqq_group(bfqq)->blkg_path, ##args);           \
 } while (0)
 
-#define bfq_log_bfqg(bfqd, bfqg, fmt, args...) do {                    \
-       char __pbuf[128];                                               \
-                                                                       \
-       blkg_path(bfqg_to_blkg(bfqg), __pbuf, sizeof(__pbuf));          \
-       blk_add_trace_msg((bfqd)->queue, "%s " fmt, __pbuf, ##args);    \
-} while (0)
+#define bfq_log_bfqg(bfqd, bfqg, fmt, args...) \
+       blk_add_trace_msg((bfqd)->queue, "%s " fmt, (bfqg)->blkg_path, ##args)
 
 #else /* CONFIG_BFQ_GROUP_IOSCHED */
 
index 5384713d48bc9929e2a4dc8b1b9f22b2e1c5bcd3..b5009a896a7faa1dfc9fe4320181798cc42ccfa5 100644 (file)
@@ -175,6 +175,9 @@ bool bio_integrity_enabled(struct bio *bio)
        if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
                return false;
 
+       if (!bio_sectors(bio))
+               return false;
+
        /* Already protected? */
        if (bio_integrity(bio))
                return false;
index 888e7801c6381edd8d995503643917b2f452282e..26b0810fb8eac14b0a39c27bdf53f2398c767fb3 100644 (file)
@@ -240,20 +240,21 @@ fallback:
        return bvl;
 }
 
-static void __bio_free(struct bio *bio)
+void bio_uninit(struct bio *bio)
 {
        bio_disassociate_task(bio);
 
        if (bio_integrity(bio))
                bio_integrity_free(bio);
 }
+EXPORT_SYMBOL(bio_uninit);
 
 static void bio_free(struct bio *bio)
 {
        struct bio_set *bs = bio->bi_pool;
        void *p;
 
-       __bio_free(bio);
+       bio_uninit(bio);
 
        if (bs) {
                bvec_free(bs->bvec_pool, bio->bi_io_vec, BVEC_POOL_IDX(bio));
@@ -271,6 +272,11 @@ static void bio_free(struct bio *bio)
        }
 }
 
+/*
+ * Users of this function have their own bio allocation. Subsequently,
+ * they must remember to pair any call to bio_init() with bio_uninit()
+ * when IO has completed, or when the bio is released.
+ */
 void bio_init(struct bio *bio, struct bio_vec *table,
              unsigned short max_vecs)
 {
@@ -297,7 +303,7 @@ void bio_reset(struct bio *bio)
 {
        unsigned long flags = bio->bi_flags & (~0UL << BIO_RESET_BITS);
 
-       __bio_free(bio);
+       bio_uninit(bio);
 
        memset(bio, 0, BIO_RESET_BYTES);
        bio->bi_flags = flags;
index 7c2947128f5813a677a0361eddcd277b5946d03e..0480892e97e501807a7f14f843eb549719f33c81 100644 (file)
@@ -74,7 +74,7 @@ static void blkg_free(struct blkcg_gq *blkg)
                        blkcg_policy[i]->pd_free_fn(blkg->pd[i]);
 
        if (blkg->blkcg != &blkcg_root)
-               blk_exit_rl(&blkg->rl);
+               blk_exit_rl(blkg->q, &blkg->rl);
 
        blkg_rwstat_exit(&blkg->stat_ios);
        blkg_rwstat_exit(&blkg->stat_bytes);
index c7068520794bd0ba060b905f850efaae6a8cbd36..a7421b772d0e0e3f4b8372fbc11aefd83763d30a 100644 (file)
@@ -648,13 +648,19 @@ int blk_init_rl(struct request_list *rl, struct request_queue *q,
        if (!rl->rq_pool)
                return -ENOMEM;
 
+       if (rl != &q->root_rl)
+               WARN_ON_ONCE(!blk_get_queue(q));
+
        return 0;
 }
 
-void blk_exit_rl(struct request_list *rl)
+void blk_exit_rl(struct request_queue *q, struct request_list *rl)
 {
-       if (rl->rq_pool)
+       if (rl->rq_pool) {
                mempool_destroy(rl->rq_pool);
+               if (rl != &q->root_rl)
+                       blk_put_queue(q);
+       }
 }
 
 struct request_queue *blk_alloc_queue(gfp_t gfp_mask)
index 1f5b692526ae1a7199ee9bbaef305c4b0a42e696..0ded5e846335667406d58ce08e8439360baeb312 100644 (file)
@@ -68,6 +68,45 @@ static void blk_mq_sched_assign_ioc(struct request_queue *q,
                __blk_mq_sched_assign_ioc(q, rq, bio, ioc);
 }
 
+/*
+ * Mark a hardware queue as needing a restart. For shared queues, maintain
+ * a count of how many hardware queues are marked for restart.
+ */
+static void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
+{
+       if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+               return;
+
+       if (hctx->flags & BLK_MQ_F_TAG_SHARED) {
+               struct request_queue *q = hctx->queue;
+
+               if (!test_and_set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+                       atomic_inc(&q->shared_hctx_restart);
+       } else
+               set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
+}
+
+static bool blk_mq_sched_restart_hctx(struct blk_mq_hw_ctx *hctx)
+{
+       if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+               return false;
+
+       if (hctx->flags & BLK_MQ_F_TAG_SHARED) {
+               struct request_queue *q = hctx->queue;
+
+               if (test_and_clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+                       atomic_dec(&q->shared_hctx_restart);
+       } else
+               clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
+
+       if (blk_mq_hctx_has_pending(hctx)) {
+               blk_mq_run_hw_queue(hctx, true);
+               return true;
+       }
+
+       return false;
+}
+
 struct request *blk_mq_sched_get_request(struct request_queue *q,
                                         struct bio *bio,
                                         unsigned int op,
@@ -266,18 +305,6 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
        return true;
 }
 
-static bool blk_mq_sched_restart_hctx(struct blk_mq_hw_ctx *hctx)
-{
-       if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) {
-               clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
-               if (blk_mq_hctx_has_pending(hctx)) {
-                       blk_mq_run_hw_queue(hctx, true);
-                       return true;
-               }
-       }
-       return false;
-}
-
 /**
  * list_for_each_entry_rcu_rr - iterate in a round-robin fashion over rcu list
  * @pos:    loop cursor.
@@ -309,6 +336,13 @@ void blk_mq_sched_restart(struct blk_mq_hw_ctx *const hctx)
        unsigned int i, j;
 
        if (set->flags & BLK_MQ_F_TAG_SHARED) {
+               /*
+                * If this is 0, then we know that no hardware queues
+                * have RESTART marked. We're done.
+                */
+               if (!atomic_read(&queue->shared_hctx_restart))
+                       return;
+
                rcu_read_lock();
                list_for_each_entry_rcu_rr(q, queue, &set->tag_list,
                                           tag_set_list) {
index edafb5383b7bbdedfd5365ed38f9a5c373ec96ab..5007edece51aced038d3db8f0adbc722c49e3d38 100644 (file)
@@ -115,15 +115,6 @@ static inline bool blk_mq_sched_has_work(struct blk_mq_hw_ctx *hctx)
        return false;
 }
 
-/*
- * Mark a hardware queue as needing a restart.
- */
-static inline void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
-{
-       if (!test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
-               set_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
-}
-
 static inline bool blk_mq_sched_needs_restart(struct blk_mq_hw_ctx *hctx)
 {
        return test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
index a69ad122ed66c6b93385f1b3959a893b407b9d05..958cedaff8b829ceb4c724dbf1c6f6d30d883aeb 100644 (file)
@@ -628,25 +628,6 @@ void blk_mq_delay_kick_requeue_list(struct request_queue *q,
 }
 EXPORT_SYMBOL(blk_mq_delay_kick_requeue_list);
 
-void blk_mq_abort_requeue_list(struct request_queue *q)
-{
-       unsigned long flags;
-       LIST_HEAD(rq_list);
-
-       spin_lock_irqsave(&q->requeue_lock, flags);
-       list_splice_init(&q->requeue_list, &rq_list);
-       spin_unlock_irqrestore(&q->requeue_lock, flags);
-
-       while (!list_empty(&rq_list)) {
-               struct request *rq;
-
-               rq = list_first_entry(&rq_list, struct request, queuelist);
-               list_del_init(&rq->queuelist);
-               blk_mq_end_request(rq, -EIO);
-       }
-}
-EXPORT_SYMBOL(blk_mq_abort_requeue_list);
-
 struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
 {
        if (tag < tags->nr_tags) {
@@ -1480,22 +1461,28 @@ static blk_qc_t request_to_qc_t(struct blk_mq_hw_ctx *hctx, struct request *rq)
        return blk_tag_to_qc_t(rq->internal_tag, hctx->queue_num, true);
 }
 
-static void __blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie,
-                                     bool may_sleep)
+static void __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
+                                       struct request *rq,
+                                       blk_qc_t *cookie, bool may_sleep)
 {
        struct request_queue *q = rq->q;
        struct blk_mq_queue_data bd = {
                .rq = rq,
                .last = true,
        };
-       struct blk_mq_hw_ctx *hctx;
        blk_qc_t new_cookie;
        int ret;
+       bool run_queue = true;
+
+       if (blk_mq_hctx_stopped(hctx)) {
+               run_queue = false;
+               goto insert;
+       }
 
        if (q->elevator)
                goto insert;
 
-       if (!blk_mq_get_driver_tag(rq, &hctx, false))
+       if (!blk_mq_get_driver_tag(rq, NULL, false))
                goto insert;
 
        new_cookie = request_to_qc_t(hctx, rq);
@@ -1519,7 +1506,7 @@ static void __blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie,
 
        __blk_mq_requeue_request(rq);
 insert:
-       blk_mq_sched_insert_request(rq, false, true, false, may_sleep);
+       blk_mq_sched_insert_request(rq, false, run_queue, false, may_sleep);
 }
 
 static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
@@ -1527,7 +1514,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
 {
        if (!(hctx->flags & BLK_MQ_F_BLOCKING)) {
                rcu_read_lock();
-               __blk_mq_try_issue_directly(rq, cookie, false);
+               __blk_mq_try_issue_directly(hctx, rq, cookie, false);
                rcu_read_unlock();
        } else {
                unsigned int srcu_idx;
@@ -1535,7 +1522,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
                might_sleep();
 
                srcu_idx = srcu_read_lock(&hctx->queue_rq_srcu);
-               __blk_mq_try_issue_directly(rq, cookie, true);
+               __blk_mq_try_issue_directly(hctx, rq, cookie, true);
                srcu_read_unlock(&hctx->queue_rq_srcu, srcu_idx);
        }
 }
@@ -1638,9 +1625,12 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
                blk_mq_put_ctx(data.ctx);
 
-               if (same_queue_rq)
+               if (same_queue_rq) {
+                       data.hctx = blk_mq_map_queue(q,
+                                       same_queue_rq->mq_ctx->cpu);
                        blk_mq_try_issue_directly(data.hctx, same_queue_rq,
                                        &cookie);
+               }
        } else if (q->nr_hw_queues > 1 && is_sync) {
                blk_mq_put_ctx(data.ctx);
                blk_mq_bio_to_request(rq, bio);
@@ -2113,20 +2103,30 @@ static void blk_mq_map_swqueue(struct request_queue *q,
        }
 }
 
+/*
+ * Caller needs to ensure that we're either frozen/quiesced, or that
+ * the queue isn't live yet.
+ */
 static void queue_set_hctx_shared(struct request_queue *q, bool shared)
 {
        struct blk_mq_hw_ctx *hctx;
        int i;
 
        queue_for_each_hw_ctx(q, hctx, i) {
-               if (shared)
+               if (shared) {
+                       if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+                               atomic_inc(&q->shared_hctx_restart);
                        hctx->flags |= BLK_MQ_F_TAG_SHARED;
-               else
+               } else {
+                       if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
+                               atomic_dec(&q->shared_hctx_restart);
                        hctx->flags &= ~BLK_MQ_F_TAG_SHARED;
+               }
        }
 }
 
-static void blk_mq_update_tag_set_depth(struct blk_mq_tag_set *set, bool shared)
+static void blk_mq_update_tag_set_depth(struct blk_mq_tag_set *set,
+                                       bool shared)
 {
        struct request_queue *q;
 
@@ -2660,7 +2660,8 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
        return ret;
 }
 
-void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
+static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
+                                                       int nr_hw_queues)
 {
        struct request_queue *q;
 
@@ -2684,6 +2685,13 @@ void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
        list_for_each_entry(q, &set->tag_list, tag_set_list)
                blk_mq_unfreeze_queue(q);
 }
+
+void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues)
+{
+       mutex_lock(&set->tag_list_lock);
+       __blk_mq_update_nr_hw_queues(set, nr_hw_queues);
+       mutex_unlock(&set->tag_list_lock);
+}
 EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues);
 
 /* Enable polling stats and return whether they were already enabled. */
index 504fee9400523e206f987542d59abf8167e31c7e..27aceab1cc31484423524caae9d6970cef9274ec 100644 (file)
@@ -777,24 +777,25 @@ static void blk_free_queue_rcu(struct rcu_head *rcu_head)
 }
 
 /**
- * blk_release_queue: - release a &struct request_queue when it is no longer needed
- * @kobj:    the kobj belonging to the request queue to be released
+ * __blk_release_queue - release a request queue when it is no longer needed
+ * @work: pointer to the release_work member of the request queue to be released
  *
  * Description:
- *     blk_release_queue is the pair to blk_init_queue() or
- *     blk_queue_make_request().  It should be called when a request queue is
- *     being released; typically when a block device is being de-registered.
- *     Currently, its primary task it to free all the &struct request
- *     structures that were allocated to the queue and the queue itself.
+ *     blk_release_queue is the counterpart of blk_init_queue(). It should be
+ *     called when a request queue is being released; typically when a block
+ *     device is being de-registered. Its primary task it to free the queue
+ *     itself.
  *
- * Note:
+ * Notes:
  *     The low level driver must have finished any outstanding requests first
  *     via blk_cleanup_queue().
- **/
-static void blk_release_queue(struct kobject *kobj)
+ *
+ *     Although blk_release_queue() may be called with preemption disabled,
+ *     __blk_release_queue() may sleep.
+ */
+static void __blk_release_queue(struct work_struct *work)
 {
-       struct request_queue *q =
-               container_of(kobj, struct request_queue, kobj);
+       struct request_queue *q = container_of(work, typeof(*q), release_work);
 
        if (test_bit(QUEUE_FLAG_POLL_STATS, &q->queue_flags))
                blk_stat_remove_callback(q, q->poll_cb);
@@ -809,7 +810,7 @@ static void blk_release_queue(struct kobject *kobj)
 
        blk_free_queue_stats(q->stats);
 
-       blk_exit_rl(&q->root_rl);
+       blk_exit_rl(q, &q->root_rl);
 
        if (q->queue_tags)
                __blk_queue_free_tags(q);
@@ -834,6 +835,15 @@ static void blk_release_queue(struct kobject *kobj)
        call_rcu(&q->rcu_head, blk_free_queue_rcu);
 }
 
+static void blk_release_queue(struct kobject *kobj)
+{
+       struct request_queue *q =
+               container_of(kobj, struct request_queue, kobj);
+
+       INIT_WORK(&q->release_work, __blk_release_queue);
+       schedule_work(&q->release_work);
+}
+
 static const struct sysfs_ops queue_sysfs_ops = {
        .show   = queue_attr_show,
        .store  = queue_attr_store,
@@ -887,10 +897,10 @@ int blk_register_queue(struct gendisk *disk)
                goto unlock;
        }
 
-       if (q->mq_ops)
+       if (q->mq_ops) {
                __blk_mq_register_dev(dev, q);
-
-       blk_mq_debugfs_register(q);
+               blk_mq_debugfs_register(q);
+       }
 
        kobject_uevent(&q->kobj, KOBJ_ADD);
 
index b78db2e5fdff1e158ea52c179313ff3eba282015..a7285bf2831c7bdbb89b753fccb198f8640e8780 100644 (file)
@@ -22,11 +22,18 @@ static int throtl_quantum = 32;
 #define DFL_THROTL_SLICE_HD (HZ / 10)
 #define DFL_THROTL_SLICE_SSD (HZ / 50)
 #define MAX_THROTL_SLICE (HZ)
-#define DFL_IDLE_THRESHOLD_SSD (1000L) /* 1 ms */
-#define DFL_IDLE_THRESHOLD_HD (100L * 1000) /* 100 ms */
 #define MAX_IDLE_TIME (5L * 1000 * 1000) /* 5 s */
-/* default latency target is 0, eg, guarantee IO latency by default */
-#define DFL_LATENCY_TARGET (0)
+#define MIN_THROTL_BPS (320 * 1024)
+#define MIN_THROTL_IOPS (10)
+#define DFL_LATENCY_TARGET (-1L)
+#define DFL_IDLE_THRESHOLD (0)
+#define DFL_HD_BASELINE_LATENCY (4000L) /* 4ms */
+#define LATENCY_FILTERED_SSD (0)
+/*
+ * For HD, very small latency comes from sequential IO. Such IO is helpless to
+ * help determine if its IO is impacted by others, hence we ignore the IO
+ */
+#define LATENCY_FILTERED_HD (1000L) /* 1ms */
 
 #define SKIP_LATENCY (((u64)1) << BLK_STAT_RES_SHIFT)
 
@@ -157,6 +164,7 @@ struct throtl_grp {
        unsigned long last_check_time;
 
        unsigned long latency_target; /* us */
+       unsigned long latency_target_conf; /* us */
        /* When did we start a new slice */
        unsigned long slice_start[2];
        unsigned long slice_end[2];
@@ -165,6 +173,7 @@ struct throtl_grp {
        unsigned long checked_last_finish_time; /* ns / 1024 */
        unsigned long avg_idletime; /* ns / 1024 */
        unsigned long idletime_threshold; /* us */
+       unsigned long idletime_threshold_conf; /* us */
 
        unsigned int bio_cnt; /* total bios */
        unsigned int bad_bio_cnt; /* bios exceeding latency threshold */
@@ -201,8 +210,6 @@ struct throtl_data
        unsigned int limit_index;
        bool limit_valid[LIMIT_CNT];
 
-       unsigned long dft_idletime_threshold; /* us */
-
        unsigned long low_upgrade_time;
        unsigned long low_downgrade_time;
 
@@ -212,6 +219,7 @@ struct throtl_data
        struct avg_latency_bucket avg_buckets[LATENCY_BUCKET_SIZE];
        struct latency_bucket __percpu *latency_buckets;
        unsigned long last_calculate_time;
+       unsigned long filtered_latency;
 
        bool track_bio_latency;
 };
@@ -294,8 +302,14 @@ static uint64_t tg_bps_limit(struct throtl_grp *tg, int rw)
 
        td = tg->td;
        ret = tg->bps[rw][td->limit_index];
-       if (ret == 0 && td->limit_index == LIMIT_LOW)
-               return tg->bps[rw][LIMIT_MAX];
+       if (ret == 0 && td->limit_index == LIMIT_LOW) {
+               /* intermediate node or iops isn't 0 */
+               if (!list_empty(&blkg->blkcg->css.children) ||
+                   tg->iops[rw][td->limit_index])
+                       return U64_MAX;
+               else
+                       return MIN_THROTL_BPS;
+       }
 
        if (td->limit_index == LIMIT_MAX && tg->bps[rw][LIMIT_LOW] &&
            tg->bps[rw][LIMIT_LOW] != tg->bps[rw][LIMIT_MAX]) {
@@ -315,10 +329,17 @@ static unsigned int tg_iops_limit(struct throtl_grp *tg, int rw)
 
        if (cgroup_subsys_on_dfl(io_cgrp_subsys) && !blkg->parent)
                return UINT_MAX;
+
        td = tg->td;
        ret = tg->iops[rw][td->limit_index];
-       if (ret == 0 && tg->td->limit_index == LIMIT_LOW)
-               return tg->iops[rw][LIMIT_MAX];
+       if (ret == 0 && tg->td->limit_index == LIMIT_LOW) {
+               /* intermediate node or bps isn't 0 */
+               if (!list_empty(&blkg->blkcg->css.children) ||
+                   tg->bps[rw][td->limit_index])
+                       return UINT_MAX;
+               else
+                       return MIN_THROTL_IOPS;
+       }
 
        if (td->limit_index == LIMIT_MAX && tg->iops[rw][LIMIT_LOW] &&
            tg->iops[rw][LIMIT_LOW] != tg->iops[rw][LIMIT_MAX]) {
@@ -482,6 +503,9 @@ static struct blkg_policy_data *throtl_pd_alloc(gfp_t gfp, int node)
        /* LIMIT_LOW will have default value 0 */
 
        tg->latency_target = DFL_LATENCY_TARGET;
+       tg->latency_target_conf = DFL_LATENCY_TARGET;
+       tg->idletime_threshold = DFL_IDLE_THRESHOLD;
+       tg->idletime_threshold_conf = DFL_IDLE_THRESHOLD;
 
        return &tg->pd;
 }
@@ -510,8 +534,6 @@ static void throtl_pd_init(struct blkg_policy_data *pd)
        if (cgroup_subsys_on_dfl(io_cgrp_subsys) && blkg->parent)
                sq->parent_sq = &blkg_to_tg(blkg->parent)->service_queue;
        tg->td = td;
-
-       tg->idletime_threshold = td->dft_idletime_threshold;
 }
 
 /*
@@ -684,7 +706,7 @@ static void throtl_dequeue_tg(struct throtl_grp *tg)
 static void throtl_schedule_pending_timer(struct throtl_service_queue *sq,
                                          unsigned long expires)
 {
-       unsigned long max_expire = jiffies + 8 * sq_to_tg(sq)->td->throtl_slice;
+       unsigned long max_expire = jiffies + 8 * sq_to_td(sq)->throtl_slice;
 
        /*
         * Since we are adjusting the throttle limit dynamically, the sleep
@@ -1349,7 +1371,7 @@ static int tg_print_conf_uint(struct seq_file *sf, void *v)
        return 0;
 }
 
-static void tg_conf_updated(struct throtl_grp *tg)
+static void tg_conf_updated(struct throtl_grp *tg, bool global)
 {
        struct throtl_service_queue *sq = &tg->service_queue;
        struct cgroup_subsys_state *pos_css;
@@ -1367,8 +1389,26 @@ static void tg_conf_updated(struct throtl_grp *tg)
         * restrictions in the whole hierarchy and allows them to bypass
         * blk-throttle.
         */
-       blkg_for_each_descendant_pre(blkg, pos_css, tg_to_blkg(tg))
-               tg_update_has_rules(blkg_to_tg(blkg));
+       blkg_for_each_descendant_pre(blkg, pos_css,
+                       global ? tg->td->queue->root_blkg : tg_to_blkg(tg)) {
+               struct throtl_grp *this_tg = blkg_to_tg(blkg);
+               struct throtl_grp *parent_tg;
+
+               tg_update_has_rules(this_tg);
+               /* ignore root/second level */
+               if (!cgroup_subsys_on_dfl(io_cgrp_subsys) || !blkg->parent ||
+                   !blkg->parent->parent)
+                       continue;
+               parent_tg = blkg_to_tg(blkg->parent);
+               /*
+                * make sure all children has lower idle time threshold and
+                * higher latency target
+                */
+               this_tg->idletime_threshold = min(this_tg->idletime_threshold,
+                               parent_tg->idletime_threshold);
+               this_tg->latency_target = max(this_tg->latency_target,
+                               parent_tg->latency_target);
+       }
 
        /*
         * We're already holding queue_lock and know @tg is valid.  Let's
@@ -1413,7 +1453,7 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
        else
                *(unsigned int *)((void *)tg + of_cft(of)->private) = v;
 
-       tg_conf_updated(tg);
+       tg_conf_updated(tg, false);
        ret = 0;
 out_finish:
        blkg_conf_finish(&ctx);
@@ -1497,34 +1537,34 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd,
            tg->iops_conf[READ][off] == iops_dft &&
            tg->iops_conf[WRITE][off] == iops_dft &&
            (off != LIMIT_LOW ||
-            (tg->idletime_threshold == tg->td->dft_idletime_threshold &&
-             tg->latency_target == DFL_LATENCY_TARGET)))
+            (tg->idletime_threshold_conf == DFL_IDLE_THRESHOLD &&
+             tg->latency_target_conf == DFL_LATENCY_TARGET)))
                return 0;
 
-       if (tg->bps_conf[READ][off] != bps_dft)
+       if (tg->bps_conf[READ][off] != U64_MAX)
                snprintf(bufs[0], sizeof(bufs[0]), "%llu",
                        tg->bps_conf[READ][off]);
-       if (tg->bps_conf[WRITE][off] != bps_dft)
+       if (tg->bps_conf[WRITE][off] != U64_MAX)
                snprintf(bufs[1], sizeof(bufs[1]), "%llu",
                        tg->bps_conf[WRITE][off]);
-       if (tg->iops_conf[READ][off] != iops_dft)
+       if (tg->iops_conf[READ][off] != UINT_MAX)
                snprintf(bufs[2], sizeof(bufs[2]), "%u",
                        tg->iops_conf[READ][off]);
-       if (tg->iops_conf[WRITE][off] != iops_dft)
+       if (tg->iops_conf[WRITE][off] != UINT_MAX)
                snprintf(bufs[3], sizeof(bufs[3]), "%u",
                        tg->iops_conf[WRITE][off]);
        if (off == LIMIT_LOW) {
-               if (tg->idletime_threshold == ULONG_MAX)
+               if (tg->idletime_threshold_conf == ULONG_MAX)
                        strcpy(idle_time, " idle=max");
                else
                        snprintf(idle_time, sizeof(idle_time), " idle=%lu",
-                               tg->idletime_threshold);
+                               tg->idletime_threshold_conf);
 
-               if (tg->latency_target == ULONG_MAX)
+               if (tg->latency_target_conf == ULONG_MAX)
                        strcpy(latency_time, " latency=max");
                else
                        snprintf(latency_time, sizeof(latency_time),
-                               " latency=%lu", tg->latency_target);
+                               " latency=%lu", tg->latency_target_conf);
        }
 
        seq_printf(sf, "%s rbps=%s wbps=%s riops=%s wiops=%s%s%s\n",
@@ -1563,8 +1603,8 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
        v[2] = tg->iops_conf[READ][index];
        v[3] = tg->iops_conf[WRITE][index];
 
-       idle_time = tg->idletime_threshold;
-       latency_time = tg->latency_target;
+       idle_time = tg->idletime_threshold_conf;
+       latency_time = tg->latency_target_conf;
        while (true) {
                char tok[27];   /* wiops=18446744073709551616 */
                char *p;
@@ -1623,17 +1663,33 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
                tg->iops_conf[READ][LIMIT_MAX]);
        tg->iops[WRITE][LIMIT_LOW] = min(tg->iops_conf[WRITE][LIMIT_LOW],
                tg->iops_conf[WRITE][LIMIT_MAX]);
+       tg->idletime_threshold_conf = idle_time;
+       tg->latency_target_conf = latency_time;
+
+       /* force user to configure all settings for low limit  */
+       if (!(tg->bps[READ][LIMIT_LOW] || tg->iops[READ][LIMIT_LOW] ||
+             tg->bps[WRITE][LIMIT_LOW] || tg->iops[WRITE][LIMIT_LOW]) ||
+           tg->idletime_threshold_conf == DFL_IDLE_THRESHOLD ||
+           tg->latency_target_conf == DFL_LATENCY_TARGET) {
+               tg->bps[READ][LIMIT_LOW] = 0;
+               tg->bps[WRITE][LIMIT_LOW] = 0;
+               tg->iops[READ][LIMIT_LOW] = 0;
+               tg->iops[WRITE][LIMIT_LOW] = 0;
+               tg->idletime_threshold = DFL_IDLE_THRESHOLD;
+               tg->latency_target = DFL_LATENCY_TARGET;
+       } else if (index == LIMIT_LOW) {
+               tg->idletime_threshold = tg->idletime_threshold_conf;
+               tg->latency_target = tg->latency_target_conf;
+       }
 
-       if (index == LIMIT_LOW) {
-               blk_throtl_update_limit_valid(tg->td);
-               if (tg->td->limit_valid[LIMIT_LOW])
+       blk_throtl_update_limit_valid(tg->td);
+       if (tg->td->limit_valid[LIMIT_LOW]) {
+               if (index == LIMIT_LOW)
                        tg->td->limit_index = LIMIT_LOW;
-               tg->idletime_threshold = (idle_time == ULONG_MAX) ?
-                       ULONG_MAX : idle_time;
-               tg->latency_target = (latency_time == ULONG_MAX) ?
-                       ULONG_MAX : latency_time;
-       }
-       tg_conf_updated(tg);
+       } else
+               tg->td->limit_index = LIMIT_MAX;
+       tg_conf_updated(tg, index == LIMIT_LOW &&
+               tg->td->limit_valid[LIMIT_LOW]);
        ret = 0;
 out_finish:
        blkg_conf_finish(&ctx);
@@ -1722,17 +1778,25 @@ static bool throtl_tg_is_idle(struct throtl_grp *tg)
        /*
         * cgroup is idle if:
         * - single idle is too long, longer than a fixed value (in case user
-        *   configure a too big threshold) or 4 times of slice
+        *   configure a too big threshold) or 4 times of idletime threshold
         * - average think time is more than threshold
         * - IO latency is largely below threshold
         */
-       unsigned long time = jiffies_to_usecs(4 * tg->td->throtl_slice);
-
-       time = min_t(unsigned long, MAX_IDLE_TIME, time);
-       return (ktime_get_ns() >> 10) - tg->last_finish_time > time ||
-              tg->avg_idletime > tg->idletime_threshold ||
-              (tg->latency_target && tg->bio_cnt &&
+       unsigned long time;
+       bool ret;
+
+       time = min_t(unsigned long, MAX_IDLE_TIME, 4 * tg->idletime_threshold);
+       ret = tg->latency_target == DFL_LATENCY_TARGET ||
+             tg->idletime_threshold == DFL_IDLE_THRESHOLD ||
+             (ktime_get_ns() >> 10) - tg->last_finish_time > time ||
+             tg->avg_idletime > tg->idletime_threshold ||
+             (tg->latency_target && tg->bio_cnt &&
                tg->bad_bio_cnt * 5 < tg->bio_cnt);
+       throtl_log(&tg->service_queue,
+               "avg_idle=%ld, idle_threshold=%ld, bad_bio=%d, total_bio=%d, is_idle=%d, scale=%d",
+               tg->avg_idletime, tg->idletime_threshold, tg->bad_bio_cnt,
+               tg->bio_cnt, ret, tg->td->scale);
+       return ret;
 }
 
 static bool throtl_tg_can_upgrade(struct throtl_grp *tg)
@@ -1828,6 +1892,7 @@ static void throtl_upgrade_state(struct throtl_data *td)
        struct cgroup_subsys_state *pos_css;
        struct blkcg_gq *blkg;
 
+       throtl_log(&td->service_queue, "upgrade to max");
        td->limit_index = LIMIT_MAX;
        td->low_upgrade_time = jiffies;
        td->scale = 0;
@@ -1850,6 +1915,7 @@ static void throtl_downgrade_state(struct throtl_data *td, int new)
 {
        td->scale /= 2;
 
+       throtl_log(&td->service_queue, "downgrade, scale %d", td->scale);
        if (td->scale) {
                td->low_upgrade_time = jiffies - td->scale * td->throtl_slice;
                return;
@@ -2023,6 +2089,11 @@ static void throtl_update_latency_buckets(struct throtl_data *td)
                td->avg_buckets[i].valid = true;
                last_latency = td->avg_buckets[i].latency;
        }
+
+       for (i = 0; i < LATENCY_BUCKET_SIZE; i++)
+               throtl_log(&td->service_queue,
+                       "Latency bucket %d: latency=%ld, valid=%d", i,
+                       td->avg_buckets[i].latency, td->avg_buckets[i].valid);
 }
 #else
 static inline void throtl_update_latency_buckets(struct throtl_data *td)
@@ -2218,7 +2289,7 @@ void blk_throtl_bio_endio(struct bio *bio)
                throtl_track_latency(tg->td, blk_stat_size(&bio->bi_issue_stat),
                        bio_op(bio), lat);
 
-       if (tg->latency_target) {
+       if (tg->latency_target && lat >= tg->td->filtered_latency) {
                int bucket;
                unsigned int threshold;
 
@@ -2354,18 +2425,19 @@ void blk_throtl_exit(struct request_queue *q)
 void blk_throtl_register_queue(struct request_queue *q)
 {
        struct throtl_data *td;
-       struct cgroup_subsys_state *pos_css;
-       struct blkcg_gq *blkg;
+       int i;
 
        td = q->td;
        BUG_ON(!td);
 
        if (blk_queue_nonrot(q)) {
                td->throtl_slice = DFL_THROTL_SLICE_SSD;
-               td->dft_idletime_threshold = DFL_IDLE_THRESHOLD_SSD;
+               td->filtered_latency = LATENCY_FILTERED_SSD;
        } else {
                td->throtl_slice = DFL_THROTL_SLICE_HD;
-               td->dft_idletime_threshold = DFL_IDLE_THRESHOLD_HD;
+               td->filtered_latency = LATENCY_FILTERED_HD;
+               for (i = 0; i < LATENCY_BUCKET_SIZE; i++)
+                       td->avg_buckets[i].latency = DFL_HD_BASELINE_LATENCY;
        }
 #ifndef CONFIG_BLK_DEV_THROTTLING_LOW
        /* if no low limit, use previous default */
@@ -2375,18 +2447,6 @@ void blk_throtl_register_queue(struct request_queue *q)
        td->track_bio_latency = !q->mq_ops && !q->request_fn;
        if (!td->track_bio_latency)
                blk_stat_enable_accounting(q);
-
-       /*
-        * some tg are created before queue is fully initialized, eg, nonrot
-        * isn't initialized yet
-        */
-       rcu_read_lock();
-       blkg_for_each_descendant_post(blkg, pos_css, q->root_blkg) {
-               struct throtl_grp *tg = blkg_to_tg(blkg);
-
-               tg->idletime_threshold = td->dft_idletime_threshold;
-       }
-       rcu_read_unlock();
 }
 
 #ifdef CONFIG_BLK_DEV_THROTTLING_LOW
index 2ed70228e44fc706e6efee71ca000e5e47433217..83c8e1100525f7dd80b9a75e83cd2f8efb0f5969 100644 (file)
@@ -59,7 +59,7 @@ void blk_free_flush_queue(struct blk_flush_queue *q);
 
 int blk_init_rl(struct request_list *rl, struct request_queue *q,
                gfp_t gfp_mask);
-void blk_exit_rl(struct request_list *rl);
+void blk_exit_rl(struct request_queue *q, struct request_list *rl);
 void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
                        struct bio *bio);
 void blk_queue_bypass_start(struct request_queue *q);
index da69b079725fbf62a407db76f7c5c430c52be3f9..b7e9c7feeab2acbd1a846d0c31285460aba076ec 100644 (file)
@@ -38,9 +38,13 @@ static const u64 cfq_target_latency = (u64)NSEC_PER_SEC * 3/10; /* 300 ms */
 static const int cfq_hist_divisor = 4;
 
 /*
- * offset from end of service tree
+ * offset from end of queue service tree for idle class
  */
 #define CFQ_IDLE_DELAY         (NSEC_PER_SEC / 5)
+/* offset from end of group service tree under time slice mode */
+#define CFQ_SLICE_MODE_GROUP_DELAY (NSEC_PER_SEC / 5)
+/* offset from end of group service under IOPS mode */
+#define CFQ_IOPS_MODE_GROUP_DELAY (HZ / 5)
 
 /*
  * below this threshold, we consider thinktime immediate
@@ -1362,6 +1366,14 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
        cfqg->vfraction = max_t(unsigned, vfr, 1);
 }
 
+static inline u64 cfq_get_cfqg_vdisktime_delay(struct cfq_data *cfqd)
+{
+       if (!iops_mode(cfqd))
+               return CFQ_SLICE_MODE_GROUP_DELAY;
+       else
+               return CFQ_IOPS_MODE_GROUP_DELAY;
+}
+
 static void
 cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
 {
@@ -1381,7 +1393,8 @@ cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
        n = rb_last(&st->rb);
        if (n) {
                __cfqg = rb_entry_cfqg(n);
-               cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY;
+               cfqg->vdisktime = __cfqg->vdisktime +
+                       cfq_get_cfqg_vdisktime_delay(cfqd);
        } else
                cfqg->vdisktime = st->min_vdisktime;
        cfq_group_service_tree_add(st, cfqg);
index ff07b9143ca456f8b2e8aaa3f41f9d6d8b5fe7a3..c5ec8246e25e1ed3eb6aef683c99e4aacd32ce2c 100644 (file)
@@ -320,8 +320,10 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
 
        if (info) {
                struct partition_meta_info *pinfo = alloc_part_info(disk);
-               if (!pinfo)
+               if (!pinfo) {
+                       err = -ENOMEM;
                        goto out_free_stats;
+               }
                memcpy(pinfo, info, sizeof(*info));
                p->info = pinfo;
        }
index 93e7c1b32eddd5aa27fc8c96f5f581f712541a53..5610cd537da78812e2633d76ca90e5c3fb66e7cc 100644 (file)
@@ -300,6 +300,8 @@ static void parse_bsd(struct parsed_partitions *state,
                        continue;
                bsd_start = le32_to_cpu(p->p_offset);
                bsd_size = le32_to_cpu(p->p_size);
+               if (memcmp(flavour, "bsd\0", 4) == 0)
+                       bsd_start += offset;
                if (offset == bsd_start && size == bsd_size)
                        /* full parent partition, we have it already */
                        continue;
index d3a989e718f53518bafe93ddb9efea419e5d9b30..3cd6e12cfc467d27ccf2830fffde82e1aaf0f45e 100644 (file)
@@ -141,7 +141,7 @@ int public_key_verify_signature(const struct public_key *pkey,
         * signature and returns that to us.
         */
        ret = crypto_akcipher_verify(req);
-       if (ret == -EINPROGRESS) {
+       if ((ret == -EINPROGRESS) || (ret == -EBUSY)) {
                wait_for_completion(&compl.completion);
                ret = compl.err;
        }
index 672a94c2c3ffa3a8683dfb7f02134a27d92a641e..d178650fd524cfe8bc390c883505f4cbc31d60f2 100644 (file)
@@ -381,7 +381,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
        }
 
 error:
-       kfree(desc);
+       kzfree(desc);
 error_no_desc:
        crypto_free_shash(tfm);
        kleave(" = %d", ret);
@@ -450,6 +450,6 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,
        ret = pefile_digest_pe(pebuf, pelen, &ctx);
 
 error:
-       kfree(ctx.digest);
+       kzfree(ctx.digest);
        return ret;
 }
index c80765b211cf0fae7a91c35494dc9ed45247eafe..dd03fead1ca358fc4f21cdb0c5c65b9896a39b38 100644 (file)
@@ -102,6 +102,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
                }
        }
 
+       ret = -ENOMEM;
        cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
        if (!cert->pub->key)
                goto error_decode;
index fa749f47013508d562366fb0484e7ea80535ba0a..cdb27ac4b2266eccff2ba89a5388ec2fbf6d18bc 100644 (file)
@@ -1767,9 +1767,8 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
                        break;
                case -EINPROGRESS:
                case -EBUSY:
-                       ret = wait_for_completion_interruptible(
-                               &drbg->ctr_completion);
-                       if (!ret && !drbg->ctr_async_err) {
+                       wait_for_completion(&drbg->ctr_completion);
+                       if (!drbg->ctr_async_err) {
                                reinit_completion(&drbg->ctr_completion);
                                break;
                        }
index b7ad808be3d4ec6c3822ce2cc5c0428d8f3b3dd0..3841b5eafa7ee244f605c28fd56c5a8c5dcaba9b 100644 (file)
@@ -152,10 +152,8 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
 
        err = crypto_skcipher_encrypt(&data->req);
        if (err == -EINPROGRESS || err == -EBUSY) {
-               err = wait_for_completion_interruptible(
-                       &data->result.completion);
-               if (!err)
-                       err = data->result.err;
+               wait_for_completion(&data->result.completion);
+               err = data->result.err;
        }
 
        if (err)
index 014af741fc6a3d78c769baa725774be7d9815851..4faa0fd53b0c120d39022ad726dbbe2c74f787bd 100644 (file)
@@ -764,6 +764,44 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
        return 0;
 }
 
+static int skcipher_setkey_unaligned(struct crypto_skcipher *tfm,
+                                    const u8 *key, unsigned int keylen)
+{
+       unsigned long alignmask = crypto_skcipher_alignmask(tfm);
+       struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
+       u8 *buffer, *alignbuffer;
+       unsigned long absize;
+       int ret;
+
+       absize = keylen + alignmask;
+       buffer = kmalloc(absize, GFP_ATOMIC);
+       if (!buffer)
+               return -ENOMEM;
+
+       alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+       memcpy(alignbuffer, key, keylen);
+       ret = cipher->setkey(tfm, alignbuffer, keylen);
+       kzfree(buffer);
+       return ret;
+}
+
+static int skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
+                          unsigned int keylen)
+{
+       struct skcipher_alg *cipher = crypto_skcipher_alg(tfm);
+       unsigned long alignmask = crypto_skcipher_alignmask(tfm);
+
+       if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
+               crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+
+       if ((unsigned long)key & alignmask)
+               return skcipher_setkey_unaligned(tfm, key, keylen);
+
+       return cipher->setkey(tfm, key, keylen);
+}
+
 static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm)
 {
        struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm);
@@ -784,7 +822,7 @@ static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm)
            tfm->__crt_alg->cra_type == &crypto_givcipher_type)
                return crypto_init_skcipher_ops_ablkcipher(tfm);
 
-       skcipher->setkey = alg->setkey;
+       skcipher->setkey = skcipher_setkey;
        skcipher->encrypt = alg->encrypt;
        skcipher->decrypt = alg->decrypt;
        skcipher->ivsize = alg->ivsize;
index 5a968a78652bd23d269fbc871957a4488fb03af6..0d2e98920069cf97ee323c8f9c3df543f8d6407a 100644 (file)
@@ -416,13 +416,18 @@ acpi_tb_get_table(struct acpi_table_desc *table_desc,
                }
        }
 
-       table_desc->validation_count++;
-       if (table_desc->validation_count == 0) {
-               ACPI_ERROR((AE_INFO,
-                           "Table %p, Validation count is zero after increment\n",
-                           table_desc));
-               table_desc->validation_count--;
-               return_ACPI_STATUS(AE_LIMIT);
+       if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
+               table_desc->validation_count++;
+
+               /*
+                * Detect validation_count overflows to ensure that the warning
+                * message will only be printed once.
+                */
+               if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
+                       ACPI_WARNING((AE_INFO,
+                                     "Table %p, Validation count overflows\n",
+                                     table_desc));
+               }
        }
 
        *out_table = table_desc->pointer;
@@ -449,13 +454,20 @@ void acpi_tb_put_table(struct acpi_table_desc *table_desc)
 
        ACPI_FUNCTION_TRACE(acpi_tb_put_table);
 
-       if (table_desc->validation_count == 0) {
-               ACPI_WARNING((AE_INFO,
-                             "Table %p, Validation count is zero before decrement\n",
-                             table_desc));
-               return_VOID;
+       if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
+               table_desc->validation_count--;
+
+               /*
+                * Detect validation_count underflows to ensure that the warning
+                * message will only be printed once.
+                */
+               if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
+                       ACPI_WARNING((AE_INFO,
+                                     "Table %p, Validation count underflows\n",
+                                     table_desc));
+                       return_VOID;
+               }
        }
-       table_desc->validation_count--;
 
        if (table_desc->validation_count == 0) {
 
index e0587c85bafdf73a299c40d531eefa27deab4761..ff096d9755b925d9f72105f42993ebcc7c0522e1 100644 (file)
@@ -474,15 +474,6 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
                                return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
                        }
 
-                       /*
-                        * The end_tag opcode must be followed by a zero byte.
-                        * Although this byte is technically defined to be a checksum,
-                        * in practice, all ASL compilers set this byte to zero.
-                        */
-                       if (*(aml + 1) != 0) {
-                               return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
-                       }
-
                        /* Return the pointer to the end_tag if requested */
 
                        if (!user_function) {
index c5fecf97ee2f52bd11188a0cd2295bd82d5d02db..797b28dc7b3410cda1e775e55d2e1d2362254dd9 100644 (file)
@@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
        int ret = -ENODEV;
        struct fwnode_handle *iort_fwnode;
 
-       /*
-        * If we already translated the fwspec there
-        * is nothing left to do, return the iommu_ops.
-        */
-       ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
-       if (ops)
-               return ops;
-
        if (node) {
                iort_fwnode = iort_get_fwnode(node);
                if (!iort_fwnode)
@@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
        u32 streamid = 0;
        int err;
 
+       /*
+        * If we already translated the fwspec there
+        * is nothing left to do, return the iommu_ops.
+        */
+       ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+       if (ops)
+               return ops;
+
        if (dev_is_pci(dev)) {
                struct pci_bus *bus = to_pci_dev(dev)->bus;
                u32 rid;
@@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
        if (err)
                ops = ERR_PTR(err);
 
+       /* Ignore all other errors apart from EPROBE_DEFER */
+       if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+               dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+               ops = NULL;
+       }
+
        return ops;
 }
 
index a9a9ab3399d47ff8087e62d495f1d2ba930fc1d3..d42eeef9d9287815ce5f4c82d8d915ae5deabe51 100644 (file)
@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
        if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
            (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
             (battery->capacity_now <= battery->alarm)))
-               pm_wakeup_hard_event(&battery->device->dev);
+               pm_wakeup_event(&battery->device->dev, 0);
 
        return result;
 }
index b7c2a06963d6fb79cb5f5aaa2576936d17d5088f..e19f530f1083a13732328516925e3bbeb6493e14 100644 (file)
@@ -57,6 +57,7 @@
 
 #define ACPI_BUTTON_LID_INIT_IGNORE    0x00
 #define ACPI_BUTTON_LID_INIT_OPEN      0x01
+#define ACPI_BUTTON_LID_INIT_METHOD    0x02
 
 #define _COMPONENT             ACPI_BUTTON_COMPONENT
 ACPI_MODULE_NAME("button");
@@ -112,7 +113,7 @@ struct acpi_button {
 
 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
 static struct acpi_device *lid_device;
-static u8 lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
+static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
 
 static unsigned long lid_report_interval __read_mostly = 500;
 module_param(lid_report_interval, ulong, 0644);
@@ -216,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
        }
 
        if (state)
-               pm_wakeup_hard_event(&device->dev);
+               pm_wakeup_event(&device->dev, 0);
 
        ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
        if (ret == NOTIFY_DONE)
@@ -376,6 +377,9 @@ static void acpi_lid_initialize_state(struct acpi_device *device)
        case ACPI_BUTTON_LID_INIT_OPEN:
                (void)acpi_lid_notify_state(device, 1);
                break;
+       case ACPI_BUTTON_LID_INIT_METHOD:
+               (void)acpi_lid_update_state(device);
+               break;
        case ACPI_BUTTON_LID_INIT_IGNORE:
        default:
                break;
@@ -398,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
                } else {
                        int keycode;
 
-                       pm_wakeup_hard_event(&device->dev);
+                       pm_wakeup_event(&device->dev, 0);
                        if (button->suspended)
                                break;
 
@@ -530,7 +534,6 @@ static int acpi_button_add(struct acpi_device *device)
                lid_device = device;
        }
 
-       device_init_wakeup(&device->dev, true);
        printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
        return 0;
 
@@ -560,6 +563,9 @@ static int param_set_lid_init_state(const char *val, struct kernel_param *kp)
        if (!strncmp(val, "open", sizeof("open") - 1)) {
                lid_init_state = ACPI_BUTTON_LID_INIT_OPEN;
                pr_info("Notify initial lid state as open\n");
+       } else if (!strncmp(val, "method", sizeof("method") - 1)) {
+               lid_init_state = ACPI_BUTTON_LID_INIT_METHOD;
+               pr_info("Notify initial lid state with _LID return value\n");
        } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) {
                lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE;
                pr_info("Do not notify initial lid state\n");
@@ -573,6 +579,8 @@ static int param_get_lid_init_state(char *buffer, struct kernel_param *kp)
        switch (lid_init_state) {
        case ACPI_BUTTON_LID_INIT_OPEN:
                return sprintf(buffer, "open");
+       case ACPI_BUTTON_LID_INIT_METHOD:
+               return sprintf(buffer, "method");
        case ACPI_BUTTON_LID_INIT_IGNORE:
                return sprintf(buffer, "ignore");
        default:
index 798d5003a039d876f275fc2d933be71cb7ebfbed..993fd31394c854c99e5ce0c2af824f36c50b7a22 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/pm_qos.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
-#include <linux/suspend.h>
 
 #include "internal.h"
 
@@ -400,7 +399,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
        mutex_lock(&acpi_pm_notifier_lock);
 
        if (adev->wakeup.flags.notifier_present) {
-               pm_wakeup_ws_event(adev->wakeup.ws, 0, true);
+               __pm_wakeup_event(adev->wakeup.ws, 0);
                if (adev->wakeup.context.work.func)
                        queue_pm_work(&adev->wakeup.context.work);
        }
index 3ba1c3472cf9e293ae70fd7cdc649eeb96abf1a0..fd86bec98dea37f0fdc7afbfdcf94d79227e8a44 100644 (file)
@@ -26,7 +26,7 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,
        struct nfit_spa *nfit_spa;
 
        /* We only care about memory errors */
-       if (!(mce->status & MCACOD))
+       if (!mce_is_memory_error(mce))
                return NOTIFY_DONE;
 
        /*
index e39ec7b7cb674fbad3cab60f4e5139d7e06a1f09..d53162997f32002828a6db353bcd1926f2a8dc97 100644 (file)
@@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
        iort_set_dma_mask(dev);
 
        iommu = iort_iommu_configure(dev);
-       if (IS_ERR(iommu))
-               return PTR_ERR(iommu);
+       if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
 
        size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
        /*
@@ -1428,6 +1428,37 @@ static void acpi_init_coherency(struct acpi_device *adev)
        adev->flags.coherent_dma = cca;
 }
 
+static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
+{
+       bool *is_spi_i2c_slave_p = data;
+
+       if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
+               return 1;
+
+       /*
+        * devices that are connected to UART still need to be enumerated to
+        * platform bus
+        */
+       if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
+               *is_spi_i2c_slave_p = true;
+
+        /* no need to do more checking */
+       return -1;
+}
+
+static bool acpi_is_spi_i2c_slave(struct acpi_device *device)
+{
+       struct list_head resource_list;
+       bool is_spi_i2c_slave = false;
+
+       INIT_LIST_HEAD(&resource_list);
+       acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
+                              &is_spi_i2c_slave);
+       acpi_dev_free_resource_list(&resource_list);
+
+       return is_spi_i2c_slave;
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
                             int type, unsigned long long sta)
 {
@@ -1443,6 +1474,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
        acpi_bus_get_flags(device);
        device->flags.match_driver = false;
        device->flags.initialized = true;
+       device->flags.spi_i2c_slave = acpi_is_spi_i2c_slave(device);
        acpi_device_clear_enumerated(device);
        device_initialize(&device->dev);
        dev_set_uevent_suppress(&device->dev, true);
@@ -1727,38 +1759,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
        return AE_OK;
 }
 
-static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
-{
-       bool *is_spi_i2c_slave_p = data;
-
-       if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
-               return 1;
-
-       /*
-        * devices that are connected to UART still need to be enumerated to
-        * platform bus
-        */
-       if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
-               *is_spi_i2c_slave_p = true;
-
-        /* no need to do more checking */
-       return -1;
-}
-
 static void acpi_default_enumeration(struct acpi_device *device)
 {
-       struct list_head resource_list;
-       bool is_spi_i2c_slave = false;
-
        /*
         * Do not enumerate SPI/I2C slaves as they will be enumerated by their
         * respective parents.
         */
-       INIT_LIST_HEAD(&resource_list);
-       acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
-                              &is_spi_i2c_slave);
-       acpi_dev_free_resource_list(&resource_list);
-       if (!is_spi_i2c_slave) {
+       if (!device->flags.spi_i2c_slave) {
                acpi_create_platform_device(device, NULL);
                acpi_device_set_enumerated(device);
        } else {
@@ -1854,7 +1861,7 @@ static void acpi_bus_attach(struct acpi_device *device)
                return;
 
        device->flags.match_driver = true;
-       if (ret > 0) {
+       if (ret > 0 && !device->flags.spi_i2c_slave) {
                acpi_device_set_enumerated(device);
                goto ok;
        }
@@ -1863,10 +1870,10 @@ static void acpi_bus_attach(struct acpi_device *device)
        if (ret < 0)
                return;
 
-       if (device->pnp.type.platform_id)
-               acpi_default_enumeration(device);
-       else
+       if (!device->pnp.type.platform_id && !device->flags.spi_i2c_slave)
                acpi_device_set_enumerated(device);
+       else
+               acpi_default_enumeration(device);
 
  ok:
        list_for_each_entry(child, &device->children, node)
index a6574d62634031ac6e351418b935a333b556b665..097d630ab8867267326121f9f4db2525cf06ef4b 100644 (file)
@@ -663,40 +663,14 @@ static int acpi_freeze_prepare(void)
        acpi_os_wait_events_complete();
        if (acpi_sci_irq_valid())
                enable_irq_wake(acpi_sci_irq);
-
        return 0;
 }
 
-static void acpi_freeze_wake(void)
-{
-       /*
-        * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means
-        * that the SCI has triggered while suspended, so cancel the wakeup in
-        * case it has not been a wakeup event (the GPEs will be checked later).
-        */
-       if (acpi_sci_irq_valid() &&
-           !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
-               pm_system_cancel_wakeup();
-}
-
-static void acpi_freeze_sync(void)
-{
-       /*
-        * Process all pending events in case there are any wakeup ones.
-        *
-        * The EC driver uses the system workqueue, so that one needs to be
-        * flushed too.
-        */
-       acpi_os_wait_events_complete();
-       flush_scheduled_work();
-}
-
 static void acpi_freeze_restore(void)
 {
        acpi_disable_wakeup_devices(ACPI_STATE_S0);
        if (acpi_sci_irq_valid())
                disable_irq_wake(acpi_sci_irq);
-
        acpi_enable_all_runtime_gpes();
 }
 
@@ -708,8 +682,6 @@ static void acpi_freeze_end(void)
 static const struct platform_freeze_ops acpi_freeze_ops = {
        .begin = acpi_freeze_begin,
        .prepare = acpi_freeze_prepare,
-       .wake = acpi_freeze_wake,
-       .sync = acpi_freeze_sync,
        .restore = acpi_freeze_restore,
        .end = acpi_freeze_end,
 };
index 1b5ee1e0e5a3073457b0b15da34aadf292a544ba..e414fabf73158d77fba356be2c10354647e81a44 100644 (file)
@@ -333,14 +333,17 @@ static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
            container_of(bin_attr, struct acpi_table_attr, attr);
        struct acpi_table_header *table_header = NULL;
        acpi_status status;
+       ssize_t rc;
 
        status = acpi_get_table(table_attr->name, table_attr->instance,
                                &table_header);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       return memory_read_from_buffer(buf, count, &offset,
-                                      table_header, table_header->length);
+       rc = memory_read_from_buffer(buf, count, &offset, table_header,
+                       table_header->length);
+       acpi_put_table(table_header);
+       return rc;
 }
 
 static int acpi_table_attr_init(struct kobject *tables_obj,
index 2fc52407306c15c27b9fb0b11c2db4ef4641aeba..c69954023c2e7d8c235aace4b66a1d32298f36eb 100644 (file)
@@ -1364,6 +1364,40 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 {}
 #endif
 
+/*
+ * On the Acer Aspire Switch Alpha 12, sometimes all SATA ports are detected
+ * as DUMMY, or detected but eventually get a "link down" and never get up
+ * again. When this happens, CAP.NP may hold a value of 0x00 or 0x01, and the
+ * port_map may hold a value of 0x00.
+ *
+ * Overriding CAP.NP to 0x02 and the port_map to 0x7 will reveal all 3 ports
+ * and can significantly reduce the occurrence of the problem.
+ *
+ * https://bugzilla.kernel.org/show_bug.cgi?id=189471
+ */
+static void acer_sa5_271_workaround(struct ahci_host_priv *hpriv,
+                                   struct pci_dev *pdev)
+{
+       static const struct dmi_system_id sysids[] = {
+               {
+                       .ident = "Acer Switch Alpha 12",
+                       .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                               DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271")
+                       },
+               },
+               { }
+       };
+
+       if (dmi_check_system(sysids)) {
+               dev_info(&pdev->dev, "enabling Acer Switch Alpha 12 workaround\n");
+               if ((hpriv->saved_cap & 0xC734FF00) == 0xC734FF00) {
+                       hpriv->port_map = 0x7;
+                       hpriv->cap = 0xC734FF02;
+               }
+       }
+}
+
 #ifdef CONFIG_ARM64
 /*
  * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
@@ -1636,6 +1670,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                         "online status unreliable, applying workaround\n");
        }
 
+
+       /* Acer SA5-271 workaround modifies private_data */
+       acer_sa5_271_workaround(hpriv, pdev);
+
        /* CAP.NP sometimes indicate the index of the last enabled
         * port, at other times, that of the last possible port, so
         * determining the maximum port number requires looking at
index aaa761b9081cc02a75792302c741f7b54ebd9823..cd2eab6aa92ea245e1a3dab839be7fe8aa938cdb 100644 (file)
@@ -514,8 +514,9 @@ int ahci_platform_init_host(struct platform_device *pdev,
 
        irq = platform_get_irq(pdev, 0);
        if (irq <= 0) {
-               dev_err(dev, "no irq\n");
-               return -EINVAL;
+               if (irq != -EPROBE_DEFER)
+                       dev_err(dev, "no irq\n");
+               return irq;
        }
 
        hpriv->irq = irq;
index 2d83b8c7596567a020300d8dd1aeefeb33a6a055..e157a0e4441916b77b53c402741b74e124012cc9 100644 (file)
@@ -6800,7 +6800,7 @@ static int __init ata_parse_force_one(char **cur,
        }
 
        force_ent->port = simple_strtoul(id, &endp, 10);
-       if (p == endp || *endp != '\0') {
+       if (id == endp || *endp != '\0') {
                *reason = "invalid port/link";
                return -EINVAL;
        }
index b66bcda88320fefa399ac9653eca64d3045a6a96..3b2246dded74fbeed89d53f913c725ab6e5c0082 100644 (file)
@@ -4067,7 +4067,6 @@ static int mv_platform_probe(struct platform_device *pdev)
        struct ata_host *host;
        struct mv_host_priv *hpriv;
        struct resource *res;
-       void __iomem *mmio;
        int n_ports = 0, irq = 0;
        int rc;
        int port;
@@ -4086,9 +4085,8 @@ static int mv_platform_probe(struct platform_device *pdev)
         * Get the register base first
         */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mmio = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(mmio))
-               return PTR_ERR(mmio);
+       if (res == NULL)
+               return -EINVAL;
 
        /* allocate host */
        if (pdev->dev.of_node) {
@@ -4132,7 +4130,12 @@ static int mv_platform_probe(struct platform_device *pdev)
        hpriv->board_idx = chip_soc;
 
        host->iomap = NULL;
-       hpriv->base = mmio - SATAHC0_REG_BASE;
+       hpriv->base = devm_ioremap(&pdev->dev, res->start,
+                                  resource_size(res));
+       if (!hpriv->base)
+               return -ENOMEM;
+
+       hpriv->base -= SATAHC0_REG_BASE;
 
        hpriv->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(hpriv->clk))
index 5d38245a7a73a7cc4fa0d49255a52c7daead7886..b7939a2c1fab53ff2a94799a261d401c1c440f2e 100644 (file)
@@ -890,7 +890,10 @@ static int sata_rcar_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "failed to get access to sata clock\n");
                return PTR_ERR(priv->clk);
        }
-       clk_prepare_enable(priv->clk);
+
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        host = ata_host_alloc(&pdev->dev, 1);
        if (!host) {
@@ -970,8 +973,11 @@ static int sata_rcar_resume(struct device *dev)
        struct ata_host *host = dev_get_drvdata(dev);
        struct sata_rcar_priv *priv = host->private_data;
        void __iomem *base = priv->base;
+       int ret;
 
-       clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        /* ack and mask */
        iowrite32(0, base + SATAINTSTAT_REG);
@@ -988,8 +994,11 @@ static int sata_rcar_restore(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
        struct sata_rcar_priv *priv = host->private_data;
+       int ret;
 
-       clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        sata_rcar_setup_port(host);
 
index e987a6f55d36747f79b470b0372a1abcff6390d7..9faee1c893e53c8dea6e14d472a73a8b7131bf96 100644 (file)
@@ -1091,6 +1091,11 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
        if (async_error)
                goto Complete;
 
+       if (pm_wakeup_pending()) {
+               async_error = -EBUSY;
+               goto Complete;
+       }
+
        if (dev->power.syscore || dev->power.direct_complete)
                goto Complete;
 
index f62082fdd6703e11c7576dc5db673dbc7dbba056..c313b600d356260fd9b98fe4848340f9cbdcf9ae 100644 (file)
@@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly;
 /* First wakeup IRQ seen by the kernel in the last cycle. */
 unsigned int pm_wakeup_irq __read_mostly;
 
-/* If greater than 0 and the system is suspending, terminate the suspend. */
-static atomic_t pm_abort_suspend __read_mostly;
+/* If set and the system is suspending, terminate the suspend. */
+static bool pm_abort_suspend __read_mostly;
 
 /*
  * Combined counters of registered wakeup events and wakeup events in progress.
@@ -512,13 +512,12 @@ static bool wakeup_source_not_registered(struct wakeup_source *ws)
 /**
  * wakup_source_activate - Mark given wakeup source as active.
  * @ws: Wakeup source to handle.
- * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
  *
  * Update the @ws' statistics and, if @ws has just been activated, notify the PM
  * core of the event by incrementing the counter of of wakeup events being
  * processed.
  */
-static void wakeup_source_activate(struct wakeup_source *ws, bool hard)
+static void wakeup_source_activate(struct wakeup_source *ws)
 {
        unsigned int cec;
 
@@ -526,9 +525,6 @@ static void wakeup_source_activate(struct wakeup_source *ws, bool hard)
                        "unregistered wakeup source\n"))
                return;
 
-       if (hard)
-               pm_system_wakeup();
-
        ws->active = true;
        ws->active_count++;
        ws->last_time = ktime_get();
@@ -554,7 +550,10 @@ static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
                ws->wakeup_count++;
 
        if (!ws->active)
-               wakeup_source_activate(ws, hard);
+               wakeup_source_activate(ws);
+
+       if (hard)
+               pm_system_wakeup();
 }
 
 /**
@@ -856,26 +855,20 @@ bool pm_wakeup_pending(void)
                pm_print_active_wakeup_sources();
        }
 
-       return ret || atomic_read(&pm_abort_suspend) > 0;
+       return ret || pm_abort_suspend;
 }
 
 void pm_system_wakeup(void)
 {
-       atomic_inc(&pm_abort_suspend);
+       pm_abort_suspend = true;
        freeze_wake();
 }
 EXPORT_SYMBOL_GPL(pm_system_wakeup);
 
-void pm_system_cancel_wakeup(void)
-{
-       atomic_dec(&pm_abort_suspend);
-}
-
-void pm_wakeup_clear(bool reset)
+void pm_wakeup_clear(void)
 {
+       pm_abort_suspend = false;
        pm_wakeup_irq = 0;
-       if (reset)
-               atomic_set(&pm_abort_suspend, 0);
 }
 
 void pm_system_irq_wakeup(unsigned int irq_number)
index b5730e17b45584ad4109df8c1c6eac5a35e81a4f..656624314f0d68dc7385b3896d0de9ae1a1cc457 100644 (file)
@@ -315,24 +315,32 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 }
 
 /* still holds resource->req_lock */
-static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
+static void drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
 {
        struct drbd_device *device = req->device;
        D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED));
 
+       if (!put)
+               return;
+
        if (!atomic_sub_and_test(put, &req->completion_ref))
-               return 0;
+               return;
 
        drbd_req_complete(req, m);
 
+       /* local completion may still come in later,
+        * we need to keep the req object around. */
+       if (req->rq_state & RQ_LOCAL_ABORTED)
+               return;
+
        if (req->rq_state & RQ_POSTPONED) {
                /* don't destroy the req object just yet,
                 * but queue it for retry */
                drbd_restart_request(req);
-               return 0;
+               return;
        }
 
-       return 1;
+       kref_put(&req->kref, drbd_req_destroy);
 }
 
 static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
@@ -519,12 +527,8 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
        if (req->i.waiting)
                wake_up(&device->misc_wait);
 
-       if (c_put) {
-               if (drbd_req_put_completion_ref(req, m, c_put))
-                       kref_put(&req->kref, drbd_req_destroy);
-       } else {
-               kref_put(&req->kref, drbd_req_destroy);
-       }
+       drbd_req_put_completion_ref(req, m, c_put);
+       kref_put(&req->kref, drbd_req_destroy);
 }
 
 static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req)
@@ -1366,8 +1370,7 @@ nodata:
        }
 
 out:
-       if (drbd_req_put_completion_ref(req, &m, 1))
-               kref_put(&req->kref, drbd_req_destroy);
+       drbd_req_put_completion_ref(req, &m, 1);
        spin_unlock_irq(&resource->req_lock);
 
        /* Even though above is a kref_put(), this is safe.
index 28d932906f24c19e7250e6c69ec903b4a4460761..ebbd0c3fe0ed997973271ba9b57020d2519843d0 100644 (file)
@@ -608,6 +608,9 @@ static int loop_switch(struct loop_device *lo, struct file *file)
  */
 static int loop_flush(struct loop_device *lo)
 {
+       /* loop not yet configured, no running thread, nothing to flush */
+       if (lo->lo_state != Lo_bound)
+               return 0;
        return loop_switch(lo, NULL);
 }
 
index 9a7bb2c2944772cad8124a965bacc17d0aa8f935..f3f191ba8ca4bbe6b7d87a7accc84bd648e4d718 100644 (file)
@@ -937,14 +937,6 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
        return -ENOSPC;
 }
 
-/* Reset all properties of an NBD device */
-static void nbd_reset(struct nbd_device *nbd)
-{
-       nbd->config = NULL;
-       nbd->tag_set.timeout = 0;
-       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
-}
-
 static void nbd_bdev_reset(struct block_device *bdev)
 {
        if (bdev->bd_openers > 1)
@@ -1029,7 +1021,11 @@ static void nbd_config_put(struct nbd_device *nbd)
                        }
                        kfree(config->socks);
                }
-               nbd_reset(nbd);
+               kfree(nbd->config);
+               nbd->config = NULL;
+
+               nbd->tag_set.timeout = 0;
+               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
 
                mutex_unlock(&nbd->config_lock);
                nbd_put(nbd);
@@ -1483,7 +1479,6 @@ static int nbd_dev_add(int index)
        disk->fops = &nbd_fops;
        disk->private_data = nbd;
        sprintf(disk->disk_name, "nbd%d", index);
-       nbd_reset(nbd);
        add_disk(disk);
        nbd_total_devices++;
        return index;
index 454bf9c34882f33d673ccbaf0c8afa4f3ee18ad4..c16f74547804ccb957275f6d59b705b0ba35eb6b 100644 (file)
@@ -4023,6 +4023,7 @@ static void rbd_queue_workfn(struct work_struct *work)
 
        switch (req_op(rq)) {
        case REQ_OP_DISCARD:
+       case REQ_OP_WRITE_ZEROES:
                op_type = OBJ_OP_DISCARD;
                break;
        case REQ_OP_WRITE:
@@ -4420,6 +4421,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        q->limits.discard_granularity = segment_size;
        q->limits.discard_alignment = segment_size;
        blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE);
+       blk_queue_max_write_zeroes_sectors(q, segment_size / SECTOR_SIZE);
 
        if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
                q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
index 726c32e35db9c542e6f050ff0a04e31e10fc2b7d..0e824091a12fac8757c2ade5d4e5dae6a1470cbd 100644 (file)
@@ -609,8 +609,6 @@ int xen_blkif_schedule(void *arg)
        unsigned long timeout;
        int ret;
 
-       xen_blkif_get(blkif);
-
        set_freezable();
        while (!kthread_should_stop()) {
                if (try_to_freeze())
@@ -665,7 +663,6 @@ purge_gnt_list:
                print_stats(ring);
 
        ring->xenblkd = NULL;
-       xen_blkif_put(blkif);
 
        return 0;
 }
@@ -1436,34 +1433,35 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
 static void make_response(struct xen_blkif_ring *ring, u64 id,
                          unsigned short op, int st)
 {
-       struct blkif_response  resp;
+       struct blkif_response *resp;
        unsigned long     flags;
        union blkif_back_rings *blk_rings;
        int notify;
 
-       resp.id        = id;
-       resp.operation = op;
-       resp.status    = st;
-
        spin_lock_irqsave(&ring->blk_ring_lock, flags);
        blk_rings = &ring->blk_rings;
        /* Place on the response ring for the relevant domain. */
        switch (ring->blkif->blk_protocol) {
        case BLKIF_PROTOCOL_NATIVE:
-               memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt),
-                      &resp, sizeof(resp));
+               resp = RING_GET_RESPONSE(&blk_rings->native,
+                                        blk_rings->native.rsp_prod_pvt);
                break;
        case BLKIF_PROTOCOL_X86_32:
-               memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt),
-                      &resp, sizeof(resp));
+               resp = RING_GET_RESPONSE(&blk_rings->x86_32,
+                                        blk_rings->x86_32.rsp_prod_pvt);
                break;
        case BLKIF_PROTOCOL_X86_64:
-               memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt),
-                      &resp, sizeof(resp));
+               resp = RING_GET_RESPONSE(&blk_rings->x86_64,
+                                        blk_rings->x86_64.rsp_prod_pvt);
                break;
        default:
                BUG();
        }
+
+       resp->id        = id;
+       resp->operation = op;
+       resp->status    = st;
+
        blk_rings->common.rsp_prod_pvt++;
        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify);
        spin_unlock_irqrestore(&ring->blk_ring_lock, flags);
index dea61f6ab8cbdbaffedceb4c64bda239b51a63a4..ecb35fe8ca8dbb54f36a85513a09064819acd67a 100644 (file)
@@ -75,9 +75,8 @@ extern unsigned int xenblk_max_queues;
 struct blkif_common_request {
        char dummy;
 };
-struct blkif_common_response {
-       char dummy;
-};
+
+/* i386 protocol version */
 
 struct blkif_x86_32_request_rw {
        uint8_t        nr_segments;  /* number of segments                   */
@@ -129,14 +128,6 @@ struct blkif_x86_32_request {
        } u;
 } __attribute__((__packed__));
 
-/* i386 protocol version */
-#pragma pack(push, 4)
-struct blkif_x86_32_response {
-       uint64_t        id;              /* copied from request */
-       uint8_t         operation;       /* copied from request */
-       int16_t         status;          /* BLKIF_RSP_???       */
-};
-#pragma pack(pop)
 /* x86_64 protocol version */
 
 struct blkif_x86_64_request_rw {
@@ -193,18 +184,12 @@ struct blkif_x86_64_request {
        } u;
 } __attribute__((__packed__));
 
-struct blkif_x86_64_response {
-       uint64_t       __attribute__((__aligned__(8))) id;
-       uint8_t         operation;       /* copied from request */
-       int16_t         status;          /* BLKIF_RSP_???       */
-};
-
 DEFINE_RING_TYPES(blkif_common, struct blkif_common_request,
-                 struct blkif_common_response);
+                 struct blkif_response);
 DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request,
-                 struct blkif_x86_32_response);
+                 struct blkif_response __packed);
 DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request,
-                 struct blkif_x86_64_response);
+                 struct blkif_response);
 
 union blkif_back_rings {
        struct blkif_back_ring        native;
@@ -281,6 +266,7 @@ struct xen_blkif_ring {
 
        wait_queue_head_t       wq;
        atomic_t                inflight;
+       bool                    active;
        /* One thread per blkif ring. */
        struct task_struct      *xenblkd;
        unsigned int            waiting_reqs;
index 8fe61b5dc5a6553d141950506344fe90bbfde2c8..792da683e70dafafa6f69e224b8e57272d3e6be1 100644 (file)
@@ -159,7 +159,7 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
                init_waitqueue_head(&ring->shutdown_wq);
                ring->blkif = blkif;
                ring->st_print = jiffies;
-               xen_blkif_get(blkif);
+               ring->active = true;
        }
 
        return 0;
@@ -249,10 +249,12 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
                struct xen_blkif_ring *ring = &blkif->rings[r];
                unsigned int i = 0;
 
+               if (!ring->active)
+                       continue;
+
                if (ring->xenblkd) {
                        kthread_stop(ring->xenblkd);
                        wake_up(&ring->shutdown_wq);
-                       ring->xenblkd = NULL;
                }
 
                /* The above kthread_stop() guarantees that at this point we
@@ -296,7 +298,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
                BUG_ON(ring->free_pages_num != 0);
                BUG_ON(ring->persistent_gnt_c != 0);
                WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
-               xen_blkif_put(blkif);
+               ring->active = false;
        }
        blkif->nr_ring_pages = 0;
        /*
@@ -312,9 +314,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
 
 static void xen_blkif_free(struct xen_blkif *blkif)
 {
-
-       xen_blkif_disconnect(blkif);
+       WARN_ON(xen_blkif_disconnect(blkif));
        xen_vbd_free(&blkif->vbd);
+       kfree(blkif->be->mode);
+       kfree(blkif->be);
 
        /* Make sure everything is drained before shutting down */
        kmem_cache_free(xen_blkif_cachep, blkif);
@@ -504,13 +507,13 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
 
        dev_set_drvdata(&dev->dev, NULL);
 
-       if (be->blkif)
+       if (be->blkif) {
                xen_blkif_disconnect(be->blkif);
 
-       /* Put the reference we set in xen_blkif_alloc(). */
-       xen_blkif_put(be->blkif);
-       kfree(be->mode);
-       kfree(be);
+               /* Put the reference we set in xen_blkif_alloc(). */
+               xen_blkif_put(be->blkif);
+       }
+
        return 0;
 }
 
index 565e4cf04a0215934e9b0f4df6f4398fbd0b2344..8249762192d55ed86a9794895a6faab01afe649e 100644 (file)
@@ -859,7 +859,11 @@ static int __init lp_setup (char *str)
        } else if (!strcmp(str, "auto")) {
                parport_nr[0] = LP_PARPORT_AUTO;
        } else if (!strcmp(str, "none")) {
-               parport_nr[parport_ptr++] = LP_PARPORT_NONE;
+               if (parport_ptr < LP_NO)
+                       parport_nr[parport_ptr++] = LP_PARPORT_NONE;
+               else
+                       printk(KERN_INFO "lp: too many ports, %s ignored.\n",
+                              str);
        } else if (!strcmp(str, "reset")) {
                reset = 1;
        }
index 7e4a9d1296bb7fb666f6b37ced2757a8585b7d75..593a8818aca99e345e03d0fb56eabd25b5ffd05a 100644 (file)
@@ -340,6 +340,11 @@ static const struct vm_operations_struct mmap_mem_ops = {
 static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 {
        size_t size = vma->vm_end - vma->vm_start;
+       phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
+
+       /* It's illegal to wrap around the end of the physical address space. */
+       if (offset + (phys_addr_t)size - 1 < offset)
+               return -EINVAL;
 
        if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
                return -EINVAL;
index d4dbd8d8e524d7b712f9668cbee57c7d722440b2..382c864814d944c79e610eaa434bc356d12bd335 100644 (file)
@@ -374,7 +374,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
 
        rc = write_sync_reg(SCR_HOST_TO_READER_START, dev);
        if (rc <= 0) {
-               DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
+               DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
                DEBUGP(2, dev, "<- cm4040_write (failed)\n");
                if (rc == -ERESTARTSYS)
                        return rc;
@@ -387,7 +387,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
        for (i = 0; i < bytes_to_write; i++) {
                rc = wait_for_bulk_out_ready(dev);
                if (rc <= 0) {
-                       DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2Zx\n",
+                       DEBUGP(5, dev, "wait_for_bulk_out_ready rc=%.2zx\n",
                               rc);
                        DEBUGP(2, dev, "<- cm4040_write (failed)\n");
                        if (rc == -ERESTARTSYS)
@@ -403,7 +403,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
        rc = write_sync_reg(SCR_HOST_TO_READER_DONE, dev);
 
        if (rc <= 0) {
-               DEBUGP(5, dev, "write_sync_reg c=%.2Zx\n", rc);
+               DEBUGP(5, dev, "write_sync_reg c=%.2zx\n", rc);
                DEBUGP(2, dev, "<- cm4040_write (failed)\n");
                if (rc == -ERESTARTSYS)
                        return rc;
index 0ab0249189072befe3cee1b8696052727f360540..01a260f67437488b425372c12d33142fce699f84 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * random.c -- A strong random number generator
  *
+ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
+ * Rights Reserved.
+ *
  * Copyright Matt Mackall <mpm@selenic.com>, 2003, 2004, 2005
  *
  * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.  All
@@ -762,6 +765,8 @@ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
 static struct crng_state **crng_node_pool __read_mostly;
 #endif
 
+static void invalidate_batched_entropy(void);
+
 static void crng_initialize(struct crng_state *crng)
 {
        int             i;
@@ -798,12 +803,13 @@ static int crng_fast_load(const char *cp, size_t len)
                p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp;
                cp++; crng_init_cnt++; len--;
        }
+       spin_unlock_irqrestore(&primary_crng.lock, flags);
        if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
+               invalidate_batched_entropy();
                crng_init = 1;
                wake_up_interruptible(&crng_init_wait);
                pr_notice("random: fast init done\n");
        }
-       spin_unlock_irqrestore(&primary_crng.lock, flags);
        return 1;
 }
 
@@ -835,13 +841,14 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
        }
        memzero_explicit(&buf, sizeof(buf));
        crng->init_time = jiffies;
+       spin_unlock_irqrestore(&primary_crng.lock, flags);
        if (crng == &primary_crng && crng_init < 2) {
+               invalidate_batched_entropy();
                crng_init = 2;
                process_random_ready_list();
                wake_up_interruptible(&crng_init_wait);
                pr_notice("random: crng init done\n");
        }
-       spin_unlock_irqrestore(&primary_crng.lock, flags);
 }
 
 static inline void crng_wait_ready(void)
@@ -1097,12 +1104,16 @@ static void add_interrupt_bench(cycles_t start)
 static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
 {
        __u32 *ptr = (__u32 *) regs;
+       unsigned int idx;
 
        if (regs == NULL)
                return 0;
-       if (f->reg_idx >= sizeof(struct pt_regs) / sizeof(__u32))
-               f->reg_idx = 0;
-       return *(ptr + f->reg_idx++);
+       idx = READ_ONCE(f->reg_idx);
+       if (idx >= sizeof(struct pt_regs) / sizeof(__u32))
+               idx = 0;
+       ptr += idx++;
+       WRITE_ONCE(f->reg_idx, idx);
+       return *ptr;
 }
 
 void add_interrupt_randomness(int irq, int irq_flags)
@@ -2019,6 +2030,7 @@ struct batched_entropy {
        };
        unsigned int position;
 };
+static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_reset_lock);
 
 /*
  * Get a random word for internal kernel use only. The quality of the random
@@ -2029,6 +2041,8 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
 u64 get_random_u64(void)
 {
        u64 ret;
+       bool use_lock = READ_ONCE(crng_init) < 2;
+       unsigned long flags = 0;
        struct batched_entropy *batch;
 
 #if BITS_PER_LONG == 64
@@ -2041,11 +2055,15 @@ u64 get_random_u64(void)
 #endif
 
        batch = &get_cpu_var(batched_entropy_u64);
+       if (use_lock)
+               read_lock_irqsave(&batched_entropy_reset_lock, flags);
        if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
                extract_crng((u8 *)batch->entropy_u64);
                batch->position = 0;
        }
        ret = batch->entropy_u64[batch->position++];
+       if (use_lock)
+               read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
        put_cpu_var(batched_entropy_u64);
        return ret;
 }
@@ -2055,22 +2073,45 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
 u32 get_random_u32(void)
 {
        u32 ret;
+       bool use_lock = READ_ONCE(crng_init) < 2;
+       unsigned long flags = 0;
        struct batched_entropy *batch;
 
        if (arch_get_random_int(&ret))
                return ret;
 
        batch = &get_cpu_var(batched_entropy_u32);
+       if (use_lock)
+               read_lock_irqsave(&batched_entropy_reset_lock, flags);
        if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
                extract_crng((u8 *)batch->entropy_u32);
                batch->position = 0;
        }
        ret = batch->entropy_u32[batch->position++];
+       if (use_lock)
+               read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
        put_cpu_var(batched_entropy_u32);
        return ret;
 }
 EXPORT_SYMBOL(get_random_u32);
 
+/* It's important to invalidate all potential batched entropy that might
+ * be stored before the crng is initialized, which we can do lazily by
+ * simply resetting the counter to zero so that it's re-extracted on the
+ * next usage. */
+static void invalidate_batched_entropy(void)
+{
+       int cpu;
+       unsigned long flags;
+
+       write_lock_irqsave(&batched_entropy_reset_lock, flags);
+       for_each_possible_cpu (cpu) {
+               per_cpu_ptr(&batched_entropy_u32, cpu)->position = 0;
+               per_cpu_ptr(&batched_entropy_u64, cpu)->position = 0;
+       }
+       write_unlock_irqrestore(&batched_entropy_reset_lock, flags);
+}
+
 /**
  * randomize_page - Generate a random, page aligned address
  * @start:     The smallest acceptable address the caller will take.
index 19480bcc704630bc2e7e084fb4cb586f0ac3c254..2f29ee1a4d005422a087de38efc3b5274b8f7a04 100644 (file)
@@ -14,6 +14,7 @@ config COMMON_CLK_MESON8B
 config COMMON_CLK_GXBB
        bool
        depends on COMMON_CLK_AMLOGIC
+       select RESET_CONTROLLER
        help
          Support for the clock controller on AmLogic S905 devices, aka gxbb.
          Say Y if you want peripherals and CPU frequency scaling to work.
index b0d551a8efe4d6d31114bc4f2cb3347173606cd9..eb89c7801f001b4a0ea0fde521fe695a298036b9 100644 (file)
@@ -156,6 +156,7 @@ config SUN8I_R_CCU
        bool "Support for Allwinner SoCs' PRCM CCUs"
        select SUNXI_CCU_DIV
        select SUNXI_CCU_GATE
+       select SUNXI_CCU_MP
        default MACH_SUN8I || (ARCH_SUNXI && ARM64)
 
 endif
index 9b3cd24b78d2326a06672555555f9752ebcf6b78..061b6fbb4f9591c0b77a54e8aa6a4ac0bb993e66 100644 (file)
@@ -31,7 +31,9 @@
 #define CLK_PLL_VIDEO0_2X              8
 #define CLK_PLL_VE                     9
 #define CLK_PLL_DDR0                   10
-#define CLK_PLL_PERIPH0                        11
+
+/* PLL_PERIPH0 exported for PRCM */
+
 #define CLK_PLL_PERIPH0_2X             12
 #define CLK_PLL_PERIPH1                        13
 #define CLK_PLL_PERIPH1_2X             14
index 5c476f966a7220c468799f5011b9994eb23c3ad4..5372bf8be5e6fb8b0a43185279d33cc1cc30bd3b 100644 (file)
@@ -243,7 +243,7 @@ static SUNXI_CCU_GATE(ahb_ss_clk,   "ahb-ss",       "ahb",
 static SUNXI_CCU_GATE(ahb_dma_clk,     "ahb-dma",      "ahb",
                      0x060, BIT(6), 0);
 static SUNXI_CCU_GATE(ahb_bist_clk,    "ahb-bist",     "ahb",
-                     0x060, BIT(6), 0);
+                     0x060, BIT(7), 0);
 static SUNXI_CCU_GATE(ahb_mmc0_clk,    "ahb-mmc0",     "ahb",
                      0x060, BIT(8), 0);
 static SUNXI_CCU_GATE(ahb_mmc1_clk,    "ahb-mmc1",     "ahb",
index 89e68d29bf456ab3d682f7d2ba7d35ad4a21bb58..df97e25aec76b505ddb88ab7d4b3dc76475fb035 100644 (file)
@@ -556,7 +556,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(lcd0_ch1_clk, "lcd0-ch1", lcd_ch1_parents,
                                 0x12c, 0, 4, 24, 3, BIT(31),
                                 CLK_SET_RATE_PARENT);
 static SUNXI_CCU_M_WITH_MUX_GATE(lcd1_ch1_clk, "lcd1-ch1", lcd_ch1_parents,
-                                0x12c, 0, 4, 24, 3, BIT(31),
+                                0x130, 0, 4, 24, 3, BIT(31),
                                 CLK_SET_RATE_PARENT);
 
 static const char * const csi_sclk_parents[] = { "pll-video0", "pll-video1",
index 85973d1e8165f9a085d9e574cc1f822430802c68..1b4baea37d810351d541d0b0a91d8a78a8524a95 100644 (file)
@@ -29,7 +29,9 @@
 #define CLK_PLL_VIDEO          6
 #define CLK_PLL_VE             7
 #define CLK_PLL_DDR            8
-#define CLK_PLL_PERIPH0                9
+
+/* PLL_PERIPH0 exported for PRCM */
+
 #define CLK_PLL_PERIPH0_2X     10
 #define CLK_PLL_GPU            11
 #define CLK_PLL_PERIPH1                12
index e58706b40ae98281d281b117f447e07c15546444..6297add857b53112a851f9bc0f1205db5996fe1b 100644 (file)
@@ -537,7 +537,7 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
        [RST_BUS_EMAC]          =  { 0x2c0, BIT(17) },
        [RST_BUS_HSTIMER]       =  { 0x2c0, BIT(19) },
        [RST_BUS_SPI0]          =  { 0x2c0, BIT(20) },
-       [RST_BUS_OTG]           =  { 0x2c0, BIT(23) },
+       [RST_BUS_OTG]           =  { 0x2c0, BIT(24) },
        [RST_BUS_EHCI0]         =  { 0x2c0, BIT(26) },
        [RST_BUS_OHCI0]         =  { 0x2c0, BIT(29) },
 
index 4bed671e490e0b15d79fd432f3d85dacfd094a96..8b5c30062d995968cc83e6c0511bcccab721873c 100644 (file)
@@ -1209,9 +1209,9 @@ arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
                return 0;
        }
 
-       rate = readl_relaxed(frame + CNTFRQ);
+       rate = readl_relaxed(base + CNTFRQ);
 
-       iounmap(frame);
+       iounmap(base);
 
        return rate;
 }
index 44e5e951583bc38fc8c4a6a9b89ea91f7587af34..8e64b8460f113f56e829f69a414e229fea3c722a 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
+#include <linux/clocksource.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
index 2e9c830ae1cd52d61e38dbb3620b2eb53dd4eb7e..c4656c4d44a6715a25b0b9ddaf432451f31ad32c 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/clk.h>
 #include <linux/clockchips.h>
+#include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
index 74ed7e9a7f27cd333a6bdf48144c0de4e6e7469e..2011fec2d6ad9d5b4ad1b089c38a1be23baeb509 100644 (file)
@@ -71,6 +71,15 @@ config ARM_HIGHBANK_CPUFREQ
 
          If in doubt, say N.
 
+config ARM_DB8500_CPUFREQ
+       tristate "ST-Ericsson DB8500 cpufreq" if COMPILE_TEST && !ARCH_U8500
+       default ARCH_U8500
+       depends on HAS_IOMEM
+       depends on !CPU_THERMAL || THERMAL
+       help
+         This adds the CPUFreq driver for ST-Ericsson Ux500 (DB8500) SoC
+         series.
+
 config ARM_IMX6Q_CPUFREQ
        tristate "Freescale i.MX6 cpufreq support"
        depends on ARCH_MXC
index b7e78f063c4f1d373bc892f84f68d6b8000a3051..ab3a42cd29ef210bcf0cad2ee48c74cb954b14f2 100644 (file)
@@ -53,7 +53,7 @@ obj-$(CONFIG_ARM_DT_BL_CPUFREQ)               += arm_big_little_dt.o
 
 obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ)  += brcmstb-avs-cpufreq.o
 obj-$(CONFIG_ARCH_DAVINCI)             += davinci-cpufreq.o
-obj-$(CONFIG_UX500_SOC_DB8500)         += dbx500-cpufreq.o
+obj-$(CONFIG_ARM_DB8500_CPUFREQ)       += dbx500-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ)   += exynos5440-cpufreq.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)     += highbank-cpufreq.o
 obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)                += imx6q-cpufreq.o
index 0e3f6496524d92c7c1717d8d2259684952d7acb8..26b643d57847de0fca4afc099f4bec49d6326be9 100644 (file)
@@ -2468,6 +2468,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
        if (!(cpufreq_driver->flags & CPUFREQ_STICKY) &&
            list_empty(&cpufreq_policy_list)) {
                /* if all ->init() calls failed, unregister */
+               ret = -ENODEV;
                pr_debug("%s: No CPU initialized for driver %s\n", __func__,
                         driver_data->name);
                goto err_if_unreg;
index 992f7c20760f3c69a07b9f4558d8774fc39520ed..88220ff3e1c226277e7ef8895317a5a1314ddee6 100644 (file)
@@ -185,8 +185,8 @@ static ssize_t store_down_threshold(struct gov_attr_set *attr_set,
        int ret;
        ret = sscanf(buf, "%u", &input);
 
-       /* cannot be lower than 11 otherwise freq will not fall */
-       if (ret != 1 || input < 11 || input > 100 ||
+       /* cannot be lower than 1 otherwise freq will not fall */
+       if (ret != 1 || input < 1 || input > 100 ||
                        input >= dbs_data->up_threshold)
                return -EINVAL;
 
index b7de5bd76a31743f52cc9095845495e596d0817d..eb1158532de31e7aee418162135a7495b10f9860 100644 (file)
@@ -571,9 +571,10 @@ static inline void update_turbo_state(void)
 static int min_perf_pct_min(void)
 {
        struct cpudata *cpu = all_cpu_data[0];
+       int turbo_pstate = cpu->pstate.turbo_pstate;
 
-       return DIV_ROUND_UP(cpu->pstate.min_pstate * 100,
-                           cpu->pstate.turbo_pstate);
+       return turbo_pstate ?
+               DIV_ROUND_UP(cpu->pstate.min_pstate * 100, turbo_pstate) : 0;
 }
 
 static s16 intel_pstate_get_epb(struct cpudata *cpu_data)
index 1b9bcd76c60e334e72a31a3b6ff1a21410ac23ff..c2dd43f3f5d8a3092e6847f18d124f0631bdf065 100644 (file)
@@ -127,7 +127,12 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
                return PTR_ERR(priv.cpu_clk);
        }
 
-       clk_prepare_enable(priv.cpu_clk);
+       err = clk_prepare_enable(priv.cpu_clk);
+       if (err) {
+               dev_err(priv.dev, "Unable to prepare cpuclk\n");
+               return err;
+       }
+
        kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000;
 
        priv.ddr_clk = of_clk_get_by_name(np, "ddrclk");
@@ -137,7 +142,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
                goto out_cpu;
        }
 
-       clk_prepare_enable(priv.ddr_clk);
+       err = clk_prepare_enable(priv.ddr_clk);
+       if (err) {
+               dev_err(priv.dev, "Unable to prepare ddrclk\n");
+               goto out_cpu;
+       }
        kirkwood_freq_table[1].frequency = clk_get_rate(priv.ddr_clk) / 1000;
 
        priv.powersave_clk = of_clk_get_by_name(np, "powersave");
@@ -146,7 +155,11 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
                err = PTR_ERR(priv.powersave_clk);
                goto out_ddr;
        }
-       clk_prepare_enable(priv.powersave_clk);
+       err = clk_prepare_enable(priv.powersave_clk);
+       if (err) {
+               dev_err(priv.dev, "Unable to prepare powersave clk\n");
+               goto out_ddr;
+       }
 
        of_node_put(np);
        np = NULL;
index ffca4fc0061d6dad4de3c0d8ce4724461d7a13da..ae8eb03598892d18155d71161b4ea699d614ce97 100644 (file)
@@ -180,8 +180,10 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
                if (!state_node)
                        break;
 
-               if (!of_device_is_available(state_node))
+               if (!of_device_is_available(state_node)) {
+                       of_node_put(state_node);
                        continue;
+               }
 
                if (!idle_state_valid(state_node, i, cpumask)) {
                        pr_warn("%s idle state not valid, bailing out\n",
index ebf43f531adaff85da90968529ec522b2660776a..922d0823f8ec2b32e14ed6bef64bfe4bfdd268e1 100644 (file)
@@ -44,6 +44,7 @@ void dax_read_unlock(int id)
 }
 EXPORT_SYMBOL_GPL(dax_read_unlock);
 
+#ifdef CONFIG_BLOCK
 int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
                pgoff_t *pgoff)
 {
@@ -112,6 +113,7 @@ int __bdev_dax_supported(struct super_block *sb, int blocksize)
        return 0;
 }
 EXPORT_SYMBOL_GPL(__bdev_dax_supported);
+#endif
 
 /**
  * struct dax_device - anchor object for dax services
@@ -208,9 +210,12 @@ EXPORT_SYMBOL_GPL(kill_dax);
 static struct inode *dax_alloc_inode(struct super_block *sb)
 {
        struct dax_device *dax_dev;
+       struct inode *inode;
 
        dax_dev = kmem_cache_alloc(dax_cache, GFP_KERNEL);
-       return &dax_dev->inode;
+       inode = &dax_dev->inode;
+       inode->i_rdev = 0;
+       return inode;
 }
 
 static struct dax_device *to_dax_dev(struct inode *inode)
@@ -225,7 +230,8 @@ static void dax_i_callback(struct rcu_head *head)
 
        kfree(dax_dev->host);
        dax_dev->host = NULL;
-       ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev));
+       if (inode->i_rdev)
+               ida_simple_remove(&dax_minor_ida, MINOR(inode->i_rdev));
        kmem_cache_free(dax_cache, dax_dev);
 }
 
@@ -421,6 +427,7 @@ static void init_once(void *_dax_dev)
        struct dax_device *dax_dev = _dax_dev;
        struct inode *inode = &dax_dev->inode;
 
+       memset(dax_dev, 0, sizeof(*dax_dev));
        inode_init_once(inode);
 }
 
index 5c3e7b11e8a66c4853a1aabf9850537eea26767a..f6e7956fc91a212538b0ce937fe34f17aa73f073 100644 (file)
@@ -267,7 +267,11 @@ static int exynos_nocp_probe(struct platform_device *pdev)
        }
        platform_set_drvdata(pdev, nocp);
 
-       clk_prepare_enable(nocp->clk);
+       ret = clk_prepare_enable(nocp->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare ppmu clock\n");
+               return ret;
+       }
 
        pr_info("exynos-nocp: new NoC Probe device registered: %s\n",
                        dev_name(dev));
index 9b7350935b73259828a897a7eea6d4fc9b2e4c4f..d96e3dc71cf8ba74fa92078d97c79d434344c949 100644 (file)
@@ -44,7 +44,7 @@ struct exynos_ppmu {
        { "ppmu-event2-"#name, PPMU_PMNCNT2 },  \
        { "ppmu-event3-"#name, PPMU_PMNCNT3 }
 
-struct __exynos_ppmu_events {
+static struct __exynos_ppmu_events {
        char *name;
        int id;
 } ppmu_events[] = {
@@ -648,7 +648,11 @@ static int exynos_ppmu_probe(struct platform_device *pdev)
                        dev_name(&pdev->dev), desc[i].name);
        }
 
-       clk_prepare_enable(info->ppmu.clk);
+       ret = clk_prepare_enable(info->ppmu.clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to prepare ppmu clock\n");
+               return ret;
+       }
 
        return 0;
 }
index d37e8dda807900fe9725aa153c20c1c2bc927a52..ec240592f5c8e7a450e2c26c20feece9d12dafad 100644 (file)
@@ -201,6 +201,7 @@ struct ep93xx_dma_engine {
        struct dma_device       dma_dev;
        bool                    m2m;
        int                     (*hw_setup)(struct ep93xx_dma_chan *);
+       void                    (*hw_synchronize)(struct ep93xx_dma_chan *);
        void                    (*hw_shutdown)(struct ep93xx_dma_chan *);
        void                    (*hw_submit)(struct ep93xx_dma_chan *);
        int                     (*hw_interrupt)(struct ep93xx_dma_chan *);
@@ -323,6 +324,8 @@ static int m2p_hw_setup(struct ep93xx_dma_chan *edmac)
                | M2P_CONTROL_ENABLE;
        m2p_set_control(edmac, control);
 
+       edmac->buffer = 0;
+
        return 0;
 }
 
@@ -331,21 +334,27 @@ static inline u32 m2p_channel_state(struct ep93xx_dma_chan *edmac)
        return (readl(edmac->regs + M2P_STATUS) >> 4) & 0x3;
 }
 
-static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+static void m2p_hw_synchronize(struct ep93xx_dma_chan *edmac)
 {
+       unsigned long flags;
        u32 control;
 
+       spin_lock_irqsave(&edmac->lock, flags);
        control = readl(edmac->regs + M2P_CONTROL);
        control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT);
        m2p_set_control(edmac, control);
+       spin_unlock_irqrestore(&edmac->lock, flags);
 
        while (m2p_channel_state(edmac) >= M2P_STATE_ON)
-               cpu_relax();
+               schedule();
+}
 
+static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac)
+{
        m2p_set_control(edmac, 0);
 
-       while (m2p_channel_state(edmac) == M2P_STATE_STALL)
-               cpu_relax();
+       while (m2p_channel_state(edmac) != M2P_STATE_IDLE)
+               dev_warn(chan2dev(edmac), "M2P: Not yet IDLE\n");
 }
 
 static void m2p_fill_desc(struct ep93xx_dma_chan *edmac)
@@ -1160,6 +1169,26 @@ fail:
        return NULL;
 }
 
+/**
+ * ep93xx_dma_synchronize - Synchronizes the termination of transfers to the
+ * current context.
+ * @chan: channel
+ *
+ * Synchronizes the DMA channel termination to the current context. When this
+ * function returns it is guaranteed that all transfers for previously issued
+ * descriptors have stopped and and it is safe to free the memory associated
+ * with them. Furthermore it is guaranteed that all complete callback functions
+ * for a previously submitted descriptor have finished running and it is safe to
+ * free resources accessed from within the complete callbacks.
+ */
+static void ep93xx_dma_synchronize(struct dma_chan *chan)
+{
+       struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
+
+       if (edmac->edma->hw_synchronize)
+               edmac->edma->hw_synchronize(edmac);
+}
+
 /**
  * ep93xx_dma_terminate_all - terminate all transactions
  * @chan: channel
@@ -1323,6 +1352,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
        dma_dev->device_prep_slave_sg = ep93xx_dma_prep_slave_sg;
        dma_dev->device_prep_dma_cyclic = ep93xx_dma_prep_dma_cyclic;
        dma_dev->device_config = ep93xx_dma_slave_config;
+       dma_dev->device_synchronize = ep93xx_dma_synchronize;
        dma_dev->device_terminate_all = ep93xx_dma_terminate_all;
        dma_dev->device_issue_pending = ep93xx_dma_issue_pending;
        dma_dev->device_tx_status = ep93xx_dma_tx_status;
@@ -1340,6 +1370,7 @@ static int __init ep93xx_dma_probe(struct platform_device *pdev)
        } else {
                dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
 
+               edma->hw_synchronize = m2p_hw_synchronize;
                edma->hw_setup = m2p_hw_setup;
                edma->hw_shutdown = m2p_hw_shutdown;
                edma->hw_submit = m2p_hw_submit;
index a28a01fcba674dc569e4d49ca6fd50def5a58645..f3e211f8f6c58c00080703f11b25937bb36dab39 100644 (file)
@@ -161,6 +161,7 @@ struct mv_xor_v2_device {
        struct mv_xor_v2_sw_desc *sw_desq;
        int desc_size;
        unsigned int npendings;
+       unsigned int hw_queue_idx;
 };
 
 /**
@@ -213,18 +214,6 @@ static void mv_xor_v2_set_data_buffers(struct mv_xor_v2_device *xor_dev,
        }
 }
 
-/*
- * Return the next available index in the DESQ.
- */
-static int mv_xor_v2_get_desq_write_ptr(struct mv_xor_v2_device *xor_dev)
-{
-       /* read the index for the next available descriptor in the DESQ */
-       u32 reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_ALLOC_OFF);
-
-       return ((reg >> MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_SHIFT)
-               & MV_XOR_V2_DMA_DESQ_ALLOC_WRPTR_MASK);
-}
-
 /*
  * notify the engine of new descriptors, and update the available index.
  */
@@ -257,22 +246,6 @@ static int mv_xor_v2_set_desc_size(struct mv_xor_v2_device *xor_dev)
        return MV_XOR_V2_EXT_DESC_SIZE;
 }
 
-/*
- * Set the IMSG threshold
- */
-static inline
-void mv_xor_v2_set_imsg_thrd(struct mv_xor_v2_device *xor_dev, int thrd_val)
-{
-       u32 reg;
-
-       reg = readl(xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
-
-       reg &= (~MV_XOR_V2_DMA_IMSG_THRD_MASK << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
-       reg |= (thrd_val << MV_XOR_V2_DMA_IMSG_THRD_SHIFT);
-
-       writel(reg, xor_dev->dma_base + MV_XOR_V2_DMA_IMSG_THRD_OFF);
-}
-
 static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
 {
        struct mv_xor_v2_device *xor_dev = data;
@@ -288,12 +261,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
        if (!ndescs)
                return IRQ_NONE;
 
-       /*
-        * Update IMSG threshold, to disable new IMSG interrupts until
-        * end of the tasklet
-        */
-       mv_xor_v2_set_imsg_thrd(xor_dev, MV_XOR_V2_DESC_NUM);
-
        /* schedule a tasklet to handle descriptors callbacks */
        tasklet_schedule(&xor_dev->irq_tasklet);
 
@@ -306,7 +273,6 @@ static irqreturn_t mv_xor_v2_interrupt_handler(int irq, void *data)
 static dma_cookie_t
 mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-       int desq_ptr;
        void *dest_hw_desc;
        dma_cookie_t cookie;
        struct mv_xor_v2_sw_desc *sw_desc =
@@ -322,15 +288,15 @@ mv_xor_v2_tx_submit(struct dma_async_tx_descriptor *tx)
        spin_lock_bh(&xor_dev->lock);
        cookie = dma_cookie_assign(tx);
 
-       /* get the next available slot in the DESQ */
-       desq_ptr = mv_xor_v2_get_desq_write_ptr(xor_dev);
-
        /* copy the HW descriptor from the SW descriptor to the DESQ */
-       dest_hw_desc = xor_dev->hw_desq_virt + desq_ptr;
+       dest_hw_desc = xor_dev->hw_desq_virt + xor_dev->hw_queue_idx;
 
        memcpy(dest_hw_desc, &sw_desc->hw_desc, xor_dev->desc_size);
 
        xor_dev->npendings++;
+       xor_dev->hw_queue_idx++;
+       if (xor_dev->hw_queue_idx >= MV_XOR_V2_DESC_NUM)
+               xor_dev->hw_queue_idx = 0;
 
        spin_unlock_bh(&xor_dev->lock);
 
@@ -344,6 +310,7 @@ static struct mv_xor_v2_sw_desc     *
 mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev)
 {
        struct mv_xor_v2_sw_desc *sw_desc;
+       bool found = false;
 
        /* Lock the channel */
        spin_lock_bh(&xor_dev->lock);
@@ -355,19 +322,23 @@ mv_xor_v2_prep_sw_desc(struct mv_xor_v2_device *xor_dev)
                return NULL;
        }
 
-       /* get a free SW descriptor from the SW DESQ */
-       sw_desc = list_first_entry(&xor_dev->free_sw_desc,
-                                  struct mv_xor_v2_sw_desc, free_list);
+       list_for_each_entry(sw_desc, &xor_dev->free_sw_desc, free_list) {
+               if (async_tx_test_ack(&sw_desc->async_tx)) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found) {
+               spin_unlock_bh(&xor_dev->lock);
+               return NULL;
+       }
+
        list_del(&sw_desc->free_list);
 
        /* Release the channel */
        spin_unlock_bh(&xor_dev->lock);
 
-       /* set the async tx descriptor */
-       dma_async_tx_descriptor_init(&sw_desc->async_tx, &xor_dev->dmachan);
-       sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit;
-       async_tx_ack(&sw_desc->async_tx);
-
        return sw_desc;
 }
 
@@ -389,6 +360,8 @@ mv_xor_v2_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest,
                __func__, len, &src, &dest, flags);
 
        sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
+       if (!sw_desc)
+               return NULL;
 
        sw_desc->async_tx.flags = flags;
 
@@ -443,6 +416,8 @@ mv_xor_v2_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
                __func__, src_cnt, len, &dest, flags);
 
        sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
+       if (!sw_desc)
+               return NULL;
 
        sw_desc->async_tx.flags = flags;
 
@@ -491,6 +466,8 @@ mv_xor_v2_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
                container_of(chan, struct mv_xor_v2_device, dmachan);
 
        sw_desc = mv_xor_v2_prep_sw_desc(xor_dev);
+       if (!sw_desc)
+               return NULL;
 
        /* set the HW descriptor */
        hw_descriptor = &sw_desc->hw_desc;
@@ -554,7 +531,6 @@ static void mv_xor_v2_tasklet(unsigned long data)
 {
        struct mv_xor_v2_device *xor_dev = (struct mv_xor_v2_device *) data;
        int pending_ptr, num_of_pending, i;
-       struct mv_xor_v2_descriptor *next_pending_hw_desc = NULL;
        struct mv_xor_v2_sw_desc *next_pending_sw_desc = NULL;
 
        dev_dbg(xor_dev->dmadev.dev, "%s %d\n", __func__, __LINE__);
@@ -562,17 +538,10 @@ static void mv_xor_v2_tasklet(unsigned long data)
        /* get the pending descriptors parameters */
        num_of_pending = mv_xor_v2_get_pending_params(xor_dev, &pending_ptr);
 
-       /* next HW descriptor */
-       next_pending_hw_desc = xor_dev->hw_desq_virt + pending_ptr;
-
        /* loop over free descriptors */
        for (i = 0; i < num_of_pending; i++) {
-
-               if (pending_ptr > MV_XOR_V2_DESC_NUM)
-                       pending_ptr = 0;
-
-               if (next_pending_sw_desc != NULL)
-                       next_pending_hw_desc++;
+               struct mv_xor_v2_descriptor *next_pending_hw_desc =
+                       xor_dev->hw_desq_virt + pending_ptr;
 
                /* get the SW descriptor related to the HW descriptor */
                next_pending_sw_desc =
@@ -608,15 +577,14 @@ static void mv_xor_v2_tasklet(unsigned long data)
 
                /* increment the next descriptor */
                pending_ptr++;
+               if (pending_ptr >= MV_XOR_V2_DESC_NUM)
+                       pending_ptr = 0;
        }
 
        if (num_of_pending != 0) {
                /* free the descriptores */
                mv_xor_v2_free_desc_from_desq(xor_dev, num_of_pending);
        }
-
-       /* Update IMSG threshold, to enable new IMSG interrupts */
-       mv_xor_v2_set_imsg_thrd(xor_dev, 0);
 }
 
 /*
@@ -648,9 +616,6 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
        writel((xor_dev->hw_desq & 0xFFFF00000000) >> 32,
               xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_BAHR_OFF);
 
-       /* enable the DMA engine */
-       writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
-
        /*
         * This is a temporary solution, until we activate the
         * SMMU. Set the attributes for reading & writing data buffers
@@ -694,6 +659,9 @@ static int mv_xor_v2_descq_init(struct mv_xor_v2_device *xor_dev)
        reg |= MV_XOR_V2_GLOB_PAUSE_AXI_TIME_DIS_VAL;
        writel(reg, xor_dev->glob_base + MV_XOR_V2_GLOB_PAUSE);
 
+       /* enable the DMA engine */
+       writel(0, xor_dev->dma_base + MV_XOR_V2_DMA_DESQ_STOP_OFF);
+
        return 0;
 }
 
@@ -725,6 +693,10 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, xor_dev);
 
+       ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
+       if (ret)
+               return ret;
+
        xor_dev->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
@@ -785,8 +757,15 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
 
        /* add all SW descriptors to the free list */
        for (i = 0; i < MV_XOR_V2_DESC_NUM; i++) {
-               xor_dev->sw_desq[i].idx = i;
-               list_add(&xor_dev->sw_desq[i].free_list,
+               struct mv_xor_v2_sw_desc *sw_desc =
+                       xor_dev->sw_desq + i;
+               sw_desc->idx = i;
+               dma_async_tx_descriptor_init(&sw_desc->async_tx,
+                                            &xor_dev->dmachan);
+               sw_desc->async_tx.tx_submit = mv_xor_v2_tx_submit;
+               async_tx_ack(&sw_desc->async_tx);
+
+               list_add(&sw_desc->free_list,
                         &xor_dev->free_sw_desc);
        }
 
index 8b0da7fa520d27ac514228130c354f121a12b848..e90a7a0d760af6d031fa465208e88f2dd6f056b4 100644 (file)
@@ -3008,7 +3008,8 @@ static int pl330_remove(struct amba_device *adev)
 
        for (i = 0; i < AMBA_NR_IRQS; i++) {
                irq = adev->irq[i];
-               devm_free_irq(&adev->dev, irq, pl330);
+               if (irq)
+                       devm_free_irq(&adev->dev, irq, pl330);
        }
 
        dma_async_device_unregister(&pl330->ddma);
index db41795fe42ae6ed355de41f12b5c90ea661bde4..bd261c9e9664b6ac951939641091bc0bb7466380 100644 (file)
@@ -1287,6 +1287,9 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan,
        if (desc->hwdescs.use) {
                dptr = (rcar_dmac_chan_read(chan, RCAR_DMACHCRB) &
                        RCAR_DMACHCRB_DPTR_MASK) >> RCAR_DMACHCRB_DPTR_SHIFT;
+               if (dptr == 0)
+                       dptr = desc->nchunks;
+               dptr--;
                WARN_ON(dptr >= desc->nchunks);
        } else {
                running = desc->running;
index 72c649713aceecd75a20957522792702fca1696a..31a145154e9f26a8562e51223cffa50e65352075 100644 (file)
@@ -117,7 +117,7 @@ struct usb_dmac {
 #define USB_DMASWR                     0x0008
 #define USB_DMASWR_SWR                 (1 << 0)
 #define USB_DMAOR                      0x0060
-#define USB_DMAOR_AE                   (1 << 2)
+#define USB_DMAOR_AE                   (1 << 1)
 #define USB_DMAOR_DME                  (1 << 0)
 
 #define USB_DMASAR                     0x0000
index 82dab1692264d04baeb409622d54bbd895e013ff..3aea5569816557b9b55503fb7fd654e9b088b6df 100644 (file)
@@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 
 static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
 {
-       u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
-       int dimm, size0, size1;
+       int dimm, size0, size1, cs0, cs1;
 
        edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
 
        for (dimm = 0; dimm < 4; dimm++) {
                size0 = 0;
+               cs0 = dimm * 2;
 
-               if (dcsb[dimm*2] & DCSB_CS_ENABLE)
-                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+               if (csrow_enabled(cs0, ctrl, pvt))
+                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);
 
                size1 = 0;
-               if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
-                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+               cs1 = dimm * 2 + 1;
+
+               if (csrow_enabled(cs1, ctrl, pvt))
+                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);
 
                amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-                               dimm * 2,     size0,
-                               dimm * 2 + 1, size1);
+                               cs0,    size0,
+                               cs1,    size1);
        }
 }
 
@@ -2756,26 +2758,22 @@ skip:
  *     encompasses
  *
  */
-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
 {
-       u32 cs_mode, nr_pages;
        u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
+       int csrow_nr = csrow_nr_orig;
+       u32 cs_mode, nr_pages;
 
+       if (!pvt->umc)
+               csrow_nr >>= 1;
 
-       /*
-        * The math on this doesn't look right on the surface because x/2*4 can
-        * be simplified to x*2 but this expression makes use of the fact that
-        * it is integral math where 1/2=0. This intermediate value becomes the
-        * number of bits to shift the DBAM register to extract the proper CSROW
-        * field.
-        */
-       cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
+       cs_mode = DBAM_DIMM(csrow_nr, dbam);
 
-       nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
-                                                          << (20 - PAGE_SHIFT);
+       nr_pages   = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
+       nr_pages <<= 20 - PAGE_SHIFT;
 
        edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
-                   csrow_nr, dct,  cs_mode);
+                   csrow_nr_orig, dct,  cs_mode);
        edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
        return nr_pages;
index 44c01390d0353fd3170fc797eb4ce6393229bd14..951b6c79f166a7d2b4ec14e12096559df9aed684 100644 (file)
@@ -47,6 +47,7 @@ DEFINE_DMI_ATTR_WITH_SHOW(product_name,               0444, DMI_PRODUCT_NAME);
 DEFINE_DMI_ATTR_WITH_SHOW(product_version,     0444, DMI_PRODUCT_VERSION);
 DEFINE_DMI_ATTR_WITH_SHOW(product_serial,      0400, DMI_PRODUCT_SERIAL);
 DEFINE_DMI_ATTR_WITH_SHOW(product_uuid,                0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(product_family,      0444, DMI_PRODUCT_FAMILY);
 DEFINE_DMI_ATTR_WITH_SHOW(board_vendor,                0444, DMI_BOARD_VENDOR);
 DEFINE_DMI_ATTR_WITH_SHOW(board_name,          0444, DMI_BOARD_NAME);
 DEFINE_DMI_ATTR_WITH_SHOW(board_version,       0444, DMI_BOARD_VERSION);
@@ -191,6 +192,7 @@ static void __init dmi_id_init_attr_table(void)
        ADD_DMI_ATTR(product_version,   DMI_PRODUCT_VERSION);
        ADD_DMI_ATTR(product_serial,    DMI_PRODUCT_SERIAL);
        ADD_DMI_ATTR(product_uuid,      DMI_PRODUCT_UUID);
+       ADD_DMI_ATTR(product_family,    DMI_PRODUCT_FAMILY);
        ADD_DMI_ATTR(board_vendor,      DMI_BOARD_VENDOR);
        ADD_DMI_ATTR(board_name,        DMI_BOARD_NAME);
        ADD_DMI_ATTR(board_version,     DMI_BOARD_VERSION);
index 54be60ead08f8068c18dc9bbfd5a40e3cb26685c..783041964439acaa60c80eac80df24080579d036 100644 (file)
@@ -144,7 +144,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
 
        buf = dmi_early_remap(dmi_base, orig_dmi_len);
        if (buf == NULL)
-               return -1;
+               return -ENOMEM;
 
        dmi_decode_table(buf, decode, NULL);
 
@@ -178,7 +178,7 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
        const char *d = (const char *) dm;
        const char *p;
 
-       if (dmi_ident[slot])
+       if (dmi_ident[slot] || dm->length <= string)
                return;
 
        p = dmi_string(dm, d[string]);
@@ -191,13 +191,14 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
 static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
                int index)
 {
-       const u8 *d = (u8 *) dm + index;
+       const u8 *d;
        char *s;
        int is_ff = 1, is_00 = 1, i;
 
-       if (dmi_ident[slot])
+       if (dmi_ident[slot] || dm->length <= index + 16)
                return;
 
+       d = (u8 *) dm + index;
        for (i = 0; i < 16 && (is_ff || is_00); i++) {
                if (d[i] != 0x00)
                        is_00 = 0;
@@ -228,16 +229,17 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
 static void __init dmi_save_type(const struct dmi_header *dm, int slot,
                int index)
 {
-       const u8 *d = (u8 *) dm + index;
+       const u8 *d;
        char *s;
 
-       if (dmi_ident[slot])
+       if (dmi_ident[slot] || dm->length <= index)
                return;
 
        s = dmi_alloc(4);
        if (!s)
                return;
 
+       d = (u8 *) dm + index;
        sprintf(s, "%u", *d & 0x7F);
        dmi_ident[slot] = s;
 }
@@ -278,9 +280,13 @@ static void __init dmi_save_devices(const struct dmi_header *dm)
 
 static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
 {
-       int i, count = *(u8 *)(dm + 1);
+       int i, count;
        struct dmi_device *dev;
 
+       if (dm->length < 0x05)
+               return;
+
+       count = *(u8 *)(dm + 1);
        for (i = 1; i <= count; i++) {
                const char *devname = dmi_string(dm, i);
 
@@ -353,6 +359,9 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
        const char *name;
        const u8 *d = (u8 *)dm;
 
+       if (dm->length < 0x0B)
+               return;
+
        /* Skip disabled device */
        if ((d[0x5] & 0x80) == 0)
                return;
@@ -387,7 +396,7 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
        const char *d = (const char *)dm;
        static int nr;
 
-       if (dm->type != DMI_ENTRY_MEM_DEVICE)
+       if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
                return;
        if (nr >= dmi_memdev_nr) {
                pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
@@ -430,6 +439,7 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
                dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
                dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
                dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
+               dmi_save_ident(dm, DMI_PRODUCT_FAMILY, 26);
                break;
        case 2:         /* Base Board Information */
                dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
@@ -648,6 +658,21 @@ void __init dmi_scan_machine(void)
                if (p == NULL)
                        goto error;
 
+               /*
+                * Same logic as above, look for a 64-bit entry point
+                * first, and if not found, fall back to 32-bit entry point.
+                */
+               memcpy_fromio(buf, p, 16);
+               for (q = p + 16; q < p + 0x10000; q += 16) {
+                       memcpy_fromio(buf + 16, q, 16);
+                       if (!dmi_smbios3_present(buf)) {
+                               dmi_available = 1;
+                               dmi_early_unmap(p, 0x10000);
+                               goto out;
+                       }
+                       memcpy(buf, buf + 16, 16);
+               }
+
                /*
                 * Iterate over all possible DMI header addresses q.
                 * Maintain the 32 bytes around q in buf.  On the
@@ -658,7 +683,7 @@ void __init dmi_scan_machine(void)
                memset(buf, 0, 16);
                for (q = p; q < p + 0x10000; q += 16) {
                        memcpy_fromio(buf + 16, q, 16);
-                       if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
+                       if (!dmi_present(buf)) {
                                dmi_available = 1;
                                dmi_early_unmap(p, 0x10000);
                                goto out;
@@ -992,7 +1017,8 @@ EXPORT_SYMBOL(dmi_get_date);
  *     @decode: Callback function
  *     @private_data: Private data to be passed to the callback function
  *
- *     Returns -1 when the DMI table can't be reached, 0 on success.
+ *     Returns 0 on success, -ENXIO if DMI is not selected or not present,
+ *     or a different negative error code if DMI walking fails.
  */
 int dmi_walk(void (*decode)(const struct dmi_header *, void *),
             void *private_data)
@@ -1000,11 +1026,11 @@ int dmi_walk(void (*decode)(const struct dmi_header *, void *),
        u8 *buf;
 
        if (!dmi_available)
-               return -1;
+               return -ENXIO;
 
        buf = dmi_remap(dmi_base, dmi_len);
        if (buf == NULL)
-               return -1;
+               return -ENOMEM;
 
        dmi_decode_table(buf, decode, private_data);
 
index 04ca8764f0c096f4e3f006ab74e4dc55996735a1..b58233e4ed71ac41709318e03ce06c1d1b2c20ce 100644 (file)
@@ -27,6 +27,26 @@ struct bmp_header {
        u32 size;
 } __packed;
 
+static bool efi_bgrt_addr_valid(u64 addr)
+{
+       efi_memory_desc_t *md;
+
+       for_each_efi_memory_desc(md) {
+               u64 size;
+               u64 end;
+
+               if (md->type != EFI_BOOT_SERVICES_DATA)
+                       continue;
+
+               size = md->num_pages << EFI_PAGE_SHIFT;
+               end = md->phys_addr + size;
+               if (addr >= md->phys_addr && addr < end)
+                       return true;
+       }
+
+       return false;
+}
+
 void __init efi_bgrt_init(struct acpi_table_header *table)
 {
        void *image;
@@ -36,6 +56,9 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
        if (acpi_disabled)
                return;
 
+       if (!efi_enabled(EFI_MEMMAP))
+               return;
+
        if (table->length < sizeof(bgrt_tab)) {
                pr_notice("Ignoring BGRT: invalid length %u (expected %zu)\n",
                       table->length, sizeof(bgrt_tab));
@@ -62,6 +85,10 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
                goto out;
        }
 
+       if (!efi_bgrt_addr_valid(bgrt->image_address)) {
+               pr_notice("Ignoring BGRT: invalid image address\n");
+               goto out;
+       }
        image = early_memremap(bgrt->image_address, sizeof(bmp_header));
        if (!image) {
                pr_notice("Ignoring BGRT: failed to map image header memory\n");
index ed3137c1ceb0c0ed0fcbb1c94bffdf1a4811bf41..ef1fafdad4008ae7fa1824396592e0e53cf61002 100644 (file)
@@ -53,6 +53,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
        if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
                   &record->type, &part, &cnt, &time, &data_type) == 5) {
                record->id = generic_id(time, part, cnt);
+               record->part = part;
                record->count = cnt;
                record->time.tv_sec = time;
                record->time.tv_nsec = 0;
@@ -64,6 +65,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
        } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
                   &record->type, &part, &cnt, &time) == 4) {
                record->id = generic_id(time, part, cnt);
+               record->part = part;
                record->count = cnt;
                record->time.tv_sec = time;
                record->time.tv_nsec = 0;
@@ -77,6 +79,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
                 * multiple logs, remains.
                 */
                record->id = generic_id(time, part, 0);
+               record->part = part;
                record->count = 0;
                record->time.tv_sec = time;
                record->time.tv_nsec = 0;
@@ -155,19 +158,14 @@ static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
  * efi_pstore_sysfs_entry_iter
  *
  * @record: pstore record to pass to callback
- * @pos: entry to begin iterating from
  *
  * You MUST call efivar_enter_iter_begin() before this function, and
  * efivar_entry_iter_end() afterwards.
  *
- * It is possible to begin iteration from an arbitrary entry within
- * the list by passing @pos. @pos is updated on return to point to
- * the next entry of the last one passed to efi_pstore_read_func().
- * To begin iterating from the beginning of the list @pos must be %NULL.
  */
-static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
-                                      struct efivar_entry **pos)
+static int efi_pstore_sysfs_entry_iter(struct pstore_record *record)
 {
+       struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data;
        struct efivar_entry *entry, *n;
        struct list_head *head = &efivar_sysfs_list;
        int size = 0;
@@ -218,7 +216,6 @@ static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
  */
 static ssize_t efi_pstore_read(struct pstore_record *record)
 {
-       struct efivar_entry *entry = (struct efivar_entry *)record->psi->data;
        ssize_t size;
 
        record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
@@ -229,7 +226,7 @@ static ssize_t efi_pstore_read(struct pstore_record *record)
                size = -EINTR;
                goto out;
        }
-       size = efi_pstore_sysfs_entry_iter(record, &entry);
+       size = efi_pstore_sysfs_entry_iter(record);
        efivar_entry_iter_end();
 
 out:
@@ -247,9 +244,15 @@ static int efi_pstore_write(struct pstore_record *record)
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
        int i, ret = 0;
 
+       record->time.tv_sec = get_seconds();
+       record->time.tv_nsec = 0;
+
+       record->id = generic_id(record->time.tv_sec, record->part,
+                               record->count);
+
        snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c",
                 record->type, record->part, record->count,
-                get_seconds(), record->compressed ? 'C' : 'D');
+                record->time.tv_sec, record->compressed ? 'C' : 'D');
 
        for (i = 0; i < DUMP_NAME_LEN; i++)
                efi_name[i] = name[i];
@@ -261,7 +264,6 @@ static int efi_pstore_write(struct pstore_record *record)
        if (record->reason == KMSG_DUMP_OOPS)
                efivar_run_worker();
 
-       record->id = record->part;
        return ret;
 };
 
@@ -293,7 +295,7 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data)
                 * holding multiple logs, remains.
                 */
                snprintf(name_old, sizeof(name_old), "dump-type%u-%u-%lu",
-                       ed->record->type, (unsigned int)ed->record->id,
+                       ed->record->type, ed->record->part,
                        ed->record->time.tv_sec);
 
                for (i = 0; i < DUMP_NAME_LEN; i++)
@@ -326,10 +328,7 @@ static int efi_pstore_erase(struct pstore_record *record)
        char name[DUMP_NAME_LEN];
        efi_char16_t efi_name[DUMP_NAME_LEN];
        int found, i;
-       unsigned int part;
 
-       do_div(record->id, 1000);
-       part = do_div(record->id, 100);
        snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu",
                 record->type, record->part, record->count,
                 record->time.tv_sec);
index 8c34d50a4d8032bbaba3322b3dee4ff22826a923..959777ec8a77bab62e49097cd93d711ccd311610 100644 (file)
 
 /* BIOS variables */
 static const efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
-static const efi_char16_t const efi_SecureBoot_name[] = {
+static const efi_char16_t efi_SecureBoot_name[] = {
        'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0
 };
-static const efi_char16_t const efi_SetupMode_name[] = {
+static const efi_char16_t efi_SetupMode_name[] = {
        'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0
 };
 
index 3ce813110d5e11bca8f3ea3e87c50cd32562b930..31058d400bda6f767c022ac179d839437cf0e64f 100644 (file)
@@ -116,9 +116,13 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len,
                return VPD_OK;
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
-       info->key = kzalloc(key_len + 1, GFP_KERNEL);
-       if (!info->key)
+       if (!info)
                return -ENOMEM;
+       info->key = kzalloc(key_len + 1, GFP_KERNEL);
+       if (!info->key) {
+               ret = -ENOMEM;
+               goto free_info;
+       }
 
        memcpy(info->key, key, key_len);
 
@@ -132,15 +136,20 @@ static int vpd_section_attrib_add(const u8 *key, s32 key_len,
        info->value = value;
 
        INIT_LIST_HEAD(&info->list);
-       list_add_tail(&info->list, &sec->attribs);
 
        ret = sysfs_create_bin_file(sec->kobj, &info->bin_attr);
-       if (ret) {
-               kfree(info->key);
-               return ret;
-       }
+       if (ret)
+               goto free_info_key;
 
+       list_add_tail(&info->list, &sec->attribs);
        return 0;
+
+free_info_key:
+       kfree(info->key);
+free_info:
+       kfree(info);
+
+       return ret;
 }
 
 static void vpd_section_attrib_destroy(struct vpd_section *sec)
@@ -149,8 +158,8 @@ static void vpd_section_attrib_destroy(struct vpd_section *sec)
        struct vpd_attrib_info *temp;
 
        list_for_each_entry_safe(info, temp, &sec->attribs, list) {
-               kfree(info->key);
                sysfs_remove_bin_file(sec->kobj, &info->bin_attr);
+               kfree(info->key);
                kfree(info);
        }
 }
@@ -235,7 +244,7 @@ static int vpd_section_destroy(struct vpd_section *sec)
 {
        if (sec->enabled) {
                vpd_section_attrib_destroy(sec);
-               kobject_del(sec->kobj);
+               kobject_put(sec->kobj);
                sysfs_remove_bin_file(vpd_kobj, &sec->bin_attr);
                kfree(sec->raw_name);
                iounmap(sec->baseaddr);
@@ -322,7 +331,7 @@ static void __exit vpd_platform_exit(void)
 {
        vpd_section_destroy(&ro_vpd);
        vpd_section_destroy(&rw_vpd);
-       kobject_del(vpd_kobj);
+       kobject_put(vpd_kobj);
 }
 
 module_init(vpd_platform_init);
index 874ff32db36668919c50eb6eda3d744327ee5dd6..00cfed3c3e1a20b7bbea4b1a93e59fcd09afc2dd 100644 (file)
@@ -202,7 +202,8 @@ static int ti_sci_debugfs_create(struct platform_device *pdev,
        info->debug_buffer[info->debug_region_size] = 0;
 
        info->d = debugfs_create_file(strncat(debug_name, dev_name(dev),
-                                             sizeof(debug_name)),
+                                             sizeof(debug_name) -
+                                             sizeof("ti_sci_debug@")),
                                      0444, NULL, info, &ti_sci_debug_fops);
        if (IS_ERR(info->d))
                return PTR_ERR(info->d);
index ccea609676eebfe8bbcd6e01acaa8f6c4499ffe7..4ca436e66bdb24f674280dd51a459a3d90809457 100644 (file)
@@ -646,6 +646,9 @@ static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
        int rc;
        int i;
 
+       if (!gpio->clk)
+               return -EINVAL;
+
        rc = usecs_to_cycles(gpio, usecs, &requested_cycles);
        if (rc < 0) {
                dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n",
index 2197368cc899d06ae231cb14d0825f7c9df1382f..e60156ec0c1842865bd7120c38ac85f58274fefd 100644 (file)
@@ -90,8 +90,18 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
 {
        int reg;
 
-       if (gpio == 94)
-               return GPIOPANELCTL;
+       if (gpio >= CRYSTALCOVE_GPIO_NUM) {
+               /*
+                * Virtual GPIO called from ACPI, for now we only support
+                * the panel ctl.
+                */
+               switch (gpio) {
+               case 0x5e:
+                       return GPIOPANELCTL;
+               default:
+                       return -EOPNOTSUPP;
+               }
+       }
 
        if (reg_type == CTRL_IN) {
                if (gpio < 8)
@@ -130,36 +140,36 @@ static void crystalcove_update_irq_ctrl(struct crystalcove_gpio *cg, int gpio)
 static int crystalcove_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
 {
        struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+       int reg = to_reg(gpio, CTRL_OUT);
 
-       if (gpio > CRYSTALCOVE_VGPIO_NUM)
+       if (reg < 0)
                return 0;
 
-       return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
-                           CTLO_INPUT_SET);
+       return regmap_write(cg->regmap, reg, CTLO_INPUT_SET);
 }
 
 static int crystalcove_gpio_dir_out(struct gpio_chip *chip, unsigned gpio,
                                    int value)
 {
        struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+       int reg = to_reg(gpio, CTRL_OUT);
 
-       if (gpio > CRYSTALCOVE_VGPIO_NUM)
+       if (reg < 0)
                return 0;
 
-       return regmap_write(cg->regmap, to_reg(gpio, CTRL_OUT),
-                           CTLO_OUTPUT_SET | value);
+       return regmap_write(cg->regmap, reg, CTLO_OUTPUT_SET | value);
 }
 
 static int crystalcove_gpio_get(struct gpio_chip *chip, unsigned gpio)
 {
        struct crystalcove_gpio *cg = gpiochip_get_data(chip);
-       int ret;
        unsigned int val;
+       int ret, reg = to_reg(gpio, CTRL_IN);
 
-       if (gpio > CRYSTALCOVE_VGPIO_NUM)
+       if (reg < 0)
                return 0;
 
-       ret = regmap_read(cg->regmap, to_reg(gpio, CTRL_IN), &val);
+       ret = regmap_read(cg->regmap, reg, &val);
        if (ret)
                return ret;
 
@@ -170,14 +180,15 @@ static void crystalcove_gpio_set(struct gpio_chip *chip,
                                 unsigned gpio, int value)
 {
        struct crystalcove_gpio *cg = gpiochip_get_data(chip);
+       int reg = to_reg(gpio, CTRL_OUT);
 
-       if (gpio > CRYSTALCOVE_VGPIO_NUM)
+       if (reg < 0)
                return;
 
        if (value)
-               regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 1);
+               regmap_update_bits(cg->regmap, reg, 1, 1);
        else
-               regmap_update_bits(cg->regmap, to_reg(gpio, CTRL_OUT), 1, 0);
+               regmap_update_bits(cg->regmap, reg, 1, 0);
 }
 
 static int crystalcove_irq_type(struct irq_data *data, unsigned type)
@@ -185,6 +196,9 @@ static int crystalcove_irq_type(struct irq_data *data, unsigned type)
        struct crystalcove_gpio *cg =
                gpiochip_get_data(irq_data_get_irq_chip_data(data));
 
+       if (data->hwirq >= CRYSTALCOVE_GPIO_NUM)
+               return 0;
+
        switch (type) {
        case IRQ_TYPE_NONE:
                cg->intcnt_value = CTLI_INTCNT_DIS;
@@ -235,8 +249,10 @@ static void crystalcove_irq_unmask(struct irq_data *data)
        struct crystalcove_gpio *cg =
                gpiochip_get_data(irq_data_get_irq_chip_data(data));
 
-       cg->set_irq_mask = false;
-       cg->update |= UPDATE_IRQ_MASK;
+       if (data->hwirq < CRYSTALCOVE_GPIO_NUM) {
+               cg->set_irq_mask = false;
+               cg->update |= UPDATE_IRQ_MASK;
+       }
 }
 
 static void crystalcove_irq_mask(struct irq_data *data)
@@ -244,8 +260,10 @@ static void crystalcove_irq_mask(struct irq_data *data)
        struct crystalcove_gpio *cg =
                gpiochip_get_data(irq_data_get_irq_chip_data(data));
 
-       cg->set_irq_mask = true;
-       cg->update |= UPDATE_IRQ_MASK;
+       if (data->hwirq < CRYSTALCOVE_GPIO_NUM) {
+               cg->set_irq_mask = true;
+               cg->update |= UPDATE_IRQ_MASK;
+       }
 }
 
 static struct irq_chip crystalcove_irqchip = {
index 19a92efabbef705b8826441c966cca4c55838bfd..c83ea68be792df45a354f38dee2438a866a1f29d 100644 (file)
@@ -721,7 +721,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
        u32 set;
 
        if (!of_device_is_compatible(mvchip->chip.of_node,
-                                    "marvell,armada-370-xp-gpio"))
+                                    "marvell,armada-370-gpio"))
                return 0;
 
        if (IS_ERR(mvchip->clk))
@@ -747,7 +747,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
                set = U32_MAX;
        else
                return -EINVAL;
-       writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip));
+       writel_relaxed(set, mvebu_gpioreg_blink_counter_select(mvchip));
 
        mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
        if (!mvpwm)
@@ -768,6 +768,13 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
        mvpwm->chip.dev = dev;
        mvpwm->chip.ops = &mvebu_pwm_ops;
        mvpwm->chip.npwm = mvchip->chip.ngpio;
+       /*
+        * There may already be some PWM allocated, so we can't force
+        * mvpwm->chip.base to a fixed point like mvchip->chip.base.
+        * So, we let pwmchip_add() do the numbering and take the next free
+        * region.
+        */
+       mvpwm->chip.base = -1;
 
        spin_lock_init(&mvpwm->lock);
 
@@ -845,7 +852,7 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
                .data       = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
        },
        {
-               .compatible = "marvell,armada-370-xp-gpio",
+               .compatible = "marvell,armada-370-gpio",
                .data       = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
        },
        {
@@ -1121,7 +1128,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                                                 mvchip);
        }
 
-       /* Armada 370/XP has simple PWM support for GPIO lines */
+       /* Some MVEBU SoCs have simple PWM support for GPIO lines */
        if (IS_ENABLED(CONFIG_PWM))
                return mvebu_pwm_probe(pdev, mvchip, id);
 
index 2185232da823e658c326063dda45aaa2d9a66f71..8fa5fcd00e9a0b66cf54b2e7b7d1efe6a4eb2817 100644 (file)
@@ -201,7 +201,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares,
                        handler = acpi_gpio_irq_handler_evt;
        }
        if (!handler)
-               return AE_BAD_PARAMETER;
+               return AE_OK;
 
        pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin);
        if (pin < 0)
index 5db44139cef8ca93af47b18f03c50b28b8893c8c..a42a1eea571430cb6ca460cd8e12ba7efd98589e 100644 (file)
@@ -708,7 +708,8 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
 
        ge.timestamp = ktime_get_real_ns();
 
-       if (le->eflags & GPIOEVENT_REQUEST_BOTH_EDGES) {
+       if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
+           && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
                int level = gpiod_get_value_cansleep(le->desc);
 
                if (level)
index 1cf78f4dd339f93ddd971088ec42a5146b9820fe..1e8e1123ddf416f18176cbc6e82fa791b3df9fb5 100644 (file)
@@ -693,6 +693,10 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)
                        DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
                                 adev->clock.default_dispclk / 100);
                        adev->clock.default_dispclk = 60000;
+               } else if (adev->clock.default_dispclk <= 60000) {
+                       DRM_INFO("Changing default dispclk from %dMhz to 625Mhz\n",
+                                adev->clock.default_dispclk / 100);
+                       adev->clock.default_dispclk = 62500;
                }
                adev->clock.dp_extclk =
                        le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
index f2d705e6a75aa4f092d3d98ff739927e15b6f26b..ab6b0d0febab810ba4941e5a527435dd5d3161d8 100644 (file)
@@ -449,6 +449,7 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        {0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        {0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        {0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
        /* Vega 10 */
        {0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
index 236d9950221b62665e8728941faa5793fc757980..c0d8c6ff6380e8a69de8faf58d28963dde29c8de 100644 (file)
@@ -425,10 +425,15 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
 
 void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev)
 {
-       struct amdgpu_fbdev *afbdev = adev->mode_info.rfbdev;
+       struct amdgpu_fbdev *afbdev;
        struct drm_fb_helper *fb_helper;
        int ret;
 
+       if (!adev)
+               return;
+
+       afbdev = adev->mode_info.rfbdev;
+
        if (!afbdev)
                return;
 
index 07ff3b1514f129edc23875c1f42053f7ef1aaa72..8ecf82c5fe74dc4d34e55d4dbaec5931bca1a2e8 100644 (file)
@@ -634,7 +634,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
                mutex_unlock(&id_mgr->lock);
        }
 
-       if (gds_switch_needed) {
+       if (ring->funcs->emit_gds_switch && gds_switch_needed) {
                id->gds_base = job->gds_base;
                id->gds_size = job->gds_size;
                id->gws_base = job->gws_base;
@@ -672,6 +672,7 @@ void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
        struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub];
        struct amdgpu_vm_id *id = &id_mgr->ids[vmid];
 
+       atomic64_set(&id->owner, 0);
        id->gds_base = 0;
        id->gds_size = 0;
        id->gws_base = 0;
@@ -680,6 +681,26 @@ void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
        id->oa_size = 0;
 }
 
+/**
+ * amdgpu_vm_reset_all_id - reset VMID to zero
+ *
+ * @adev: amdgpu device structure
+ *
+ * Reset VMID to force flush on next use
+ */
+void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev)
+{
+       unsigned i, j;
+
+       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
+               struct amdgpu_vm_id_manager *id_mgr =
+                       &adev->vm_manager.id_mgr[i];
+
+               for (j = 1; j < id_mgr->num_ids; ++j)
+                       amdgpu_vm_reset_id(adev, i, j);
+       }
+}
+
 /**
  * amdgpu_vm_bo_find - find the bo_va for a specific vm & bo
  *
@@ -2270,7 +2291,6 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
        for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
                adev->vm_manager.seqno[i] = 0;
 
-
        atomic_set(&adev->vm_manager.vm_pte_next_ring, 0);
        atomic64_set(&adev->vm_manager.client_counter, 0);
        spin_lock_init(&adev->vm_manager.prt_lock);
index d97e28b4bdc41cbb52e70647685b58db4886514a..e1d951ece4333672512f96ae914ee740f0a5922b 100644 (file)
@@ -204,6 +204,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
 int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
 void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
                        unsigned vmid);
+void amdgpu_vm_reset_all_ids(struct amdgpu_device *adev);
 int amdgpu_vm_update_directories(struct amdgpu_device *adev,
                                 struct amdgpu_vm *vm);
 int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
index a4831fe0223bffebdda4727589453aa6cb8fb7b1..a2c59a08b2bd69919b23989feddff71a88855617 100644 (file)
@@ -220,9 +220,9 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
 }
 
 const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = {
-       amdgpu_vram_mgr_init,
-       amdgpu_vram_mgr_fini,
-       amdgpu_vram_mgr_new,
-       amdgpu_vram_mgr_del,
-       amdgpu_vram_mgr_debug
+       .init           = amdgpu_vram_mgr_init,
+       .takedown       = amdgpu_vram_mgr_fini,
+       .get_node       = amdgpu_vram_mgr_new,
+       .put_node       = amdgpu_vram_mgr_del,
+       .debug          = amdgpu_vram_mgr_debug
 };
index 8c9bc75a9c2db63288f2c6765b02f68f63875194..8a0818b23ea40fadde57f6b469b2153330b710ab 100644 (file)
@@ -165,7 +165,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)
        struct drm_device *dev = crtc->dev;
        struct amdgpu_device *adev = dev->dev_private;
        int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
-       ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;
+       ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
 
        memset(&args, 0, sizeof(args));
 
@@ -178,7 +178,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)
 void amdgpu_atombios_crtc_powergate_init(struct amdgpu_device *adev)
 {
        int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating);
-       ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args;
+       ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;
 
        memset(&args, 0, sizeof(args));
 
index 6dc1410b380f376982551dbebe06f4dd84edf3b2..ec93714e4524eeaf80dbd5181da396e48024827b 100644 (file)
@@ -906,6 +906,12 @@ static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev)
        u32 vblank_time = amdgpu_dpm_get_vblank_time(adev);
        u32 switch_limit = adev->mc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300;
 
+       /* disable mclk switching if the refresh is >120Hz, even if the
+        * blanking period would allow it
+        */
+       if (amdgpu_dpm_get_vrefresh(adev) > 120)
+               return true;
+
        if (vblank_time < switch_limit)
                return true;
        else
index 0cdeb6a2e4a0166d8f33a542e950e7c87abc11fa..5dffa27afa45a2dff164d46b53f6af2e24ca00ab 100644 (file)
@@ -1207,8 +1207,11 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
        u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
        if (amdgpu_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
 
                /* watermark for high clocks */
                if (adev->pm.dpm_enabled) {
index 773654a19749fa7594250c6683d688e50bb12172..47bbc87f96d2bbf291db431e964b0dc9b0c5424e 100644 (file)
@@ -1176,8 +1176,11 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
        u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
        if (amdgpu_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
 
                /* watermark for high clocks */
                if (adev->pm.dpm_enabled) {
index 1f3552967ba374c2e5677a742b70e2040f867d65..d8c9a959493ed512104e8b8414ffb1742c9566e3 100644 (file)
@@ -983,8 +983,11 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
        fixed20_12 a, b, c;
 
        if (amdgpu_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
                priority_a_cnt = 0;
                priority_b_cnt = 0;
 
index 3c558c170e5e685ad58aafa8dc6df301e879f264..db30c6ba563a4a2362e3fde4545ed92d35b1bae9 100644 (file)
@@ -1091,8 +1091,11 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
        u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
 
        if (amdgpu_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
 
                /* watermark for high clocks */
                if (adev->pm.dpm_enabled) {
index a572979f186cdaeba52701fb8183850e16581143..d860939152df234517e7806135015a23aa316df9 100644 (file)
@@ -950,10 +950,6 @@ static int gmc_v6_0_suspend(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (adev->vm_manager.enabled) {
-               gmc_v6_0_vm_fini(adev);
-               adev->vm_manager.enabled = false;
-       }
        gmc_v6_0_hw_fini(adev);
 
        return 0;
@@ -968,16 +964,9 @@ static int gmc_v6_0_resume(void *handle)
        if (r)
                return r;
 
-       if (!adev->vm_manager.enabled) {
-               r = gmc_v6_0_vm_init(adev);
-               if (r) {
-                       dev_err(adev->dev, "vm manager initialization failed (%d).\n", r);
-                       return r;
-               }
-               adev->vm_manager.enabled = true;
-       }
+       amdgpu_vm_reset_all_ids(adev);
 
-       return r;
+       return 0;
 }
 
 static bool gmc_v6_0_is_idle(void *handle)
index a9083a16a250920c64605bc447ca19c8b3014f3a..2750e5c2381301ceebddb8f614f7e5868de23d2c 100644 (file)
@@ -1117,10 +1117,6 @@ static int gmc_v7_0_suspend(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (adev->vm_manager.enabled) {
-               gmc_v7_0_vm_fini(adev);
-               adev->vm_manager.enabled = false;
-       }
        gmc_v7_0_hw_fini(adev);
 
        return 0;
@@ -1135,16 +1131,9 @@ static int gmc_v7_0_resume(void *handle)
        if (r)
                return r;
 
-       if (!adev->vm_manager.enabled) {
-               r = gmc_v7_0_vm_init(adev);
-               if (r) {
-                       dev_err(adev->dev, "vm manager initialization failed (%d).\n", r);
-                       return r;
-               }
-               adev->vm_manager.enabled = true;
-       }
+       amdgpu_vm_reset_all_ids(adev);
 
-       return r;
+       return 0;
 }
 
 static bool gmc_v7_0_is_idle(void *handle)
index 4ac99784160a3ed9fbb59c5bf53a8d1b0a6ec1b4..f56b4089ee9f3fe7581cd6c541d434867c613cbb 100644 (file)
@@ -1209,10 +1209,6 @@ static int gmc_v8_0_suspend(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (adev->vm_manager.enabled) {
-               gmc_v8_0_vm_fini(adev);
-               adev->vm_manager.enabled = false;
-       }
        gmc_v8_0_hw_fini(adev);
 
        return 0;
@@ -1227,16 +1223,9 @@ static int gmc_v8_0_resume(void *handle)
        if (r)
                return r;
 
-       if (!adev->vm_manager.enabled) {
-               r = gmc_v8_0_vm_init(adev);
-               if (r) {
-                       dev_err(adev->dev, "vm manager initialization failed (%d).\n", r);
-                       return r;
-               }
-               adev->vm_manager.enabled = true;
-       }
+       amdgpu_vm_reset_all_ids(adev);
 
-       return r;
+       return 0;
 }
 
 static bool gmc_v8_0_is_idle(void *handle)
index dc1e1c1d6b2430cb9957047a454cde87bf439561..f936332a069d2d1c9329a3d52a17f9e44776f659 100644 (file)
@@ -791,10 +791,6 @@ static int gmc_v9_0_suspend(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (adev->vm_manager.enabled) {
-               gmc_v9_0_vm_fini(adev);
-               adev->vm_manager.enabled = false;
-       }
        gmc_v9_0_hw_fini(adev);
 
        return 0;
@@ -809,17 +805,9 @@ static int gmc_v9_0_resume(void *handle)
        if (r)
                return r;
 
-       if (!adev->vm_manager.enabled) {
-               r = gmc_v9_0_vm_init(adev);
-               if (r) {
-                       dev_err(adev->dev,
-                               "vm manager initialization failed (%d).\n", r);
-                       return r;
-               }
-               adev->vm_manager.enabled = true;
-       }
+       amdgpu_vm_reset_all_ids(adev);
 
-       return r;
+       return 0;
 }
 
 static bool gmc_v9_0_is_idle(void *handle)
index fb08193599092d0d6562e0c5b4c019b6be45bed2..90332f55cfba91b7a543da4ec3820809bb876336 100644 (file)
@@ -77,13 +77,26 @@ static int vce_v3_0_set_clockgating_state(void *handle,
 static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
+       u32 v;
+
+       mutex_lock(&adev->grbm_idx_mutex);
+       if (adev->vce.harvest_config == 0 ||
+               adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1)
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
+       else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0)
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
 
        if (ring == &adev->vce.ring[0])
-               return RREG32(mmVCE_RB_RPTR);
+               v = RREG32(mmVCE_RB_RPTR);
        else if (ring == &adev->vce.ring[1])
-               return RREG32(mmVCE_RB_RPTR2);
+               v = RREG32(mmVCE_RB_RPTR2);
        else
-               return RREG32(mmVCE_RB_RPTR3);
+               v = RREG32(mmVCE_RB_RPTR3);
+
+       WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
+       mutex_unlock(&adev->grbm_idx_mutex);
+
+       return v;
 }
 
 /**
@@ -96,13 +109,26 @@ static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
 static uint64_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
+       u32 v;
+
+       mutex_lock(&adev->grbm_idx_mutex);
+       if (adev->vce.harvest_config == 0 ||
+               adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1)
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
+       else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0)
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
 
        if (ring == &adev->vce.ring[0])
-               return RREG32(mmVCE_RB_WPTR);
+               v = RREG32(mmVCE_RB_WPTR);
        else if (ring == &adev->vce.ring[1])
-               return RREG32(mmVCE_RB_WPTR2);
+               v = RREG32(mmVCE_RB_WPTR2);
        else
-               return RREG32(mmVCE_RB_WPTR3);
+               v = RREG32(mmVCE_RB_WPTR3);
+
+       WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
+       mutex_unlock(&adev->grbm_idx_mutex);
+
+       return v;
 }
 
 /**
@@ -116,12 +142,22 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
 
+       mutex_lock(&adev->grbm_idx_mutex);
+       if (adev->vce.harvest_config == 0 ||
+               adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1)
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
+       else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0)
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
+
        if (ring == &adev->vce.ring[0])
                WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
        else if (ring == &adev->vce.ring[1])
                WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
        else
                WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr));
+
+       WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
+       mutex_unlock(&adev->grbm_idx_mutex);
 }
 
 static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override)
@@ -231,33 +267,38 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
        struct amdgpu_ring *ring;
        int idx, r;
 
-       ring = &adev->vce.ring[0];
-       WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr));
-       WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
-       WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
-       WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
-       WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
-
-       ring = &adev->vce.ring[1];
-       WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr));
-       WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
-       WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
-       WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
-       WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
-
-       ring = &adev->vce.ring[2];
-       WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr));
-       WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr));
-       WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr);
-       WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr));
-       WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4);
-
        mutex_lock(&adev->grbm_idx_mutex);
        for (idx = 0; idx < 2; ++idx) {
                if (adev->vce.harvest_config & (1 << idx))
                        continue;
 
                WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
+
+               /* Program instance 0 reg space for two instances or instance 0 case
+               program instance 1 reg space for only instance 1 available case */
+               if (idx != 1 || adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) {
+                       ring = &adev->vce.ring[0];
+                       WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr));
+                       WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));
+                       WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
+                       WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
+                       WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);
+
+                       ring = &adev->vce.ring[1];
+                       WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr));
+                       WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));
+                       WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
+                       WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
+                       WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
+
+                       ring = &adev->vce.ring[2];
+                       WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr));
+                       WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr));
+                       WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr);
+                       WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr));
+                       WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4);
+               }
+
                vce_v3_0_mc_resume(adev, idx);
                WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
 
index a74a3db3056c9c4a991e2b4525eb09de8a234a0a..102eb6d029faeb27887215ada8aeccf93d4039b0 100644 (file)
@@ -2655,6 +2655,28 @@ static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr)
        return sizeof(struct smu7_power_state);
 }
 
+static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr,
+                                uint32_t vblank_time_us)
+{
+       struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+       uint32_t switch_limit_us;
+
+       switch (hwmgr->chip_id) {
+       case CHIP_POLARIS10:
+       case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
+               switch_limit_us = data->is_memory_gddr5 ? 190 : 150;
+               break;
+       default:
+               switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
+               break;
+       }
+
+       if (vblank_time_us < switch_limit_us)
+               return true;
+       else
+               return false;
+}
 
 static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
                                struct pp_power_state *request_ps,
@@ -2669,6 +2691,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
        bool disable_mclk_switching;
        bool disable_mclk_switching_for_frame_lock;
        struct cgs_display_info info = {0};
+       struct cgs_mode_info mode_info = {0};
        const struct phm_clock_and_voltage_limits *max_limits;
        uint32_t i;
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -2677,6 +2700,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
        int32_t count;
        int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
 
+       info.mode_info = &mode_info;
        data->battery_state = (PP_StateUILabel_Battery ==
                        request_ps->classification.ui_label);
 
@@ -2703,8 +2727,6 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
 
        cgs_get_active_displays_info(hwmgr->device, &info);
 
-       /*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
-
        minimum_clocks.engineClock = hwmgr->display_config.min_core_set_clock;
        minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock;
 
@@ -2769,8 +2791,10 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
                                    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
 
 
-       disable_mclk_switching = (1 < info.display_count) ||
-                                   disable_mclk_switching_for_frame_lock;
+       disable_mclk_switching = ((1 < info.display_count) ||
+                                 disable_mclk_switching_for_frame_lock ||
+                                 smu7_vblank_too_short(hwmgr, mode_info.vblank_time_us) ||
+                                 (mode_info.refresh_rate > 120));
 
        sclk = smu7_ps->performance_levels[0].engine_clock;
        mclk = smu7_ps->performance_levels[0].memory_clock;
index ad30f5d3a10d5ea2a0118203ff66110a11b0583a..2614af2f553f3007ae25cb70e1f8f322c23a62d6 100644 (file)
@@ -4186,7 +4186,7 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, uint32_t mask)
 {
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
-       uint32_t i;
+       int i;
 
        if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
                return -EINVAL;
index d5f53d04fa08c30a4053aa9fd07b04c795177e4e..83e40fe51b6212f6bbcf44b119c47a86b3fb1638 100644 (file)
@@ -709,17 +709,17 @@ static int tf_vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr,
 
 static struct phm_master_table_item
 vega10_thermal_start_thermal_controller_master_list[] = {
-       {NULL, tf_vega10_thermal_initialize},
-       {NULL, tf_vega10_thermal_set_temperature_range},
-       {NULL, tf_vega10_thermal_enable_alert},
+       { .tableFunction = tf_vega10_thermal_initialize },
+       { .tableFunction = tf_vega10_thermal_set_temperature_range },
+       { .tableFunction = tf_vega10_thermal_enable_alert },
 /* We should restrict performance levels to low before we halt the SMC.
  * On the other hand we are still in boot state when we do this
  * so it would be pointless.
  * If this assumption changes we have to revisit this table.
  */
-       {NULL, tf_vega10_thermal_setup_fan_table},
-       {NULL, tf_vega10_thermal_start_smc_fan_control},
-       {NULL, NULL}
+       { .tableFunction = tf_vega10_thermal_setup_fan_table },
+       { .tableFunction = tf_vega10_thermal_start_smc_fan_control },
+       { }
 };
 
 static struct phm_master_table_header
@@ -731,10 +731,10 @@ vega10_thermal_start_thermal_controller_master = {
 
 static struct phm_master_table_item
 vega10_thermal_set_temperature_range_master_list[] = {
-       {NULL, tf_vega10_thermal_disable_alert},
-       {NULL, tf_vega10_thermal_set_temperature_range},
-       {NULL, tf_vega10_thermal_enable_alert},
-       {NULL, NULL}
+       { .tableFunction = tf_vega10_thermal_disable_alert },
+       { .tableFunction = tf_vega10_thermal_set_temperature_range },
+       { .tableFunction = tf_vega10_thermal_enable_alert },
+       { }
 };
 
 struct phm_master_table_header
index 798a3cc480a2eefc8510417a883dcded6dedc741..1a3359c0f6cd2e80441977114ca55aea85c19cb8 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
@@ -226,16 +227,33 @@ 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;
+       struct drm_rect clip = { 0 };
+       struct drm_crtc_state *crtc_state;
+       u32 src_h = state->src_h >> 16;
 
-       src_w = state->src_w >> 16;
-       src_h = state->src_h >> 16;
+       /* only the HDLCD_REG_FB_LINE_COUNT register has a limit */
+       if (src_h >= HDLCD_MAX_YRES) {
+               DRM_DEBUG_KMS("Invalid source width: %d\n", src_h);
+               return -EINVAL;
+       }
+
+       if (!state->fb || !state->crtc)
+               return 0;
 
-       /* we can't do any scaling of the plane source */
-       if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
+       crtc_state = drm_atomic_get_existing_crtc_state(state->state,
+                                                       state->crtc);
+       if (!crtc_state) {
+               DRM_DEBUG_KMS("Invalid crtc state\n");
                return -EINVAL;
+       }
 
-       return 0;
+       clip.x2 = crtc_state->adjusted_mode.hdisplay;
+       clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+       return drm_plane_helper_check_state(state, &clip,
+                                           DRM_PLANE_HELPER_NO_SCALING,
+                                           DRM_PLANE_HELPER_NO_SCALING,
+                                           false, true);
 }
 
 static void hdlcd_plane_atomic_update(struct drm_plane *plane,
@@ -244,21 +262,20 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
        struct drm_framebuffer *fb = plane->state->fb;
        struct hdlcd_drm_private *hdlcd;
        struct drm_gem_cma_object *gem;
-       u32 src_w, src_h, dest_w, dest_h;
+       u32 src_x, src_y, dest_h;
        dma_addr_t scanout_start;
 
        if (!fb)
                return;
 
-       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;
+       src_x = plane->state->src.x1 >> 16;
+       src_y = plane->state->src.y1 >> 16;
+       dest_h = drm_rect_height(&plane->state->dst);
        gem = drm_fb_cma_get_gem_obj(fb, 0);
+
        scanout_start = gem->paddr + fb->offsets[0] +
-               plane->state->crtc_y * fb->pitches[0] +
-               plane->state->crtc_x *
-               fb->format->cpp[0];
+                       src_y * fb->pitches[0] +
+                       src_x * fb->format->cpp[0];
 
        hdlcd = plane->dev->dev_private;
        hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
@@ -305,7 +322,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
                                       formats, ARRAY_SIZE(formats),
                                       DRM_PLANE_TYPE_PRIMARY, NULL);
        if (ret) {
-               devm_kfree(drm->dev, plane);
                return ERR_PTR(ret);
        }
 
@@ -329,7 +345,6 @@ int hdlcd_setup_crtc(struct drm_device *drm)
                                        &hdlcd_crtc_funcs, NULL);
        if (ret) {
                hdlcd_plane_destroy(primary);
-               devm_kfree(drm->dev, primary);
                return ret;
        }
 
index 65a3bd7a0c00dbf919d46e6d464d8bce8a5ccfd1..423dda2785d44fd2a900a406d7b1d86c3269d970 100644 (file)
@@ -152,8 +152,7 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
-                                      const struct device_node *np)
+static int atmel_hlcdc_attach_endpoint(struct drm_device *dev, int endpoint)
 {
        struct atmel_hlcdc_dc *dc = dev->dev_private;
        struct atmel_hlcdc_rgb_output *output;
@@ -161,6 +160,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
        struct drm_bridge *bridge;
        int ret;
 
+       ret = drm_of_find_panel_or_bridge(dev->dev->of_node, 0, endpoint,
+                                         &panel, &bridge);
+       if (ret)
+               return ret;
+
        output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
        if (!output)
                return -EINVAL;
@@ -177,10 +181,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
 
        output->encoder.possible_crtcs = 0x1;
 
-       ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
-       if (ret)
-               return ret;
-
        if (panel) {
                output->connector.dpms = DRM_MODE_DPMS_OFF;
                output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -220,22 +220,14 @@ err_encoder_cleanup:
 
 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
-       struct device_node *remote;
-       int ret = -ENODEV;
-       int endpoint = 0;
-
-       while (true) {
-               /* Loop thru possible multiple connections to the output */
-               remote = of_graph_get_remote_node(dev->dev->of_node, 0,
-                                                 endpoint++);
-               if (!remote)
-                       break;
-
-               ret = atmel_hlcdc_attach_endpoint(dev, remote);
-               of_node_put(remote);
-               if (ret)
-                       return ret;
-       }
+       int endpoint, ret = 0;
+
+       for (endpoint = 0; !ret; endpoint++)
+               ret = atmel_hlcdc_attach_endpoint(dev, endpoint);
+
+       /* At least one device was successfully attached.*/
+       if (ret == -ENODEV && endpoint)
+               return 0;
 
        return ret;
 }
index 40d2827a6d19846c96d6e06ff84c0fdfc63567d1..53e78d092d18e3b9085d0784772639f8fa01f21c 100644 (file)
@@ -1,6 +1,7 @@
 config DRM_DW_HDMI
        tristate
        select DRM_KMS_HELPER
+       select REGMAP_MMIO
 
 config DRM_DW_HDMI_AHB_AUDIO
        tristate "Synopsys Designware AHB Audio interface"
index 8be9719284b047f3d6046fd6a22c80bb617fa0f7..aa885a614e27c9882ea597456c4b2e16fb25b62b 100644 (file)
@@ -508,6 +508,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                bool has_connectors =
                        !!new_crtc_state->connector_mask;
 
+               WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+
                if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) {
                        DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n",
                                         crtc->base.id, crtc->name);
@@ -551,6 +553,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
        for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {
                const struct drm_connector_helper_funcs *funcs = connector->helper_private;
 
+               WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+
                /*
                 * This only sets crtc->connectors_changed for routing changes,
                 * drivers must set crtc->connectors_changed themselves when
@@ -650,6 +654,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
        for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 
+               WARN_ON(!drm_modeset_is_locked(&plane->mutex));
+
                funcs = plane->helper_private;
 
                drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane);
@@ -2663,7 +2669,12 @@ int drm_atomic_helper_resume(struct drm_device *dev,
 
        drm_modeset_acquire_init(&ctx, 0);
        while (1) {
+               err = drm_modeset_lock_all_ctx(dev, &ctx);
+               if (err)
+                       goto out;
+
                err = drm_atomic_helper_commit_duplicated_state(state, &ctx);
+out:
                if (err != -EDEADLK)
                        break;
 
index 9f847615ac74ab012f6203a141627a5c6f5993e2..48ca2457df8c964977f3f7edae0980bc227b97cf 100644 (file)
@@ -1229,21 +1229,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
        if (!connector)
                return -ENOENT;
 
-       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-       encoder = drm_connector_get_encoder(connector);
-       if (encoder)
-               out_resp->encoder_id = encoder->base.id;
-       else
-               out_resp->encoder_id = 0;
-
-       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
-                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
-                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
-                       &out_resp->count_props);
-       drm_modeset_unlock(&dev->mode_config.connection_mutex);
-       if (ret)
-               goto out_unref;
-
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
                if (connector->encoder_ids[i] != 0)
                        encoders_count++;
@@ -1256,7 +1241,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
                                if (put_user(connector->encoder_ids[i],
                                             encoder_ptr + copied)) {
                                        ret = -EFAULT;
-                                       goto out_unref;
+                                       goto out;
                                }
                                copied++;
                        }
@@ -1300,15 +1285,32 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
                        if (copy_to_user(mode_ptr + copied,
                                         &u_mode, sizeof(u_mode))) {
                                ret = -EFAULT;
+                               mutex_unlock(&dev->mode_config.mutex);
+
                                goto out;
                        }
                        copied++;
                }
        }
        out_resp->count_modes = mode_count;
-out:
        mutex_unlock(&dev->mode_config.mutex);
-out_unref:
+
+       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+       encoder = drm_connector_get_encoder(connector);
+       if (encoder)
+               out_resp->encoder_id = encoder->base.id;
+       else
+               out_resp->encoder_id = 0;
+
+       /* Only grab properties after probing, to make sure EDID and other
+        * properties reflect the latest status. */
+       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
+                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
+                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
+                       &out_resp->count_props);
+       drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+out:
        drm_connector_put(connector);
 
        return ret;
index 3e5f52110ea17384c84f568ba9b1a4955922523c..213fb837e1c40fe79bf536d54b083d99dee1c192 100644 (file)
@@ -1208,3 +1208,86 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux)
        return 0;
 }
 EXPORT_SYMBOL(drm_dp_stop_crc);
+
+struct dpcd_quirk {
+       u8 oui[3];
+       bool is_branch;
+       u32 quirks;
+};
+
+#define OUI(first, second, third) { (first), (second), (third) }
+
+static const struct dpcd_quirk dpcd_quirk_list[] = {
+       /* Analogix 7737 needs reduced M and N at HBR2 link rates */
+       { OUI(0x00, 0x22, 0xb9), true, BIT(DP_DPCD_QUIRK_LIMITED_M_N) },
+};
+
+#undef OUI
+
+/*
+ * Get a bit mask of DPCD quirks for the sink/branch device identified by
+ * ident. The quirk data is shared but it's up to the drivers to act on the
+ * data.
+ *
+ * For now, only the OUI (first three bytes) is used, but this may be extended
+ * to device identification string and hardware/firmware revisions later.
+ */
+static u32
+drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch)
+{
+       const struct dpcd_quirk *quirk;
+       u32 quirks = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dpcd_quirk_list); i++) {
+               quirk = &dpcd_quirk_list[i];
+
+               if (quirk->is_branch != is_branch)
+                       continue;
+
+               if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0)
+                       continue;
+
+               quirks |= quirk->quirks;
+       }
+
+       return quirks;
+}
+
+/**
+ * drm_dp_read_desc - read sink/branch descriptor from DPCD
+ * @aux: DisplayPort AUX channel
+ * @desc: Device decriptor to fill from DPCD
+ * @is_branch: true for branch devices, false for sink devices
+ *
+ * Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the
+ * identification.
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,
+                    bool is_branch)
+{
+       struct drm_dp_dpcd_ident *ident = &desc->ident;
+       unsigned int offset = is_branch ? DP_BRANCH_OUI : DP_SINK_OUI;
+       int ret, dev_id_len;
+
+       ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident));
+       if (ret < 0)
+               return ret;
+
+       desc->quirks = drm_dp_get_quirks(ident, is_branch);
+
+       dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id));
+
+       DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n",
+                     is_branch ? "branch" : "sink",
+                     (int)sizeof(ident->oui), ident->oui,
+                     dev_id_len, ident->device_id,
+                     ident->hw_rev >> 4, ident->hw_rev & 0xf,
+                     ident->sw_major_rev, ident->sw_minor_rev,
+                     desc->quirks);
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_dp_read_desc);
index b5c6bb46a4251bdac218832ba61e52109e5a1768..37b8ad3e30d80440aea9ea2654a7a99696b50a57 100644 (file)
@@ -358,7 +358,12 @@ EXPORT_SYMBOL(drm_put_dev);
 void drm_unplug_dev(struct drm_device *dev)
 {
        /* for a USB device */
-       drm_dev_unregister(dev);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_modeset_unregister_all(dev);
+
+       drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
+       drm_minor_unregister(dev, DRM_MINOR_RENDER);
+       drm_minor_unregister(dev, DRM_MINOR_CONTROL);
 
        mutex_lock(&drm_global_mutex);
 
index fedd4d60d9cd5b2bab64ed8aae1391ea2f402fc5..5dc8c4350602a561fe4cfd77fce77e26770696fb 100644 (file)
@@ -948,8 +948,6 @@ retry:
        }
 
 out:
-       if (ret && crtc->funcs->page_flip_target)
-               drm_crtc_vblank_put(crtc);
        if (fb)
                drm_framebuffer_put(fb);
        if (crtc->primary->old_fb)
@@ -964,5 +962,8 @@ out:
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
 
+       if (ret && crtc->funcs->page_flip_target)
+               drm_crtc_vblank_put(crtc);
+
        return ret;
 }
index c4a091e874269fd9ac79a025f9d37f250ac95520..e437fba1209d925cca7bf7f33b5651c3eeeda21a 100644 (file)
@@ -106,9 +106,10 @@ struct etnaviv_gem_submit {
        struct etnaviv_gpu *gpu;
        struct ww_acquire_ctx ticket;
        struct dma_fence *fence;
+       u32 flags;
        unsigned int nr_bos;
        struct etnaviv_gem_submit_bo bos[0];
-       u32 flags;
+       /* No new members here, the previous one is variable-length! */
 };
 
 int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
index e1909429837eebc2072d00d9a9f590c6e5f87bd2..1013765274da4a4853c21b302dbc646dacba5760 100644 (file)
@@ -44,6 +44,7 @@ static struct etnaviv_gem_submit *submit_create(struct drm_device *dev,
 
                /* initially, until copy_from_user() and bo lookup succeeds: */
                submit->nr_bos = 0;
+               submit->fence = NULL;
 
                ww_acquire_init(&submit->ticket, &reservation_ww_class);
        }
@@ -171,7 +172,7 @@ static int submit_fence_sync(const struct etnaviv_gem_submit *submit)
        for (i = 0; i < submit->nr_bos; i++) {
                struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
                bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE;
-               bool explicit = !(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
+               bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);
 
                ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write,
                                                 explicit);
@@ -294,7 +295,8 @@ static void submit_cleanup(struct etnaviv_gem_submit *submit)
        }
 
        ww_acquire_fini(&submit->ticket);
-       dma_fence_put(submit->fence);
+       if (submit->fence)
+               dma_fence_put(submit->fence);
        kfree(submit);
 }
 
index 09d3c4c3c858e8a05dcf4cbc9a14feb5910ff132..50294a7bd29da10f99e9dca59701b66c385bb66b 100644 (file)
@@ -82,14 +82,9 @@ err_file_priv_free:
        return ret;
 }
 
-static void exynos_drm_preclose(struct drm_device *dev,
-                                       struct drm_file *file)
-{
-       exynos_drm_subdrv_close(dev, file);
-}
-
 static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
 {
+       exynos_drm_subdrv_close(dev, file);
        kfree(file->driver_priv);
        file->driver_priv = NULL;
 }
@@ -145,7 +140,6 @@ static struct drm_driver exynos_drm_driver = {
        .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME
                                  | DRIVER_ATOMIC | DRIVER_RENDER,
        .open                   = exynos_drm_open,
-       .preclose               = exynos_drm_preclose,
        .lastclose              = exynos_drm_lastclose,
        .postclose              = exynos_drm_postclose,
        .gem_free_object_unlocked = exynos_drm_gem_free_object,
index cb317693059696b3c86bda9c93c2e5ebcefad921..39c740572034a6d4f3d69f2ab861b1d0a8f80803 100644 (file)
@@ -160,12 +160,9 @@ struct exynos_drm_clk {
  *     drm framework doesn't support multiple irq yet.
  *     we can refer to the crtc to current hardware interrupt occurred through
  *     this pipe value.
- * @enabled: if the crtc is enabled or not
- * @event: vblank event that is currently queued for flip
- * @wait_update: wait all pending planes updates to finish
- * @pending_update: number of pending plane updates in this crtc
  * @ops: pointer to callbacks for exynos drm specific functionality
  * @ctx: A pointer to the crtc's implementation specific context
+ * @pipe_clk: A pointer to the crtc's pipeline clock.
  */
 struct exynos_drm_crtc {
        struct drm_crtc                 base;
index fc4fda738906251de7a6047c3fc8f3699c469b79..d404de86d5f9de1d5fe07f856fe4a10fafdefd91 100644 (file)
@@ -1633,7 +1633,6 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
 {
        struct device *dev = dsi->dev;
        struct device_node *node = dev->of_node;
-       struct device_node *ep;
        int ret;
 
        ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency",
@@ -1641,32 +1640,21 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
        if (ret < 0)
                return ret;
 
-       ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0);
-       if (!ep) {
-               dev_err(dev, "no output port with endpoint specified\n");
-               return -EINVAL;
-       }
-
-       ret = exynos_dsi_of_read_u32(ep, "samsung,burst-clock-frequency",
+       ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency",
                                     &dsi->burst_clk_rate);
        if (ret < 0)
-               goto end;
+               return ret;
 
-       ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
+       ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency",
                                     &dsi->esc_clk_rate);
        if (ret < 0)
-               goto end;
-
-       of_node_put(ep);
+               return ret;
 
        dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0);
        if (!dsi->bridge_node)
                return -EINVAL;
 
-end:
-       of_node_put(ep);
-
-       return ret;
+       return 0;
 }
 
 static int exynos_dsi_bind(struct device *dev, struct device *master,
@@ -1817,6 +1805,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
 static int exynos_dsi_remove(struct platform_device *pdev)
 {
+       struct exynos_dsi *dsi = platform_get_drvdata(pdev);
+
+       of_node_put(dsi->bridge_node);
+
        pm_runtime_disable(&pdev->dev);
 
        component_del(&pdev->dev, &exynos_dsi_component_ops);
index 0066fe7e622ef75de181cc54770daeb2006a2d24..be3eefec5152aa0cdf9dd891bf4d4fe423ff87d4 100644 (file)
@@ -759,20 +759,23 @@ void psb_intel_lvds_init(struct drm_device *dev,
                if (scan->type & DRM_MODE_TYPE_PREFERRED) {
                        mode_dev->panel_fixed_mode =
                            drm_mode_duplicate(dev, scan);
+                       DRM_DEBUG_KMS("Using mode from DDC\n");
                        goto out;       /* FIXME: check for quirks */
                }
        }
 
        /* Failed to get EDID, what about VBT? do we need this? */
-       if (mode_dev->vbt_mode)
+       if (dev_priv->lfp_lvds_vbt_mode) {
                mode_dev->panel_fixed_mode =
-                   drm_mode_duplicate(dev, mode_dev->vbt_mode);
+                       drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
 
-       if (!mode_dev->panel_fixed_mode)
-               if (dev_priv->lfp_lvds_vbt_mode)
-                       mode_dev->panel_fixed_mode =
-                               drm_mode_duplicate(dev,
-                                       dev_priv->lfp_lvds_vbt_mode);
+               if (mode_dev->panel_fixed_mode) {
+                       mode_dev->panel_fixed_mode->type |=
+                               DRM_MODE_TYPE_PREFERRED;
+                       DRM_DEBUG_KMS("Using mode from VBT\n");
+                       goto out;
+               }
+       }
 
        /*
         * If we didn't get EDID, try checking if the panel is already turned
@@ -789,6 +792,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
                if (mode_dev->panel_fixed_mode) {
                        mode_dev->panel_fixed_mode->type |=
                            DRM_MODE_TYPE_PREFERRED;
+                       DRM_DEBUG_KMS("Using pre-programmed mode\n");
                        goto out;       /* FIXME: check for quirks */
                }
        }
index 5abc69c9630fc28789a32c87b19e44397d1d58ba..f77dcfaade6c5dfb74d7d600d8181d4fbb006f76 100644 (file)
@@ -760,7 +760,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
         * Get the endpoint node. In our case, dsi has one output port1
         * to which the external HDMI bridge is connected.
         */
-       ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge);
+       ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge);
        if (ret)
                return ret;
 
index dca989eb2d42ed48f6c13c15fe9d3f8a9cbfaab2..24fe04d6307b0383da918308827a12027ded9fbe 100644 (file)
@@ -779,8 +779,26 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)
        vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
 }
 
+static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask)
+{
+       struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+       struct intel_engine_cs *engine;
+       struct intel_vgpu_workload *pos, *n;
+       unsigned int tmp;
+
+       /* free the unsubmited workloads in the queues. */
+       for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
+               list_for_each_entry_safe(pos, n,
+                       &vgpu->workload_q_head[engine->id], list) {
+                       list_del_init(&pos->list);
+                       free_workload(pos);
+               }
+       }
+}
+
 void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu)
 {
+       clean_workloads(vgpu, ALL_ENGINES);
        kmem_cache_destroy(vgpu->workloads);
 }
 
@@ -811,17 +829,9 @@ void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
 {
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
        struct intel_engine_cs *engine;
-       struct intel_vgpu_workload *pos, *n;
        unsigned int tmp;
 
-       for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
-               /* free the unsubmited workload in the queue */
-               list_for_each_entry_safe(pos, n,
-                       &vgpu->workload_q_head[engine->id], list) {
-                       list_del_init(&pos->list);
-                       free_workload(pos);
-               }
-
+       clean_workloads(vgpu, engine_mask);
+       for_each_engine_masked(engine, dev_priv, engine_mask, tmp)
                init_vgpu_execlist(vgpu, engine->id);
-       }
 }
index 0ad1a508e2af478dc9fb91df18bdc95304efad44..0ffd696545927277200d8b2332a024168672c5c5 100644 (file)
@@ -1244,7 +1244,7 @@ static int dma_ctrl_write(struct intel_vgpu *vgpu, unsigned int offset,
        mode = vgpu_vreg(vgpu, offset);
 
        if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) {
-               WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n",
+               WARN_ONCE(1, "VM(%d): iGVT-g doesn't support GuC\n",
                                vgpu->id);
                return 0;
        }
@@ -1366,18 +1366,28 @@ static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset,
                void *p_data, unsigned int bytes)
 {
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
-       i915_reg_t reg = {.reg = offset};
+       u32 v = *(u32 *)p_data;
+
+       if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv))
+               return intel_vgpu_default_mmio_write(vgpu,
+                               offset, p_data, bytes);
 
        switch (offset) {
        case 0x4ddc:
-               vgpu_vreg(vgpu, offset) = 0x8000003c;
-               /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl */
-               I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+               /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */
+               vgpu_vreg(vgpu, offset) = v & ~(1 << 31);
                break;
        case 0x42080:
-               vgpu_vreg(vgpu, offset) = 0x8000;
-               /* WaCompressedResourceDisplayNewHashMode:skl */
-               I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+               /* bypass WaCompressedResourceDisplayNewHashMode */
+               vgpu_vreg(vgpu, offset) = v & ~(1 << 15);
+               break;
+       case 0xe194:
+               /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */
+               vgpu_vreg(vgpu, offset) = v & ~(1 << 8);
+               break;
+       case 0x7014:
+               /* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */
+               vgpu_vreg(vgpu, offset) = v & ~(1 << 13);
                break;
        default:
                return -EINVAL;
@@ -1634,7 +1644,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(GAM_ECOCHK, D_ALL, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS,
                NULL, NULL);
-       MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL,
+                skl_misc_ctl_write);
        MMIO_DFH(0x9030, D_ALL, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(0x20a0, D_ALL, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(0x2420, D_ALL, F_CMD_ACCESS, NULL, NULL);
@@ -2568,7 +2579,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_D(0x6e570, D_BDW_PLUS);
        MMIO_D(0x65f10, D_BDW_PLUS);
 
-       MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL,
+                skl_misc_ctl_write);
        MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
index c6e7972ac21da8eda7143619a401554e2575a160..a5e11d89df2f86d13dc546f7b3e1a9e9c8ba7d97 100644 (file)
@@ -340,6 +340,9 @@ void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id)
                } else
                        v = mmio->value;
 
+               if (mmio->in_context)
+                       continue;
+
                I915_WRITE(mmio->reg, v);
                POSTING_READ(mmio->reg);
 
index 79ba4b3440aafd9537f287028d1e23a6186109a1..f25ff133865f1327936483ac166b97c41e0baa60 100644 (file)
@@ -129,9 +129,13 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
        struct vgpu_sched_data *vgpu_data;
        ktime_t cur_time;
 
-       /* no target to schedule */
-       if (!scheduler->next_vgpu)
+       /* no need to schedule if next_vgpu is the same with current_vgpu,
+        * let scheduler chose next_vgpu again by setting it to NULL.
+        */
+       if (scheduler->next_vgpu == scheduler->current_vgpu) {
+               scheduler->next_vgpu = NULL;
                return;
+       }
 
        /*
         * after the flag is set, workload dispatch thread will
index d689e511744e8f2fc9508e2d7345827c6a70bbb2..4bd1467c17b17c6225e27e05ccbde63444012f39 100644 (file)
@@ -292,6 +292,8 @@ static int per_file_stats(int id, void *ptr, void *data)
        struct file_stats *stats = data;
        struct i915_vma *vma;
 
+       lockdep_assert_held(&obj->base.dev->struct_mutex);
+
        stats->count++;
        stats->total += obj->base.size;
        if (!obj->bind_count)
@@ -476,6 +478,8 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
                struct drm_i915_gem_request *request;
                struct task_struct *task;
 
+               mutex_lock(&dev->struct_mutex);
+
                memset(&stats, 0, sizeof(stats));
                stats.file_priv = file->driver_priv;
                spin_lock(&file->table_lock);
@@ -487,7 +491,6 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
                 * still alive (e.g. get_pid(current) => fork() => exit()).
                 * Therefore, we need to protect this ->comm access using RCU.
                 */
-               mutex_lock(&dev->struct_mutex);
                request = list_first_entry_or_null(&file_priv->mm.request_list,
                                                   struct drm_i915_gem_request,
                                                   client_link);
@@ -497,6 +500,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data)
                                PIDTYPE_PID);
                print_file_stats(m, task ? task->comm : "<unknown>", stats);
                rcu_read_unlock();
+
                mutex_unlock(&dev->struct_mutex);
        }
        mutex_unlock(&dev->filelist_mutex);
index 3036d4835b0fa7a3b366a31d0b6ed18fc7889ae1..48428672fc6ece0927416d17a8dde8c41f00f500 100644 (file)
@@ -1235,6 +1235,15 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_fini;
 
        pci_set_drvdata(pdev, &dev_priv->drm);
+       /*
+        * Disable the system suspend direct complete optimization, which can
+        * leave the device suspended skipping the driver's suspend handlers
+        * if the device was already runtime suspended. This is needed due to
+        * the difference in our runtime and system suspend sequence and
+        * becaue the HDA driver may require us to enable the audio power
+        * domain during system suspend.
+        */
+       pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
 
        ret = i915_driver_init_early(dev_priv, ent);
        if (ret < 0)
@@ -1272,10 +1281,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        dev_priv->ipc_enabled = false;
 
-       /* Everything is in place, we can now relax! */
-       DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
-                driver.name, driver.major, driver.minor, driver.patchlevel,
-                driver.date, pci_name(pdev), dev_priv->drm.primary->index);
        if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))
                DRM_INFO("DRM_I915_DEBUG enabled\n");
        if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
index c9b0949f6c1a2aba281c9a4bbf8d8b2c9ede3785..2c453a4e97d5ba28ca3a21da372f73eed0131268 100644 (file)
@@ -562,7 +562,8 @@ struct intel_link_m_n {
 
 void intel_link_compute_m_n(int bpp, int nlanes,
                            int pixel_clock, int link_clock,
-                           struct intel_link_m_n *m_n);
+                           struct intel_link_m_n *m_n,
+                           bool reduce_m_n);
 
 /* Interface history:
  *
@@ -2990,6 +2991,16 @@ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
        return false;
 }
 
+static inline bool
+intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv)
+{
+#ifdef CONFIG_INTEL_IOMMU
+       if (IS_BROXTON(dev_priv) && intel_iommu_gfx_mapped)
+               return true;
+#endif
+       return false;
+}
+
 int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
                                int enable_ppgtt);
 
index b6ac3df18b582534b118ab44aae1dbfe9f75186e..615f0a855222f630d07311c92dce17d3bd371298 100644 (file)
@@ -2285,8 +2285,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
        struct page *page;
        unsigned long last_pfn = 0;     /* suppress gcc warning */
        unsigned int max_segment;
+       gfp_t noreclaim;
        int ret;
-       gfp_t gfp;
 
        /* Assert that the object is not currently in any GPU domain. As it
         * wasn't in the GTT, there shouldn't be any way it could have been in
@@ -2315,22 +2315,31 @@ rebuild_st:
         * Fail silently without starting the shrinker
         */
        mapping = obj->base.filp->f_mapping;
-       gfp = mapping_gfp_constraint(mapping, ~(__GFP_IO | __GFP_RECLAIM));
-       gfp |= __GFP_NORETRY | __GFP_NOWARN;
+       noreclaim = mapping_gfp_constraint(mapping,
+                                          ~(__GFP_IO | __GFP_RECLAIM));
+       noreclaim |= __GFP_NORETRY | __GFP_NOWARN;
+
        sg = st->sgl;
        st->nents = 0;
        for (i = 0; i < page_count; i++) {
-               page = shmem_read_mapping_page_gfp(mapping, i, gfp);
-               if (unlikely(IS_ERR(page))) {
-                       i915_gem_shrink(dev_priv,
-                                       page_count,
-                                       I915_SHRINK_BOUND |
-                                       I915_SHRINK_UNBOUND |
-                                       I915_SHRINK_PURGEABLE);
+               const unsigned int shrink[] = {
+                       I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_PURGEABLE,
+                       0,
+               }, *s = shrink;
+               gfp_t gfp = noreclaim;
+
+               do {
                        page = shmem_read_mapping_page_gfp(mapping, i, gfp);
-               }
-               if (unlikely(IS_ERR(page))) {
-                       gfp_t reclaim;
+                       if (likely(!IS_ERR(page)))
+                               break;
+
+                       if (!*s) {
+                               ret = PTR_ERR(page);
+                               goto err_sg;
+                       }
+
+                       i915_gem_shrink(dev_priv, 2 * page_count, *s++);
+                       cond_resched();
 
                        /* We've tried hard to allocate the memory by reaping
                         * our own buffer, now let the real VM do its job and
@@ -2340,15 +2349,26 @@ rebuild_st:
                         * defer the oom here by reporting the ENOMEM back
                         * to userspace.
                         */
-                       reclaim = mapping_gfp_mask(mapping);
-                       reclaim |= __GFP_NORETRY; /* reclaim, but no oom */
-
-                       page = shmem_read_mapping_page_gfp(mapping, i, reclaim);
-                       if (IS_ERR(page)) {
-                               ret = PTR_ERR(page);
-                               goto err_sg;
+                       if (!*s) {
+                               /* reclaim and warn, but no oom */
+                               gfp = mapping_gfp_mask(mapping);
+
+                               /* Our bo are always dirty and so we require
+                                * kswapd to reclaim our pages (direct reclaim
+                                * does not effectively begin pageout of our
+                                * buffers on its own). However, direct reclaim
+                                * only waits for kswapd when under allocation
+                                * congestion. So as a result __GFP_RECLAIM is
+                                * unreliable and fails to actually reclaim our
+                                * dirty pages -- unless you try over and over
+                                * again with !__GFP_NORETRY. However, we still
+                                * want to fail this allocation rather than
+                                * trigger the out-of-memory killer and for
+                                * this we want the future __GFP_MAYFAIL.
+                                */
                        }
-               }
+               } while (1);
+
                if (!i ||
                    sg->length >= max_segment ||
                    page_to_pfn(page) != last_pfn + 1) {
@@ -3298,6 +3318,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
 {
        int ret;
 
+       /* If the device is asleep, we have no requests outstanding */
+       if (!READ_ONCE(i915->gt.awake))
+               return 0;
+
        if (flags & I915_WAIT_LOCKED) {
                struct i915_gem_timeline *tl;
 
@@ -4218,6 +4242,7 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size)
 
        mapping = obj->base.filp->f_mapping;
        mapping_set_gfp_mask(mapping, mask);
+       GEM_BUG_ON(!(mapping_gfp_mask(mapping) & __GFP_RECLAIM));
 
        i915_gem_object_init(obj, &i915_gem_object_ops);
 
index a3e59c8ef27baf4f3584ff5016635d8005735af6..9ad13eeed904d4d012c3fe93f6124b5ed5884b04 100644 (file)
@@ -546,11 +546,12 @@ repeat:
 }
 
 static int
-i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
+i915_gem_execbuffer_relocate_entry(struct i915_vma *vma,
                                   struct eb_vmas *eb,
                                   struct drm_i915_gem_relocation_entry *reloc,
                                   struct reloc_cache *cache)
 {
+       struct drm_i915_gem_object *obj = vma->obj;
        struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
        struct drm_gem_object *target_obj;
        struct drm_i915_gem_object *target_i915_obj;
@@ -628,6 +629,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
                return -EINVAL;
        }
 
+       /*
+        * If we write into the object, we need to force the synchronisation
+        * barrier, either with an asynchronous clflush or if we executed the
+        * patching using the GPU (though that should be serialised by the
+        * timeline). To be completely sure, and since we are required to
+        * do relocations we are already stalling, disable the user's opt
+        * of our synchronisation.
+        */
+       vma->exec_entry->flags &= ~EXEC_OBJECT_ASYNC;
+
        ret = relocate_entry(obj, reloc, cache, target_offset);
        if (ret)
                return ret;
@@ -678,7 +689,7 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,
                do {
                        u64 offset = r->presumed_offset;
 
-                       ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r, &cache);
+                       ret = i915_gem_execbuffer_relocate_entry(vma, eb, r, &cache);
                        if (ret)
                                goto out;
 
@@ -726,7 +737,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,
 
        reloc_cache_init(&cache, eb->i915);
        for (i = 0; i < entry->relocation_count; i++) {
-               ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i], &cache);
+               ret = i915_gem_execbuffer_relocate_entry(vma, eb, &relocs[i], &cache);
                if (ret)
                        break;
        }
index 2aa6b97fd22f28436b984a6ae9a537f36ada545a..f1989b8792dd6f21ba1a944113b424fb8dc3184d 100644 (file)
@@ -195,9 +195,12 @@ static int ppgtt_bind_vma(struct i915_vma *vma,
        u32 pte_flags;
        int ret;
 
-       ret = vma->vm->allocate_va_range(vma->vm, vma->node.start, vma->size);
-       if (ret)
-               return ret;
+       if (!(vma->flags & I915_VMA_LOCAL_BIND)) {
+               ret = vma->vm->allocate_va_range(vma->vm, vma->node.start,
+                                                vma->size);
+               if (ret)
+                       return ret;
+       }
 
        vma->pages = vma->obj->mm.pages;
 
@@ -2188,6 +2191,101 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
                gen8_set_pte(&gtt_base[i], scratch_pte);
 }
 
+static void bxt_vtd_ggtt_wa(struct i915_address_space *vm)
+{
+       struct drm_i915_private *dev_priv = vm->i915;
+
+       /*
+        * Make sure the internal GAM fifo has been cleared of all GTT
+        * writes before exiting stop_machine(). This guarantees that
+        * any aperture accesses waiting to start in another process
+        * cannot back up behind the GTT writes causing a hang.
+        * The register can be any arbitrary GAM register.
+        */
+       POSTING_READ(GFX_FLSH_CNTL_GEN6);
+}
+
+struct insert_page {
+       struct i915_address_space *vm;
+       dma_addr_t addr;
+       u64 offset;
+       enum i915_cache_level level;
+};
+
+static int bxt_vtd_ggtt_insert_page__cb(void *_arg)
+{
+       struct insert_page *arg = _arg;
+
+       gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset, arg->level, 0);
+       bxt_vtd_ggtt_wa(arg->vm);
+
+       return 0;
+}
+
+static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm,
+                                         dma_addr_t addr,
+                                         u64 offset,
+                                         enum i915_cache_level level,
+                                         u32 unused)
+{
+       struct insert_page arg = { vm, addr, offset, level };
+
+       stop_machine(bxt_vtd_ggtt_insert_page__cb, &arg, NULL);
+}
+
+struct insert_entries {
+       struct i915_address_space *vm;
+       struct sg_table *st;
+       u64 start;
+       enum i915_cache_level level;
+};
+
+static int bxt_vtd_ggtt_insert_entries__cb(void *_arg)
+{
+       struct insert_entries *arg = _arg;
+
+       gen8_ggtt_insert_entries(arg->vm, arg->st, arg->start, arg->level, 0);
+       bxt_vtd_ggtt_wa(arg->vm);
+
+       return 0;
+}
+
+static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm,
+                                            struct sg_table *st,
+                                            u64 start,
+                                            enum i915_cache_level level,
+                                            u32 unused)
+{
+       struct insert_entries arg = { vm, st, start, level };
+
+       stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL);
+}
+
+struct clear_range {
+       struct i915_address_space *vm;
+       u64 start;
+       u64 length;
+};
+
+static int bxt_vtd_ggtt_clear_range__cb(void *_arg)
+{
+       struct clear_range *arg = _arg;
+
+       gen8_ggtt_clear_range(arg->vm, arg->start, arg->length);
+       bxt_vtd_ggtt_wa(arg->vm);
+
+       return 0;
+}
+
+static void bxt_vtd_ggtt_clear_range__BKL(struct i915_address_space *vm,
+                                         u64 start,
+                                         u64 length)
+{
+       struct clear_range arg = { vm, start, length };
+
+       stop_machine(bxt_vtd_ggtt_clear_range__cb, &arg, NULL);
+}
+
 static void gen6_ggtt_clear_range(struct i915_address_space *vm,
                                  u64 start, u64 length)
 {
@@ -2306,10 +2404,11 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
        if (flags & I915_VMA_LOCAL_BIND) {
                struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
 
-               if (appgtt->base.allocate_va_range) {
+               if (!(vma->flags & I915_VMA_LOCAL_BIND) &&
+                   appgtt->base.allocate_va_range) {
                        ret = appgtt->base.allocate_va_range(&appgtt->base,
                                                             vma->node.start,
-                                                            vma->node.size);
+                                                            vma->size);
                        if (ret)
                                goto err_pages;
                }
@@ -2781,6 +2880,14 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
 
        ggtt->base.insert_entries = gen8_ggtt_insert_entries;
 
+       /* Serialize GTT updates with aperture access on BXT if VT-d is on. */
+       if (intel_ggtt_update_needs_vtd_wa(dev_priv)) {
+               ggtt->base.insert_entries = bxt_vtd_ggtt_insert_entries__BKL;
+               ggtt->base.insert_page    = bxt_vtd_ggtt_insert_page__BKL;
+               if (ggtt->base.clear_range != nop_clear_range)
+                       ggtt->base.clear_range = bxt_vtd_ggtt_clear_range__BKL;
+       }
+
        ggtt->invalidate = gen6_ggtt_invalidate;
 
        return ggtt_probe_common(ggtt, size);
@@ -2993,7 +3100,8 @@ void i915_ggtt_enable_guc(struct drm_i915_private *i915)
 
 void i915_ggtt_disable_guc(struct drm_i915_private *i915)
 {
-       i915->ggtt.invalidate = gen6_ggtt_invalidate;
+       if (i915->ggtt.invalidate == guc_ggtt_invalidate)
+               i915->ggtt.invalidate = gen6_ggtt_invalidate;
 }
 
 void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
index 5ddbc94997751adf5c9f04f7dd4a37a74d70de24..a74d0ac737cbeb7f9b9c5e93ea712a396e3c09d5 100644 (file)
@@ -623,7 +623,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
         * GPU processing the request, we never over-estimate the
         * position of the head.
         */
-       req->head = req->ring->tail;
+       req->head = req->ring->emit;
 
        /* Check that we didn't interrupt ourselves with a new request */
        GEM_BUG_ON(req->timeline->seqno != req->fence.seqno);
index 129ed303a6c46e2f856eb1abc84990079abefb65..57d9f7f4ef159cd6eb30f9bc0bd10683eec5123f 100644 (file)
@@ -59,9 +59,6 @@ static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock)
                return;
 
        mutex_unlock(&dev->struct_mutex);
-
-       /* expedite the RCU grace period to free some request slabs */
-       synchronize_rcu_expedited();
 }
 
 static bool any_vma_pinned(struct drm_i915_gem_object *obj)
@@ -274,8 +271,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)
                                I915_SHRINK_ACTIVE);
        intel_runtime_pm_put(dev_priv);
 
-       synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */
-
        return freed;
 }
 
index a0d6d4317a490bba6487891a4048ddef6b358fe4..fb5231f98c0d620f1ccf03a9872607b1373dc0e2 100644 (file)
@@ -278,7 +278,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,
                        obj->mm.quirked = false;
                }
                if (!i915_gem_object_is_tiled(obj)) {
-                       GEM_BUG_ON(!obj->mm.quirked);
+                       GEM_BUG_ON(obj->mm.quirked);
                        __i915_gem_object_pin_pages(obj);
                        obj->mm.quirked = true;
                }
index 1642fff9cf135d5edbe85864d1b327d59002c026..ab5140ba108ddcb2c9c5382cc6439223704f9fda 100644 (file)
@@ -480,9 +480,7 @@ static void guc_wq_item_append(struct i915_guc_client *client,
        GEM_BUG_ON(freespace < wqi_size);
 
        /* The GuC firmware wants the tail index in QWords, not bytes */
-       tail = rq->tail;
-       assert_ring_tail_valid(rq->ring, rq->tail);
-       tail >>= 3;
+       tail = intel_ring_set_tail(rq->ring, rq->tail) >> 3;
        GEM_BUG_ON(tail > WQ_RING_TAIL_MAX);
 
        /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
index fd97fe00cd0d2ad00e1c7258eeb51ecf0f60d4c1..190f6aa5d15eb82bf51cbaed00b16ea8c5d4f5bc 100644 (file)
@@ -2953,7 +2953,6 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
        u32 pipestat_mask;
        u32 enable_mask;
        enum pipe pipe;
-       u32 val;
 
        pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
                        PIPE_CRC_DONE_INTERRUPT_STATUS;
@@ -2964,18 +2963,16 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
 
        enable_mask = I915_DISPLAY_PORT_INTERRUPT |
                I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+               I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
+               I915_LPE_PIPE_A_INTERRUPT |
+               I915_LPE_PIPE_B_INTERRUPT;
+
        if (IS_CHERRYVIEW(dev_priv))
-               enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
+               enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
+                       I915_LPE_PIPE_C_INTERRUPT;
 
        WARN_ON(dev_priv->irq_mask != ~0);
 
-       val = (I915_LPE_PIPE_A_INTERRUPT |
-               I915_LPE_PIPE_B_INTERRUPT |
-               I915_LPE_PIPE_C_INTERRUPT);
-
-       enable_mask |= val;
-
        dev_priv->irq_mask = ~enable_mask;
 
        GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);
index f87b0c4e564d8b85de91e93f7a8d9a6e6f219b61..1a78363c7f4a9e974edbc4e4f31ec7d64d26b6ad 100644 (file)
@@ -208,7 +208,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
 static const struct intel_device_info intel_ironlake_m_info = {
        GEN5_FEATURES,
        .platform = INTEL_IRONLAKE,
-       .is_mobile = 1,
+       .is_mobile = 1, .has_fbc = 1,
 };
 
 #define GEN6_FEATURES \
@@ -390,7 +390,6 @@ static const struct intel_device_info intel_skylake_gt3_info = {
        .has_hw_contexts = 1, \
        .has_logical_ring_contexts = 1, \
        .has_guc = 1, \
-       .has_decoupled_mmio = 1, \
        .has_aliasing_ppgtt = 1, \
        .has_full_ppgtt = 1, \
        .has_full_48bit_ppgtt = 1, \
index c0cb2974caacdb0357b8fcde1a585da51ead7b43..2cfe96d3e5d13e0dd1f6cc689a9af78608007617 100644 (file)
 #define VGT_VERSION_MAJOR 1
 #define VGT_VERSION_MINOR 0
 
-#define INTEL_VGT_IF_VERSION_ENCODE(major, minor) ((major) << 16 | (minor))
-#define INTEL_VGT_IF_VERSION \
-       INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR)
-
 /*
  * notifications from guest to vgpu device model
  */
@@ -55,8 +51,8 @@ enum vgt_g2v_type {
 
 struct vgt_if {
        u64 magic;              /* VGT_MAGIC */
-       uint16_t version_major;
-       uint16_t version_minor;
+       u16 version_major;
+       u16 version_minor;
        u32 vgt_id;             /* ID of vGT instance */
        u32 rsv1[12];           /* pad to offset 0x40 */
        /*
index 11b12f4124920b07a65aaf7e02b81c8784bece46..65b837e96fe629d58f539b253dc1ab14595a459b 100644 (file)
@@ -3051,10 +3051,14 @@ enum skl_disp_power_wells {
 #define CLKCFG_FSB_667                                 (3 << 0)        /* hrawclk 166 */
 #define CLKCFG_FSB_800                                 (2 << 0)        /* hrawclk 200 */
 #define CLKCFG_FSB_1067                                        (6 << 0)        /* hrawclk 266 */
+#define CLKCFG_FSB_1067_ALT                            (0 << 0)        /* hrawclk 266 */
 #define CLKCFG_FSB_1333                                        (7 << 0)        /* hrawclk 333 */
-/* Note, below two are guess */
-#define CLKCFG_FSB_1600                                        (4 << 0)        /* hrawclk 400 */
-#define CLKCFG_FSB_1600_ALT                            (0 << 0)        /* hrawclk 400 */
+/*
+ * Note that on at least on ELK the below value is reported for both
+ * 333 and 400 MHz BIOS FSB setting, but given that the gmch datasheet
+ * lists only 200/266/333 MHz FSB as supported let's decode it as 333 MHz.
+ */
+#define CLKCFG_FSB_1333_ALT                            (4 << 0)        /* hrawclk 333 */
 #define CLKCFG_FSB_MASK                                        (7 << 0)
 #define CLKCFG_MEM_533                                 (1 << 4)
 #define CLKCFG_MEM_667                                 (2 << 4)
@@ -8276,7 +8280,7 @@ enum {
 
 /* MIPI DSI registers */
 
-#define _MIPI_PORT(port, a, c) ((port) ? c : a)        /* ports A and C only */
+#define _MIPI_PORT(port, a, c) (((port) == PORT_A) ? a : c)    /* ports A and C only */
 #define _MMIO_MIPI(port, a, c) _MMIO(_MIPI_PORT(port, a, c))
 
 #define MIPIO_TXESC_CLK_DIV1                   _MMIO(0x160004)
index 4ab8a973b61f155c47ba528d1a907385e22b3b94..2e739018fb4c69581832d49800c5364d02160fb5 100644 (file)
@@ -60,8 +60,8 @@
  */
 void i915_check_vgpu(struct drm_i915_private *dev_priv)
 {
-       uint64_t magic;
-       uint32_t version;
+       u64 magic;
+       u16 version_major;
 
        BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
 
@@ -69,10 +69,8 @@ void i915_check_vgpu(struct drm_i915_private *dev_priv)
        if (magic != VGT_MAGIC)
                return;
 
-       version = INTEL_VGT_IF_VERSION_ENCODE(
-               __raw_i915_read16(dev_priv, vgtif_reg(version_major)),
-               __raw_i915_read16(dev_priv, vgtif_reg(version_minor)));
-       if (version != INTEL_VGT_IF_VERSION) {
+       version_major = __raw_i915_read16(dev_priv, vgtif_reg(version_major));
+       if (version_major < VGT_VERSION_MAJOR) {
                DRM_INFO("VGT interface version mismatch!\n");
                return;
        }
index 1aba47024656817190168984f1d076ceea710e9b..f066e2d785f5c9d30fbe544b3caec698a3b4f8d1 100644 (file)
@@ -650,6 +650,11 @@ int i915_vma_unbind(struct i915_vma *vma)
                                break;
                }
 
+               if (!ret) {
+                       ret = i915_gem_active_retire(&vma->last_fence,
+                                                    &vma->vm->i915->drm.struct_mutex);
+               }
+
                __i915_vma_unpin(vma);
                if (ret)
                        return ret;
index dd3ad52b7dfeac5e7d6f8eb59ee18b372f20a77f..f29a226e24d8836d86c6e976ce07bcfc26a53c28 100644 (file)
@@ -1798,13 +1798,11 @@ static int g4x_hrawclk(struct drm_i915_private *dev_priv)
        case CLKCFG_FSB_800:
                return 200000;
        case CLKCFG_FSB_1067:
+       case CLKCFG_FSB_1067_ALT:
                return 266667;
        case CLKCFG_FSB_1333:
+       case CLKCFG_FSB_1333_ALT:
                return 333333;
-       /* these two are just a guess; one of them might be right */
-       case CLKCFG_FSB_1600:
-       case CLKCFG_FSB_1600_ALT:
-               return 400000;
        default:
                return 133333;
        }
index 3617927af269afb9872b0d5d419873f0945f880c..9106ea32b048cac4783ae316d7cc198a4bf8ae88 100644 (file)
@@ -120,7 +120,8 @@ static void intel_crtc_init_scalers(struct intel_crtc *crtc,
 static void skylake_pfit_enable(struct intel_crtc *crtc);
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
-static void intel_modeset_setup_hw_state(struct drm_device *dev);
+static void intel_modeset_setup_hw_state(struct drm_device *dev,
+                                        struct drm_modeset_acquire_ctx *ctx);
 static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
 
 struct intel_limit {
@@ -3449,7 +3450,7 @@ __intel_display_resume(struct drm_device *dev,
        struct drm_crtc *crtc;
        int i, ret;
 
-       intel_modeset_setup_hw_state(dev);
+       intel_modeset_setup_hw_state(dev, ctx);
        i915_redisable_vga(to_i915(dev));
 
        if (!state)
@@ -4598,7 +4599,7 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
 
 static int
 skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
-                 unsigned scaler_user, int *scaler_id, unsigned int rotation,
+                 unsigned int scaler_user, int *scaler_id,
                  int src_w, int src_h, int dst_w, int dst_h)
 {
        struct intel_crtc_scaler_state *scaler_state =
@@ -4607,9 +4608,12 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
                to_intel_crtc(crtc_state->base.crtc);
        int need_scaling;
 
-       need_scaling = drm_rotation_90_or_270(rotation) ?
-               (src_h != dst_w || src_w != dst_h):
-               (src_w != dst_w || src_h != dst_h);
+       /*
+        * Src coordinates are already rotated by 270 degrees for
+        * the 90/270 degree plane rotation cases (to match the
+        * GTT mapping), hence no need to account for rotation here.
+        */
+       need_scaling = src_w != dst_w || src_h != dst_h;
 
        /*
         * if plane is being disabled or scaler is no more required or force detach
@@ -4671,7 +4675,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
        const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
 
        return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
-               &state->scaler_state.scaler_id, DRM_ROTATE_0,
+               &state->scaler_state.scaler_id,
                state->pipe_src_w, state->pipe_src_h,
                adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
 }
@@ -4700,7 +4704,6 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
        ret = skl_update_scaler(crtc_state, force_detach,
                                drm_plane_index(&intel_plane->base),
                                &plane_state->scaler_id,
-                               plane_state->base.rotation,
                                drm_rect_width(&plane_state->base.src) >> 16,
                                drm_rect_height(&plane_state->base.src) >> 16,
                                drm_rect_width(&plane_state->base.dst),
@@ -5823,7 +5826,8 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
                intel_update_watermarks(intel_crtc);
 }
 
-static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
+static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
+                                       struct drm_modeset_acquire_ctx *ctx)
 {
        struct intel_encoder *encoder;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -5853,7 +5857,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
                return;
        }
 
-       state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
+       state->acquire_ctx = ctx;
 
        /* Everything's already locked, -EDEADLK can't happen. */
        crtc_state = intel_atomic_get_crtc_state(state, intel_crtc);
@@ -6101,7 +6105,7 @@ retry:
        pipe_config->fdi_lanes = lane;
 
        intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
-                              link_bw, &pipe_config->fdi_m_n);
+                              link_bw, &pipe_config->fdi_m_n, false);
 
        ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
        if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
@@ -6277,7 +6281,8 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)
 }
 
 static void compute_m_n(unsigned int m, unsigned int n,
-                       uint32_t *ret_m, uint32_t *ret_n)
+                       uint32_t *ret_m, uint32_t *ret_n,
+                       bool reduce_m_n)
 {
        /*
         * Reduce M/N as much as possible without loss in precision. Several DP
@@ -6285,9 +6290,11 @@ static void compute_m_n(unsigned int m, unsigned int n,
         * values. The passed in values are more likely to have the least
         * significant bits zero than M after rounding below, so do this first.
         */
-       while ((m & 1) == 0 && (n & 1) == 0) {
-               m >>= 1;
-               n >>= 1;
+       if (reduce_m_n) {
+               while ((m & 1) == 0 && (n & 1) == 0) {
+                       m >>= 1;
+                       n >>= 1;
+               }
        }
 
        *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
@@ -6298,16 +6305,19 @@ static void compute_m_n(unsigned int m, unsigned int n,
 void
 intel_link_compute_m_n(int bits_per_pixel, int nlanes,
                       int pixel_clock, int link_clock,
-                      struct intel_link_m_n *m_n)
+                      struct intel_link_m_n *m_n,
+                      bool reduce_m_n)
 {
        m_n->tu = 64;
 
        compute_m_n(bits_per_pixel * pixel_clock,
                    link_clock * nlanes * 8,
-                   &m_n->gmch_m, &m_n->gmch_n);
+                   &m_n->gmch_m, &m_n->gmch_n,
+                   reduce_m_n);
 
        compute_m_n(pixel_clock, link_clock,
-                   &m_n->link_m, &m_n->link_n);
+                   &m_n->link_m, &m_n->link_n,
+                   reduce_m_n);
 }
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
@@ -12197,6 +12207,15 @@ static void update_scanline_offset(struct intel_crtc *crtc)
         * type. For DP ports it behaves like most other platforms, but on HDMI
         * there's an extra 1 line difference. So we need to add two instead of
         * one to the value.
+        *
+        * On VLV/CHV DSI the scanline counter would appear to increment
+        * approx. 1/3 of a scanline before start of vblank. Unfortunately
+        * that means we can't tell whether we're in vblank or not while
+        * we're on that particular line. We must still set scanline_offset
+        * to 1 so that the vblank timestamps come out correct when we query
+        * the scanline counter from within the vblank interrupt handler.
+        * However if queried just before the start of vblank we'll get an
+        * answer that's slightly in the future.
         */
        if (IS_GEN2(dev_priv)) {
                const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
@@ -15013,7 +15032,7 @@ int intel_modeset_init(struct drm_device *dev)
        intel_setup_outputs(dev_priv);
 
        drm_modeset_lock_all(dev);
-       intel_modeset_setup_hw_state(dev);
+       intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx);
        drm_modeset_unlock_all(dev);
 
        for_each_intel_crtc(dev, crtc) {
@@ -15050,13 +15069,13 @@ int intel_modeset_init(struct drm_device *dev)
        return 0;
 }
 
-static void intel_enable_pipe_a(struct drm_device *dev)
+static void intel_enable_pipe_a(struct drm_device *dev,
+                               struct drm_modeset_acquire_ctx *ctx)
 {
        struct intel_connector *connector;
        struct drm_connector_list_iter conn_iter;
        struct drm_connector *crt = NULL;
        struct intel_load_detect_pipe load_detect_temp;
-       struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;
        int ret;
 
        /* We can't just switch on the pipe A, we need to set things up with a
@@ -15128,7 +15147,8 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv,
                (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == TRANSCODER_A);
 }
 
-static void intel_sanitize_crtc(struct intel_crtc *crtc)
+static void intel_sanitize_crtc(struct intel_crtc *crtc,
+                               struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -15174,7 +15194,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                plane = crtc->plane;
                crtc->base.primary->state->visible = true;
                crtc->plane = !plane;
-               intel_crtc_disable_noatomic(&crtc->base);
+               intel_crtc_disable_noatomic(&crtc->base, ctx);
                crtc->plane = plane;
        }
 
@@ -15184,13 +15204,13 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                 * resume. Force-enable the pipe to fix this, the update_dpms
                 * call below we restore the pipe to the right state, but leave
                 * the required bits on. */
-               intel_enable_pipe_a(dev);
+               intel_enable_pipe_a(dev, ctx);
        }
 
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
        if (crtc->active && !intel_crtc_has_encoders(crtc))
-               intel_crtc_disable_noatomic(&crtc->base);
+               intel_crtc_disable_noatomic(&crtc->base, ctx);
 
        if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) {
                /*
@@ -15488,7 +15508,8 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
  * and sanitizes it to the current state
  */
 static void
-intel_modeset_setup_hw_state(struct drm_device *dev)
+intel_modeset_setup_hw_state(struct drm_device *dev,
+                            struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        enum pipe pipe;
@@ -15508,7 +15529,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)
        for_each_pipe(dev_priv, pipe) {
                crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
-               intel_sanitize_crtc(crtc);
+               intel_sanitize_crtc(crtc, ctx);
                intel_dump_pipe_config(crtc, crtc->config,
                                       "[setup_hw_state]");
        }
index ee77b519835c5fd9d8c582a9c3169b43d06ebab6..fc691b8b317cf3924a98adfb51ca1183a6f2a6b3 100644 (file)
@@ -1507,37 +1507,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
        DRM_DEBUG_KMS("common rates: %s\n", str);
 }
 
-bool
-__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc)
-{
-       u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI :
-                                                     DP_SINK_OUI;
-
-       return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) ==
-              sizeof(*desc);
-}
-
-bool intel_dp_read_desc(struct intel_dp *intel_dp)
-{
-       struct intel_dp_desc *desc = &intel_dp->desc;
-       bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] &
-                      DP_OUI_SUPPORT;
-       int dev_id_len;
-
-       if (!__intel_dp_read_desc(intel_dp, desc))
-               return false;
-
-       dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id));
-       DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n",
-                     drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink",
-                     (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)",
-                     dev_id_len, desc->device_id,
-                     desc->hw_rev >> 4, desc->hw_rev & 0xf,
-                     desc->sw_major_rev, desc->sw_minor_rev);
-
-       return true;
-}
-
 static int rate_to_index(int find, const int *rates)
 {
        int i = 0;
@@ -1624,6 +1593,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        int common_rates[DP_MAX_SUPPORTED_RATES] = {};
        int common_len;
        uint8_t link_bw, rate_select;
+       bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
+                                          DP_DPCD_QUIRK_LIMITED_M_N);
 
        common_len = intel_dp_common_rates(intel_dp, common_rates);
 
@@ -1753,7 +1724,8 @@ found:
        intel_link_compute_m_n(bpp, lane_count,
                               adjusted_mode->crtc_clock,
                               pipe_config->port_clock,
-                              &pipe_config->dp_m_n);
+                              &pipe_config->dp_m_n,
+                              reduce_m_n);
 
        if (intel_connector->panel.downclock_mode != NULL &&
                dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) {
@@ -1761,7 +1733,8 @@ found:
                        intel_link_compute_m_n(bpp, lane_count,
                                intel_connector->panel.downclock_mode->clock,
                                pipe_config->port_clock,
-                               &pipe_config->dp_m2_n2);
+                               &pipe_config->dp_m2_n2,
+                               reduce_m_n);
        }
 
        /*
@@ -3622,7 +3595,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
        if (!intel_dp_read_dpcd(intel_dp))
                return false;
 
-       intel_dp_read_desc(intel_dp);
+       drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
+                        drm_dp_is_branch(intel_dp->dpcd));
 
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
                dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
@@ -4624,7 +4598,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 
        intel_dp_print_rates(intel_dp);
 
-       intel_dp_read_desc(intel_dp);
+       drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc,
+                        drm_dp_is_branch(intel_dp->dpcd));
 
        intel_dp_configure_mst(intel_dp);
 
index 6532e226db29b63da766a8571de231de4f7261f6..40ba3134545ef7e339c5bfe347501eeb7715dac0 100644 (file)
@@ -119,8 +119,6 @@ static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
        struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
        struct intel_panel *panel = &connector->panel;
 
-       intel_dp_aux_enable_backlight(connector);
-
        if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
                panel->backlight.max = 0xFFFF;
        else
index c1f62eb07c07a7ce49b3ed39e1e6ee2b23eb65e8..989e25577ac0445f9e7632a575a6de38d7f9ec49 100644 (file)
@@ -44,6 +44,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
        int lane_count, slots;
        const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
        int mst_pbn;
+       bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
+                                          DP_DPCD_QUIRK_LIMITED_M_N);
 
        pipe_config->has_pch_encoder = false;
        bpp = 24;
@@ -75,7 +77,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
        intel_link_compute_m_n(bpp, lane_count,
                               adjusted_mode->crtc_clock,
                               pipe_config->port_clock,
-                              &pipe_config->dp_m_n);
+                              &pipe_config->dp_m_n,
+                              reduce_m_n);
 
        pipe_config->dp_m_n.tu = slots;
 
index aaee3949a42267603a5dfa9deb9be87dd0f7b2b4..f630c7af50205540b64481d9c3ee559fbdfc8f7f 100644 (file)
@@ -906,14 +906,6 @@ enum link_m_n_set {
        M2_N2
 };
 
-struct intel_dp_desc {
-       u8 oui[3];
-       u8 device_id[6];
-       u8 hw_rev;
-       u8 sw_major_rev;
-       u8 sw_minor_rev;
-} __packed;
-
 struct intel_dp_compliance_data {
        unsigned long edid;
        uint8_t video_pattern;
@@ -957,7 +949,7 @@ struct intel_dp {
        /* Max link BW for the sink as per DPCD registers */
        int max_sink_link_bw;
        /* sink or branch descriptor */
-       struct intel_dp_desc desc;
+       struct drm_dp_desc desc;
        struct drm_dp_aux aux;
        enum intel_display_power_domain aux_power_domain;
        uint8_t train_set[4];
@@ -1532,9 +1524,6 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
 }
 
 bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
-bool __intel_dp_read_desc(struct intel_dp *intel_dp,
-                         struct intel_dp_desc *desc);
-bool intel_dp_read_desc(struct intel_dp *intel_dp);
 int intel_dp_link_required(int pixel_clock, int bpp);
 int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
 bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
index 3ffe8b1f1d486f5e7352f50a62091cbb60831c83..fc0ef492252ac7c93f7b7ccb4e6a4b95d30f6294 100644 (file)
@@ -410,11 +410,10 @@ static void glk_dsi_device_ready(struct intel_encoder *encoder)
                val |= (ULPS_STATE_ENTER | DEVICE_READY);
                I915_WRITE(MIPI_DEVICE_READY(port), val);
 
-               /* Wait for ULPS Not active */
+               /* Wait for ULPS active */
                if (intel_wait_for_register(dev_priv,
-                               MIPI_CTRL(port), GLK_ULPS_NOT_ACTIVE,
-                               GLK_ULPS_NOT_ACTIVE, 20))
-                       DRM_ERROR("ULPS is still active\n");
+                               MIPI_CTRL(port), GLK_ULPS_NOT_ACTIVE, 0, 20))
+                       DRM_ERROR("ULPS not active\n");
 
                /* Exit ULPS */
                val = I915_READ(MIPI_DEVICE_READY(port));
index 854e8e0c836bd2099c1cfcb72e12e3ec5ff21915..f94eacff196c5d0980690ae95cda45c42e3a4e9b 100644 (file)
@@ -1075,6 +1075,22 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
        return 0;
 }
 
+static bool ring_is_idle(struct intel_engine_cs *engine)
+{
+       struct drm_i915_private *dev_priv = engine->i915;
+       bool idle = true;
+
+       intel_runtime_pm_get(dev_priv);
+
+       /* No bit for gen2, so assume the CS parser is idle */
+       if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
+               idle = false;
+
+       intel_runtime_pm_put(dev_priv);
+
+       return idle;
+}
+
 /**
  * intel_engine_is_idle() - Report if the engine has finished process all work
  * @engine: the intel_engine_cs
@@ -1084,8 +1100,6 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
  */
 bool intel_engine_is_idle(struct intel_engine_cs *engine)
 {
-       struct drm_i915_private *dev_priv = engine->i915;
-
        /* Any inflight/incomplete requests? */
        if (!i915_seqno_passed(intel_engine_get_seqno(engine),
                               intel_engine_last_submit(engine)))
@@ -1100,7 +1114,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)
                return false;
 
        /* Ring stopped? */
-       if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
+       if (!ring_is_idle(engine))
                return false;
 
        return true;
index ded2add18b26122d7f6395d0d5532da26dd21f34..d93c58410bffe9701d148e546db753dff84c4083 100644 (file)
@@ -82,20 +82,10 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)
 static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache,
                                            int *width, int *height)
 {
-       int w, h;
-
-       if (drm_rotation_90_or_270(cache->plane.rotation)) {
-               w = cache->plane.src_h;
-               h = cache->plane.src_w;
-       } else {
-               w = cache->plane.src_w;
-               h = cache->plane.src_h;
-       }
-
        if (width)
-               *width = w;
+               *width = cache->plane.src_w;
        if (height)
-               *height = h;
+               *height = cache->plane.src_h;
 }
 
 static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
@@ -746,6 +736,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
                cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate;
 
        cache->plane.rotation = plane_state->base.rotation;
+       /*
+        * Src coordinates are already rotated by 270 degrees for
+        * the 90/270 degree plane rotation cases (to match the
+        * GTT mapping), hence no need to account for rotation here.
+        */
        cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;
        cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16;
        cache->plane.visible = plane_state->base.visible;
index 25d8e76489e40ff989fd616386f03b36f9ba03fa..292fedf30b0010c33e1eefd8f643b1b87bd38edd 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/acpi.h>
 #include <linux/device.h>
 #include <linux/pci.h>
+#include <linux/pm_runtime.h>
 
 #include "i915_drv.h"
 #include <linux/delay.h>
@@ -121,6 +122,10 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
 
        kfree(rsc);
 
+       pm_runtime_forbid(&platdev->dev);
+       pm_runtime_set_active(&platdev->dev);
+       pm_runtime_enable(&platdev->dev);
+
        return platdev;
 
 err:
@@ -144,44 +149,10 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)
 
 static void lpe_audio_irq_unmask(struct irq_data *d)
 {
-       struct drm_i915_private *dev_priv = d->chip_data;
-       unsigned long irqflags;
-       u32 val = (I915_LPE_PIPE_A_INTERRUPT |
-               I915_LPE_PIPE_B_INTERRUPT);
-
-       if (IS_CHERRYVIEW(dev_priv))
-               val |= I915_LPE_PIPE_C_INTERRUPT;
-
-       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-
-       dev_priv->irq_mask &= ~val;
-       I915_WRITE(VLV_IIR, val);
-       I915_WRITE(VLV_IIR, val);
-       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-       POSTING_READ(VLV_IMR);
-
-       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
 static void lpe_audio_irq_mask(struct irq_data *d)
 {
-       struct drm_i915_private *dev_priv = d->chip_data;
-       unsigned long irqflags;
-       u32 val = (I915_LPE_PIPE_A_INTERRUPT |
-               I915_LPE_PIPE_B_INTERRUPT);
-
-       if (IS_CHERRYVIEW(dev_priv))
-               val |= I915_LPE_PIPE_C_INTERRUPT;
-
-       spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-
-       dev_priv->irq_mask |= val;
-       I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-       I915_WRITE(VLV_IIR, val);
-       I915_WRITE(VLV_IIR, val);
-       POSTING_READ(VLV_IIR);
-
-       spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
 static struct irq_chip lpe_audio_irqchip = {
@@ -325,8 +296,6 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)
 
        desc = irq_to_desc(dev_priv->lpe_audio.irq);
 
-       lpe_audio_irq_mask(&desc->irq_data);
-
        lpe_audio_platdev_destroy(dev_priv);
 
        irq_free_desc(dev_priv->lpe_audio.irq);
index c8f7c631fc1f8e354cac0038c80aa35d0a1dd0d2..62f44d3e7c43c0d90df093050d5af6d3d68fe3a3 100644 (file)
@@ -326,8 +326,7 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq)
                rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt;
        u32 *reg_state = ce->lrc_reg_state;
 
-       assert_ring_tail_valid(rq->ring, rq->tail);
-       reg_state[CTX_RING_TAIL+1] = rq->tail;
+       reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);
 
        /* True 32b PPGTT with dynamic page allocation: update PDP
         * registers and point the unallocated PDPs to scratch page.
@@ -1989,7 +1988,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
 
        ce->ring = ring;
        ce->state = vma;
-       ce->initialised = engine->init_context == NULL;
+       ce->initialised |= engine->init_context == NULL;
 
        return 0;
 
@@ -2036,8 +2035,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv)
                        ce->state->obj->mm.dirty = true;
                        i915_gem_object_unpin_map(ce->state->obj);
 
-                       ce->ring->head = ce->ring->tail = 0;
-                       intel_ring_update_space(ce->ring);
+                       intel_ring_reset(ce->ring, 0);
                }
        }
 }
index 71cbe9c089320cbc305c827bacd41fcbf1e542ce..5abef482eacf1b24780edea4c40ab7e593a42dc6 100644 (file)
@@ -240,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
                return false;
        }
 
-       intel_dp_read_desc(dp);
+       drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
 
        DRM_DEBUG_KMS("Success: LSPCON init\n");
        return true;
index 570bd603f401d513ac3f08c67fc78d6d1523b762..078fd1bfa5ea8aaa47cd552a8b37766394e76d01 100644 (file)
@@ -3373,20 +3373,26 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate,
 
        /* n.b., src is 16.16 fixed point, dst is whole integer */
        if (plane->id == PLANE_CURSOR) {
+               /*
+                * Cursors only support 0/180 degree rotation,
+                * hence no need to account for rotation here.
+                */
                src_w = pstate->base.src_w;
                src_h = pstate->base.src_h;
                dst_w = pstate->base.crtc_w;
                dst_h = pstate->base.crtc_h;
        } else {
+               /*
+                * Src coordinates are already rotated by 270 degrees for
+                * the 90/270 degree plane rotation cases (to match the
+                * GTT mapping), hence no need to account for rotation here.
+                */
                src_w = drm_rect_width(&pstate->base.src);
                src_h = drm_rect_height(&pstate->base.src);
                dst_w = drm_rect_width(&pstate->base.dst);
                dst_h = drm_rect_height(&pstate->base.dst);
        }
 
-       if (drm_rotation_90_or_270(pstate->base.rotation))
-               swap(dst_w, dst_h);
-
        downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
        downscale_w = max(src_w / dst_w, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
 
@@ -3417,12 +3423,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
        if (y && format != DRM_FORMAT_NV12)
                return 0;
 
+       /*
+        * Src coordinates are already rotated by 270 degrees for
+        * the 90/270 degree plane rotation cases (to match the
+        * GTT mapping), hence no need to account for rotation here.
+        */
        width = drm_rect_width(&intel_pstate->base.src) >> 16;
        height = drm_rect_height(&intel_pstate->base.src) >> 16;
 
-       if (drm_rotation_90_or_270(pstate->rotation))
-               swap(width, height);
-
        /* for planar format */
        if (format == DRM_FORMAT_NV12) {
                if (y)  /* y-plane data rate */
@@ -3505,12 +3513,14 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,
            fb->modifier != I915_FORMAT_MOD_Yf_TILED)
                return 8;
 
+       /*
+        * Src coordinates are already rotated by 270 degrees for
+        * the 90/270 degree plane rotation cases (to match the
+        * GTT mapping), hence no need to account for rotation here.
+        */
        src_w = drm_rect_width(&intel_pstate->base.src) >> 16;
        src_h = drm_rect_height(&intel_pstate->base.src) >> 16;
 
-       if (drm_rotation_90_or_270(pstate->rotation))
-               swap(src_w, src_h);
-
        /* Halve UV plane width and height for NV12 */
        if (fb->format->format == DRM_FORMAT_NV12 && !y) {
                src_w /= 2;
@@ -3794,13 +3804,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
                width = intel_pstate->base.crtc_w;
                height = intel_pstate->base.crtc_h;
        } else {
+               /*
+                * Src coordinates are already rotated by 270 degrees for
+                * the 90/270 degree plane rotation cases (to match the
+                * GTT mapping), hence no need to account for rotation here.
+                */
                width = drm_rect_width(&intel_pstate->base.src) >> 16;
                height = drm_rect_height(&intel_pstate->base.src) >> 16;
        }
 
-       if (drm_rotation_90_or_270(pstate->rotation))
-               swap(width, height);
-
        cpp = fb->format->cpp[0];
        plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate);
 
@@ -4335,10 +4347,18 @@ skl_compute_wm(struct drm_atomic_state *state)
        struct drm_crtc_state *cstate;
        struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        struct skl_wm_values *results = &intel_state->wm_results;
+       struct drm_device *dev = state->dev;
        struct skl_pipe_wm *pipe_wm;
        bool changed = false;
        int ret, i;
 
+       /*
+        * When we distrust bios wm we always need to recompute to set the
+        * expected DDB allocations for each CRTC.
+        */
+       if (to_i915(dev)->wm.distrust_bios_wm)
+               changed = true;
+
        /*
         * If this transaction isn't actually touching any CRTC's, don't
         * bother with watermark calculation.  Note that if we pass this
@@ -4349,6 +4369,7 @@ skl_compute_wm(struct drm_atomic_state *state)
         */
        for_each_new_crtc_in_state(state, crtc, cstate, i)
                changed = true;
+
        if (!changed)
                return 0;
 
index c3780d0d2baf752ce9d590b6f6c8db67674ec745..559f1ab42bfc23e005020d9bb3cb88e0f0d57943 100644 (file)
@@ -435,8 +435,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
        }
 
        /* PSR2 is restricted to work with panel resolutions upto 3200x2000 */
-       if (intel_crtc->config->pipe_src_w > 3200 ||
-                               intel_crtc->config->pipe_src_h > 2000) {
+       if (dev_priv->psr.psr2_support &&
+           (intel_crtc->config->pipe_src_w > 3200 ||
+            intel_crtc->config->pipe_src_h > 2000)) {
                dev_priv->psr.psr2_support = false;
                return false;
        }
index 66a2b8b83972691d04f2737337e7ea6cf6a72851..513a0f4b469b32c9d0ac2e87c089bb6f2e4907ba 100644 (file)
@@ -49,7 +49,7 @@ static int __intel_ring_space(int head, int tail, int size)
 
 void intel_ring_update_space(struct intel_ring *ring)
 {
-       ring->space = __intel_ring_space(ring->head, ring->tail, ring->size);
+       ring->space = __intel_ring_space(ring->head, ring->emit, ring->size);
 }
 
 static int
@@ -774,8 +774,8 @@ static void i9xx_submit_request(struct drm_i915_gem_request *request)
 
        i915_gem_request_submit(request);
 
-       assert_ring_tail_valid(request->ring, request->tail);
-       I915_WRITE_TAIL(request->engine, request->tail);
+       I915_WRITE_TAIL(request->engine,
+                       intel_ring_set_tail(request->ring, request->tail));
 }
 
 static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs)
@@ -1316,11 +1316,23 @@ err:
        return PTR_ERR(addr);
 }
 
+void intel_ring_reset(struct intel_ring *ring, u32 tail)
+{
+       GEM_BUG_ON(!list_empty(&ring->request_list));
+       ring->tail = tail;
+       ring->head = tail;
+       ring->emit = tail;
+       intel_ring_update_space(ring);
+}
+
 void intel_ring_unpin(struct intel_ring *ring)
 {
        GEM_BUG_ON(!ring->vma);
        GEM_BUG_ON(!ring->vaddr);
 
+       /* Discard any unused bytes beyond that submitted to hw. */
+       intel_ring_reset(ring, ring->tail);
+
        if (i915_vma_is_map_and_fenceable(ring->vma))
                i915_vma_unpin_iomap(ring->vma);
        else
@@ -1562,8 +1574,9 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
 
+       /* Restart from the beginning of the rings for convenience */
        for_each_engine(engine, dev_priv, id)
-               engine->buffer->head = engine->buffer->tail;
+               intel_ring_reset(engine->buffer, 0);
 }
 
 static int ring_request_alloc(struct drm_i915_gem_request *request)
@@ -1616,7 +1629,7 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
                unsigned space;
 
                /* Would completion of this request free enough space? */
-               space = __intel_ring_space(target->postfix, ring->tail,
+               space = __intel_ring_space(target->postfix, ring->emit,
                                           ring->size);
                if (space >= bytes)
                        break;
@@ -1641,8 +1654,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
 u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
 {
        struct intel_ring *ring = req->ring;
-       int remain_actual = ring->size - ring->tail;
-       int remain_usable = ring->effective_size - ring->tail;
+       int remain_actual = ring->size - ring->emit;
+       int remain_usable = ring->effective_size - ring->emit;
        int bytes = num_dwords * sizeof(u32);
        int total_bytes, wait_bytes;
        bool need_wrap = false;
@@ -1678,17 +1691,17 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
 
        if (unlikely(need_wrap)) {
                GEM_BUG_ON(remain_actual > ring->space);
-               GEM_BUG_ON(ring->tail + remain_actual > ring->size);
+               GEM_BUG_ON(ring->emit + remain_actual > ring->size);
 
                /* Fill the tail with MI_NOOP */
-               memset(ring->vaddr + ring->tail, 0, remain_actual);
-               ring->tail = 0;
+               memset(ring->vaddr + ring->emit, 0, remain_actual);
+               ring->emit = 0;
                ring->space -= remain_actual;
        }
 
-       GEM_BUG_ON(ring->tail > ring->size - bytes);
-       cs = ring->vaddr + ring->tail;
-       ring->tail += bytes;
+       GEM_BUG_ON(ring->emit > ring->size - bytes);
+       cs = ring->vaddr + ring->emit;
+       ring->emit += bytes;
        ring->space -= bytes;
        GEM_BUG_ON(ring->space < 0);
 
@@ -1699,7 +1712,7 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
 int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
 {
        int num_dwords =
-               (req->ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
+               (req->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
        u32 *cs;
 
        if (num_dwords == 0)
index a82a0807f64dbd0624728fe3c65215abe3647565..f7144fe0961347826c62e620af879bb4db9f0d77 100644 (file)
@@ -145,6 +145,7 @@ struct intel_ring {
 
        u32 head;
        u32 tail;
+       u32 emit;
 
        int space;
        int size;
@@ -488,6 +489,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
 struct intel_ring *
 intel_engine_create_ring(struct intel_engine_cs *engine, int size);
 int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias);
+void intel_ring_reset(struct intel_ring *ring, u32 tail);
+void intel_ring_update_space(struct intel_ring *ring);
 void intel_ring_unpin(struct intel_ring *ring);
 void intel_ring_free(struct intel_ring *ring);
 
@@ -511,7 +514,7 @@ intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs)
         * reserved for the command packet (i.e. the value passed to
         * intel_ring_begin()).
         */
-       GEM_BUG_ON((req->ring->vaddr + req->ring->tail) != cs);
+       GEM_BUG_ON((req->ring->vaddr + req->ring->emit) != cs);
 }
 
 static inline u32
@@ -540,7 +543,19 @@ assert_ring_tail_valid(const struct intel_ring *ring, unsigned int tail)
        GEM_BUG_ON(tail >= ring->size);
 }
 
-void intel_ring_update_space(struct intel_ring *ring);
+static inline unsigned int
+intel_ring_set_tail(struct intel_ring *ring, unsigned int tail)
+{
+       /* Whilst writes to the tail are strictly order, there is no
+        * serialisation between readers and the writers. The tail may be
+        * read by i915_gem_request_retire() just as it is being updated
+        * by execlists, as although the breadcrumb is complete, the context
+        * switch hasn't been seen.
+        */
+       assert_ring_tail_valid(ring, tail);
+       ring->tail = tail;
+       return tail;
+}
 
 void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
 
index 8c87c717c7cda92c4256cf277828e594f96a0ad1..e6517edcd16b55608c125452b56904f2b48e90df 100644 (file)
@@ -83,10 +83,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
  */
 void intel_pipe_update_start(struct intel_crtc *crtc)
 {
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
        long timeout = msecs_to_jiffies_timeout(1);
        int scanline, min, max, vblank_start;
        wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
+       bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+               intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI);
        DEFINE_WAIT(wait);
 
        vblank_start = adjusted_mode->crtc_vblank_start;
@@ -139,6 +142,24 @@ void intel_pipe_update_start(struct intel_crtc *crtc)
 
        drm_crtc_vblank_put(&crtc->base);
 
+       /*
+        * On VLV/CHV DSI the scanline counter would appear to
+        * increment approx. 1/3 of a scanline before start of vblank.
+        * The registers still get latched at start of vblank however.
+        * This means we must not write any registers on the first
+        * line of vblank (since not the whole line is actually in
+        * vblank). And unfortunately we can't use the interrupt to
+        * wait here since it will fire too soon. We could use the
+        * frame start interrupt instead since it will fire after the
+        * critical scanline, but that would require more changes
+        * in the interrupt code. So for now we'll just do the nasty
+        * thing and poll for the bad scanline to pass us by.
+        *
+        * FIXME figure out if BXT+ DSI suffers from this as well
+        */
+       while (need_vlv_dsi_wa && scanline == vblank_start)
+               scanline = intel_get_crtc_scanline(crtc);
+
        crtc->debug.scanline_start = scanline;
        crtc->debug.start_vbl_time = ktime_get();
        crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
index 4b7f73aeddac6475db31d184853f833c8ba3d510..f84115261ae78b02591a64cb77de96c3fda167bb 100644 (file)
@@ -59,8 +59,6 @@ struct drm_i915_gem_request;
  *                available in the work queue (note, the queue is shared,
  *                not per-engine). It is OK for this to be nonzero, but
  *                it should not be huge!
- *   q_fail: failed to enqueue a work item. This should never happen,
- *           because we check for space beforehand.
  *   b_fail: failed to ring the doorbell. This should never happen, unless
  *           somehow the hardware misbehaves, or maybe if the GuC firmware
  *           crashes? We probably need to reset the GPU to recover.
index 1afb8b06e3e19bf23ed287277415afb364504b23..12b85b3278cd1cfc53b159253e9152e3d8f1784b 100644 (file)
@@ -320,7 +320,7 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj)
 static int igt_ctx_exec(void *arg)
 {
        struct drm_i915_private *i915 = arg;
-       struct drm_i915_gem_object *obj;
+       struct drm_i915_gem_object *obj = NULL;
        struct drm_file *file;
        IGT_TIMEOUT(end_time);
        LIST_HEAD(objects);
@@ -359,7 +359,7 @@ static int igt_ctx_exec(void *arg)
                }
 
                for_each_engine(engine, i915, id) {
-                       if (dw == 0) {
+                       if (!obj) {
                                obj = create_test_object(ctx, file, &objects);
                                if (IS_ERR(obj)) {
                                        err = PTR_ERR(obj);
@@ -376,8 +376,10 @@ static int igt_ctx_exec(void *arg)
                                goto out_unlock;
                        }
 
-                       if (++dw == max_dwords(obj))
+                       if (++dw == max_dwords(obj)) {
+                               obj = NULL;
                                dw = 0;
+                       }
                        ndwords++;
                }
                ncontexts++;
index 8fb801fab039b10225765b044a4e535cf7a4201d..8b05ecb8fdefccafeed07755d501e8902ccba0c3 100644 (file)
@@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                ret = drm_of_find_panel_or_bridge(child,
                                                  imx_ldb->lvds_mux ? 4 : 2, 0,
                                                  &channel->panel, &channel->bridge);
-               if (ret)
+               if (ret && ret != -ENODEV)
                        return ret;
 
                /* panel ddc only if there is no bridge */
index 808b995a990f5529b303e23cb1085b4b7f478355..b5cc6e12334cf96e8faacc01a1a8fb5dcec48202 100644 (file)
@@ -19,6 +19,7 @@
 #include <drm/drm_of.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -900,16 +901,12 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
 
 static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
 {
-       u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
-
-       while (timeout_ms--) {
-               if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
-                       break;
-
-               usleep_range(2, 4);
-       }
+       int ret;
+       u32 val;
 
-       if (timeout_ms == 0) {
+       ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY),
+                                4, 2000000);
+       if (ret) {
                DRM_WARN("polling dsi wait not busy timeout!\n");
 
                mtk_dsi_enable(dsi);
index 41a1c03b03476b620a511731518b8d0f7772417d..0a4ffd7241468dcbd064fa3a210f17094d10697b 100644 (file)
@@ -1062,7 +1062,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
        }
 
        err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
-       if (err) {
+       if (err < 0) {
                dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
                        err);
                return err;
index 75382f5f0fcec00a8749df932cfd7dba9eb19542..10b227d83e9ac7af98b8177188bb56d48823f2b1 100644 (file)
@@ -152,7 +152,7 @@ static struct regmap_config meson_regmap_config = {
        .max_register   = 0x1000,
 };
 
-static int meson_drv_bind(struct device *dev)
+static int meson_drv_bind_master(struct device *dev, bool has_components)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct meson_drm *priv;
@@ -233,10 +233,12 @@ static int meson_drv_bind(struct device *dev)
        if (ret)
                goto free_drm;
 
-       ret = component_bind_all(drm->dev, drm);
-       if (ret) {
-               dev_err(drm->dev, "Couldn't bind all components\n");
-               goto free_drm;
+       if (has_components) {
+               ret = component_bind_all(drm->dev, drm);
+               if (ret) {
+                       dev_err(drm->dev, "Couldn't bind all components\n");
+                       goto free_drm;
+               }
        }
 
        ret = meson_plane_create(priv);
@@ -276,6 +278,11 @@ free_drm:
        return ret;
 }
 
+static int meson_drv_bind(struct device *dev)
+{
+       return meson_drv_bind_master(dev, true);
+}
+
 static void meson_drv_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
@@ -357,6 +364,9 @@ static int meson_drv_probe(struct platform_device *pdev)
                count += meson_probe_remote(pdev, &match, np, remote);
        }
 
+       if (count && !match)
+               return meson_drv_bind_master(&pdev->dev, false);
+
        /* If some endpoints were found, initialize the nodes */
        if (count) {
                dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count);
index adb411a078e8237c0fcb5ecde76bdf1287f9df50..f4b53588e071e4cdc10ecbf152fcb0cee3d55e10 100644 (file)
@@ -1173,7 +1173,10 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,
 
 
        if (IS_G200_SE(mdev)) {
-               if (mdev->unique_rev_id >= 0x02) {
+               if  (mdev->unique_rev_id >= 0x04) {
+                       WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
+                       WREG8(MGAREG_CRTCEXT_DATA, 0);
+               } else if (mdev->unique_rev_id >= 0x02) {
                        u8 hi_pri_lvl;
                        u32 bpp;
                        u32 mb;
@@ -1639,6 +1642,10 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
                        if (mga_vga_calculate_mode_bandwidth(mode, bpp)
                                > (30100 * 1024))
                                return MODE_BANDWIDTH;
+               } else {
+                       if (mga_vga_calculate_mode_bandwidth(mode, bpp)
+                               > (55000 * 1024))
+                               return MODE_BANDWIDTH;
                }
        } else if (mdev->type == G200_WB) {
                if (mode->hdisplay > 1280)
index 5b8e23d051f2f3752a180df4abedccefcfebc3ed..0a31cd6d01ce145f3f112b8c19d17dcdd46ea524 100644 (file)
@@ -13,6 +13,7 @@ config DRM_MSM
        select QCOM_SCM
        select SND_SOC_HDMI_CODEC if SND_SOC
        select SYNC_FILE
+       select PM_OPP
        default y
        help
          DRM/KMS driver for MSM/snapdragon.
index f8f48d014978c0ccd5cc9ffcc3d699b86f779399..9c34d7824988654ab2f8366741724da8ac18b82a 100644 (file)
@@ -116,7 +116,7 @@ static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
-static struct irq_domain_ops mdss_hw_irqdomain_ops = {
+static const struct irq_domain_ops mdss_hw_irqdomain_ops = {
        .map = mdss_hw_irqdomain_map,
        .xlate = irq_domain_xlate_onecell,
 };
index a38c5fe6cc19752a9832618af1a4f146bab4a8df..7d3741215387110bb7f7ad622cb54d0d411fb9f1 100644 (file)
@@ -225,9 +225,10 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)
 
        mdp5_state = kmemdup(to_mdp5_plane_state(plane->state),
                        sizeof(*mdp5_state), GFP_KERNEL);
+       if (!mdp5_state)
+               return NULL;
 
-       if (mdp5_state && mdp5_state->base.fb)
-               drm_framebuffer_reference(mdp5_state->base.fb);
+       __drm_atomic_helper_plane_duplicate_state(plane, &mdp5_state->base);
 
        return &mdp5_state->base;
 }
@@ -444,6 +445,10 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
                        mdp5_pipe_release(state->state, old_hwpipe);
                        mdp5_pipe_release(state->state, old_right_hwpipe);
                }
+       } else {
+               mdp5_pipe_release(state->state, mdp5_state->hwpipe);
+               mdp5_pipe_release(state->state, mdp5_state->r_hwpipe);
+               mdp5_state->hwpipe = mdp5_state->r_hwpipe = NULL;
        }
 
        return 0;
index 87b5695d4034df0e118475617167ee990ccfc490..9d498eb81906220705d85c57260cd4b1f82fa1fc 100644 (file)
@@ -830,6 +830,7 @@ static struct drm_driver msm_driver = {
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export   = drm_gem_prime_export,
        .gem_prime_import   = drm_gem_prime_import,
+       .gem_prime_res_obj  = msm_gem_prime_res_obj,
        .gem_prime_pin      = msm_gem_prime_pin,
        .gem_prime_unpin    = msm_gem_prime_unpin,
        .gem_prime_get_sg_table = msm_gem_prime_get_sg_table,
index 28b6f9ba50664509bb44fa2b5704d3bcc86a67af..1b26ca626528ab5f4435f689d0a213f0e672aaa5 100644 (file)
@@ -224,6 +224,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);
 void *msm_gem_prime_vmap(struct drm_gem_object *obj);
 void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj);
 struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
                struct dma_buf_attachment *attach, struct sg_table *sg);
 int msm_gem_prime_pin(struct drm_gem_object *obj);
index 3f299c537b77ae347bce4c92368ed774c7695459..a2f89bac9c160674f5f103f75a04a7a92e7c5b99 100644 (file)
@@ -99,8 +99,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
 }
 
 struct msm_fence {
-       struct msm_fence_context *fctx;
        struct dma_fence base;
+       struct msm_fence_context *fctx;
 };
 
 static inline struct msm_fence *to_msm_fence(struct dma_fence *fence)
@@ -130,19 +130,13 @@ static bool msm_fence_signaled(struct dma_fence *fence)
        return fence_completed(f->fctx, f->base.seqno);
 }
 
-static void msm_fence_release(struct dma_fence *fence)
-{
-       struct msm_fence *f = to_msm_fence(fence);
-       kfree_rcu(f, base.rcu);
-}
-
 static const struct dma_fence_ops msm_fence_ops = {
        .get_driver_name = msm_fence_get_driver_name,
        .get_timeline_name = msm_fence_get_timeline_name,
        .enable_signaling = msm_fence_enable_signaling,
        .signaled = msm_fence_signaled,
        .wait = dma_fence_default_wait,
-       .release = msm_fence_release,
+       .release = dma_fence_free,
 };
 
 struct dma_fence *
index 68e509b3b9e4d08730e3901f46a397519c33e77c..50289a23baf8df27c4bc1aebf067da2b011b8f28 100644 (file)
@@ -758,6 +758,8 @@ static int msm_gem_new_impl(struct drm_device *dev,
        struct msm_gem_object *msm_obj;
        bool use_vram = false;
 
+       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
        switch (flags & MSM_BO_CACHE_MASK) {
        case MSM_BO_UNCACHED:
        case MSM_BO_CACHED:
@@ -853,7 +855,11 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
 
        size = PAGE_ALIGN(dmabuf->size);
 
+       /* Take mutex so we can modify the inactive list in msm_gem_new_impl */
+       mutex_lock(&dev->struct_mutex);
        ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj);
+       mutex_unlock(&dev->struct_mutex);
+
        if (ret)
                goto fail;
 
index 60bb290700cef9c32fc2ca0dd2db229a6a7ffedf..13403c6da6c75012fa5f17f4b0b63075ddf20874 100644 (file)
@@ -70,3 +70,10 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj)
        if (!obj->import_attach)
                msm_gem_put_pages(obj);
 }
+
+struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj)
+{
+       struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+       return msm_obj->resv;
+}
index 1c545ebe6a5a0f875a995b1db3a1204b0b21d57e..7832e6421d250d0bd78400057e46dce07dc2d18c 100644 (file)
@@ -410,12 +410,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                if (!in_fence)
                        return -EINVAL;
 
-               /* TODO if we get an array-fence due to userspace merging multiple
-                * fences, we need a way to determine if all the backing fences
-                * are from our own context..
+               /*
+                * Wait if the fence is from a foreign context, or if the fence
+                * array contains any fence from a foreign context.
                 */
-
-               if (in_fence->context != gpu->fctx->context) {
+               if (!dma_fence_match_context(in_fence, gpu->fctx->context)) {
                        ret = dma_fence_wait(in_fence, true);
                        if (ret)
                                return ret;
@@ -496,8 +495,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                        goto out;
                }
 
-               if ((submit_cmd.size + submit_cmd.submit_offset) >=
-                               msm_obj->base.size) {
+               if (!submit_cmd.size ||
+                       ((submit_cmd.size + submit_cmd.submit_offset) >
+                               msm_obj->base.size)) {
                        DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size);
                        ret = -EINVAL;
                        goto out;
index 97b9c38c6b3ff7e05adf9ea84e8328d19e32b90f..0fdc88d79ca87b3a54709aa4d527db80ca0997dc 100644 (file)
@@ -549,9 +549,9 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)
                gpu->grp_clks[i] = get_clock(dev, name);
 
                /* Remember the key clocks that we need to control later */
-               if (!strcmp(name, "core"))
+               if (!strcmp(name, "core") || !strcmp(name, "core_clk"))
                        gpu->core_clk = gpu->grp_clks[i];
-               else if (!strcmp(name, "rbbmtimer"))
+               else if (!strcmp(name, "rbbmtimer") || !strcmp(name, "rbbmtimer_clk"))
                        gpu->rbbmtimer_clk = gpu->grp_clks[i];
 
                ++i;
index 1144e0c9e8942ddb6226a7f409ed07f25a0eb96a..0abe77675b76d36ceaa38ece5a2a14afdf3eb060 100644 (file)
 #include "mxsfb_drv.h"
 #include "mxsfb_regs.h"
 
+#define MXS_SET_ADDR           0x4
+#define MXS_CLR_ADDR           0x8
+#define MODULE_CLKGATE         BIT(30)
+#define MODULE_SFTRST          BIT(31)
+/* 1 second delay should be plenty of time for block reset */
+#define RESET_TIMEOUT          1000000
+
 static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
 {
        return (val & mxsfb->devdata->hs_wdth_mask) <<
@@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
                clk_disable_unprepare(mxsfb->clk_disp_axi);
 }
 
+/*
+ * Clear the bit and poll it cleared.  This is usually called with
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
+ * (bit 30).
+ */
+static int clear_poll_bit(void __iomem *addr, u32 mask)
+{
+       u32 reg;
+
+       writel(mask, addr + MXS_CLR_ADDR);
+       return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
+}
+
+static int mxsfb_reset_block(void __iomem *reset_addr)
+{
+       int ret;
+
+       ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+       if (ret)
+               return ret;
+
+       writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
+
+       ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
+       if (ret)
+               return ret;
+
+       return clear_poll_bit(reset_addr, MODULE_CLKGATE);
+}
+
 static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
 {
        struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
@@ -173,6 +210,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
         */
        mxsfb_enable_axi_clk(mxsfb);
 
+       /* Mandatory eLCDIF reset as per the Reference Manual */
+       err = mxsfb_reset_block(mxsfb->base);
+       if (err)
+               return;
+
        /* Clear the FIFOs */
        writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
 
index 6a567fe347b369a2c01d5e89c67ac0a881a49420..820a4805916f1da8115b798cf3c93d5750ae8196 100644 (file)
@@ -4,6 +4,7 @@
 
 struct nvkm_alarm {
        struct list_head head;
+       struct list_head exec;
        u64 timestamp;
        void (*func)(struct nvkm_alarm *);
 };
index 21b10f9840c95e29cd177e9e36d93b8d6155b48d..549763f5e17d8f3c2de2e5d6dbe460363e98c923 100644 (file)
@@ -360,6 +360,8 @@ nouveau_display_hpd_work(struct work_struct *work)
        pm_runtime_get_sync(drm->dev->dev);
 
        drm_helper_hpd_irq_event(drm->dev);
+       /* enable polling for external displays */
+       drm_kms_helper_poll_enable(drm->dev);
 
        pm_runtime_mark_last_busy(drm->dev->dev);
        pm_runtime_put_sync(drm->dev->dev);
@@ -413,10 +415,6 @@ nouveau_display_init(struct drm_device *dev)
        if (ret)
                return ret;
 
-       /* enable polling for external displays */
-       if (!dev->mode_config.poll_enabled)
-               drm_kms_helper_poll_enable(dev);
-
        /* enable hotplug interrupts */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct nouveau_connector *conn = nouveau_connector(connector);
index 2b6ac24ce6901013fd1dc99b4b4e8b27de6125db..15a13d09d431c9a8d4822fb5f997bcf3225a2d4c 100644 (file)
@@ -80,7 +80,7 @@ int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)");
-int nouveau_runtime_pm = -1;
+static int nouveau_runtime_pm = -1;
 module_param_named(runpm, nouveau_runtime_pm, int, 0400);
 
 static struct drm_driver driver_stub;
@@ -495,13 +495,16 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
        nouveau_fbcon_init(dev);
        nouveau_led_init(dev);
 
-       if (nouveau_runtime_pm != 0) {
+       if (nouveau_pmops_runtime()) {
                pm_runtime_use_autosuspend(dev->dev);
                pm_runtime_set_autosuspend_delay(dev->dev, 5000);
                pm_runtime_set_active(dev->dev);
                pm_runtime_allow(dev->dev);
                pm_runtime_mark_last_busy(dev->dev);
                pm_runtime_put(dev->dev);
+       } else {
+               /* enable polling for external displays */
+               drm_kms_helper_poll_enable(dev);
        }
        return 0;
 
@@ -524,7 +527,7 @@ nouveau_drm_unload(struct drm_device *dev)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
 
-       if (nouveau_runtime_pm != 0) {
+       if (nouveau_pmops_runtime()) {
                pm_runtime_get_sync(dev->dev);
                pm_runtime_forbid(dev->dev);
        }
@@ -723,6 +726,14 @@ nouveau_pmops_thaw(struct device *dev)
        return nouveau_do_resume(drm_dev, false);
 }
 
+bool
+nouveau_pmops_runtime()
+{
+       if (nouveau_runtime_pm == -1)
+               return nouveau_is_optimus() || nouveau_is_v1_dsm();
+       return nouveau_runtime_pm == 1;
+}
+
 static int
 nouveau_pmops_runtime_suspend(struct device *dev)
 {
@@ -730,14 +741,7 @@ nouveau_pmops_runtime_suspend(struct device *dev)
        struct drm_device *drm_dev = pci_get_drvdata(pdev);
        int ret;
 
-       if (nouveau_runtime_pm == 0) {
-               pm_runtime_forbid(dev);
-               return -EBUSY;
-       }
-
-       /* are we optimus enabled? */
-       if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
-               DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+       if (!nouveau_pmops_runtime()) {
                pm_runtime_forbid(dev);
                return -EBUSY;
        }
@@ -762,8 +766,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
        struct nvif_device *device = &nouveau_drm(drm_dev)->client.device;
        int ret;
 
-       if (nouveau_runtime_pm == 0)
-               return -EINVAL;
+       if (!nouveau_pmops_runtime()) {
+               pm_runtime_forbid(dev);
+               return -EBUSY;
+       }
 
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
@@ -774,9 +780,6 @@ nouveau_pmops_runtime_resume(struct device *dev)
 
        ret = nouveau_do_resume(drm_dev, true);
 
-       if (!drm_dev->mode_config.poll_enabled)
-               drm_kms_helper_poll_enable(drm_dev);
-
        /* do magic */
        nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
@@ -796,14 +799,7 @@ nouveau_pmops_runtime_idle(struct device *dev)
        struct nouveau_drm *drm = nouveau_drm(drm_dev);
        struct drm_crtc *crtc;
 
-       if (nouveau_runtime_pm == 0) {
-               pm_runtime_forbid(dev);
-               return -EBUSY;
-       }
-
-       /* are we optimus enabled? */
-       if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {
-               DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+       if (!nouveau_pmops_runtime()) {
                pm_runtime_forbid(dev);
                return -EBUSY;
        }
index eadec2f49ad318cf44d3464ff39dbe201e7074cb..a11b6aaed325f17ddf6f82c8fd8ced531191574a 100644 (file)
@@ -108,8 +108,6 @@ nouveau_cli(struct drm_file *fpriv)
 #include <nvif/object.h>
 #include <nvif/device.h>
 
-extern int nouveau_runtime_pm;
-
 struct nouveau_drm {
        struct nouveau_cli client;
        struct drm_device *dev;
@@ -195,6 +193,7 @@ nouveau_drm(struct drm_device *dev)
 
 int nouveau_pmops_suspend(struct device *);
 int nouveau_pmops_resume(struct device *);
+bool nouveau_pmops_runtime(void);
 
 #include <nvkm/core/tegra.h>
 
index a4aacbc0cec8efe603d18152099aaecdeab93dce..02fe0efb9e1643f3a4802b947b3ab306bdd690bd 100644 (file)
@@ -87,7 +87,7 @@ void
 nouveau_vga_init(struct nouveau_drm *drm)
 {
        struct drm_device *dev = drm->dev;
-       bool runtime = false;
+       bool runtime = nouveau_pmops_runtime();
 
        /* only relevant for PCI devices */
        if (!dev->pdev)
@@ -99,10 +99,6 @@ nouveau_vga_init(struct nouveau_drm *drm)
        if (pci_is_thunderbolt_attached(dev->pdev))
                return;
 
-       if (nouveau_runtime_pm == 1)
-               runtime = true;
-       if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
-               runtime = true;
        vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime);
 
        if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
@@ -113,18 +109,13 @@ void
 nouveau_vga_fini(struct nouveau_drm *drm)
 {
        struct drm_device *dev = drm->dev;
-       bool runtime = false;
+       bool runtime = nouveau_pmops_runtime();
 
        vga_client_register(dev->pdev, NULL, NULL, NULL);
 
        if (pci_is_thunderbolt_attached(dev->pdev))
                return;
 
-       if (nouveau_runtime_pm == 1)
-               runtime = true;
-       if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
-               runtime = true;
-
        vga_switcheroo_unregister_client(dev->pdev);
        if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
                vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
index a7663249b3baf2df1c5c75d87d3b32109984ba97..06e564a9ccb253b3018b45d2f0a96cc53430ab2c 100644 (file)
@@ -2107,7 +2107,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
                                        asyc->set.dither = true;
                        }
                } else {
-                       asyc->set.mask = ~0;
+                       if (asyc)
+                               asyc->set.mask = ~0;
                        asyh->set.mask = ~0;
                }
 
index 3a24788c3185ba6a65156389b7a6b849d13d3a11..a7e55c422501cf9c4fc98bc7e7798d2b2213cfcf 100644 (file)
@@ -148,7 +148,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl)
        case NVKM_MEM_TARGET_NCOH: target = 3; break;
        default:
                WARN_ON(1);
-               return;
+               goto unlock;
        }
 
        nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) |
@@ -160,6 +160,7 @@ gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl)
                                       & 0x00100000),
                               msecs_to_jiffies(2000)) == 0)
                nvkm_error(subdev, "runlist %d update timeout\n", runl);
+unlock:
        mutex_unlock(&subdev->mutex);
 }
 
index d1cf02d22db1ff24926ddd881b7f15cbcd78d82c..1b0c793c0192b940103701142e5561ffb1b5263a 100644 (file)
@@ -116,6 +116,7 @@ ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img,
        ret = nvkm_firmware_get(subdev->device, f, &sig);
        if (ret)
                goto free_data;
+
        img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL);
        if (!img->sig) {
                ret = -ENOMEM;
@@ -126,8 +127,9 @@ ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img,
        img->ucode_data = ls_ucode_img_build(bl, code, data,
                                             &img->ucode_desc);
        if (IS_ERR(img->ucode_data)) {
+               kfree(img->sig);
                ret = PTR_ERR(img->ucode_data);
-               goto free_data;
+               goto free_sig;
        }
        img->ucode_size = img->ucode_desc.image_size;
 
index f2a86eae0a0d624b31cb8ee9a65e6487705a6c1a..2437f7d41ca20de616a7193f2d6fdec6d7daea00 100644 (file)
@@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
                /* Move to completed list.  We'll drop the lock before
                 * executing the callback so it can reschedule itself.
                 */
-               list_move_tail(&alarm->head, &exec);
+               list_del_init(&alarm->head);
+               list_add(&alarm->exec, &exec);
        }
 
        /* Shut down interrupt if no more pending alarms. */
@@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
        spin_unlock_irqrestore(&tmr->lock, flags);
 
        /* Execute completed callbacks. */
-       list_for_each_entry_safe(alarm, atemp, &exec, head) {
-               list_del_init(&alarm->head);
+       list_for_each_entry_safe(alarm, atemp, &exec, exec) {
+               list_del(&alarm->exec);
                alarm->func(alarm);
        }
 }
index 058340a002c29daef072f21bf90e1e8a572b3fa9..4a340efd8ba67ac23aadc6611ea3ce7e7d460e1a 100644 (file)
@@ -575,8 +575,6 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
        if (ret)
                return;
 
-       cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
-
        if (fb != old_state->fb) {
                obj = to_qxl_framebuffer(fb)->obj;
                user_bo = gem_to_qxl_bo(obj);
@@ -614,6 +612,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
                qxl_bo_kunmap(cursor_bo);
                qxl_bo_kunmap(user_bo);
 
+               cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
                cmd->u.set.visible = 1;
                cmd->u.set.shape = qxl_bo_physical_address(qdev,
                                                           cursor_bo, 0);
@@ -624,6 +623,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
                if (ret)
                        goto out_free_release;
 
+               cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release);
                cmd->type = QXL_CURSOR_MOVE;
        }
 
index 7ba450832e6b7a59db9499a0919a8bb5f4a3fd1a..ea36dc4dd5d22ec7b30678ea811dcf5009f454f7 100644 (file)
@@ -776,6 +776,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev)
        u32 vblank_time = r600_dpm_get_vblank_time(rdev);
        u32 switch_limit = pi->mem_gddr5 ? 450 : 300;
 
+       /* disable mclk switching if the refresh is >120Hz, even if the
+        * blanking period would allow it
+        */
+       if (r600_dpm_get_vrefresh(rdev) > 120)
+               return true;
+
        if (vblank_time < switch_limit)
                return true;
        else
index ccebe0f8d2e1e3b4ec15d6170b788e2e8fc8b980..ca44233ceaccb87482068d992e4c415f756fa540 100644 (file)
@@ -7401,7 +7401,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
        if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp = RREG32(DC_HPD6_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
@@ -7431,7 +7431,7 @@ static inline void cik_irq_ack(struct radeon_device *rdev)
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
        if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp = RREG32(DC_HPD6_INT_CONTROL);
                tmp |= DC_HPDx_RX_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
@@ -9267,8 +9267,11 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
        u32 tmp, wm_mask;
 
        if (radeon_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
 
                /* watermark for high clocks */
                if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
index f130ec41ee4bbcad63516335dfaf17e24e782b60..534637203e709909bc11c934c7e1e20b4551e31e 100644 (file)
@@ -2266,8 +2266,11 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
        fixed20_12 a, b, c;
 
        if (radeon_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
                priority_a_cnt = 0;
                priority_b_cnt = 0;
                dram_channels = evergreen_get_number_of_dram_channels(rdev);
@@ -4927,7 +4930,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
        if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp = RREG32(DC_HPD6_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
@@ -4958,7 +4961,7 @@ static void evergreen_irq_ack(struct radeon_device *rdev)
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
        if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp = RREG32(DC_HPD6_INT_CONTROL);
                tmp |= DC_HPDx_RX_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
index 0a085176e79b35b2887c19f7b33091804b58e645..e06e2d8feab397822361ba18a3e4b420cc2f0c4d 100644 (file)
@@ -3988,7 +3988,7 @@ static void r600_irq_ack(struct radeon_device *rdev)
                        WREG32(DC_HPD5_INT_CONTROL, tmp);
                }
                if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) {
-                       tmp = RREG32(DC_HPD5_INT_CONTROL);
+                       tmp = RREG32(DC_HPD6_INT_CONTROL);
                        tmp |= DC_HPDx_INT_ACK;
                        WREG32(DC_HPD6_INT_CONTROL, tmp);
                }
index 432480ff9d228857d57170b3353c143bf0501c3f..3178ba0c537c1915af3b857aad83efd6371f17ad 100644 (file)
@@ -3393,6 +3393,13 @@ void radeon_combios_asic_init(struct drm_device *dev)
            rdev->pdev->subsystem_vendor == 0x103c &&
            rdev->pdev->subsystem_device == 0x280a)
                return;
+       /* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume
+        * - it hangs on resume inside the dynclk 1 table.
+        */
+       if (rdev->family == CHIP_RS400 &&
+           rdev->pdev->subsystem_vendor == 0x1179 &&
+           rdev->pdev->subsystem_device == 0xff31)
+               return;
 
        /* DYN CLK 1 */
        table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE);
index 6ecf42783d4b0c45539325edd2e5ffd2fc08e29f..0a6444d72000c434a6b494229a75c1a7d3e41631 100644 (file)
@@ -136,6 +136,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
         * https://bugzilla.kernel.org/show_bug.cgi?id=51381
         */
        { PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
+       /* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU
+        * https://bugs.freedesktop.org/show_bug.cgi?id=101491
+        */
+       { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
        /* macbook pro 8.2 */
        { PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
        { 0, 0, 0, 0, 0 },
index e3e7cb1d10a2941d1790d36a9f5250f70aeb78cd..4761f27f2ca2a073a8ffb30806a9cac905003f23 100644 (file)
@@ -116,7 +116,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
        if ((radeon_runtime_pm != 0) &&
            radeon_has_atpx() &&
            ((flags & RADEON_IS_IGP) == 0) &&
-           !pci_is_thunderbolt_attached(rdev->pdev))
+           !pci_is_thunderbolt_attached(dev->pdev))
                flags |= RADEON_IS_PX;
 
        /* radeon_device_init should report only fatal error
index 7431eb4a11b7f721fc8e44240c09742b02dc0446..d34d1cf33895766c55a122adad041be62e42c70c 100644 (file)
@@ -621,7 +621,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
        }
 
        /* TODO: is this still necessary on NI+ ? */
-       if ((cmd == 0 || cmd == 1 || cmd == 0x3) &&
+       if ((cmd == 0 || cmd == 0x3) &&
            (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
                DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
                          start, end);
index ceee87f029d9a3479d374c4fc305338377dee961..5303f25d5280ed49548db40007444dee7cf79abe 100644 (file)
@@ -2284,8 +2284,11 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
        fixed20_12 a, b, c;
 
        if (radeon_crtc->base.enabled && num_heads && mode) {
-               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
-               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
+               active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
+                                           (u32)mode->clock);
+               line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
+                                         (u32)mode->clock);
+               line_time = min(line_time, (u32)65535);
                priority_a_cnt = 0;
                priority_b_cnt = 0;
 
@@ -6317,7 +6320,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
        if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) {
-               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp = RREG32(DC_HPD6_INT_CONTROL);
                tmp |= DC_HPDx_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
@@ -6348,7 +6351,7 @@ static inline void si_irq_ack(struct radeon_device *rdev)
                WREG32(DC_HPD5_INT_CONTROL, tmp);
        }
        if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) {
-               tmp = RREG32(DC_HPD5_INT_CONTROL);
+               tmp = RREG32(DC_HPD6_INT_CONTROL);
                tmp |= DC_HPDx_RX_INT_ACK;
                WREG32(DC_HPD6_INT_CONTROL, tmp);
        }
index d8fa7a9c9240bdf53f06d214f5952af7f85e5ee4..ce5f2d1f9994113b6322a708f47f1e23049ef3ba 100644 (file)
@@ -245,8 +245,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
                                      struct drm_connector_state *conn_state)
 {
        struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
-       struct rockchip_dp_device *dp = to_dp(encoder);
-       int ret;
 
        /*
         * The hardware IC designed that VOP must output the RGB10 video
@@ -258,16 +256,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
 
        s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
        s->output_type = DRM_MODE_CONNECTOR_eDP;
-       if (dp->data->chip_type == RK3399_EDP) {
-               /*
-                * For RK3399, VOP Lit must code the out mode to RGB888,
-                * VOP Big must code the out mode to RGB10.
-                */
-               ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node,
-                                                       encoder);
-               if (ret > 0)
-                       s->output_mode = ROCKCHIP_OUT_MODE_P888;
-       }
 
        return 0;
 }
index a2169dd3d26b915c851bd089f25373495c188174..14fa1f8351e8df22ab30560fbb6a1906841ba43d 100644 (file)
@@ -615,7 +615,6 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
 {
        struct cdn_dp_device *dp = encoder_to_dp(encoder);
        int ret, val;
-       struct rockchip_crtc_state *state;
 
        ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
        if (ret < 0) {
@@ -625,14 +624,10 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
 
        DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n",
                          (ret) ? "LIT" : "BIG");
-       state = to_rockchip_crtc_state(encoder->crtc->state);
-       if (ret) {
+       if (ret)
                val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16);
-               state->output_mode = ROCKCHIP_OUT_MODE_P888;
-       } else {
+       else
                val = DP_SEL_VOP_LIT << 16;
-               state->output_mode = ROCKCHIP_OUT_MODE_AAAA;
-       }
 
        ret = cdn_dp_grf_write(dp, GRF_SOC_CON9, val);
        if (ret)
index 3f7a82d1e0956e6a37e1478412210955db38aa19..45589d6ce65ed0fd0a7e1be60f83dd03bd3d47b5 100644 (file)
@@ -875,6 +875,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,
 static void vop_crtc_enable(struct drm_crtc *crtc)
 {
        struct vop *vop = to_vop(crtc);
+       const struct vop_data *vop_data = vop->data;
        struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
        struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
        u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
@@ -967,6 +968,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
                DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",
                              s->output_type);
        }
+
+       /*
+        * if vop is not support RGB10 output, need force RGB10 to RGB888.
+        */
+       if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA &&
+           !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10))
+               s->output_mode = ROCKCHIP_OUT_MODE_P888;
        VOP_CTRL_SET(vop, out_mode, s->output_mode);
 
        VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
index 5a4faa85dbd29d91af08ae51a8c2ac69012cb33c..9979fd0c22821d7efa3d7054468e0914619e0692 100644 (file)
@@ -142,6 +142,9 @@ struct vop_data {
        const struct vop_intr *intr;
        const struct vop_win_data *win;
        unsigned int win_size;
+
+#define VOP_FEATURE_OUTPUT_RGB10       BIT(0)
+       u64 feature;
 };
 
 /* interrupt define */
index 0da44442aab097b8f4b40d67c8995be625bccfcd..bafd698a28b1b491c01823d2be293a41e67c3722 100644 (file)
@@ -275,6 +275,7 @@ static const struct vop_intr rk3288_vop_intr = {
 static const struct vop_data rk3288_vop = {
        .init_table = rk3288_init_reg_table,
        .table_size = ARRAY_SIZE(rk3288_init_reg_table),
+       .feature = VOP_FEATURE_OUTPUT_RGB10,
        .intr = &rk3288_vop_intr,
        .ctrl = &rk3288_ctrl_data,
        .win = rk3288_vop_win_data,
@@ -343,6 +344,7 @@ static const struct vop_reg_data rk3399_init_reg_table[] = {
 static const struct vop_data rk3399_vop_big = {
        .init_table = rk3399_init_reg_table,
        .table_size = ARRAY_SIZE(rk3399_init_reg_table),
+       .feature = VOP_FEATURE_OUTPUT_RGB10,
        .intr = &rk3399_vop_intr,
        .ctrl = &rk3399_ctrl_data,
        /*
index 9a1e34e48f64fb0ab684a20811a0be0ff0a09ab6..81f86a67c10d28416a3fbe3d69694b8c7dfc34ee 100644 (file)
@@ -451,18 +451,6 @@ fail:
 
 
 #ifdef CONFIG_DRM_TEGRA_STAGING
-static struct tegra_drm_context *
-tegra_drm_file_get_context(struct tegra_drm_file *file, u32 id)
-{
-       struct tegra_drm_context *context;
-
-       mutex_lock(&file->lock);
-       context = idr_find(&file->contexts, id);
-       mutex_unlock(&file->lock);
-
-       return context;
-}
-
 static int tegra_gem_create(struct drm_device *drm, void *data,
                            struct drm_file *file)
 {
@@ -551,7 +539,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,
        if (err < 0)
                return err;
 
-       err = idr_alloc(&fpriv->contexts, context, 0, 0, GFP_KERNEL);
+       err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);
        if (err < 0) {
                client->ops->close_channel(context);
                return err;
@@ -606,7 +594,7 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = tegra_drm_file_get_context(fpriv, args->context);
+       context = idr_find(&fpriv->contexts, args->context);
        if (!context) {
                err = -EINVAL;
                goto unlock;
@@ -631,7 +619,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = tegra_drm_file_get_context(fpriv, args->context);
+       context = idr_find(&fpriv->contexts, args->context);
        if (!context) {
                err = -ENODEV;
                goto unlock;
@@ -660,7 +648,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = tegra_drm_file_get_context(fpriv, args->context);
+       context = idr_find(&fpriv->contexts, args->context);
        if (!context) {
                err = -ENODEV;
                goto unlock;
@@ -685,7 +673,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = tegra_drm_file_get_context(fpriv, args->context);
+       context = idr_find(&fpriv->contexts, args->context);
        if (!context) {
                err = -ENODEV;
                goto unlock;
index 13db8a2851edd475cc1e44adedd44796c3ccbca1..1f013d45c9e9a3959dfa19300ba76fc37820592a 100644 (file)
@@ -321,6 +321,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
        list_for_each_entry_safe(entry, next, &man->list, head)
                vmw_cmdbuf_res_free(man, entry);
 
+       drm_ht_remove(&man->resources);
        kfree(man);
 }
 
index 130d51c5ec6a2dab1211337d71313e6b1de15323..4b948fba9eec274b794a0546fec0179b3de1cadf 100644 (file)
@@ -41,9 +41,9 @@
 #include <drm/ttm/ttm_module.h>
 #include "vmwgfx_fence.h"
 
-#define VMWGFX_DRIVER_DATE "20170221"
+#define VMWGFX_DRIVER_DATE "20170607"
 #define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 12
+#define VMWGFX_DRIVER_MINOR 13
 #define VMWGFX_DRIVER_PATCHLEVEL 0
 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
index b6a0806b06bffaf6da9178905f9b2f6bb037d384..a1c68e6a689e32fd0dd4d74c805ee4afd0836a99 100644 (file)
@@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,
                                return fifo_state->static_buffer;
                        else {
                                fifo_state->dynamic_buffer = vmalloc(bytes);
+                               if (!fifo_state->dynamic_buffer)
+                                       goto out_err;
                                return fifo_state->dynamic_buffer;
                        }
                }
index ef9f3a2a40303290287b5259b7a71d2a8791ddb4..1d2db5d912b03c572b50f9b64b2f5d2a39de1365 100644 (file)
@@ -274,108 +274,6 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
 }
 
 
-
-/**
- * vmw_du_cursor_plane_update() - Update cursor image and location
- *
- * @plane: plane object to update
- * @crtc: owning CRTC of @plane
- * @fb: framebuffer to flip onto plane
- * @crtc_x: x offset of plane on crtc
- * @crtc_y: y offset of plane on crtc
- * @crtc_w: width of plane rectangle on crtc
- * @crtc_h: height of plane rectangle on crtc
- * @src_x: Not used
- * @src_y: Not used
- * @src_w: Not used
- * @src_h: Not used
- *
- *
- * RETURNS:
- * Zero on success, error code on failure
- */
-int vmw_du_cursor_plane_update(struct drm_plane *plane,
-                              struct drm_crtc *crtc,
-                              struct drm_framebuffer *fb,
-                              int crtc_x, int crtc_y,
-                              unsigned int crtc_w,
-                              unsigned int crtc_h,
-                              uint32_t src_x, uint32_t src_y,
-                              uint32_t src_w, uint32_t src_h)
-{
-       struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-       struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
-       struct vmw_surface *surface = NULL;
-       struct vmw_dma_buffer *dmabuf = NULL;
-       s32 hotspot_x, hotspot_y;
-       int ret;
-
-       hotspot_x = du->hotspot_x + fb->hot_x;
-       hotspot_y = du->hotspot_y + fb->hot_y;
-
-       /* A lot of the code assumes this */
-       if (crtc_w != 64 || crtc_h != 64) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (vmw_framebuffer_to_vfb(fb)->dmabuf)
-               dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
-       else
-               surface = vmw_framebuffer_to_vfbs(fb)->surface;
-
-       if (surface && !surface->snooper.image) {
-               DRM_ERROR("surface not suitable for cursor\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* setup new image */
-       ret = 0;
-       if (surface) {
-               /* vmw_user_surface_lookup takes one reference */
-               du->cursor_surface = surface;
-
-               du->cursor_age = du->cursor_surface->snooper.age;
-
-               ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
-                                             64, 64, hotspot_x, hotspot_y);
-       } else if (dmabuf) {
-               /* vmw_user_surface_lookup takes one reference */
-               du->cursor_dmabuf = dmabuf;
-
-               ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
-                                              hotspot_x, hotspot_y);
-       } else {
-               vmw_cursor_update_position(dev_priv, false, 0, 0);
-               goto out;
-       }
-
-       if (!ret) {
-               du->cursor_x = crtc_x + du->set_gui_x;
-               du->cursor_y = crtc_y + du->set_gui_y;
-
-               vmw_cursor_update_position(dev_priv, true,
-                                          du->cursor_x + hotspot_x,
-                                          du->cursor_y + hotspot_y);
-       }
-
-out:
-       return ret;
-}
-
-
-int vmw_du_cursor_plane_disable(struct drm_plane *plane)
-{
-       if (plane->fb) {
-               drm_framebuffer_unreference(plane->fb);
-               plane->fb = NULL;
-       }
-
-       return -EINVAL;
-}
-
-
 void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
 {
        vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
@@ -472,18 +370,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
 }
 
 
-void
-vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
-                                  struct drm_plane_state *old_state)
-{
-       struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
-       struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-
-       drm_atomic_set_fb_for_plane(plane->state, NULL);
-       vmw_cursor_update_position(dev_priv, false, 0, 0);
-}
-
-
 void
 vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
                                  struct drm_plane_state *old_state)
@@ -1498,6 +1384,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
         */
        if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)  &&
            dmabuf && only_2d &&
+           mode_cmd->width > 64 &&  /* Don't create a proxy for cursor */
            dev_priv->active_display_unit == vmw_du_screen_target) {
                ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd,
                                              dmabuf, &surface);
index 13f2f1d2818a755012098df126938989ba1fb297..5f8d678ae675156178dc306efc2fc83338c390ba 100644 (file)
@@ -256,10 +256,6 @@ int vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
                           u16 *r, u16 *g, u16 *b,
                           uint32_t size,
                           struct drm_modeset_acquire_ctx *ctx);
-int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
-                           uint32_t handle, uint32_t width, uint32_t height,
-                           int32_t hot_x, int32_t hot_y);
-int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 int vmw_du_connector_set_property(struct drm_connector *connector,
                                  struct drm_property *property,
                                  uint64_t val);
@@ -339,15 +335,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
 /* Universal Plane Helpers */
 void vmw_du_primary_plane_destroy(struct drm_plane *plane);
 void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
-int vmw_du_cursor_plane_disable(struct drm_plane *plane);
-int vmw_du_cursor_plane_update(struct drm_plane *plane,
-                              struct drm_crtc *crtc,
-                              struct drm_framebuffer *fb,
-                              int crtc_x, int crtc_y,
-                              unsigned int crtc_w,
-                              unsigned int crtc_h,
-                              uint32_t src_x, uint32_t src_y,
-                              uint32_t src_w, uint32_t src_h);
 
 /* Atomic Helpers */
 int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
@@ -356,8 +343,6 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
                                     struct drm_plane_state *state);
 void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
                                       struct drm_plane_state *old_state);
-void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
-                                       struct drm_plane_state *old_state);
 int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
                                   struct drm_plane_state *new_state);
 void vmw_du_plane_cleanup_fb(struct drm_plane *plane,
index bad31bdf09b6c1d8bd31663c7973e1ebb912f340..50be1f034f9efa701f2c6feda57fe28d8cf6d596 100644 (file)
@@ -56,6 +56,8 @@ enum stdu_content_type {
  * @right: Right side of bounding box.
  * @top: Top side of bounding box.
  * @bottom: Bottom side of bounding box.
+ * @fb_left: Left side of the framebuffer/content bounding box
+ * @fb_top: Top of the framebuffer/content bounding box
  * @buf: DMA buffer when DMA-ing between buffer and screen targets.
  * @sid: Surface ID when copying between surface and screen targets.
  */
@@ -63,6 +65,7 @@ struct vmw_stdu_dirty {
        struct vmw_kms_dirty base;
        SVGA3dTransferType  transfer;
        s32 left, right, top, bottom;
+       s32 fb_left, fb_top;
        u32 pitch;
        union {
                struct vmw_dma_buffer *buf;
@@ -647,7 +650,7 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)
  *
  * @dirty: The closure structure.
  *
- * This function calculates the bounding box for all the incoming clips
+ * This function calculates the bounding box for all the incoming clips.
  */
 static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
 {
@@ -656,11 +659,19 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)
 
        dirty->num_hits = 1;
 
-       /* Calculate bounding box */
+       /* Calculate destination bounding box */
        ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);
        ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);
        ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);
        ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2);
+
+       /*
+        * Calculate content bounding box.  We only need the top-left
+        * coordinate because width and height will be the same as the
+        * destination bounding box above
+        */
+       ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x);
+       ddirty->fb_top  = min_t(s32, ddirty->fb_top, dirty->fb_y);
 }
 
 
@@ -697,11 +708,11 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
        /* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */
        src_pitch = stdu->display_srf->base_size.width * stdu->cpp;
        src = ttm_kmap_obj_virtual(&stdu->host_map, &not_used);
-       src += dirty->unit_y1 * src_pitch + dirty->unit_x1 * stdu->cpp;
+       src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;
 
        dst_pitch = ddirty->pitch;
        dst = ttm_kmap_obj_virtual(&stdu->guest_map, &not_used);
-       dst += dirty->fb_y * dst_pitch + dirty->fb_x * stdu->cpp;
+       dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;
 
 
        /* Figure out the real direction */
@@ -760,7 +771,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
        }
 
 out_cleanup:
-       ddirty->left = ddirty->top = S32_MAX;
+       ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
        ddirty->right = ddirty->bottom = S32_MIN;
 }
 
@@ -812,6 +823,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
                SVGA3D_READ_HOST_VRAM;
        ddirty.left = ddirty.top = S32_MAX;
        ddirty.right = ddirty.bottom = S32_MIN;
+       ddirty.fb_left = ddirty.fb_top = S32_MAX;
        ddirty.pitch = vfb->base.pitches[0];
        ddirty.buf = buf;
        ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit;
@@ -1355,6 +1367,11 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
                DRM_ERROR("Failed to bind surface to STDU.\n");
        else
                crtc->primary->fb = plane->state->fb;
+
+       ret = vmw_stdu_update_st(dev_priv, stdu);
+
+       if (ret)
+               DRM_ERROR("Failed to update STDU.\n");
 }
 
 
index 7681341fe32b8725840d70b137782f5f1f316bc0..6b70bd259953580204ccecd4ec4334c73e73eed7 100644 (file)
@@ -1274,11 +1274,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
        int ret;
        uint32_t size;
-       uint32_t backup_handle;
+       uint32_t backup_handle = 0;
 
        if (req->multisample_count != 0)
                return -EINVAL;
 
+       if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
+               return -EINVAL;
+
        if (unlikely(vmw_user_surface_size == 0))
                vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
                        128;
@@ -1314,12 +1317,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
                ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
                                             &res->backup,
                                             &user_srf->backup_base);
-               if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
-                   res->backup_size) {
-                       DRM_ERROR("Surface backup buffer is too small.\n");
-                       vmw_dmabuf_unreference(&res->backup);
-                       ret = -EINVAL;
-                       goto out_unlock;
+               if (ret == 0) {
+                       if (res->backup->base.num_pages * PAGE_SIZE <
+                           res->backup_size) {
+                               DRM_ERROR("Surface backup buffer is too small.\n");
+                               vmw_dmabuf_unreference(&res->backup);
+                               ret = -EINVAL;
+                               goto out_unlock;
+                       } else {
+                               backup_handle = req->buffer_handle;
+                       }
                }
        } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
                ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
@@ -1491,7 +1498,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
                                 dev_priv->stdu_max_height);
 
                if (size.width > max_width || size.height > max_height) {
-                       DRM_ERROR("%ux%u\n, exeeds max surface size %ux%u",
+                       DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u",
                                  size.width, size.height,
                                  max_width, max_height);
                        return -EINVAL;
index b2fd029d67b308ce60490d61cd908d743a9e520b..91916326957f9c3b842178b2c1cbdd60e9db5bf3 100644 (file)
@@ -1,6 +1,7 @@
 config TEGRA_HOST1X
        tristate "NVIDIA Tegra host1x driver"
        depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
+       select IOMMU_IOVA if IOMMU_SUPPORT
        help
          Driver for the NVIDIA Tegra host1x hardware.
 
index f05ebb14fa636bce578c2fd00db88dbc835fdbe9..ac65f52850a6351e3ecb3ee27816b4c3d8df5e67 100644 (file)
@@ -172,7 +172,7 @@ static int host1x_probe(struct platform_device *pdev)
 
        host->rst = devm_reset_control_get(&pdev->dev, "host1x");
        if (IS_ERR(host->rst)) {
-               err = PTR_ERR(host->clk);
+               err = PTR_ERR(host->rst);
                dev_err(&pdev->dev, "failed to get reset: %d\n", err);
                return err;
        }
index 16d556816b5fcaa62758549d9bceaa88bd4bc839..2fb5f432a54c1afd0f7c6104facb1860dbcb3f3a 100644 (file)
@@ -725,15 +725,16 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)
        spin_lock_irqsave(&ipu->lock, flags);
 
        val = ipu_cm_read(ipu, IPU_CONF);
-       if (vdi) {
+       if (vdi)
                val |= IPU_CONF_IC_INPUT;
-       } else {
+       else
                val &= ~IPU_CONF_IC_INPUT;
-               if (csi_id == 1)
-                       val |= IPU_CONF_CSI_SEL;
-               else
-                       val &= ~IPU_CONF_CSI_SEL;
-       }
+
+       if (csi_id == 1)
+               val |= IPU_CONF_CSI_SEL;
+       else
+               val &= ~IPU_CONF_CSI_SEL;
+
        ipu_cm_write(ipu, val, IPU_CONF);
 
        spin_unlock_irqrestore(&ipu->lock, flags);
index c55563379e2e3ca2a1957ce777b2ac2c3586d9b7..c35f74c830657f26a3e29c34f7cef7e9f864f71a 100644 (file)
@@ -131,8 +131,6 @@ int ipu_pre_get(struct ipu_pre *pre)
        if (pre->in_use)
                return -EBUSY;
 
-       clk_prepare_enable(pre->clk_axi);
-
        /* first get the engine out of reset and remove clock gating */
        writel(0, pre->regs + IPU_PRE_CTRL);
 
@@ -149,12 +147,7 @@ int ipu_pre_get(struct ipu_pre *pre)
 
 void ipu_pre_put(struct ipu_pre *pre)
 {
-       u32 val;
-
-       val = IPU_PRE_CTRL_SFTRST | IPU_PRE_CTRL_CLKGATE;
-       writel(val, pre->regs + IPU_PRE_CTRL);
-
-       clk_disable_unprepare(pre->clk_axi);
+       writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);
 
        pre->in_use = false;
 }
@@ -249,6 +242,8 @@ static int ipu_pre_probe(struct platform_device *pdev)
        if (!pre->buffer_virt)
                return -ENOMEM;
 
+       clk_prepare_enable(pre->clk_axi);
+
        pre->dev = dev;
        platform_set_drvdata(pdev, pre);
        mutex_lock(&ipu_pre_list_mutex);
@@ -268,6 +263,8 @@ static int ipu_pre_remove(struct platform_device *pdev)
        available_pres--;
        mutex_unlock(&ipu_pre_list_mutex);
 
+       clk_disable_unprepare(pre->clk_axi);
+
        if (pre->buffer_virt)
                gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,
                              IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4);
index fe40e5e499dd4122ce0f623d9df776c0a0cf2bdf..687705c5079422a82b9977e5694d0cd45b2a47bc 100644 (file)
@@ -275,10 +275,12 @@ config HID_EMS_FF
         - Trio Linker Plus II
 
 config HID_ELECOM
-       tristate "ELECOM BM084 bluetooth mouse"
+       tristate "ELECOM HID devices"
        depends on HID
        ---help---
-       Support for the ELECOM BM084 (bluetooth mouse).
+       Support for ELECOM devices:
+         - BM084 Bluetooth Mouse
+         - DEFT Trackball (Wired and wireless)
 
 config HID_ELO
        tristate "ELO USB 4000/4500 touchscreen"
index 16df6cc902359ea620de3f079be796d32be4783a..a6268f2f7408a520660c6add3c734a8006474393 100644 (file)
@@ -69,6 +69,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
 #define QUIRK_IS_MULTITOUCH            BIT(3)
 #define QUIRK_NO_CONSUMER_USAGES       BIT(4)
 #define QUIRK_USE_KBD_BACKLIGHT                BIT(5)
+#define QUIRK_T100_KEYBOARD            BIT(6)
 
 #define I2C_KEYBOARD_QUIRKS                    (QUIRK_FIX_NOTEBOOK_REPORT | \
                                                 QUIRK_NO_INIT_REPORTS | \
@@ -536,6 +537,8 @@ static void asus_remove(struct hid_device *hdev)
                drvdata->kbd_backlight->removed = true;
                cancel_work_sync(&drvdata->kbd_backlight->work);
        }
+
+       hid_hw_stop(hdev);
 }
 
 static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -548,6 +551,12 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
                rdesc[55] = 0xdd;
        }
+       if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
+                *rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) {
+               hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
+               rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
+       }
+
        return rdesc;
 }
 
@@ -560,6 +569,9 @@ static const struct hid_device_id asus_devices[] = {
                USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
                USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
+               USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
+         QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
        { }
 };
 MODULE_DEVICE_TABLE(hid, asus_devices);
index 37084b6457851ebe0d52361e327db9df07b86b2c..6e040692f1d8f2c7032c51ad96540a341f80c35b 100644 (file)
@@ -826,11 +826,35 @@ static int hid_scan_report(struct hid_device *hid)
                                 * hid-rmi should take care of them,
                                 * not hid-generic
                                 */
-                               if (IS_ENABLED(CONFIG_HID_RMI))
-                                       hid->group = HID_GROUP_RMI;
+                               hid->group = HID_GROUP_RMI;
                break;
        }
 
+       /* fall back to generic driver in case specific driver doesn't exist */
+       switch (hid->group) {
+       case HID_GROUP_MULTITOUCH_WIN_8:
+               /* fall-through */
+       case HID_GROUP_MULTITOUCH:
+               if (!IS_ENABLED(CONFIG_HID_MULTITOUCH))
+                       hid->group = HID_GROUP_GENERIC;
+               break;
+       case HID_GROUP_SENSOR_HUB:
+               if (!IS_ENABLED(CONFIG_HID_SENSOR_HUB))
+                       hid->group = HID_GROUP_GENERIC;
+               break;
+       case HID_GROUP_RMI:
+               if (!IS_ENABLED(CONFIG_HID_RMI))
+                       hid->group = HID_GROUP_GENERIC;
+               break;
+       case HID_GROUP_WACOM:
+               if (!IS_ENABLED(CONFIG_HID_WACOM))
+                       hid->group = HID_GROUP_GENERIC;
+               break;
+       case HID_GROUP_LOGITECH_DJ_DEVICE:
+               if (!IS_ENABLED(CONFIG_HID_LOGITECH_DJ))
+                       hid->group = HID_GROUP_GENERIC;
+               break;
+       }
        vfree(parser);
        return 0;
 }
@@ -1763,15 +1787,23 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
  * used as a driver. See hid_scan_report().
  */
 static const struct hid_device_id hid_have_special_driver[] = {
+#if IS_ENABLED(CONFIG_HID_A4TECH)
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ACCUTOUCH)
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ACRUX)
        { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ALPS)
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_APPLE)
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
@@ -1792,11 +1824,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
@@ -1851,59 +1878,100 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+#endif
+#if IS_ENABLED(CONFIG_HID_APPLEIR)
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ASUS)
        { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD) },
        { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_AUREAL)
        { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
+#endif
+#if IS_ENABLED(CONFIG_HID_BELKIN)
        { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_BETOP_FF)
        { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) },
        { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CHERRY)
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CHICONY)
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CMEDIA)
+       { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CORSAIR)
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CP2112)
        { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
+#endif
+#if IS_ENABLED(CONFIG_HID_CYPRESS)
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) },
+#endif
+#if IS_ENABLED(CONFIG_HID_DRAGONRISE)
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
        { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
-#if IS_ENABLED(CONFIG_HID_MAYFLASH)
-       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },
 #endif
-       { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) },
+#if IS_ENABLED(CONFIG_HID_ELECOM)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ELO)
        { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
+#endif
+#if IS_ENABLED(CONFIG_HID_EMS_FF)
        { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
+#endif
+#if IS_ENABLED(CONFIG_HID_EZKEY)
        { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GEMBIRD)
        { HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GFRM)
+        { HID_BLUETOOTH_DEVICE(0x58, 0x2000) },
+        { HID_BLUETOOTH_DEVICE(0x471, 0x2210) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GREENASIA)
        { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GT683R)
+       { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_GYRATION)
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
+#endif
+#if IS_ENABLED(CONFIG_HID_HOLTEK)
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
@@ -1912,12 +1980,17 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_ZEN_AIO_KBD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ICADE)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_KENSINGTON)
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_KEYTOUCH)
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
+#endif
+#if IS_ENABLED(CONFIG_HID_KYE)
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GILA_GAMING_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_MANTICORE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_GENIUS_GX_IMPERATOR) },
@@ -1927,21 +2000,29 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LCPOWER)
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LED)
+       { HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_LUXAFOR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
+#endif
 #if IS_ENABLED(CONFIG_HID_LENOVO)
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
 #endif
-       { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) },
+#if IS_ENABLED(CONFIG_HID_LOGITECH)
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
@@ -1954,7 +2035,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
@@ -1966,17 +2046,30 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) },
-#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ)
-       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
-#endif
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_LUXAFOR) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LOGITECH_HIDPP)
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_LOGITECH_DJ)
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MAGICMOUSE)
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MAYFLASH)
+       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MICROSOFT)
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
@@ -1992,9 +2085,22 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MONTEREY)
        { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_MULTITOUCH)
+       { HID_USB_DEVICE(USB_VENDOR_ID_LG, USB_DEVICE_ID_LG_MELFAS_MT) },
+#endif
+#if IS_ENABLED(CONFIG_HID_WIIMOTE)
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
+#endif
+#if IS_ENABLED(CONFIG_HID_NTI)
        { HID_USB_DEVICE(USB_VENDOR_ID_NTI, USB_DEVICE_ID_USB_SUN) },
+#endif
+#if IS_ENABLED(CONFIG_HID_NTRIG)
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2) },
@@ -2014,13 +2120,41 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
        { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ORTEK)
        { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PANTHERLORD)
+       { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PENMOUNT)
        { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PETALYNX)
        { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PICOLCD)
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PLANTRONICS)
        { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PRIMAX)
        { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) },
+#endif
+#if IS_ENABLED(CONFIG_HID_PRODIKEYS)
+       { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
+#endif
+#if IS_ENABLED(CONFIG_HID_RMI)
+       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
+#endif
 #if IS_ENABLED(CONFIG_HID_ROCCAT)
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
@@ -2048,9 +2182,21 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
 #endif
+#if IS_ENABLED(CONFIG_HID_SAMSUNG)
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SMARTJOYPLUS)
+       { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SONY)
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) },
@@ -2069,9 +2215,17 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SPEEDLINK)
+       { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_STEELSERIES)
        { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
+#endif
+#if IS_ENABLED(CONFIG_HID_SUNPLUS)
        { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
+#endif
+#if IS_ENABLED(CONFIG_HID_THRUSTMASTER)
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
@@ -2080,12 +2234,25 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
+#endif
+#if IS_ENABLED(CONFIG_HID_TIVO)
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) },
+#endif
+#if IS_ENABLED(CONFIG_HID_TOPSEED)
+       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
+#endif
+#if IS_ENABLED(CONFIG_HID_TWINHAN)
        { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_UCLOGIC)
+       { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
@@ -2093,20 +2260,17 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
        { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_EX07S) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
+#endif
+#if IS_ENABLED(CONFIG_HID_UDRAW_PS3)
+       { HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
+#endif
+#if IS_ENABLED(CONFIG_HID_WALTOP)
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) },
@@ -2114,19 +2278,18 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_XINMO)
        { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_THT_2P_ARCADE) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ZEROPLUS)
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
+#endif
+#if IS_ENABLED(CONFIG_HID_ZYDACRON)
        { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) },
-
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM6533) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
+#endif
        { }
 };
 
index 6e3848a8d8dd1416a0091ce0e7d263325dd8910b..e2c7465df69f3ae74c2cb1979c531b02e2934089 100644 (file)
@@ -1,10 +1,8 @@
 /*
- *  HID driver for Elecom BM084 (bluetooth mouse).
- *  Removes a non-existing horizontal wheel from
- *  the HID descriptor.
- *  (This module is based on "hid-ortek".)
- *
+ *  HID driver for ELECOM devices.
  *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
+ *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
+ *  Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
  */
 
 /*
 static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
-       if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
-               hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
-               rdesc[47] = 0x00;
+       switch (hdev->product) {
+       case USB_DEVICE_ID_ELECOM_BM084:
+               /* The BM084 Bluetooth mouse includes a non-existing horizontal
+                * wheel in the HID descriptor. */
+               if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) {
+                       hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
+                       rdesc[47] = 0x00;
+               }
+               break;
+       case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
+       case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
+               /* The DEFT trackball has eight buttons, but its descriptor only
+                * reports five, disabling the three Fn buttons on the top of
+                * the mouse.
+                *
+                * Apply the following diff to the descriptor:
+                *
+                * Collection (Physical),              Collection (Physical),
+                *     Report ID (1),                      Report ID (1),
+                *     Report Count (5),           ->      Report Count (8),
+                *     Report Size (1),                    Report Size (1),
+                *     Usage Page (Button),                Usage Page (Button),
+                *     Usage Minimum (01h),                Usage Minimum (01h),
+                *     Usage Maximum (05h),        ->      Usage Maximum (08h),
+                *     Logical Minimum (0),                Logical Minimum (0),
+                *     Logical Maximum (1),                Logical Maximum (1),
+                *     Input (Variable),                   Input (Variable),
+                *     Report Count (1),           ->      Report Count (0),
+                *     Report Size (3),                    Report Size (3),
+                *     Input (Constant),                   Input (Constant),
+                *     Report Size (16),                   Report Size (16),
+                *     Report Count (2),                   Report Count (2),
+                *     Usage Page (Desktop),               Usage Page (Desktop),
+                *     Usage (X),                          Usage (X),
+                *     Usage (Y),                          Usage (Y),
+                *     Logical Minimum (-32768),           Logical Minimum (-32768),
+                *     Logical Maximum (32767),            Logical Maximum (32767),
+                *     Input (Variable, Relative),         Input (Variable, Relative),
+                * End Collection,                     End Collection,
+                */
+               if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
+                       hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n");
+                       rdesc[13] = 8; /* Button/Variable Report Count */
+                       rdesc[21] = 8; /* Button/Variable Usage Maximum */
+                       rdesc[29] = 0; /* Button/Constant Report Count */
+               }
+               break;
        }
        return rdesc;
 }
 
 static const struct hid_device_id elecom_devices[] = {
-       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084)},
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, elecom_devices);
index 643390ba749d96c5ddb5fbde68fda45c38569c3d..4f9a3938189a020ca6257b85182e6c1b53426158 100644 (file)
 #define USB_VENDOR_ID_ASUSTEK          0x0b05
 #define USB_DEVICE_ID_ASUSTEK_LCM      0x1726
 #define USB_DEVICE_ID_ASUSTEK_LCM2     0x175b
+#define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD    0x17e0
 #define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD     0x8585
 #define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD     0x0101
 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
 #define USB_VENDOR_ID_DELCOM           0x0fc5
 #define USB_DEVICE_ID_DELCOM_VISUAL_IND        0xb080
 
+#define USB_VENDOR_ID_DELL                             0x413c
+#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE    0x301a
+
 #define USB_VENDOR_ID_DELORME          0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE        0x0100
 #define USB_DEVICE_ID_DELORME_EM_LT20  0x0200
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
+#define USB_DEVICE_ID_ELECOM_DEFT_WIRED        0x00fe
+#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS     0x00ff
 
 #define USB_VENDOR_ID_DREAM_CHEEKY     0x1d34
 #define USB_DEVICE_ID_DREAM_CHEEKY_WN  0x0004
index 8daa8ce64ebba51e91e57ec801fa7e702fb2a072..fb55fb4c39fcfecaca55c0b8720d28d2f9717678 100644 (file)
@@ -897,6 +897,15 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
        return 0;
 }
 
+static void i2c_hid_acpi_fix_up_power(struct device *dev)
+{
+       acpi_handle handle = ACPI_HANDLE(dev);
+       struct acpi_device *adev;
+
+       if (handle && acpi_bus_get_device(handle, &adev) == 0)
+               acpi_device_fix_up_power(adev);
+}
+
 static const struct acpi_device_id i2c_hid_acpi_match[] = {
        {"ACPI0C50", 0 },
        {"PNP0C50", 0 },
@@ -909,6 +918,8 @@ static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
 {
        return -ENODEV;
 }
+
+static inline void i2c_hid_acpi_fix_up_power(struct device *dev) {}
 #endif
 
 #ifdef CONFIG_OF
@@ -1030,6 +1041,8 @@ static int i2c_hid_probe(struct i2c_client *client,
        if (ret < 0)
                goto err_regulator;
 
+       i2c_hid_acpi_fix_up_power(&client->dev);
+
        pm_runtime_get_noresume(&client->dev);
        pm_runtime_set_active(&client->dev);
        pm_runtime_enable(&client->dev);
index 6316498b78128574ff63b0047772f009e6d0cfeb..a88e7c7bea0a0cb7d069c262c026231f3bc75dea 100644 (file)
@@ -85,6 +85,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT },
index 4b225fb19a16842f635026d1b1023d5d1cf5068e..e274c9dc32f3a211d97d02f2b6477f20c9121fac 100644 (file)
@@ -1571,37 +1571,38 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 {
        unsigned char *data = wacom->data;
 
-       if (wacom->pen_input)
+       if (wacom->pen_input) {
                dev_dbg(wacom->pen_input->dev.parent,
                        "%s: received report #%d\n", __func__, data[0]);
-       else if (wacom->touch_input)
+
+               if (len == WACOM_PKGLEN_PENABLED ||
+                   data[0] == WACOM_REPORT_PENABLED)
+                       return wacom_tpc_pen(wacom);
+       }
+       else if (wacom->touch_input) {
                dev_dbg(wacom->touch_input->dev.parent,
                        "%s: received report #%d\n", __func__, data[0]);
 
-       switch (len) {
-       case WACOM_PKGLEN_TPC1FG:
-               return wacom_tpc_single_touch(wacom, len);
+               switch (len) {
+               case WACOM_PKGLEN_TPC1FG:
+                       return wacom_tpc_single_touch(wacom, len);
 
-       case WACOM_PKGLEN_TPC2FG:
-               return wacom_tpc_mt_touch(wacom);
+               case WACOM_PKGLEN_TPC2FG:
+                       return wacom_tpc_mt_touch(wacom);
 
-       case WACOM_PKGLEN_PENABLED:
-               return wacom_tpc_pen(wacom);
+               default:
+                       switch (data[0]) {
+                       case WACOM_REPORT_TPC1FG:
+                       case WACOM_REPORT_TPCHID:
+                       case WACOM_REPORT_TPCST:
+                       case WACOM_REPORT_TPC1FGE:
+                               return wacom_tpc_single_touch(wacom, len);
 
-       default:
-               switch (data[0]) {
-               case WACOM_REPORT_TPC1FG:
-               case WACOM_REPORT_TPCHID:
-               case WACOM_REPORT_TPCST:
-               case WACOM_REPORT_TPC1FGE:
-                       return wacom_tpc_single_touch(wacom, len);
-
-               case WACOM_REPORT_TPCMT:
-               case WACOM_REPORT_TPCMT2:
-                       return wacom_mt_touch(wacom);
+                       case WACOM_REPORT_TPCMT:
+                       case WACOM_REPORT_TPCMT2:
+                               return wacom_mt_touch(wacom);
 
-               case WACOM_REPORT_PENABLED:
-                       return wacom_tpc_pen(wacom);
+                       }
                }
        }
 
index 26b05106f0d3152e74bc0377dc9006203fc2c7db..93d28c0ec8bf0ef867bc958592c58f60d3ce2913 100644 (file)
@@ -1066,7 +1066,7 @@ static void ssip_pn_setup(struct net_device *dev)
        dev->addr_len           = 1;
        dev->tx_queue_len       = SSIP_TXQUEUE_LEN;
 
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->header_ops         = &phonet_header_ops;
 }
 
index 22d5eafd681541374817314a1a2db164bb235ce7..5ef2814345ef7f37aa47fd47b8765ce6cc7fad1b 100644 (file)
@@ -343,6 +343,7 @@ config SENSORS_ASB100
 
 config SENSORS_ASPEED
        tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver"
+       select REGMAP
        help
          This driver provides support for ASPEED AST2400/AST2500 PWM
          and Fan Tacho controllers.
index 48403a2115beb68df404766350cfa844974a55e3..9de13d626c6896d379da385ab48da29258e5f3ee 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/errno.h>
 #include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/hwmon.h>
@@ -494,7 +495,7 @@ static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data
        return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
 }
 
-static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
+static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
                                      u8 fan_tach_ch)
 {
        u32 raw_data, tach_div, clk_source, sec, val;
@@ -510,6 +511,9 @@ static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
        msleep(sec);
 
        regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
+       if (!(val & RESULT_STATUS_MASK))
+               return -ETIMEDOUT;
+
        raw_data = val & RESULT_VALUE_MASK;
        tach_div = priv->type_fan_tach_clock_division[type];
        tach_div = 0x4 << (tach_div * 2);
@@ -561,12 +565,14 @@ static ssize_t show_rpm(struct device *dev, struct device_attribute *attr,
 {
        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
        int index = sensor_attr->index;
-       u32 rpm;
+       int rpm;
        struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
 
        rpm = aspeed_get_fan_tach_ch_rpm(priv, index);
+       if (rpm < 0)
+               return rpm;
 
-       return sprintf(buf, "%u\n", rpm);
+       return sprintf(buf, "%d\n", rpm);
 }
 
 static umode_t pwm_is_visible(struct kobject *kobj,
@@ -591,24 +597,23 @@ static umode_t fan_dev_is_visible(struct kobject *kobj,
        return a->mode;
 }
 
-static SENSOR_DEVICE_ATTR(pwm0, 0644,
-                       show_pwm, set_pwm, 0);
 static SENSOR_DEVICE_ATTR(pwm1, 0644,
-                       show_pwm, set_pwm, 1);
+                       show_pwm, set_pwm, 0);
 static SENSOR_DEVICE_ATTR(pwm2, 0644,
-                       show_pwm, set_pwm, 2);
+                       show_pwm, set_pwm, 1);
 static SENSOR_DEVICE_ATTR(pwm3, 0644,
-                       show_pwm, set_pwm, 3);
+                       show_pwm, set_pwm, 2);
 static SENSOR_DEVICE_ATTR(pwm4, 0644,
-                       show_pwm, set_pwm, 4);
+                       show_pwm, set_pwm, 3);
 static SENSOR_DEVICE_ATTR(pwm5, 0644,
-                       show_pwm, set_pwm, 5);
+                       show_pwm, set_pwm, 4);
 static SENSOR_DEVICE_ATTR(pwm6, 0644,
-                       show_pwm, set_pwm, 6);
+                       show_pwm, set_pwm, 5);
 static SENSOR_DEVICE_ATTR(pwm7, 0644,
+                       show_pwm, set_pwm, 6);
+static SENSOR_DEVICE_ATTR(pwm8, 0644,
                        show_pwm, set_pwm, 7);
 static struct attribute *pwm_dev_attrs[] = {
-       &sensor_dev_attr_pwm0.dev_attr.attr,
        &sensor_dev_attr_pwm1.dev_attr.attr,
        &sensor_dev_attr_pwm2.dev_attr.attr,
        &sensor_dev_attr_pwm3.dev_attr.attr,
@@ -616,6 +621,7 @@ static struct attribute *pwm_dev_attrs[] = {
        &sensor_dev_attr_pwm5.dev_attr.attr,
        &sensor_dev_attr_pwm6.dev_attr.attr,
        &sensor_dev_attr_pwm7.dev_attr.attr,
+       &sensor_dev_attr_pwm8.dev_attr.attr,
        NULL,
 };
 
@@ -624,40 +630,39 @@ static const struct attribute_group pwm_dev_group = {
        .is_visible = pwm_is_visible,
 };
 
-static SENSOR_DEVICE_ATTR(fan0_input, 0444,
-               show_rpm, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_input, 0444,
-               show_rpm, NULL, 1);
+               show_rpm, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan2_input, 0444,
-               show_rpm, NULL, 2);
+               show_rpm, NULL, 1);
 static SENSOR_DEVICE_ATTR(fan3_input, 0444,
-               show_rpm, NULL, 3);
+               show_rpm, NULL, 2);
 static SENSOR_DEVICE_ATTR(fan4_input, 0444,
-               show_rpm, NULL, 4);
+               show_rpm, NULL, 3);
 static SENSOR_DEVICE_ATTR(fan5_input, 0444,
-               show_rpm, NULL, 5);
+               show_rpm, NULL, 4);
 static SENSOR_DEVICE_ATTR(fan6_input, 0444,
-               show_rpm, NULL, 6);
+               show_rpm, NULL, 5);
 static SENSOR_DEVICE_ATTR(fan7_input, 0444,
-               show_rpm, NULL, 7);
+               show_rpm, NULL, 6);
 static SENSOR_DEVICE_ATTR(fan8_input, 0444,
-               show_rpm, NULL, 8);
+               show_rpm, NULL, 7);
 static SENSOR_DEVICE_ATTR(fan9_input, 0444,
-               show_rpm, NULL, 9);
+               show_rpm, NULL, 8);
 static SENSOR_DEVICE_ATTR(fan10_input, 0444,
-               show_rpm, NULL, 10);
+               show_rpm, NULL, 9);
 static SENSOR_DEVICE_ATTR(fan11_input, 0444,
-               show_rpm, NULL, 11);
+               show_rpm, NULL, 10);
 static SENSOR_DEVICE_ATTR(fan12_input, 0444,
-               show_rpm, NULL, 12);
+               show_rpm, NULL, 11);
 static SENSOR_DEVICE_ATTR(fan13_input, 0444,
-               show_rpm, NULL, 13);
+               show_rpm, NULL, 12);
 static SENSOR_DEVICE_ATTR(fan14_input, 0444,
-               show_rpm, NULL, 14);
+               show_rpm, NULL, 13);
 static SENSOR_DEVICE_ATTR(fan15_input, 0444,
+               show_rpm, NULL, 14);
+static SENSOR_DEVICE_ATTR(fan16_input, 0444,
                show_rpm, NULL, 15);
 static struct attribute *fan_dev_attrs[] = {
-       &sensor_dev_attr_fan0_input.dev_attr.attr,
        &sensor_dev_attr_fan1_input.dev_attr.attr,
        &sensor_dev_attr_fan2_input.dev_attr.attr,
        &sensor_dev_attr_fan3_input.dev_attr.attr,
@@ -673,6 +678,7 @@ static struct attribute *fan_dev_attrs[] = {
        &sensor_dev_attr_fan13_input.dev_attr.attr,
        &sensor_dev_attr_fan14_input.dev_attr.attr,
        &sensor_dev_attr_fan15_input.dev_attr.attr,
+       &sensor_dev_attr_fan16_input.dev_attr.attr,
        NULL
 };
 
@@ -802,7 +808,6 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
                if (ret)
                        return ret;
        }
-       of_node_put(np);
 
        priv->groups[0] = &pwm_dev_group;
        priv->groups[1] = &fan_dev_group;
index 3ac4c03ba77ba3e0c79fd4dc11c606c09c8b3cbf..c13a4fd86b3cbaf47f48e1d7a24fa2c845513743 100644 (file)
@@ -604,6 +604,13 @@ static int coretemp_cpu_online(unsigned int cpu)
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct platform_data *pdata;
 
+       /*
+        * Don't execute this on resume as the offline callback did
+        * not get executed on suspend.
+        */
+       if (cpuhp_tasks_frozen)
+               return 0;
+
        /*
         * CPUID.06H.EAX[0] indicates whether the CPU has thermal
         * sensors. We check this bit only, all the early CPUs
@@ -654,6 +661,13 @@ static int coretemp_cpu_offline(unsigned int cpu)
        struct temp_data *tdata;
        int indx, target;
 
+       /*
+        * Don't execute this on suspend as the device remove locks
+        * up the machine.
+        */
+       if (cpuhp_tasks_frozen)
+               return 0;
+
        /* If the physical CPU device does not exist, just return */
        if (!pdev)
                return 0;
index f2acd4b6bf0116fe2537c8d6b411b3279fd03959..d1263b82d646a1524697b38e2f63b31bd14f153d 100644 (file)
@@ -94,6 +94,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
 static int dw_i2c_acpi_configure(struct platform_device *pdev)
 {
        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+       u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
        acpi_handle handle = ACPI_HANDLE(&pdev->dev);
        const struct acpi_device_id *id;
        struct acpi_device *adev;
@@ -107,23 +108,24 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
         * Try to get SDA hold time and *CNT values from an ACPI method for
         * selected speed modes.
         */
+       dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht);
+       dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht);
+       dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
+       dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
+
        switch (dev->clk_freq) {
        case 100000:
-               dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = ss_ht;
                break;
        case 1000000:
-               dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = fp_ht;
                break;
        case 3400000:
-               dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = hs_ht;
                break;
        case 400000:
        default:
-               dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = fs_ht;
                break;
        }
 
index 95ed17183e73e904e06b13c383bee28410797172..54a47b40546f69c7ea0d3dbf033c22c95f106516 100644 (file)
@@ -734,9 +734,9 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
                 * the first read operation, otherwise the first read cost
                 * one extra clock cycle.
                 */
-               temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+               temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
                temp |= I2CR_MTX;
-               writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+               imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
        }
        msgs->buf[msgs->len-1] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
 
@@ -857,9 +857,9 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
                                 * the first read operation, otherwise the first read cost
                                 * one extra clock cycle.
                                 */
-                               temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+                               temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
                                temp |= I2CR_MTX;
-                               writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+                               imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
                        }
                } else if (i == (msgs->len - 2)) {
                        dev_dbg(&i2c_imx->adapter.dev,
index f573448d2132161d4839a17d11afb1c1f4104188..e98e44e584a44a6e17dc3af00ae1f02ce50ae95b 100644 (file)
@@ -584,7 +584,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
 
        /* unmap the data buffer */
        if (dma_size != 0)
-               dma_unmap_single(&adap->dev, dma_addr, dma_size, dma_direction);
+               dma_unmap_single(dev, dma_addr, dma_size, dma_direction);
 
        if (unlikely(!time_left)) {
                dev_err(dev, "completion wait timed out\n");
index cf737ec8563b873042a519e6f1337e3f095e10dd..5c4db65c5019b7692c645dfaec9d391623355a81 100644 (file)
@@ -819,7 +819,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
                rc = -EINVAL;
                goto out;
        }
-       drv_data->irq = irq_of_parse_and_map(np, 0);
 
        drv_data->rstc = devm_reset_control_get_optional(dev, NULL);
        if (IS_ERR(drv_data->rstc)) {
@@ -902,10 +901,11 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        if (!IS_ERR(drv_data->clk))
                clk_prepare_enable(drv_data->clk);
 
+       drv_data->irq = platform_get_irq(pd, 0);
+
        if (pdata) {
                drv_data->freq_m = pdata->freq_m;
                drv_data->freq_n = pdata->freq_n;
-               drv_data->irq = platform_get_irq(pd, 0);
                drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
                drv_data->offload_enabled = false;
                memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets));
@@ -915,7 +915,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
                        goto exit_clk;
        }
        if (drv_data->irq < 0) {
-               rc = -ENXIO;
+               rc = drv_data->irq;
                goto exit_reset;
        }
 
index 214bf2835d1f95ff176cb0ded24654b20b821944..8be3e6cb8fe686a02b62eb1b699a1763e0186df5 100644 (file)
@@ -319,7 +319,7 @@ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)
        rcar_i2c_write(priv, ICFBSCR, TCYC06);
 
        dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
-                        priv->msg->len, priv->dma_direction);
+                        sg_dma_len(&priv->sg), priv->dma_direction);
 
        priv->dma_direction = DMA_NONE;
 }
index 0ed77eeff31e661fe5a4c6b8426c7d2cd6a10f89..a2e3dd715380c74397a5cf2c1a778786eb12826b 100644 (file)
@@ -178,22 +178,39 @@ static int usb_read(struct i2c_adapter *adapter, int cmd,
                    int value, int index, void *data, int len)
 {
        struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+       void *dmadata = kmalloc(len, GFP_KERNEL);
+       int ret;
+
+       if (!dmadata)
+               return -ENOMEM;
 
        /* do control transfer */
-       return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
+       ret = usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
                               cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
-                              USB_DIR_IN, value, index, data, len, 2000);
+                              USB_DIR_IN, value, index, dmadata, len, 2000);
+
+       memcpy(data, dmadata, len);
+       kfree(dmadata);
+       return ret;
 }
 
 static int usb_write(struct i2c_adapter *adapter, int cmd,
                     int value, int index, void *data, int len)
 {
        struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
+       void *dmadata = kmemdup(data, len, GFP_KERNEL);
+       int ret;
+
+       if (!dmadata)
+               return -ENOMEM;
 
        /* do control transfer */
-       return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
+       ret = usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
                               cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                              value, index, data, len, 2000);
+                              value, index, dmadata, len, 2000);
+
+       kfree(dmadata);
+       return ret;
 }
 
 static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
index dbe7e44c9321279bbcd7b3f8d2006dbe1365e0b7..6ba6c83ca8f1bc9ee0c22bbb99e004e6bb50a77f 100644 (file)
@@ -416,6 +416,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
        adapter->class = I2C_CLASS_HWMON;
        adapter->dev.parent = &pdev->dev;
        adapter->dev.of_node = pdev->dev.of_node;
+       ACPI_COMPANION_SET(&adapter->dev, ACPI_COMPANION(&pdev->dev));
        i2c_set_adapdata(adapter, ctx);
        rc = i2c_add_adapter(adapter);
        if (rc) {
index 26f7237558bad75f8a111037e725a37b519d751e..9669ca4937b891063d4cd63e552344d818f5eefa 100644 (file)
@@ -395,18 +395,20 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
        if (force_nr) {
                priv->adap.nr = force_nr;
                ret = i2c_add_numbered_adapter(&priv->adap);
-               dev_err(&parent->dev,
-                       "failed to add mux-adapter %u as bus %u (error=%d)\n",
-                       chan_id, force_nr, ret);
+               if (ret < 0) {
+                       dev_err(&parent->dev,
+                               "failed to add mux-adapter %u as bus %u (error=%d)\n",
+                               chan_id, force_nr, ret);
+                       goto err_free_priv;
+               }
        } else {
                ret = i2c_add_adapter(&priv->adap);
-               dev_err(&parent->dev,
-                       "failed to add mux-adapter %u (error=%d)\n",
-                       chan_id, ret);
-       }
-       if (ret < 0) {
-               kfree(priv);
-               return ret;
+               if (ret < 0) {
+                       dev_err(&parent->dev,
+                               "failed to add mux-adapter %u (error=%d)\n",
+                               chan_id, ret);
+                       goto err_free_priv;
+               }
        }
 
        WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
@@ -422,6 +424,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
 
        muxc->adapter[muxc->num_adapters++] = &priv->adap;
        return 0;
+
+err_free_priv:
+       kfree(priv);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
 
index 406d5059072cbe41964105d752a42236e66f7c8d..d97031804de8b477e9e77da0b2b31bb1abdcc907 100644 (file)
@@ -196,20 +196,25 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                mux->data.reg_size = resource_size(res);
                mux->data.reg = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(mux->data.reg))
-                       return PTR_ERR(mux->data.reg);
+               if (IS_ERR(mux->data.reg)) {
+                       ret = PTR_ERR(mux->data.reg);
+                       goto err_put_parent;
+               }
        }
 
        if (mux->data.reg_size != 4 && mux->data.reg_size != 2 &&
            mux->data.reg_size != 1) {
                dev_err(&pdev->dev, "Invalid register size\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_put_parent;
        }
 
        muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
                             i2c_mux_reg_select, NULL);
-       if (!muxc)
-               return -ENOMEM;
+       if (!muxc) {
+               ret = -ENOMEM;
+               goto err_put_parent;
+       }
        muxc->priv = mux;
 
        platform_set_drvdata(pdev, muxc);
@@ -223,7 +228,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 
                ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
                if (ret)
-                       goto add_adapter_failed;
+                       goto err_del_mux_adapters;
        }
 
        dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
@@ -231,8 +236,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 
        return 0;
 
-add_adapter_failed:
+err_del_mux_adapters:
        i2c_mux_del_adapters(muxc);
+err_put_parent:
+       i2c_put_adapter(parent);
 
        return ret;
 }
index 21d38c8af21e560990915b93af8715827d33ee49..7f4f9c4150e3ebfc304cf491050166e7bdffc5a5 100644 (file)
@@ -143,7 +143,7 @@ static void iproc_adc_reg_dump(struct iio_dev *indio_dev)
        iproc_adc_dbg_reg(dev, adc_priv, IPROC_SOFT_BYPASS_DATA);
 }
 
-static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
+static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
 {
        u32 channel_intr_status;
        u32 intr_status;
@@ -167,7 +167,7 @@ static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
        return IRQ_NONE;
 }
 
-static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
+static irqreturn_t iproc_adc_interrupt_handler(int irq, void *data)
 {
        irqreturn_t retval = IRQ_NONE;
        struct iproc_adc_priv *adc_priv;
@@ -181,7 +181,7 @@ static irqreturn_t iproc_adc_interrupt_thread(int irq, void *data)
        adc_priv = iio_priv(indio_dev);
 
        regmap_read(adc_priv->regmap, IPROC_INTERRUPT_STATUS, &intr_status);
-       dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_thread(),INTRPT_STS:%x\n",
+       dev_dbg(&indio_dev->dev, "iproc_adc_interrupt_handler(),INTRPT_STS:%x\n",
                        intr_status);
 
        intr_channels = (intr_status & IPROC_ADC_INTR_MASK) >> IPROC_ADC_INTR;
@@ -566,8 +566,8 @@ static int iproc_adc_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_threaded_irq(&pdev->dev, adc_priv->irqno,
-                               iproc_adc_interrupt_thread,
                                iproc_adc_interrupt_handler,
+                               iproc_adc_interrupt_thread,
                                IRQF_SHARED, "iproc-adc", indio_dev);
        if (ret) {
                dev_err(&pdev->dev, "request_irq error %d\n", ret);
index ec82106480e124d6188ddb0a000c13bfb3addb76..b0526e4b9530a00265f5051736a22ba845f8004f 100644 (file)
@@ -438,10 +438,10 @@ static ssize_t max9611_shunt_resistor_show(struct device *dev,
        struct max9611_dev *max9611 = iio_priv(dev_to_iio_dev(dev));
        unsigned int i, r;
 
-       i = max9611->shunt_resistor_uohm / 1000;
-       r = max9611->shunt_resistor_uohm % 1000;
+       i = max9611->shunt_resistor_uohm / 1000000;
+       r = max9611->shunt_resistor_uohm % 1000000;
 
-       return sprintf(buf, "%u.%03u\n", i, r);
+       return sprintf(buf, "%u.%06u\n", i, r);
 }
 
 static IIO_DEVICE_ATTR(in_power_shunt_resistor, 0444,
@@ -536,8 +536,8 @@ static int max9611_probe(struct i2c_client *client,
        int ret;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*max9611));
-       if (IS_ERR(indio_dev))
-               return PTR_ERR(indio_dev);
+       if (!indio_dev)
+               return -ENOMEM;
 
        i2c_set_clientdata(client, indio_dev);
 
index dd4190b50df6a71a43d0fb22175ddb3f1e7d64c7..6066bbfc42fe4126a849495563e1eae58d4244d4 100644 (file)
@@ -468,13 +468,13 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
 static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev)
 {
        struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
-       int count;
+       unsigned int count, tmp;
 
        for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) {
                if (!meson_sar_adc_get_fifo_count(indio_dev))
                        break;
 
-               regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, 0);
+               regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp);
        }
 }
 
index b0c7d8ee5cb8d859d683b2b0aca40ef5999d2546..6888167ca1e6cb65ab926b36fe8199684a00527d 100644 (file)
@@ -718,9 +718,12 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev)
        adc->dev = dev;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iores)
+               return -EINVAL;
+
        adc->base = devm_ioremap(dev, iores->start, resource_size(iores));
-       if (IS_ERR(adc->base))
-               return PTR_ERR(adc->base);
+       if (!adc->base)
+               return -ENOMEM;
 
        init_completion(&adc->completion);
        spin_lock_init(&adc->lock);
index b2352730908805f8a29822a6a00413452a3464cb..81d4c39e414a4da6b0f8df0ebd8922d371a909d7 100644 (file)
@@ -105,6 +105,8 @@ struct sun4i_gpadc_iio {
        bool                            no_irq;
        /* prevents concurrent reads of temperature and ADC */
        struct mutex                    mutex;
+       struct thermal_zone_device      *tzd;
+       struct device                   *sensor_device;
 };
 
 #define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) {             \
@@ -502,7 +504,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
 {
        struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
        const struct of_device_id *of_dev;
-       struct thermal_zone_device *tzd;
        struct resource *mem;
        void __iomem *base;
        int ret;
@@ -532,13 +533,14 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
        if (!IS_ENABLED(CONFIG_THERMAL_OF))
                return 0;
 
-       tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
-                                                  &sun4i_ts_tz_ops);
-       if (IS_ERR(tzd))
+       info->sensor_device = &pdev->dev;
+       info->tzd = thermal_zone_of_sensor_register(info->sensor_device, 0,
+                                                   info, &sun4i_ts_tz_ops);
+       if (IS_ERR(info->tzd))
                dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
-                       PTR_ERR(tzd));
+                       PTR_ERR(info->tzd));
 
-       return PTR_ERR_OR_ZERO(tzd);
+       return PTR_ERR_OR_ZERO(info->tzd);
 }
 
 static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
@@ -584,15 +586,15 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
                 * of_node, and the device from this driver as third argument to
                 * return the temperature.
                 */
-               struct thermal_zone_device *tzd;
-               tzd = devm_thermal_zone_of_sensor_register(pdev->dev.parent, 0,
-                                                          info,
-                                                          &sun4i_ts_tz_ops);
-               if (IS_ERR(tzd)) {
+               info->sensor_device = pdev->dev.parent;
+               info->tzd = thermal_zone_of_sensor_register(info->sensor_device,
+                                                           0, info,
+                                                           &sun4i_ts_tz_ops);
+               if (IS_ERR(info->tzd)) {
                        dev_err(&pdev->dev,
                                "could not register thermal sensor: %ld\n",
-                               PTR_ERR(tzd));
-                       return PTR_ERR(tzd);
+                               PTR_ERR(info->tzd));
+                       return PTR_ERR(info->tzd);
                }
        } else {
                indio_dev->num_channels =
@@ -688,7 +690,13 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
 
        pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
-       if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))
+
+       if (!IS_ENABLED(CONFIG_THERMAL_OF))
+               return 0;
+
+       thermal_zone_of_sensor_unregister(info->sensor_device, info->tzd);
+
+       if (!info->no_irq)
                iio_map_array_unregister(indio_dev);
 
        return 0;
@@ -700,6 +708,7 @@ static const struct platform_device_id sun4i_gpadc_id[] = {
        { "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id);
 
 static struct platform_driver sun4i_gpadc_driver = {
        .driver = {
@@ -711,6 +720,7 @@ static struct platform_driver sun4i_gpadc_driver = {
        .probe = sun4i_gpadc_probe,
        .remove = sun4i_gpadc_remove,
 };
+MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
 
 module_platform_driver(sun4i_gpadc_driver);
 
index 4282ceca3d8f9f417a1a511b3d608896a7ad4159..6cbed7eb118a60d976afbb826d9edd32b62f101d 100644 (file)
@@ -614,7 +614,7 @@ static int tiadc_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev));
+       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
        if (indio_dev == NULL) {
                dev_err(&pdev->dev, "failed to allocate iio device\n");
                return -ENOMEM;
index dd99d273bae9bf620f2543b39400d10e5ae66fd6..ff03324dee132f49455fd156bacbc9b450146a19 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/poll.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/buffer_impl.h>
 #include <linux/iio/buffer-dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/sizes.h>
index 9fabed47053ddaf2517500845d337429f6c9af22..2b5a320f42c51e1872835b19454f8924f2e004ea 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/buffer_impl.h>
 #include <linux/iio/buffer-dma.h>
 #include <linux/iio/buffer-dmaengine.h>
 
index 96dabbd2f004b3d91c1cde6cca2f6dfdaf091d58..88a7c5d4e4d2850ae9755b5fb79ff595855cac7c 100644 (file)
@@ -41,6 +41,7 @@ static const int accel_scale[] = {598, 1196, 2392, 4785};
 static const struct inv_mpu6050_reg_map reg_set_6500 = {
        .sample_rate_div        = INV_MPU6050_REG_SAMPLE_RATE_DIV,
        .lpf                    = INV_MPU6050_REG_CONFIG,
+       .accel_lpf              = INV_MPU6500_REG_ACCEL_CONFIG_2,
        .user_ctrl              = INV_MPU6050_REG_USER_CTRL,
        .fifo_en                = INV_MPU6050_REG_FIFO_EN,
        .gyro_config            = INV_MPU6050_REG_GYRO_CONFIG,
@@ -210,6 +211,37 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
 }
 EXPORT_SYMBOL_GPL(inv_mpu6050_set_power_itg);
 
+/**
+ *  inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent
+ *
+ *  MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope
+ *  MPU6500 and above have a dedicated register for accelerometer
+ */
+static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
+                                   enum inv_mpu6050_filter_e val)
+{
+       int result;
+
+       result = regmap_write(st->map, st->reg->lpf, val);
+       if (result)
+               return result;
+
+       switch (st->chip_type) {
+       case INV_MPU6050:
+       case INV_MPU6000:
+       case INV_MPU9150:
+               /* old chips, nothing to do */
+               result = 0;
+               break;
+       default:
+               /* set accel lpf */
+               result = regmap_write(st->map, st->reg->accel_lpf, val);
+               break;
+       }
+
+       return result;
+}
+
 /**
  *  inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
  *
@@ -233,8 +265,7 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
        if (result)
                return result;
 
-       d = INV_MPU6050_FILTER_20HZ;
-       result = regmap_write(st->map, st->reg->lpf, d);
+       result = inv_mpu6050_set_lpf_regs(st, INV_MPU6050_FILTER_20HZ);
        if (result)
                return result;
 
@@ -537,6 +568,8 @@ error_write_raw:
  *                  would be alising. This function basically search for the
  *                  correct low pass parameters based on the fifo rate, e.g,
  *                  sampling frequency.
+ *
+ *  lpf is set automatically when setting sampling rate to avoid any aliases.
  */
 static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
 {
@@ -552,7 +585,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
        while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
                i++;
        data = d[i];
-       result = regmap_write(st->map, st->reg->lpf, data);
+       result = inv_mpu6050_set_lpf_regs(st, data);
        if (result)
                return result;
        st->chip_config.lpf = data;
index ef13de7a2c20fd6ef3e450f8d3094483af71b9a9..953a0c09d5685a18d447e4ad07f3f334b32cd8cf 100644 (file)
@@ -28,6 +28,7 @@
  *  struct inv_mpu6050_reg_map - Notable registers.
  *  @sample_rate_div:  Divider applied to gyro output rate.
  *  @lpf:              Configures internal low pass filter.
+ *  @accel_lpf:                Configures accelerometer low pass filter.
  *  @user_ctrl:                Enables/resets the FIFO.
  *  @fifo_en:          Determines which data will appear in FIFO.
  *  @gyro_config:      gyro config register.
@@ -47,6 +48,7 @@
 struct inv_mpu6050_reg_map {
        u8 sample_rate_div;
        u8 lpf;
+       u8 accel_lpf;
        u8 user_ctrl;
        u8 fifo_en;
        u8 gyro_config;
@@ -188,6 +190,7 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_FIFO_THRESHOLD           500
 
 /* mpu6500 registers */
+#define INV_MPU6500_REG_ACCEL_CONFIG_2      0x1D
 #define INV_MPU6500_REG_ACCEL_OFFSET        0x77
 
 /* delay time in milliseconds */
index 978e1592c2a37869eac3b07a48f27354dc6036ff..4061fed93f1f8f015cd99acb307c08962dd0bee0 100644 (file)
@@ -451,7 +451,8 @@ static ssize_t iio_trigger_write_current(struct device *dev,
        return len;
 
 out_trigger_put:
-       iio_trigger_put(trig);
+       if (trig)
+               iio_trigger_put(trig);
        return ret;
 }
 
index b30e0c1c6cc4b70eecab00d4ae49b616a26a7e94..67838edd8b37fbad0e6289f249c223e99f221740 100644 (file)
@@ -74,9 +74,9 @@ static const int int_time_mapping[] = {100000, 50000, 200000, 400000};
 static const struct reg_field reg_field_it =
                                REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4);
 static const struct reg_field reg_field_als_intr =
-                               REG_FIELD(LTR501_INTR, 0, 0);
-static const struct reg_field reg_field_ps_intr =
                                REG_FIELD(LTR501_INTR, 1, 1);
+static const struct reg_field reg_field_ps_intr =
+                               REG_FIELD(LTR501_INTR, 0, 0);
 static const struct reg_field reg_field_als_rate =
                                REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2);
 static const struct reg_field reg_field_ps_rate =
index ddf9bee89f777872ec27db426a46c18dd5da2fc3..aa4df0dcc8c9b81d67b3ebaedc9b9d25392bbfef 100644 (file)
@@ -40,9 +40,9 @@
 #define AS3935_AFE_PWR_BIT     BIT(0)
 
 #define AS3935_INT             0x03
-#define AS3935_INT_MASK                0x07
+#define AS3935_INT_MASK                0x0f
 #define AS3935_EVENT_INT       BIT(3)
-#define AS3935_NOISE_INT       BIT(1)
+#define AS3935_NOISE_INT       BIT(0)
 
 #define AS3935_DATA            0x07
 #define AS3935_DATA_MASK       0x3F
@@ -215,7 +215,7 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private)
 
        st->buffer[0] = val & AS3935_DATA_MASK;
        iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
-                                          pf->timestamp);
+                                          iio_get_time_ns(indio_dev));
 err_read:
        iio_trigger_notify_done(indio_dev->trig);
 
@@ -244,7 +244,7 @@ static void as3935_event_work(struct work_struct *work)
 
        switch (val) {
        case AS3935_EVENT_INT:
-               iio_trigger_poll(st->trig);
+               iio_trigger_poll_chained(st->trig);
                break;
        case AS3935_NOISE_INT:
                dev_warn(&st->spi->dev, "noise level is too high\n");
@@ -269,8 +269,6 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private)
 
 static void calibrate_as3935(struct as3935_state *st)
 {
-       mutex_lock(&st->lock);
-
        /* mask disturber interrupt bit */
        as3935_write(st, AS3935_INT, BIT(5));
 
@@ -280,8 +278,6 @@ static void calibrate_as3935(struct as3935_state *st)
 
        mdelay(2);
        as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
-
-       mutex_unlock(&st->lock);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -318,6 +314,8 @@ static int as3935_resume(struct device *dev)
        val &= ~AS3935_AFE_PWR_BIT;
        ret = as3935_write(st, AS3935_AFE_GAIN, val);
 
+       calibrate_as3935(st);
+
 err_resume:
        mutex_unlock(&st->lock);
 
index 02971e239a182debc69aea1306169be981d97086..ece6926fa2e6aa242e38a189a7b3a8f7ed22e140 100644 (file)
@@ -449,12 +449,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
                return ret;
 
        rt = (struct rt6_info *)dst;
-       if (ipv6_addr_any(&fl6.saddr)) {
-               ret = ipv6_dev_get_saddr(addr->net, ip6_dst_idev(dst)->dev,
-                                        &fl6.daddr, 0, &fl6.saddr);
-               if (ret)
-                       goto put;
-
+       if (ipv6_addr_any(&src_in->sin6_addr)) {
                src_in->sin6_family = AF_INET6;
                src_in->sin6_addr = fl6.saddr;
        }
@@ -471,9 +466,6 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 
        *pdst = dst;
        return 0;
-put:
-       dst_release(dst);
-       return ret;
 }
 #else
 static int addr6_resolve(struct sockaddr_in6 *src_in,
index 1844770f3ae838bd63f3837bc0f475b0c8b5f1b1..2b4d613a347491295a51932699264c6edcd4bb51 100644 (file)
@@ -1429,7 +1429,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
        primary_path->packet_life_time =
                cm_req_get_primary_local_ack_timeout(req_msg);
        primary_path->packet_life_time -= (primary_path->packet_life_time > 0);
-       sa_path_set_service_id(primary_path, req_msg->service_id);
+       primary_path->service_id = req_msg->service_id;
 
        if (req_msg->alt_local_lid) {
                alt_path->dgid = req_msg->alt_local_gid;
@@ -1452,7 +1452,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
                alt_path->packet_life_time =
                        cm_req_get_alt_local_ack_timeout(req_msg);
                alt_path->packet_life_time -= (alt_path->packet_life_time > 0);
-               sa_path_set_service_id(alt_path, req_msg->service_id);
+               alt_path->service_id = req_msg->service_id;
        }
 }
 
index 91b7a2fe5a55488ce1e5bb886ba19023bd624328..31bb82d8ecd7f19bbee90bd95a83cec7fe5abca7 100644 (file)
@@ -1140,7 +1140,7 @@ static void cma_save_ib_info(struct sockaddr *src_addr,
                        ib->sib_pkey = path->pkey;
                        ib->sib_flowinfo = path->flow_label;
                        memcpy(&ib->sib_addr, &path->sgid, 16);
-                       ib->sib_sid = sa_path_get_service_id(path);
+                       ib->sib_sid = path->service_id;
                        ib->sib_scope_id = 0;
                } else {
                        ib->sib_pkey = listen_ib->sib_pkey;
@@ -1274,8 +1274,7 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
                memcpy(&req->local_gid, &req_param->primary_path->sgid,
                       sizeof(req->local_gid));
                req->has_gid    = true;
-               req->service_id =
-                       sa_path_get_service_id(req_param->primary_path);
+               req->service_id = req_param->primary_path->service_id;
                req->pkey       = be16_to_cpu(req_param->primary_path->pkey);
                if (req->pkey != req_param->bth_pkey)
                        pr_warn_ratelimited("RDMA CMA: got different BTH P_Key (0x%x) and primary path P_Key (0x%x)\n"
@@ -1827,7 +1826,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
        struct rdma_route *rt;
        const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family;
        struct sa_path_rec *path = ib_event->param.req_rcvd.primary_path;
-       const __be64 service_id = sa_path_get_service_id(path);
+       const __be64 service_id =
+               ib_event->param.req_rcvd.primary_path->service_id;
        int ret;
 
        id = rdma_create_id(listen_id->route.addr.dev_addr.net,
@@ -2345,9 +2345,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
        path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
        path_rec.numb_path = 1;
        path_rec.reversible = 1;
-       sa_path_set_service_id(&path_rec,
-                              rdma_get_service_id(&id_priv->id,
-                                                  cma_dst_addr(id_priv)));
+       path_rec.service_id = rdma_get_service_id(&id_priv->id,
+                                                 cma_dst_addr(id_priv));
 
        comp_mask = IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
                    IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH |
index cb7d372e4bdf877206d8da9141d46a590395bcd9..d92ab4eaa8f311a44bc3854107d9b7f352c0bca7 100644 (file)
@@ -169,6 +169,16 @@ void ib_mad_cleanup(void);
 int ib_sa_init(void);
 void ib_sa_cleanup(void);
 
+int ibnl_init(void);
+void ibnl_cleanup(void);
+
+/**
+ * Check if there are any listeners to the netlink group
+ * @group: the netlink group ID
+ * Returns 0 on success or a negative for no listeners.
+ */
+int ibnl_chk_listeners(unsigned int group);
+
 int ib_nl_handle_resolve_resp(struct sk_buff *skb,
                              struct netlink_callback *cb);
 int ib_nl_handle_set_timeout(struct sk_buff *skb,
index b784055423c8346b80e00f98d58f6499e7adc8ef..94931c474d41db72b606f654cb0d334087600ee5 100644 (file)
@@ -37,6 +37,7 @@
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <rdma/rdma_netlink.h>
+#include "core_priv.h"
 
 struct ibnl_client {
        struct list_head                list;
@@ -55,7 +56,6 @@ int ibnl_chk_listeners(unsigned int group)
                return -1;
        return 0;
 }
-EXPORT_SYMBOL(ibnl_chk_listeners);
 
 int ibnl_add_client(int index, int nops,
                    const struct ibnl_client_cbs cb_table[])
index e335b09c022ef69c58db15e8c37a43bfce9e8a42..fb7aec4047c8be90d0b70c39f66fdf6606c6fd7e 100644 (file)
@@ -194,7 +194,7 @@ static u32 tid;
        .field_name          = "sa_path_rec:" #field
 
 static const struct ib_field path_rec_table[] = {
-       { PATH_REC_FIELD(ib.service_id),
+       { PATH_REC_FIELD(service_id),
          .offset_words = 0,
          .offset_bits  = 0,
          .size_bits    = 64 },
@@ -296,7 +296,7 @@ static const struct ib_field path_rec_table[] = {
        .field_name          = "sa_path_rec:" #field
 
 static const struct ib_field opa_path_rec_table[] = {
-       { OPA_PATH_REC_FIELD(opa.service_id),
+       { OPA_PATH_REC_FIELD(service_id),
          .offset_words = 0,
          .offset_bits  = 0,
          .size_bits    = 64 },
@@ -774,7 +774,7 @@ static void ib_nl_set_path_rec_attrs(struct sk_buff *skb,
 
        /* Now build the attributes */
        if (comp_mask & IB_SA_PATH_REC_SERVICE_ID) {
-               val64 = be64_to_cpu(sa_path_get_service_id(sa_rec));
+               val64 = be64_to_cpu(sa_rec->service_id);
                nla_put(skb, RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_SERVICE_ID,
                        sizeof(val64), &val64);
        }
index 3dbf811d3c517232e4ebbff5f6970d34d8f518ca..21e60b1e2ff41b1c27e98ebad68e5f4b0ccb7f42 100644 (file)
@@ -58,7 +58,7 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
        for_each_sg(umem->sg_head.sgl, sg, umem->npages, i) {
 
                page = sg_page(sg);
-               if (umem->writable && dirty)
+               if (!PageDirty(page) && umem->writable && dirty)
                        set_page_dirty_lock(page);
                put_page(page);
        }
index 0780b1afefa9d996c870e6982bfc9c5f9b13fb2a..8c4ec564e49583f6d05eab8df5e57e4378582f08 100644 (file)
@@ -321,11 +321,15 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem,
                struct vm_area_struct *vma;
                struct hstate *h;
 
+               down_read(&mm->mmap_sem);
                vma = find_vma(mm, ib_umem_start(umem));
-               if (!vma || !is_vm_hugetlb_page(vma))
+               if (!vma || !is_vm_hugetlb_page(vma)) {
+                       up_read(&mm->mmap_sem);
                        return -EINVAL;
+               }
                h = hstate_vma(vma);
                umem->page_shift = huge_page_shift(h);
+               up_read(&mm->mmap_sem);
                umem->hugetlb = 1;
        } else {
                umem->hugetlb = 0;
index 8b9587fe23033fd69708dd60c7e76b18eb2e23ff..94fd989c90600b2640d2fb36f2397c9814160583 100644 (file)
@@ -96,11 +96,11 @@ void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
 }
 EXPORT_SYMBOL(ib_copy_qp_attr_to_user);
 
-void __ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
-                               struct sa_path_rec *src)
+static void __ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+                                      struct sa_path_rec *src)
 {
-       memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid);
-       memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid);
+       memcpy(dst->dgid, src->dgid.raw, sizeof(src->dgid));
+       memcpy(dst->sgid, src->sgid.raw, sizeof(src->sgid));
 
        dst->dlid               = htons(ntohl(sa_path_get_dlid(src)));
        dst->slid               = htons(ntohl(sa_path_get_slid(src)));
index ebf7be8d4139b87dd8232568603ab1aa8c19d045..08772836fded416e41be8eccfe53cf3e8427691b 100644 (file)
 #define BNXT_RE_MAX_SRQC_COUNT         (64 * 1024)
 #define BNXT_RE_MAX_CQ_COUNT           (64 * 1024)
 
+#define BNXT_RE_UD_QP_HW_STALL         0x400000
+
+#define BNXT_RE_RQ_WQE_THRESHOLD       32
+
 struct bnxt_re_work {
        struct work_struct      work;
        unsigned long           event;
index 7ba9e699d7abc65cb82fbd588e9ea12e7f71433b..c7bd68311d0c5317973ecf9c3fb8fce8fe8ffad4 100644 (file)
 #include "ib_verbs.h"
 #include <rdma/bnxt_re-abi.h>
 
+static int __from_ib_access_flags(int iflags)
+{
+       int qflags = 0;
+
+       if (iflags & IB_ACCESS_LOCAL_WRITE)
+               qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
+       if (iflags & IB_ACCESS_REMOTE_READ)
+               qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
+       if (iflags & IB_ACCESS_REMOTE_WRITE)
+               qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
+       if (iflags & IB_ACCESS_REMOTE_ATOMIC)
+               qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
+       if (iflags & IB_ACCESS_MW_BIND)
+               qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
+       if (iflags & IB_ZERO_BASED)
+               qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
+       if (iflags & IB_ACCESS_ON_DEMAND)
+               qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
+       return qflags;
+};
+
+static enum ib_access_flags __to_ib_access_flags(int qflags)
+{
+       enum ib_access_flags iflags = 0;
+
+       if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
+               iflags |= IB_ACCESS_LOCAL_WRITE;
+       if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
+               iflags |= IB_ACCESS_REMOTE_WRITE;
+       if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
+               iflags |= IB_ACCESS_REMOTE_READ;
+       if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
+               iflags |= IB_ACCESS_REMOTE_ATOMIC;
+       if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
+               iflags |= IB_ACCESS_MW_BIND;
+       if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
+               iflags |= IB_ZERO_BASED;
+       if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
+               iflags |= IB_ACCESS_ON_DEMAND;
+       return iflags;
+};
+
 static int bnxt_re_build_sgl(struct ib_sge *ib_sg_list,
                             struct bnxt_qplib_sge *sg_list, int num)
 {
@@ -149,8 +191,8 @@ int bnxt_re_query_device(struct ib_device *ibdev,
        ib_attr->max_total_mcast_qp_attach = 0;
        ib_attr->max_ah = dev_attr->max_ah;
 
-       ib_attr->max_fmr = dev_attr->max_fmr;
-       ib_attr->max_map_per_fmr = 1;   /* ? */
+       ib_attr->max_fmr = 0;
+       ib_attr->max_map_per_fmr = 0;
 
        ib_attr->max_srq = dev_attr->max_srq;
        ib_attr->max_srq_wr = dev_attr->max_srq_wqes;
@@ -410,6 +452,158 @@ enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
        return IB_LINK_LAYER_ETHERNET;
 }
 
+#define        BNXT_RE_FENCE_PBL_SIZE  DIV_ROUND_UP(BNXT_RE_FENCE_BYTES, PAGE_SIZE)
+
+static void bnxt_re_create_fence_wqe(struct bnxt_re_pd *pd)
+{
+       struct bnxt_re_fence_data *fence = &pd->fence;
+       struct ib_mr *ib_mr = &fence->mr->ib_mr;
+       struct bnxt_qplib_swqe *wqe = &fence->bind_wqe;
+
+       memset(wqe, 0, sizeof(*wqe));
+       wqe->type = BNXT_QPLIB_SWQE_TYPE_BIND_MW;
+       wqe->wr_id = BNXT_QPLIB_FENCE_WRID;
+       wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
+       wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
+       wqe->bind.zero_based = false;
+       wqe->bind.parent_l_key = ib_mr->lkey;
+       wqe->bind.va = (u64)(unsigned long)fence->va;
+       wqe->bind.length = fence->size;
+       wqe->bind.access_cntl = __from_ib_access_flags(IB_ACCESS_REMOTE_READ);
+       wqe->bind.mw_type = SQ_BIND_MW_TYPE_TYPE1;
+
+       /* Save the initial rkey in fence structure for now;
+        * wqe->bind.r_key will be set at (re)bind time.
+        */
+       fence->bind_rkey = ib_inc_rkey(fence->mw->rkey);
+}
+
+static int bnxt_re_bind_fence_mw(struct bnxt_qplib_qp *qplib_qp)
+{
+       struct bnxt_re_qp *qp = container_of(qplib_qp, struct bnxt_re_qp,
+                                            qplib_qp);
+       struct ib_pd *ib_pd = qp->ib_qp.pd;
+       struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
+       struct bnxt_re_fence_data *fence = &pd->fence;
+       struct bnxt_qplib_swqe *fence_wqe = &fence->bind_wqe;
+       struct bnxt_qplib_swqe wqe;
+       int rc;
+
+       memcpy(&wqe, fence_wqe, sizeof(wqe));
+       wqe.bind.r_key = fence->bind_rkey;
+       fence->bind_rkey = ib_inc_rkey(fence->bind_rkey);
+
+       dev_dbg(rdev_to_dev(qp->rdev),
+               "Posting bind fence-WQE: rkey: %#x QP: %d PD: %p\n",
+               wqe.bind.r_key, qp->qplib_qp.id, pd);
+       rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
+       if (rc) {
+               dev_err(rdev_to_dev(qp->rdev), "Failed to bind fence-WQE\n");
+               return rc;
+       }
+       bnxt_qplib_post_send_db(&qp->qplib_qp);
+
+       return rc;
+}
+
+static void bnxt_re_destroy_fence_mr(struct bnxt_re_pd *pd)
+{
+       struct bnxt_re_fence_data *fence = &pd->fence;
+       struct bnxt_re_dev *rdev = pd->rdev;
+       struct device *dev = &rdev->en_dev->pdev->dev;
+       struct bnxt_re_mr *mr = fence->mr;
+
+       if (fence->mw) {
+               bnxt_re_dealloc_mw(fence->mw);
+               fence->mw = NULL;
+       }
+       if (mr) {
+               if (mr->ib_mr.rkey)
+                       bnxt_qplib_dereg_mrw(&rdev->qplib_res, &mr->qplib_mr,
+                                            true);
+               if (mr->ib_mr.lkey)
+                       bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
+               kfree(mr);
+               fence->mr = NULL;
+       }
+       if (fence->dma_addr) {
+               dma_unmap_single(dev, fence->dma_addr, BNXT_RE_FENCE_BYTES,
+                                DMA_BIDIRECTIONAL);
+               fence->dma_addr = 0;
+       }
+}
+
+static int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
+{
+       int mr_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_MW_BIND;
+       struct bnxt_re_fence_data *fence = &pd->fence;
+       struct bnxt_re_dev *rdev = pd->rdev;
+       struct device *dev = &rdev->en_dev->pdev->dev;
+       struct bnxt_re_mr *mr = NULL;
+       dma_addr_t dma_addr = 0;
+       struct ib_mw *mw;
+       u64 pbl_tbl;
+       int rc;
+
+       dma_addr = dma_map_single(dev, fence->va, BNXT_RE_FENCE_BYTES,
+                                 DMA_BIDIRECTIONAL);
+       rc = dma_mapping_error(dev, dma_addr);
+       if (rc) {
+               dev_err(rdev_to_dev(rdev), "Failed to dma-map fence-MR-mem\n");
+               rc = -EIO;
+               fence->dma_addr = 0;
+               goto fail;
+       }
+       fence->dma_addr = dma_addr;
+
+       /* Allocate a MR */
+       mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+       if (!mr) {
+               rc = -ENOMEM;
+               goto fail;
+       }
+       fence->mr = mr;
+       mr->rdev = rdev;
+       mr->qplib_mr.pd = &pd->qplib_pd;
+       mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
+       mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
+       rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
+       if (rc) {
+               dev_err(rdev_to_dev(rdev), "Failed to alloc fence-HW-MR\n");
+               goto fail;
+       }
+
+       /* Register MR */
+       mr->ib_mr.lkey = mr->qplib_mr.lkey;
+       mr->qplib_mr.va = (u64)(unsigned long)fence->va;
+       mr->qplib_mr.total_size = BNXT_RE_FENCE_BYTES;
+       pbl_tbl = dma_addr;
+       rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, &pbl_tbl,
+                              BNXT_RE_FENCE_PBL_SIZE, false);
+       if (rc) {
+               dev_err(rdev_to_dev(rdev), "Failed to register fence-MR\n");
+               goto fail;
+       }
+       mr->ib_mr.rkey = mr->qplib_mr.rkey;
+
+       /* Create a fence MW only for kernel consumers */
+       mw = bnxt_re_alloc_mw(&pd->ib_pd, IB_MW_TYPE_1, NULL);
+       if (!mw) {
+               dev_err(rdev_to_dev(rdev),
+                       "Failed to create fence-MW for PD: %p\n", pd);
+               rc = -EINVAL;
+               goto fail;
+       }
+       fence->mw = mw;
+
+       bnxt_re_create_fence_wqe(pd);
+       return 0;
+
+fail:
+       bnxt_re_destroy_fence_mr(pd);
+       return rc;
+}
+
 /* Protection Domains */
 int bnxt_re_dealloc_pd(struct ib_pd *ib_pd)
 {
@@ -417,6 +611,7 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd)
        struct bnxt_re_dev *rdev = pd->rdev;
        int rc;
 
+       bnxt_re_destroy_fence_mr(pd);
        if (ib_pd->uobject && pd->dpi.dbr) {
                struct ib_ucontext *ib_uctx = ib_pd->uobject->context;
                struct bnxt_re_ucontext *ucntx;
@@ -498,6 +693,10 @@ struct ib_pd *bnxt_re_alloc_pd(struct ib_device *ibdev,
                }
        }
 
+       if (!udata)
+               if (bnxt_re_create_fence_mr(pd))
+                       dev_warn(rdev_to_dev(rdev),
+                                "Failed to create Fence-MR\n");
        return &pd->ib_pd;
 dbfail:
        (void)bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
@@ -849,12 +1048,16 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
        /* Shadow QP SQ depth should be same as QP1 RQ depth */
        qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
        qp->qplib_qp.sq.max_sge = 2;
+       /* Q full delta can be 1 since it is internal QP */
+       qp->qplib_qp.sq.q_full_delta = 1;
 
        qp->qplib_qp.scq = qp1_qp->scq;
        qp->qplib_qp.rcq = qp1_qp->rcq;
 
        qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
        qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
+       /* Q full delta can be 1 since it is internal QP */
+       qp->qplib_qp.rq.q_full_delta = 1;
 
        qp->qplib_qp.mtu = qp1_qp->mtu;
 
@@ -917,10 +1120,6 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
        qp->qplib_qp.sig_type = ((qp_init_attr->sq_sig_type ==
                                  IB_SIGNAL_ALL_WR) ? true : false);
 
-       entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
-       qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
-                                       dev_attr->max_qp_wqes + 1);
-
        qp->qplib_qp.sq.max_sge = qp_init_attr->cap.max_send_sge;
        if (qp->qplib_qp.sq.max_sge > dev_attr->max_qp_sges)
                qp->qplib_qp.sq.max_sge = dev_attr->max_qp_sges;
@@ -959,6 +1158,9 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
                qp->qplib_qp.rq.max_wqe = min_t(u32, entries,
                                                dev_attr->max_qp_wqes + 1);
 
+               qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
+                                               qp_init_attr->cap.max_recv_wr;
+
                qp->qplib_qp.rq.max_sge = qp_init_attr->cap.max_recv_sge;
                if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
                        qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
@@ -967,6 +1169,12 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
        qp->qplib_qp.mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
 
        if (qp_init_attr->qp_type == IB_QPT_GSI) {
+               /* Allocate 1 more than what's provided */
+               entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
+               qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
+                                               dev_attr->max_qp_wqes + 1);
+               qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
+                                               qp_init_attr->cap.max_send_wr;
                qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
                if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
                        qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
@@ -1006,6 +1214,22 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
                }
 
        } else {
+               /* Allocate 128 + 1 more than what's provided */
+               entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr +
+                                            BNXT_QPLIB_RESERVED_QP_WRS + 1);
+               qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
+                                               dev_attr->max_qp_wqes +
+                                               BNXT_QPLIB_RESERVED_QP_WRS + 1);
+               qp->qplib_qp.sq.q_full_delta = BNXT_QPLIB_RESERVED_QP_WRS + 1;
+
+               /*
+                * Reserving one slot for Phantom WQE. Application can
+                * post one extra entry in this case. But allowing this to avoid
+                * unexpected Queue full condition
+                */
+
+               qp->qplib_qp.sq.q_full_delta -= 1;
+
                qp->qplib_qp.max_rd_atomic = dev_attr->max_qp_rd_atom;
                qp->qplib_qp.max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
                if (udata) {
@@ -1025,6 +1249,7 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
 
        qp->ib_qp.qp_num = qp->qplib_qp.id;
        spin_lock_init(&qp->sq_lock);
+       spin_lock_init(&qp->rq_lock);
 
        if (udata) {
                struct bnxt_re_qp_resp resp;
@@ -1129,48 +1354,6 @@ static enum ib_mtu __to_ib_mtu(u32 mtu)
        }
 }
 
-static int __from_ib_access_flags(int iflags)
-{
-       int qflags = 0;
-
-       if (iflags & IB_ACCESS_LOCAL_WRITE)
-               qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
-       if (iflags & IB_ACCESS_REMOTE_READ)
-               qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
-       if (iflags & IB_ACCESS_REMOTE_WRITE)
-               qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
-       if (iflags & IB_ACCESS_REMOTE_ATOMIC)
-               qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
-       if (iflags & IB_ACCESS_MW_BIND)
-               qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
-       if (iflags & IB_ZERO_BASED)
-               qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
-       if (iflags & IB_ACCESS_ON_DEMAND)
-               qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
-       return qflags;
-};
-
-static enum ib_access_flags __to_ib_access_flags(int qflags)
-{
-       enum ib_access_flags iflags = 0;
-
-       if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
-               iflags |= IB_ACCESS_LOCAL_WRITE;
-       if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
-               iflags |= IB_ACCESS_REMOTE_WRITE;
-       if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
-               iflags |= IB_ACCESS_REMOTE_READ;
-       if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
-               iflags |= IB_ACCESS_REMOTE_ATOMIC;
-       if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
-               iflags |= IB_ACCESS_MW_BIND;
-       if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
-               iflags |= IB_ZERO_BASED;
-       if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
-               iflags |= IB_ACCESS_ON_DEMAND;
-       return iflags;
-};
-
 static int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev,
                                    struct bnxt_re_qp *qp1_qp,
                                    int qp_attr_mask)
@@ -1378,11 +1561,21 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
                entries = roundup_pow_of_two(qp_attr->cap.max_send_wr);
                qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
                                                dev_attr->max_qp_wqes + 1);
+               qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
+                                               qp_attr->cap.max_send_wr;
+               /*
+                * Reserving one slot for Phantom WQE. Some application can
+                * post one extra entry in this case. Allowing this to avoid
+                * unexpected Queue full condition
+                */
+               qp->qplib_qp.sq.q_full_delta -= 1;
                qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge;
                if (qp->qplib_qp.rq.max_wqe) {
                        entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr);
                        qp->qplib_qp.rq.max_wqe =
                                min_t(u32, entries, dev_attr->max_qp_wqes + 1);
+                       qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
+                                                      qp_attr->cap.max_recv_wr;
                        qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
                } else {
                        /* SRQ was used prior, just ignore the RQ caps */
@@ -1883,6 +2076,22 @@ static int bnxt_re_copy_wr_payload(struct bnxt_re_dev *rdev,
        return payload_sz;
 }
 
+static void bnxt_ud_qp_hw_stall_workaround(struct bnxt_re_qp *qp)
+{
+       if ((qp->ib_qp.qp_type == IB_QPT_UD ||
+            qp->ib_qp.qp_type == IB_QPT_GSI ||
+            qp->ib_qp.qp_type == IB_QPT_RAW_ETHERTYPE) &&
+            qp->qplib_qp.wqe_cnt == BNXT_RE_UD_QP_HW_STALL) {
+               int qp_attr_mask;
+               struct ib_qp_attr qp_attr;
+
+               qp_attr_mask = IB_QP_STATE;
+               qp_attr.qp_state = IB_QPS_RTS;
+               bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, qp_attr_mask, NULL);
+               qp->qplib_qp.wqe_cnt = 0;
+       }
+}
+
 static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
                                       struct bnxt_re_qp *qp,
                                struct ib_send_wr *wr)
@@ -1928,6 +2137,7 @@ bad:
                wr = wr->next;
        }
        bnxt_qplib_post_send_db(&qp->qplib_qp);
+       bnxt_ud_qp_hw_stall_workaround(qp);
        spin_unlock_irqrestore(&qp->sq_lock, flags);
        return rc;
 }
@@ -2024,6 +2234,7 @@ bad:
                wr = wr->next;
        }
        bnxt_qplib_post_send_db(&qp->qplib_qp);
+       bnxt_ud_qp_hw_stall_workaround(qp);
        spin_unlock_irqrestore(&qp->sq_lock, flags);
 
        return rc;
@@ -2071,7 +2282,10 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
        struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
        struct bnxt_qplib_swqe wqe;
        int rc = 0, payload_sz = 0;
+       unsigned long flags;
+       u32 count = 0;
 
+       spin_lock_irqsave(&qp->rq_lock, flags);
        while (wr) {
                /* House keeping */
                memset(&wqe, 0, sizeof(wqe));
@@ -2100,9 +2314,21 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
                        *bad_wr = wr;
                        break;
                }
+
+               /* Ring DB if the RQEs posted reaches a threshold value */
+               if (++count >= BNXT_RE_RQ_WQE_THRESHOLD) {
+                       bnxt_qplib_post_recv_db(&qp->qplib_qp);
+                       count = 0;
+               }
+
                wr = wr->next;
        }
-       bnxt_qplib_post_recv_db(&qp->qplib_qp);
+
+       if (count)
+               bnxt_qplib_post_recv_db(&qp->qplib_qp);
+
+       spin_unlock_irqrestore(&qp->rq_lock, flags);
+
        return rc;
 }
 
@@ -2643,12 +2869,36 @@ static void bnxt_re_process_res_ud_wc(struct ib_wc *wc,
                wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
 }
 
+static int send_phantom_wqe(struct bnxt_re_qp *qp)
+{
+       struct bnxt_qplib_qp *lib_qp = &qp->qplib_qp;
+       unsigned long flags;
+       int rc = 0;
+
+       spin_lock_irqsave(&qp->sq_lock, flags);
+
+       rc = bnxt_re_bind_fence_mw(lib_qp);
+       if (!rc) {
+               lib_qp->sq.phantom_wqe_cnt++;
+               dev_dbg(&lib_qp->sq.hwq.pdev->dev,
+                       "qp %#x sq->prod %#x sw_prod %#x phantom_wqe_cnt %d\n",
+                       lib_qp->id, lib_qp->sq.hwq.prod,
+                       HWQ_CMP(lib_qp->sq.hwq.prod, &lib_qp->sq.hwq),
+                       lib_qp->sq.phantom_wqe_cnt);
+       }
+
+       spin_unlock_irqrestore(&qp->sq_lock, flags);
+       return rc;
+}
+
 int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
 {
        struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
        struct bnxt_re_qp *qp;
        struct bnxt_qplib_cqe *cqe;
        int i, ncqe, budget;
+       struct bnxt_qplib_q *sq;
+       struct bnxt_qplib_qp *lib_qp;
        u32 tbl_idx;
        struct bnxt_re_sqp_entries *sqp_entry = NULL;
        unsigned long flags;
@@ -2661,7 +2911,21 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
        }
        cqe = &cq->cql[0];
        while (budget) {
-               ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget);
+               lib_qp = NULL;
+               ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget, &lib_qp);
+               if (lib_qp) {
+                       sq = &lib_qp->sq;
+                       if (sq->send_phantom) {
+                               qp = container_of(lib_qp,
+                                                 struct bnxt_re_qp, qplib_qp);
+                               if (send_phantom_wqe(qp) == -ENOMEM)
+                                       dev_err(rdev_to_dev(cq->rdev),
+                                               "Phantom failed! Scheduled to send again\n");
+                               else
+                                       sq->send_phantom = false;
+                       }
+               }
+
                if (!ncqe)
                        break;
 
@@ -2822,6 +3086,12 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
        struct bnxt_re_dev *rdev = mr->rdev;
        int rc;
 
+       rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
+       if (rc) {
+               dev_err(rdev_to_dev(rdev), "Dereg MR failed: %#x\n", rc);
+               return rc;
+       }
+
        if (mr->npages && mr->pages) {
                rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
                                                        &mr->qplib_frpl);
@@ -2829,8 +3099,6 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
                mr->npages = 0;
                mr->pages = NULL;
        }
-       rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
-
        if (!IS_ERR_OR_NULL(mr->ib_umem))
                ib_umem_release(mr->ib_umem);
 
@@ -2914,97 +3182,52 @@ fail:
        return ERR_PTR(rc);
 }
 
-/* Fast Memory Regions */
-struct ib_fmr *bnxt_re_alloc_fmr(struct ib_pd *ib_pd, int mr_access_flags,
-                                struct ib_fmr_attr *fmr_attr)
+struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
+                              struct ib_udata *udata)
 {
        struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
        struct bnxt_re_dev *rdev = pd->rdev;
-       struct bnxt_re_fmr *fmr;
+       struct bnxt_re_mw *mw;
        int rc;
 
-       if (fmr_attr->max_pages > MAX_PBL_LVL_2_PGS ||
-           fmr_attr->max_maps > rdev->dev_attr.max_map_per_fmr) {
-               dev_err(rdev_to_dev(rdev), "Allocate FMR exceeded Max limit");
+       mw = kzalloc(sizeof(*mw), GFP_KERNEL);
+       if (!mw)
                return ERR_PTR(-ENOMEM);
-       }
-       fmr = kzalloc(sizeof(*fmr), GFP_KERNEL);
-       if (!fmr)
-               return ERR_PTR(-ENOMEM);
-
-       fmr->rdev = rdev;
-       fmr->qplib_fmr.pd = &pd->qplib_pd;
-       fmr->qplib_fmr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
+       mw->rdev = rdev;
+       mw->qplib_mw.pd = &pd->qplib_pd;
 
-       rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &fmr->qplib_fmr);
-       if (rc)
+       mw->qplib_mw.type = (type == IB_MW_TYPE_1 ?
+                              CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 :
+                              CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B);
+       rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mw->qplib_mw);
+       if (rc) {
+               dev_err(rdev_to_dev(rdev), "Allocate MW failed!");
                goto fail;
+       }
+       mw->ib_mw.rkey = mw->qplib_mw.rkey;
 
-       fmr->qplib_fmr.flags = __from_ib_access_flags(mr_access_flags);
-       fmr->ib_fmr.lkey = fmr->qplib_fmr.lkey;
-       fmr->ib_fmr.rkey = fmr->ib_fmr.lkey;
+       atomic_inc(&rdev->mw_count);
+       return &mw->ib_mw;
 
-       atomic_inc(&rdev->mr_count);
-       return &fmr->ib_fmr;
 fail:
-       kfree(fmr);
+       kfree(mw);
        return ERR_PTR(rc);
 }
 
-int bnxt_re_map_phys_fmr(struct ib_fmr *ib_fmr, u64 *page_list, int list_len,
-                        u64 iova)
+int bnxt_re_dealloc_mw(struct ib_mw *ib_mw)
 {
-       struct bnxt_re_fmr *fmr = container_of(ib_fmr, struct bnxt_re_fmr,
-                                            ib_fmr);
-       struct bnxt_re_dev *rdev = fmr->rdev;
+       struct bnxt_re_mw *mw = container_of(ib_mw, struct bnxt_re_mw, ib_mw);
+       struct bnxt_re_dev *rdev = mw->rdev;
        int rc;
 
-       fmr->qplib_fmr.va = iova;
-       fmr->qplib_fmr.total_size = list_len * PAGE_SIZE;
-
-       rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &fmr->qplib_fmr, page_list,
-                              list_len, true);
-       if (rc)
-               dev_err(rdev_to_dev(rdev), "Failed to map FMR for lkey = 0x%x!",
-                       fmr->ib_fmr.lkey);
-       return rc;
-}
-
-int bnxt_re_unmap_fmr(struct list_head *fmr_list)
-{
-       struct bnxt_re_dev *rdev;
-       struct bnxt_re_fmr *fmr;
-       struct ib_fmr *ib_fmr;
-       int rc = 0;
-
-       /* Validate each FMRs inside the fmr_list */
-       list_for_each_entry(ib_fmr, fmr_list, list) {
-               fmr = container_of(ib_fmr, struct bnxt_re_fmr, ib_fmr);
-               rdev = fmr->rdev;
-
-               if (rdev) {
-                       rc = bnxt_qplib_dereg_mrw(&rdev->qplib_res,
-                                                 &fmr->qplib_fmr, true);
-                       if (rc)
-                               break;
-               }
+       rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mw->qplib_mw);
+       if (rc) {
+               dev_err(rdev_to_dev(rdev), "Free MW failed: %#x\n", rc);
+               return rc;
        }
-       return rc;
-}
-
-int bnxt_re_dealloc_fmr(struct ib_fmr *ib_fmr)
-{
-       struct bnxt_re_fmr *fmr = container_of(ib_fmr, struct bnxt_re_fmr,
-                                              ib_fmr);
-       struct bnxt_re_dev *rdev = fmr->rdev;
-       int rc;
 
-       rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &fmr->qplib_fmr);
-       if (rc)
-               dev_err(rdev_to_dev(rdev), "Failed to free FMR");
-
-       kfree(fmr);
-       atomic_dec(&rdev->mr_count);
+       kfree(mw);
+       atomic_dec(&rdev->mw_count);
        return rc;
 }
 
index 5c3d71765454f6e8476b86fd329d63b45d7735f6..6c160f6a5398702d4b73a3c319db3660f472c190 100644 (file)
@@ -44,11 +44,23 @@ struct bnxt_re_gid_ctx {
        u32                     refcnt;
 };
 
+#define BNXT_RE_FENCE_BYTES    64
+struct bnxt_re_fence_data {
+       u32 size;
+       u8 va[BNXT_RE_FENCE_BYTES];
+       dma_addr_t dma_addr;
+       struct bnxt_re_mr *mr;
+       struct ib_mw *mw;
+       struct bnxt_qplib_swqe bind_wqe;
+       u32 bind_rkey;
+};
+
 struct bnxt_re_pd {
        struct bnxt_re_dev      *rdev;
        struct ib_pd            ib_pd;
        struct bnxt_qplib_pd    qplib_pd;
        struct bnxt_qplib_dpi   dpi;
+       struct bnxt_re_fence_data fence;
 };
 
 struct bnxt_re_ah {
@@ -62,6 +74,7 @@ struct bnxt_re_qp {
        struct bnxt_re_dev      *rdev;
        struct ib_qp            ib_qp;
        spinlock_t              sq_lock;        /* protect sq */
+       spinlock_t              rq_lock;        /* protect rq */
        struct bnxt_qplib_qp    qplib_qp;
        struct ib_umem          *sumem;
        struct ib_umem          *rumem;
@@ -181,12 +194,9 @@ int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
 struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type,
                               u32 max_num_sg);
 int bnxt_re_dereg_mr(struct ib_mr *mr);
-struct ib_fmr *bnxt_re_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
-                                struct ib_fmr_attr *fmr_attr);
-int bnxt_re_map_phys_fmr(struct ib_fmr *fmr, u64 *page_list, int list_len,
-                        u64 iova);
-int bnxt_re_unmap_fmr(struct list_head *fmr_list);
-int bnxt_re_dealloc_fmr(struct ib_fmr *fmr);
+struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
+                              struct ib_udata *udata);
+int bnxt_re_dealloc_mw(struct ib_mw *mw);
 struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
                                  u64 virt_addr, int mr_access_flags,
                                  struct ib_udata *udata);
index 5d355401179b8ae5107e411421c673db86164696..1fce5e73216be1bc74c23d2773690dc824d0e251 100644 (file)
@@ -507,10 +507,6 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
        ibdev->dereg_mr                 = bnxt_re_dereg_mr;
        ibdev->alloc_mr                 = bnxt_re_alloc_mr;
        ibdev->map_mr_sg                = bnxt_re_map_mr_sg;
-       ibdev->alloc_fmr                = bnxt_re_alloc_fmr;
-       ibdev->map_phys_fmr             = bnxt_re_map_phys_fmr;
-       ibdev->unmap_fmr                = bnxt_re_unmap_fmr;
-       ibdev->dealloc_fmr              = bnxt_re_dealloc_fmr;
 
        ibdev->reg_user_mr              = bnxt_re_reg_user_mr;
        ibdev->alloc_ucontext           = bnxt_re_alloc_ucontext;
index 43d08b5e908525eae96b567178fdc8ad15dec9c5..f05500bcdcf1e35d21a88aba70b013d0d0d8a2cf 100644 (file)
@@ -284,7 +284,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_create_qp1 req;
-       struct creq_create_qp1_resp *resp;
+       struct creq_create_qp1_resp resp;
        struct bnxt_qplib_pbl *pbl;
        struct bnxt_qplib_q *sq = &qp->sq;
        struct bnxt_qplib_q *rq = &qp->rq;
@@ -394,31 +394,12 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
 
        req.pd_id = cpu_to_le32(qp->pd->id);
 
-       resp = (struct creq_create_qp1_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&res->pdev->dev, "QPLIB: FP: CREATE_QP1 send failed");
-               rc = -EINVAL;
-               goto fail;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 timed out");
-               rc = -ETIMEDOUT;
-               goto fail;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               rc = -EINVAL;
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
                goto fail;
-       }
-       qp->id = le32_to_cpu(resp->xid);
+
+       qp->id = le32_to_cpu(resp.xid);
        qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET;
        sq->flush_in_progress = false;
        rq->flush_in_progress = false;
@@ -442,7 +423,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct sq_send *hw_sq_send_hdr, **hw_sq_send_ptr;
        struct cmdq_create_qp req;
-       struct creq_create_qp_resp *resp;
+       struct creq_create_qp_resp resp;
        struct bnxt_qplib_pbl *pbl;
        struct sq_psn_search **psn_search_ptr;
        unsigned long int psn_search, poff = 0;
@@ -627,31 +608,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
        }
        req.pd_id = cpu_to_le32(qp->pd->id);
 
-       resp = (struct creq_create_qp_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP send failed");
-               rc = -EINVAL;
-               goto fail;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP timed out");
-               rc = -ETIMEDOUT;
-               goto fail;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               rc = -EINVAL;
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
                goto fail;
-       }
-       qp->id = le32_to_cpu(resp->xid);
+
+       qp->id = le32_to_cpu(resp.xid);
        qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET;
        sq->flush_in_progress = false;
        rq->flush_in_progress = false;
@@ -769,10 +731,11 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_modify_qp req;
-       struct creq_modify_qp_resp *resp;
+       struct creq_modify_qp_resp resp;
        u16 cmd_flags = 0, pkey;
        u32 temp32[4];
        u32 bmask;
+       int rc;
 
        RCFW_CMD_PREP(req, MODIFY_QP, cmd_flags);
 
@@ -862,27 +825,10 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
 
        req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id);
 
-       resp = (struct creq_modify_qp_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
+               return rc;
        qp->cur_qp_state = qp->state;
        return 0;
 }
@@ -891,37 +837,26 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_query_qp req;
-       struct creq_query_qp_resp *resp;
+       struct creq_query_qp_resp resp;
+       struct bnxt_qplib_rcfw_sbuf *sbuf;
        struct creq_query_qp_resp_sb *sb;
        u16 cmd_flags = 0;
        u32 temp32[4];
-       int i;
+       int i, rc = 0;
 
        RCFW_CMD_PREP(req, QUERY_QP, cmd_flags);
 
+       sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
+       if (!sbuf)
+               return -ENOMEM;
+       sb = sbuf->sb;
+
        req.qp_cid = cpu_to_le32(qp->id);
        req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
-       resp = (struct creq_query_qp_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    (void **)&sb, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         (void *)sbuf, 0);
+       if (rc)
+               goto bail;
        /* Extract the context from the side buffer */
        qp->state = sb->en_sqd_async_notify_state &
                        CREQ_QUERY_QP_RESP_SB_STATE_MASK;
@@ -976,7 +911,9 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
        qp->dest_qpn = le32_to_cpu(sb->dest_qp_id);
        memcpy(qp->smac, sb->src_mac, 6);
        qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id);
-       return 0;
+bail:
+       bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
+       return rc;
 }
 
 static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp)
@@ -1021,34 +958,18 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_destroy_qp req;
-       struct creq_destroy_qp_resp *resp;
+       struct creq_destroy_qp_resp resp;
        unsigned long flags;
        u16 cmd_flags = 0;
+       int rc;
 
        RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags);
 
        req.qp_cid = cpu_to_le32(qp->id);
-       resp = (struct creq_destroy_qp_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
+               return rc;
 
        /* Must walk the associated CQs to nullified the QP ptr */
        spin_lock_irqsave(&qp->scq->hwq.lock, flags);
@@ -1162,8 +1083,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
                rc = -EINVAL;
                goto done;
        }
-       if (HWQ_CMP((sq->hwq.prod + 1), &sq->hwq) ==
-           HWQ_CMP(sq->hwq.cons, &sq->hwq)) {
+
+       if (bnxt_qplib_queue_full(sq)) {
+               dev_err(&sq->hwq.pdev->dev,
+                       "QPLIB: prod = %#x cons = %#x qdepth = %#x delta = %#x",
+                       sq->hwq.prod, sq->hwq.cons, sq->hwq.max_elements,
+                       sq->q_full_delta);
                rc = -ENOMEM;
                goto done;
        }
@@ -1373,6 +1298,9 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
        }
 
        sq->hwq.prod++;
+
+       qp->wqe_cnt++;
+
 done:
        return rc;
 }
@@ -1411,8 +1339,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
                rc = -EINVAL;
                goto done;
        }
-       if (HWQ_CMP((rq->hwq.prod + 1), &rq->hwq) ==
-           HWQ_CMP(rq->hwq.cons, &rq->hwq)) {
+       if (bnxt_qplib_queue_full(rq)) {
                dev_err(&rq->hwq.pdev->dev,
                        "QPLIB: FP: QP (0x%x) RQ is full!", qp->id);
                rc = -EINVAL;
@@ -1483,7 +1410,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_create_cq req;
-       struct creq_create_cq_resp *resp;
+       struct creq_create_cq_resp resp;
        struct bnxt_qplib_pbl *pbl;
        u16 cmd_flags = 0;
        int rc;
@@ -1525,30 +1452,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
                        (cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) <<
                         CMDQ_CREATE_CQ_CNQ_ID_SFT);
 
-       resp = (struct creq_create_cq_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ timed out");
-               rc = -ETIMEDOUT;
-               goto fail;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               rc = -EINVAL;
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
                goto fail;
-       }
-       cq->id = le32_to_cpu(resp->xid);
+
+       cq->id = le32_to_cpu(resp.xid);
        cq->dbr_base = res->dpi_tbl.dbr_bar_reg_iomem;
        cq->period = BNXT_QPLIB_QUEUE_START_PERIOD;
        init_waitqueue_head(&cq->waitq);
@@ -1566,33 +1475,17 @@ int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_destroy_cq req;
-       struct creq_destroy_cq_resp *resp;
+       struct creq_destroy_cq_resp resp;
        u16 cmd_flags = 0;
+       int rc;
 
        RCFW_CMD_PREP(req, DESTROY_CQ, cmd_flags);
 
        req.cq_cid = cpu_to_le32(cq->id);
-       resp = (struct creq_destroy_cq_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
+               return rc;
        bnxt_qplib_free_hwq(res->pdev, &cq->hwq);
        return 0;
 }
@@ -1664,14 +1557,113 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp,
        return rc;
 }
 
+/* Note: SQE is valid from sw_sq_cons up to cqe_sq_cons (exclusive)
+ *       CQE is track from sw_cq_cons to max_element but valid only if VALID=1
+ */
+static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
+                    u32 cq_cons, u32 sw_sq_cons, u32 cqe_sq_cons)
+{
+       struct bnxt_qplib_q *sq = &qp->sq;
+       struct bnxt_qplib_swq *swq;
+       u32 peek_sw_cq_cons, peek_raw_cq_cons, peek_sq_cons_idx;
+       struct cq_base *peek_hwcqe, **peek_hw_cqe_ptr;
+       struct cq_req *peek_req_hwcqe;
+       struct bnxt_qplib_qp *peek_qp;
+       struct bnxt_qplib_q *peek_sq;
+       int i, rc = 0;
+
+       /* Normal mode */
+       /* Check for the psn_search marking before completing */
+       swq = &sq->swq[sw_sq_cons];
+       if (swq->psn_search &&
+           le32_to_cpu(swq->psn_search->flags_next_psn) & 0x80000000) {
+               /* Unmark */
+               swq->psn_search->flags_next_psn = cpu_to_le32
+                       (le32_to_cpu(swq->psn_search->flags_next_psn)
+                                    & ~0x80000000);
+               dev_dbg(&cq->hwq.pdev->dev,
+                       "FP: Process Req cq_cons=0x%x qp=0x%x sq cons sw=0x%x cqe=0x%x marked!\n",
+                       cq_cons, qp->id, sw_sq_cons, cqe_sq_cons);
+               sq->condition = true;
+               sq->send_phantom = true;
+
+               /* TODO: Only ARM if the previous SQE is ARMALL */
+               bnxt_qplib_arm_cq(cq, DBR_DBR_TYPE_CQ_ARMALL);
+
+               rc = -EAGAIN;
+               goto out;
+       }
+       if (sq->condition) {
+               /* Peek at the completions */
+               peek_raw_cq_cons = cq->hwq.cons;
+               peek_sw_cq_cons = cq_cons;
+               i = cq->hwq.max_elements;
+               while (i--) {
+                       peek_sw_cq_cons = HWQ_CMP((peek_sw_cq_cons), &cq->hwq);
+                       peek_hw_cqe_ptr = (struct cq_base **)cq->hwq.pbl_ptr;
+                       peek_hwcqe = &peek_hw_cqe_ptr[CQE_PG(peek_sw_cq_cons)]
+                                                    [CQE_IDX(peek_sw_cq_cons)];
+                       /* If the next hwcqe is VALID */
+                       if (CQE_CMP_VALID(peek_hwcqe, peek_raw_cq_cons,
+                                         cq->hwq.max_elements)) {
+                               /* If the next hwcqe is a REQ */
+                               if ((peek_hwcqe->cqe_type_toggle &
+                                   CQ_BASE_CQE_TYPE_MASK) ==
+                                   CQ_BASE_CQE_TYPE_REQ) {
+                                       peek_req_hwcqe = (struct cq_req *)
+                                                        peek_hwcqe;
+                                       peek_qp = (struct bnxt_qplib_qp *)
+                                               ((unsigned long)
+                                                le64_to_cpu
+                                                (peek_req_hwcqe->qp_handle));
+                                       peek_sq = &peek_qp->sq;
+                                       peek_sq_cons_idx = HWQ_CMP(le16_to_cpu(
+                                               peek_req_hwcqe->sq_cons_idx) - 1
+                                               , &sq->hwq);
+                                       /* If the hwcqe's sq's wr_id matches */
+                                       if (peek_sq == sq &&
+                                           sq->swq[peek_sq_cons_idx].wr_id ==
+                                           BNXT_QPLIB_FENCE_WRID) {
+                                               /*
+                                                *  Unbreak only if the phantom
+                                                *  comes back
+                                                */
+                                               dev_dbg(&cq->hwq.pdev->dev,
+                                                       "FP:Got Phantom CQE");
+                                               sq->condition = false;
+                                               sq->single = true;
+                                               rc = 0;
+                                               goto out;
+                                       }
+                               }
+                               /* Valid but not the phantom, so keep looping */
+                       } else {
+                               /* Not valid yet, just exit and wait */
+                               rc = -EINVAL;
+                               goto out;
+                       }
+                       peek_sw_cq_cons++;
+                       peek_raw_cq_cons++;
+               }
+               dev_err(&cq->hwq.pdev->dev,
+                       "Should not have come here! cq_cons=0x%x qp=0x%x sq cons sw=0x%x hw=0x%x",
+                       cq_cons, qp->id, sw_sq_cons, cqe_sq_cons);
+               rc = -EINVAL;
+       }
+out:
+       return rc;
+}
+
 static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
                                     struct cq_req *hwcqe,
-                                    struct bnxt_qplib_cqe **pcqe, int *budget)
+                                    struct bnxt_qplib_cqe **pcqe, int *budget,
+                                    u32 cq_cons, struct bnxt_qplib_qp **lib_qp)
 {
        struct bnxt_qplib_qp *qp;
        struct bnxt_qplib_q *sq;
        struct bnxt_qplib_cqe *cqe;
-       u32 sw_cons, cqe_cons;
+       u32 sw_sq_cons, cqe_sq_cons;
+       struct bnxt_qplib_swq *swq;
        int rc = 0;
 
        qp = (struct bnxt_qplib_qp *)((unsigned long)
@@ -1683,13 +1675,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
        }
        sq = &qp->sq;
 
-       cqe_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq);
-       if (cqe_cons > sq->hwq.max_elements) {
+       cqe_sq_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq);
+       if (cqe_sq_cons > sq->hwq.max_elements) {
                dev_err(&cq->hwq.pdev->dev,
                        "QPLIB: FP: CQ Process req reported ");
                dev_err(&cq->hwq.pdev->dev,
                        "QPLIB: sq_cons_idx 0x%x which exceeded max 0x%x",
-                       cqe_cons, sq->hwq.max_elements);
+                       cqe_sq_cons, sq->hwq.max_elements);
                return -EINVAL;
        }
        /* If we were in the middle of flushing the SQ, continue */
@@ -1698,53 +1690,74 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
 
        /* Require to walk the sq's swq to fabricate CQEs for all previously
         * signaled SWQEs due to CQE aggregation from the current sq cons
-        * to the cqe_cons
+        * to the cqe_sq_cons
         */
        cqe = *pcqe;
        while (*budget) {
-               sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq);
-               if (sw_cons == cqe_cons)
+               sw_sq_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq);
+               if (sw_sq_cons == cqe_sq_cons)
+                       /* Done */
                        break;
+
+               swq = &sq->swq[sw_sq_cons];
                memset(cqe, 0, sizeof(*cqe));
                cqe->opcode = CQ_BASE_CQE_TYPE_REQ;
                cqe->qp_handle = (u64)(unsigned long)qp;
                cqe->src_qp = qp->id;
-               cqe->wr_id = sq->swq[sw_cons].wr_id;
-               cqe->type = sq->swq[sw_cons].type;
+               cqe->wr_id = swq->wr_id;
+               if (cqe->wr_id == BNXT_QPLIB_FENCE_WRID)
+                       goto skip;
+               cqe->type = swq->type;
 
                /* For the last CQE, check for status.  For errors, regardless
                 * of the request being signaled or not, it must complete with
                 * the hwcqe error status
                 */
-               if (HWQ_CMP((sw_cons + 1), &sq->hwq) == cqe_cons &&
+               if (HWQ_CMP((sw_sq_cons + 1), &sq->hwq) == cqe_sq_cons &&
                    hwcqe->status != CQ_REQ_STATUS_OK) {
                        cqe->status = hwcqe->status;
                        dev_err(&cq->hwq.pdev->dev,
                                "QPLIB: FP: CQ Processed Req ");
                        dev_err(&cq->hwq.pdev->dev,
                                "QPLIB: wr_id[%d] = 0x%llx with status 0x%x",
-                               sw_cons, cqe->wr_id, cqe->status);
+                               sw_sq_cons, cqe->wr_id, cqe->status);
                        cqe++;
                        (*budget)--;
                        sq->flush_in_progress = true;
                        /* Must block new posting of SQ and RQ */
                        qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
+                       sq->condition = false;
+                       sq->single = false;
                } else {
-                       if (sq->swq[sw_cons].flags &
-                           SQ_SEND_FLAGS_SIGNAL_COMP) {
+                       if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
+                               /* Before we complete, do WA 9060 */
+                               if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
+                                             cqe_sq_cons)) {
+                                       *lib_qp = qp;
+                                       goto out;
+                               }
                                cqe->status = CQ_REQ_STATUS_OK;
                                cqe++;
                                (*budget)--;
                        }
                }
+skip:
                sq->hwq.cons++;
+               if (sq->single)
+                       break;
        }
+out:
        *pcqe = cqe;
-       if (!*budget && HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_cons) {
+       if (HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_sq_cons) {
                /* Out of budget */
                rc = -EAGAIN;
                goto done;
        }
+       /*
+        * Back to normal completion mode only after it has completed all of
+        * the WC for this CQE
+        */
+       sq->single = false;
        if (!sq->flush_in_progress)
                goto done;
 flush:
@@ -2074,7 +2087,7 @@ static int bnxt_qplib_cq_process_cutoff(struct bnxt_qplib_cq *cq,
 }
 
 int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
-                      int num_cqes)
+                      int num_cqes, struct bnxt_qplib_qp **lib_qp)
 {
        struct cq_base *hw_cqe, **hw_cqe_ptr;
        unsigned long flags;
@@ -2099,7 +2112,8 @@ int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
                case CQ_BASE_CQE_TYPE_REQ:
                        rc = bnxt_qplib_cq_process_req(cq,
                                                       (struct cq_req *)hw_cqe,
-                                                      &cqe, &budget);
+                                                      &cqe, &budget,
+                                                      sw_cons, lib_qp);
                        break;
                case CQ_BASE_CQE_TYPE_RES_RC:
                        rc = bnxt_qplib_cq_process_res_rc(cq,
index f0150f8da1e3929b309d14006b68469a965d8945..36b7b7db0e3f9782104ee8b049e674edb830226b 100644 (file)
@@ -88,6 +88,7 @@ struct bnxt_qplib_swq {
 
 struct bnxt_qplib_swqe {
        /* General */
+#define        BNXT_QPLIB_FENCE_WRID   0x46454E43      /* "FENC" */
        u64                             wr_id;
        u8                              reqs_type;
        u8                              type;
@@ -216,9 +217,16 @@ struct bnxt_qplib_q {
        struct scatterlist              *sglist;
        u32                             nmap;
        u32                             max_wqe;
+       u16                             q_full_delta;
        u16                             max_sge;
        u32                             psn;
        bool                            flush_in_progress;
+       bool                            condition;
+       bool                            single;
+       bool                            send_phantom;
+       u32                             phantom_wqe_cnt;
+       u32                             phantom_cqe_cnt;
+       u32                             next_cq_cons;
 };
 
 struct bnxt_qplib_qp {
@@ -242,6 +250,7 @@ struct bnxt_qplib_qp {
        u8                              timeout;
        u8                              retry_cnt;
        u8                              rnr_retry;
+       u64                             wqe_cnt;
        u32                             min_rnr_timer;
        u32                             max_rd_atomic;
        u32                             max_dest_rd_atomic;
@@ -301,6 +310,13 @@ struct bnxt_qplib_qp {
        (!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) ==         \
           !((raw_cons) & (cp_bit)))
 
+static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *qplib_q)
+{
+       return HWQ_CMP((qplib_q->hwq.prod + qplib_q->q_full_delta),
+                      &qplib_q->hwq) == HWQ_CMP(qplib_q->hwq.cons,
+                                                &qplib_q->hwq);
+}
+
 struct bnxt_qplib_cqe {
        u8                              status;
        u8                              type;
@@ -432,7 +448,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
 int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
 int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
 int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
-                      int num);
+                      int num, struct bnxt_qplib_qp **qp);
 void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type);
 void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq);
 int bnxt_qplib_alloc_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq);
index 23fb7260662b134b8d030f6c0ef7c6648976c434..16e42754dbeccfef863509b0bd8226683582df2a 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <linux/prefetch.h>
+#include <linux/delay.h>
+
 #include "roce_hsi.h"
 #include "qplib_res.h"
 #include "qplib_rcfw.h"
 static void bnxt_qplib_service_creq(unsigned long data);
 
 /* Hardware communication channel */
-int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
+static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
 {
        u16 cbit;
        int rc;
 
-       cookie &= RCFW_MAX_COOKIE_VALUE;
        cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
-       if (!test_bit(cbit, rcfw->cmdq_bitmap))
-               dev_warn(&rcfw->pdev->dev,
-                        "QPLIB: CMD bit %d for cookie 0x%x is not set?",
-                        cbit, cookie);
-
        rc = wait_event_timeout(rcfw->waitq,
                                !test_bit(cbit, rcfw->cmdq_bitmap),
                                msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
-       if (!rc) {
-               dev_warn(&rcfw->pdev->dev,
-                        "QPLIB: Bono Error: timeout %d msec, msg {0x%x}\n",
-                        RCFW_CMD_WAIT_TIME_MS, cookie);
-       }
-
-       return rc;
+       return rc ? 0 : -ETIMEDOUT;
 };
 
-int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
+static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
 {
-       u32 count = -1;
+       u32 count = RCFW_BLOCKED_CMD_WAIT_COUNT;
        u16 cbit;
 
-       cookie &= RCFW_MAX_COOKIE_VALUE;
        cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
        if (!test_bit(cbit, rcfw->cmdq_bitmap))
                goto done;
        do {
+               mdelay(1); /* 1m sec */
                bnxt_qplib_service_creq((unsigned long)rcfw);
        } while (test_bit(cbit, rcfw->cmdq_bitmap) && --count);
 done:
-       return count;
+       return count ? 0 : -ETIMEDOUT;
 };
 
-void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
-                                  struct cmdq_base *req, void **crsbe,
-                                  u8 is_block)
+static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
+                         struct creq_base *resp, void *sb, u8 is_block)
 {
-       struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
        struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr;
        struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
-       struct bnxt_qplib_hwq *crsb = &rcfw->crsb;
-       struct bnxt_qplib_crsqe *crsqe = NULL;
-       struct bnxt_qplib_crsbe **crsb_ptr;
+       struct bnxt_qplib_crsq *crsqe;
        u32 sw_prod, cmdq_prod;
-       u8 retry_cnt = 0xFF;
-       dma_addr_t dma_addr;
        unsigned long flags;
        u32 size, opcode;
        u16 cookie, cbit;
        int pg, idx;
        u8 *preq;
 
-retry:
        opcode = req->opcode;
        if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
            (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
@@ -112,63 +95,50 @@ retry:
                dev_err(&rcfw->pdev->dev,
                        "QPLIB: RCFW not initialized, reject opcode 0x%x",
                        opcode);
-               return NULL;
+               return -EINVAL;
        }
 
        if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
            opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
                dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
-               return NULL;
+               return -EINVAL;
        }
 
        /* Cmdq are in 16-byte units, each request can consume 1 or more
         * cmdqe
         */
        spin_lock_irqsave(&cmdq->lock, flags);
-       if (req->cmd_size > cmdq->max_elements -
-           ((HWQ_CMP(cmdq->prod, cmdq) - HWQ_CMP(cmdq->cons, cmdq)) &
-            (cmdq->max_elements - 1))) {
+       if (req->cmd_size >= HWQ_FREE_SLOTS(cmdq)) {
                dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!");
                spin_unlock_irqrestore(&cmdq->lock, flags);
-
-               if (!retry_cnt--)
-                       return NULL;
-               goto retry;
+               return -EAGAIN;
        }
 
-       retry_cnt = 0xFF;
 
-       cookie = atomic_inc_return(&rcfw->seq_num) & RCFW_MAX_COOKIE_VALUE;
+       cookie = rcfw->seq_num & RCFW_MAX_COOKIE_VALUE;
        cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
        if (is_block)
                cookie |= RCFW_CMD_IS_BLOCKING;
+
+       set_bit(cbit, rcfw->cmdq_bitmap);
        req->cookie = cpu_to_le16(cookie);
-       if (test_and_set_bit(cbit, rcfw->cmdq_bitmap)) {
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: RCFW MAX outstanding cmd reached!");
-               atomic_dec(&rcfw->seq_num);
+       crsqe = &rcfw->crsqe_tbl[cbit];
+       if (crsqe->resp) {
                spin_unlock_irqrestore(&cmdq->lock, flags);
-
-               if (!retry_cnt--)
-                       return NULL;
-               goto retry;
+               return -EBUSY;
        }
-       /* Reserve a resp buffer slot if requested */
-       if (req->resp_size && crsbe) {
-               spin_lock(&crsb->lock);
-               sw_prod = HWQ_CMP(crsb->prod, crsb);
-               crsb_ptr = (struct bnxt_qplib_crsbe **)crsb->pbl_ptr;
-               *crsbe = (void *)&crsb_ptr[get_crsb_pg(sw_prod)]
-                                         [get_crsb_idx(sw_prod)];
-               bnxt_qplib_crsb_dma_next(crsb->pbl_dma_ptr, sw_prod, &dma_addr);
-               req->resp_addr = cpu_to_le64(dma_addr);
-               crsb->prod++;
-               spin_unlock(&crsb->lock);
-
-               req->resp_size = (sizeof(struct bnxt_qplib_crsbe) +
-                                 BNXT_QPLIB_CMDQE_UNITS - 1) /
-                                BNXT_QPLIB_CMDQE_UNITS;
+       memset(resp, 0, sizeof(*resp));
+       crsqe->resp = (struct creq_qp_event *)resp;
+       crsqe->resp->cookie = req->cookie;
+       crsqe->req_size = req->cmd_size;
+       if (req->resp_size && sb) {
+               struct bnxt_qplib_rcfw_sbuf *sbuf = sb;
+
+               req->resp_addr = cpu_to_le64(sbuf->dma_addr);
+               req->resp_size = (sbuf->size + BNXT_QPLIB_CMDQE_UNITS - 1) /
+                                 BNXT_QPLIB_CMDQE_UNITS;
        }
+
        cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
        preq = (u8 *)req;
        size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
@@ -190,23 +160,24 @@ retry:
                preq += min_t(u32, size, sizeof(*cmdqe));
                size -= min_t(u32, size, sizeof(*cmdqe));
                cmdq->prod++;
+               rcfw->seq_num++;
        } while (size > 0);
 
+       rcfw->seq_num++;
+
        cmdq_prod = cmdq->prod;
        if (rcfw->flags & FIRMWARE_FIRST_FLAG) {
-               /* The very first doorbell write is required to set this flag
-                * which prompts the FW to reset its internal pointers
+               /* The very first doorbell write
+                * is required to set this flag
+                * which prompts the FW to reset
+                * its internal pointers
                 */
                cmdq_prod |= FIRMWARE_FIRST_FLAG;
                rcfw->flags &= ~FIRMWARE_FIRST_FLAG;
        }
-       sw_prod = HWQ_CMP(crsq->prod, crsq);
-       crsqe = &crsq->crsq[sw_prod];
-       memset(crsqe, 0, sizeof(*crsqe));
-       crsq->prod++;
-       crsqe->req_size = req->cmd_size;
 
        /* ring CMDQ DB */
+       wmb();
        writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem +
               rcfw->cmdq_bar_reg_prod_off);
        writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem +
@@ -214,9 +185,56 @@ retry:
 done:
        spin_unlock_irqrestore(&cmdq->lock, flags);
        /* Return the CREQ response pointer */
-       return crsqe ? &crsqe->qp_event : NULL;
+       return 0;
 }
 
+int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
+                                struct cmdq_base *req,
+                                struct creq_base *resp,
+                                void *sb, u8 is_block)
+{
+       struct creq_qp_event *evnt = (struct creq_qp_event *)resp;
+       u16 cookie;
+       u8 opcode, retry_cnt = 0xFF;
+       int rc = 0;
+
+       do {
+               opcode = req->opcode;
+               rc = __send_message(rcfw, req, resp, sb, is_block);
+               cookie = le16_to_cpu(req->cookie) & RCFW_MAX_COOKIE_VALUE;
+               if (!rc)
+                       break;
+
+               if (!retry_cnt || (rc != -EAGAIN && rc != -EBUSY)) {
+                       /* send failed */
+                       dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x send failed",
+                               cookie, opcode);
+                       return rc;
+               }
+               is_block ? mdelay(1) : usleep_range(500, 1000);
+
+       } while (retry_cnt--);
+
+       if (is_block)
+               rc = __block_for_resp(rcfw, cookie);
+       else
+               rc = __wait_for_resp(rcfw, cookie);
+       if (rc) {
+               /* timed out */
+               dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x timedout (%d)msec",
+                       cookie, opcode, RCFW_CMD_WAIT_TIME_MS);
+               return rc;
+       }
+
+       if (evnt->status) {
+               /* failed with status */
+               dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x status %#x",
+                       cookie, opcode, evnt->status);
+               rc = -EFAULT;
+       }
+
+       return rc;
+}
 /* Completions */
 static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
                                         struct creq_func_event *func_event)
@@ -260,12 +278,12 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
 static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                                       struct creq_qp_event *qp_event)
 {
-       struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
        struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
-       struct bnxt_qplib_crsqe *crsqe;
-       u16 cbit, cookie, blocked = 0;
+       struct bnxt_qplib_crsq *crsqe;
        unsigned long flags;
-       u32 sw_cons;
+       u16 cbit, blocked = 0;
+       u16 cookie;
+       __le16  mcookie;
 
        switch (qp_event->event) {
        case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
@@ -275,24 +293,31 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
        default:
                /* Command Response */
                spin_lock_irqsave(&cmdq->lock, flags);
-               sw_cons = HWQ_CMP(crsq->cons, crsq);
-               crsqe = &crsq->crsq[sw_cons];
-               crsq->cons++;
-               memcpy(&crsqe->qp_event, qp_event, sizeof(crsqe->qp_event));
-
-               cookie = le16_to_cpu(crsqe->qp_event.cookie);
+               cookie = le16_to_cpu(qp_event->cookie);
+               mcookie = qp_event->cookie;
                blocked = cookie & RCFW_CMD_IS_BLOCKING;
                cookie &= RCFW_MAX_COOKIE_VALUE;
                cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
+               crsqe = &rcfw->crsqe_tbl[cbit];
+               if (crsqe->resp &&
+                   crsqe->resp->cookie  == mcookie) {
+                       memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
+                       crsqe->resp = NULL;
+               } else {
+                       dev_err(&rcfw->pdev->dev,
+                               "QPLIB: CMD %s resp->cookie = %#x, evnt->cookie = %#x",
+                               crsqe->resp ? "mismatch" : "collision",
+                               crsqe->resp ? crsqe->resp->cookie : 0, mcookie);
+               }
                if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap))
                        dev_warn(&rcfw->pdev->dev,
                                 "QPLIB: CMD bit %d was not requested", cbit);
-
                cmdq->cons += crsqe->req_size;
-               spin_unlock_irqrestore(&cmdq->lock, flags);
+               crsqe->req_size = 0;
+
                if (!blocked)
                        wake_up(&rcfw->waitq);
-               break;
+               spin_unlock_irqrestore(&cmdq->lock, flags);
        }
        return 0;
 }
@@ -305,12 +330,12 @@ static void bnxt_qplib_service_creq(unsigned long data)
        struct creq_base *creqe, **creq_ptr;
        u32 sw_cons, raw_cons;
        unsigned long flags;
-       u32 type;
+       u32 type, budget = CREQ_ENTRY_POLL_BUDGET;
 
-       /* Service the CREQ until empty */
+       /* Service the CREQ until budget is over */
        spin_lock_irqsave(&creq->lock, flags);
        raw_cons = creq->cons;
-       while (1) {
+       while (budget > 0) {
                sw_cons = HWQ_CMP(raw_cons, creq);
                creq_ptr = (struct creq_base **)creq->pbl_ptr;
                creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
@@ -320,15 +345,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
                type = creqe->type & CREQ_BASE_TYPE_MASK;
                switch (type) {
                case CREQ_BASE_TYPE_QP_EVENT:
-                       if (!bnxt_qplib_process_qp_event
-                           (rcfw, (struct creq_qp_event *)creqe))
-                               rcfw->creq_qp_event_processed++;
-                       else {
-                               dev_warn(&rcfw->pdev->dev, "QPLIB: crsqe with");
-                               dev_warn(&rcfw->pdev->dev,
-                                        "QPLIB: type = 0x%x not handled",
-                                        type);
-                       }
+                       bnxt_qplib_process_qp_event
+                               (rcfw, (struct creq_qp_event *)creqe);
+                       rcfw->creq_qp_event_processed++;
                        break;
                case CREQ_BASE_TYPE_FUNC_EVENT:
                        if (!bnxt_qplib_process_func_event
@@ -346,7 +365,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
                        break;
                }
                raw_cons++;
+               budget--;
        }
+
        if (creq->cons != raw_cons) {
                creq->cons = raw_cons;
                CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
@@ -375,23 +396,16 @@ static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
 /* RCFW */
 int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw)
 {
-       struct creq_deinitialize_fw_resp *resp;
        struct cmdq_deinitialize_fw req;
+       struct creq_deinitialize_fw_resp resp;
        u16 cmd_flags = 0;
+       int rc;
 
        RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags);
-       resp = (struct creq_deinitialize_fw_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp)
-               return -EINVAL;
-
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie)))
-               return -ETIMEDOUT;
-
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie))
-               return -EFAULT;
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         NULL, 0);
+       if (rc)
+               return rc;
 
        clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
        return 0;
@@ -417,9 +431,10 @@ static int __get_pbl_pg_idx(struct bnxt_qplib_pbl *pbl)
 int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
                         struct bnxt_qplib_ctx *ctx, int is_virtfn)
 {
-       struct creq_initialize_fw_resp *resp;
        struct cmdq_initialize_fw req;
+       struct creq_initialize_fw_resp resp;
        u16 cmd_flags = 0, level;
+       int rc;
 
        RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags);
 
@@ -482,37 +497,19 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
 
 skip_ctx_setup:
        req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
-       resp = (struct creq_initialize_fw_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: RCFW: INITIALIZE_FW send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: RCFW: INITIALIZE_FW timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: RCFW: INITIALIZE_FW failed");
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         NULL, 0);
+       if (rc)
+               return rc;
        set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
        return 0;
 }
 
 void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
 {
-       bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->crsb);
-       kfree(rcfw->crsq.crsq);
+       kfree(rcfw->crsqe_tbl);
        bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq);
        bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq);
-
        rcfw->pdev = NULL;
 }
 
@@ -539,21 +536,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev,
                goto fail;
        }
 
-       rcfw->crsq.max_elements = rcfw->cmdq.max_elements;
-       rcfw->crsq.crsq = kcalloc(rcfw->crsq.max_elements,
-                                 sizeof(*rcfw->crsq.crsq), GFP_KERNEL);
-       if (!rcfw->crsq.crsq)
+       rcfw->crsqe_tbl = kcalloc(rcfw->cmdq.max_elements,
+                                 sizeof(*rcfw->crsqe_tbl), GFP_KERNEL);
+       if (!rcfw->crsqe_tbl)
                goto fail;
 
-       rcfw->crsb.max_elements = BNXT_QPLIB_CRSBE_MAX_CNT;
-       if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->crsb, NULL, 0,
-                                     &rcfw->crsb.max_elements,
-                                     BNXT_QPLIB_CRSBE_UNITS, 0, PAGE_SIZE,
-                                     HWQ_TYPE_CTX)) {
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: HW channel CRSB allocation failed");
-               goto fail;
-       }
        return 0;
 
 fail:
@@ -606,7 +593,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
        int rc;
 
        /* General */
-       atomic_set(&rcfw->seq_num, 0);
+       rcfw->seq_num = 0;
        rcfw->flags = FIRMWARE_FIRST_FLAG;
        bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD *
                                  sizeof(unsigned long));
@@ -636,10 +623,6 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
 
        rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET;
 
-       /* CRSQ */
-       rcfw->crsq.prod = 0;
-       rcfw->crsq.cons = 0;
-
        /* CREQ */
        rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION;
        res_base = pci_resource_start(pdev, rcfw->creq_bar_reg);
@@ -692,3 +675,34 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
        __iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4);
        return 0;
 }
+
+struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
+               struct bnxt_qplib_rcfw *rcfw,
+               u32 size)
+{
+       struct bnxt_qplib_rcfw_sbuf *sbuf;
+
+       sbuf = kzalloc(sizeof(*sbuf), GFP_ATOMIC);
+       if (!sbuf)
+               return NULL;
+
+       sbuf->size = size;
+       sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
+                                      &sbuf->dma_addr, GFP_ATOMIC);
+       if (!sbuf->sb)
+               goto bail;
+
+       return sbuf;
+bail:
+       kfree(sbuf);
+       return NULL;
+}
+
+void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
+                              struct bnxt_qplib_rcfw_sbuf *sbuf)
+{
+       if (sbuf->sb)
+               dma_free_coherent(&rcfw->pdev->dev, sbuf->size,
+                                 sbuf->sb, sbuf->dma_addr);
+       kfree(sbuf);
+}
index d3567d75bf58fe4e5e496c78ec27643af7d80cdc..09ce121770cdafd1af01bd815788f6b25eac3bf0 100644 (file)
@@ -73,6 +73,7 @@
 #define RCFW_MAX_OUTSTANDING_CMD       BNXT_QPLIB_CMDQE_MAX_CNT
 #define RCFW_MAX_COOKIE_VALUE          0x7FFF
 #define RCFW_CMD_IS_BLOCKING           0x8000
+#define RCFW_BLOCKED_CMD_WAIT_COUNT    0x4E20
 
 /* Cmdq contains a fix number of a 16-Byte slots */
 struct bnxt_qplib_cmdqe {
@@ -94,32 +95,6 @@ struct bnxt_qplib_crsbe {
        u8                      data[1024];
 };
 
-/* CRSQ SB */
-#define BNXT_QPLIB_CRSBE_MAX_CNT       4
-#define BNXT_QPLIB_CRSBE_UNITS         sizeof(struct bnxt_qplib_crsbe)
-#define BNXT_QPLIB_CRSBE_CNT_PER_PG    (PAGE_SIZE / BNXT_QPLIB_CRSBE_UNITS)
-
-#define MAX_CRSB_IDX                   (BNXT_QPLIB_CRSBE_MAX_CNT - 1)
-#define MAX_CRSB_IDX_PER_PG            (BNXT_QPLIB_CRSBE_CNT_PER_PG - 1)
-
-static inline u32 get_crsb_pg(u32 val)
-{
-       return (val & ~MAX_CRSB_IDX_PER_PG) / BNXT_QPLIB_CRSBE_CNT_PER_PG;
-}
-
-static inline u32 get_crsb_idx(u32 val)
-{
-       return val & MAX_CRSB_IDX_PER_PG;
-}
-
-static inline void bnxt_qplib_crsb_dma_next(dma_addr_t *pg_map_arr,
-                                           u32 prod, dma_addr_t *dma_addr)
-{
-               *dma_addr = pg_map_arr[(prod) / BNXT_QPLIB_CRSBE_CNT_PER_PG];
-               *dma_addr += ((prod) % BNXT_QPLIB_CRSBE_CNT_PER_PG) *
-                             BNXT_QPLIB_CRSBE_UNITS;
-}
-
 /* CREQ */
 /* Allocate 1 per QP for async error notification for now */
 #define BNXT_QPLIB_CREQE_MAX_CNT       (64 * 1024)
@@ -158,17 +133,19 @@ static inline u32 get_creq_idx(u32 val)
 #define CREQ_DB(db, raw_cons, cp_bit)                          \
        writel(CREQ_DB_CP_FLAGS | ((raw_cons) & ((cp_bit) - 1)), db)
 
+#define CREQ_ENTRY_POLL_BUDGET         0x100
+
 /* HWQ */
-struct bnxt_qplib_crsqe {
-       struct creq_qp_event    qp_event;
+
+struct bnxt_qplib_crsq {
+       struct creq_qp_event    *resp;
        u32                     req_size;
 };
 
-struct bnxt_qplib_crsq {
-       struct bnxt_qplib_crsqe *crsq;
-       u32                     prod;
-       u32                     cons;
-       u32                     max_elements;
+struct bnxt_qplib_rcfw_sbuf {
+       void *sb;
+       dma_addr_t dma_addr;
+       u32 size;
 };
 
 /* RCFW Communication Channels */
@@ -185,7 +162,7 @@ struct bnxt_qplib_rcfw {
        wait_queue_head_t       waitq;
        int                     (*aeq_handler)(struct bnxt_qplib_rcfw *,
                                               struct creq_func_event *);
-       atomic_t                seq_num;
+       u32                     seq_num;
 
        /* Bar region info */
        void __iomem            *cmdq_bar_reg_iomem;
@@ -203,8 +180,7 @@ struct bnxt_qplib_rcfw {
 
        /* Actual Cmd and Resp Queues */
        struct bnxt_qplib_hwq   cmdq;
-       struct bnxt_qplib_crsq  crsq;
-       struct bnxt_qplib_hwq   crsb;
+       struct bnxt_qplib_crsq  *crsqe_tbl;
 };
 
 void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
@@ -219,11 +195,14 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
                                        (struct bnxt_qplib_rcfw *,
                                         struct creq_func_event *));
 
-int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie);
-int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie);
-void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
-                                  struct cmdq_base *req, void **crsbe,
-                                  u8 is_block);
+struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
+                               struct bnxt_qplib_rcfw *rcfw,
+                               u32 size);
+void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
+                              struct bnxt_qplib_rcfw_sbuf *sbuf);
+int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
+                                struct cmdq_base *req, struct creq_base *resp,
+                                void *sbuf, u8 is_block);
 
 int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
 int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
index 6277d802ca4bc7e231e010331b5045c92cb57aad..2e4855509719cbf5ffa1725c8bee4d7e8e2c2f34 100644 (file)
@@ -48,6 +48,10 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
 
 #define HWQ_CMP(idx, hwq)      ((idx) & ((hwq)->max_elements - 1))
 
+#define HWQ_FREE_SLOTS(hwq)    (hwq->max_elements - \
+                               ((HWQ_CMP(hwq->prod, hwq)\
+                               - HWQ_CMP(hwq->cons, hwq))\
+                               & (hwq->max_elements - 1)))
 enum bnxt_qplib_hwq_type {
        HWQ_TYPE_CTX,
        HWQ_TYPE_QUEUE,
index 7b31eccedf11fa8f36a29e6251127144e75a59a5..fde18cf0e406b9f78e2af96d70077622f3d02732 100644 (file)
@@ -55,37 +55,30 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
                            struct bnxt_qplib_dev_attr *attr)
 {
        struct cmdq_query_func req;
-       struct creq_query_func_resp *resp;
+       struct creq_query_func_resp resp;
+       struct bnxt_qplib_rcfw_sbuf *sbuf;
        struct creq_query_func_resp_sb *sb;
        u16 cmd_flags = 0;
        u32 temp;
        u8 *tqm_alloc;
-       int i;
+       int i, rc = 0;
 
        RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags);
 
-       req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
-       resp = (struct creq_query_func_resp *)
-               bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void **)&sb,
-                                            0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC failed ");
+       sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
+       if (!sbuf) {
                dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
+                       "QPLIB: SP: QUERY_FUNC alloc side buffer failed");
+               return -ENOMEM;
        }
+
+       sb = sbuf->sb;
+       req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         (void *)sbuf, 0);
+       if (rc)
+               goto bail;
+
        /* Extract the context from the side buffer */
        attr->max_qp = le32_to_cpu(sb->max_qp);
        attr->max_qp_rd_atom =
@@ -95,6 +88,11 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
                sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
                BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
        attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
+       /*
+        * 128 WQEs needs to be reserved for the HW (8916). Prevent
+        * reporting the max number
+        */
+       attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS;
        attr->max_qp_sges = sb->max_sge;
        attr->max_cq = le32_to_cpu(sb->max_cq);
        attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
@@ -130,7 +128,10 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
                attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
                attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
        }
-       return 0;
+
+bail:
+       bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
+       return rc;
 }
 
 /* SGID */
@@ -178,8 +179,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
        /* Remove GID from the SGID table */
        if (update) {
                struct cmdq_delete_gid req;
-               struct creq_delete_gid_resp *resp;
+               struct creq_delete_gid_resp resp;
                u16 cmd_flags = 0;
+               int rc;
 
                RCFW_CMD_PREP(req, DELETE_GID, cmd_flags);
                if (sgid_tbl->hw_id[index] == 0xFFFF) {
@@ -188,31 +190,10 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                        return -EINVAL;
                }
                req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]);
-               resp = (struct creq_delete_gid_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL,
-                                                    0);
-               if (!resp) {
-                       dev_err(&res->pdev->dev,
-                               "QPLIB: SP: DELETE_GID send failed");
-                       return -EINVAL;
-               }
-               if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
-                                                  le16_to_cpu(req.cookie))) {
-                       /* Cmd timed out */
-                       dev_err(&res->pdev->dev,
-                               "QPLIB: SP: DELETE_GID timed out");
-                       return -ETIMEDOUT;
-               }
-               if (resp->status ||
-                   le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-                       dev_err(&res->pdev->dev,
-                               "QPLIB: SP: DELETE_GID failed ");
-                       dev_err(&res->pdev->dev,
-                               "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                               resp->status, le16_to_cpu(req.cookie),
-                               le16_to_cpu(resp->cookie));
-                       return -EINVAL;
-               }
+               rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                                 (void *)&resp, NULL, 0);
+               if (rc)
+                       return rc;
        }
        memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
               sizeof(bnxt_qplib_gid_zero));
@@ -234,7 +215,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                                                   struct bnxt_qplib_res,
                                                   sgid_tbl);
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
-       int i, free_idx, rc = 0;
+       int i, free_idx;
 
        if (!sgid_tbl) {
                dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated");
@@ -266,10 +247,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
        }
        if (update) {
                struct cmdq_add_gid req;
-               struct creq_add_gid_resp *resp;
+               struct creq_add_gid_resp resp;
                u16 cmd_flags = 0;
                u32 temp32[4];
                u16 temp16[3];
+               int rc;
 
                RCFW_CMD_PREP(req, ADD_GID, cmd_flags);
 
@@ -290,31 +272,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
                req.src_mac[1] = cpu_to_be16(temp16[1]);
                req.src_mac[2] = cpu_to_be16(temp16[2]);
 
-               resp = (struct creq_add_gid_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-               if (!resp) {
-                       dev_err(&res->pdev->dev,
-                               "QPLIB: SP: ADD_GID send failed");
-                       return -EINVAL;
-               }
-               if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
-                                                  le16_to_cpu(req.cookie))) {
-                       /* Cmd timed out */
-                       dev_err(&res->pdev->dev,
-                               "QPIB: SP: ADD_GID timed out");
-                       return -ETIMEDOUT;
-               }
-               if (resp->status ||
-                   le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-                       dev_err(&res->pdev->dev, "QPLIB: SP: ADD_GID failed ");
-                       dev_err(&res->pdev->dev,
-                               "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                               resp->status, le16_to_cpu(req.cookie),
-                               le16_to_cpu(resp->cookie));
-                       return -EINVAL;
-               }
-               sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp->xid);
+               rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                                 (void *)&resp, NULL, 0);
+               if (rc)
+                       return rc;
+               sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid);
        }
        /* Add GID to the sgid_tbl */
        memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
@@ -325,7 +287,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
 
        *index = free_idx;
        /* unlock */
-       return rc;
+       return 0;
 }
 
 /* pkeys */
@@ -422,10 +384,11 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_create_ah req;
-       struct creq_create_ah_resp *resp;
+       struct creq_create_ah_resp resp;
        u16 cmd_flags = 0;
        u32 temp32[4];
        u16 temp16[3];
+       int rc;
 
        RCFW_CMD_PREP(req, CREATE_AH, cmd_flags);
 
@@ -450,28 +413,12 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
        req.dest_mac[1] = cpu_to_le16(temp16[1]);
        req.dest_mac[2] = cpu_to_le16(temp16[2]);
 
-       resp = (struct creq_create_ah_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 1);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
-       ah->id = le32_to_cpu(resp->xid);
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         NULL, 1);
+       if (rc)
+               return rc;
+
+       ah->id = le32_to_cpu(resp.xid);
        return 0;
 }
 
@@ -479,35 +426,19 @@ int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_destroy_ah req;
-       struct creq_destroy_ah_resp *resp;
+       struct creq_destroy_ah_resp resp;
        u16 cmd_flags = 0;
+       int rc;
 
        /* Clean up the AH table in the device */
        RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
 
        req.ah_cid = cpu_to_le32(ah->id);
 
-       resp = (struct creq_destroy_ah_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 1);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         NULL, 1);
+       if (rc)
+               return rc;
        return 0;
 }
 
@@ -516,8 +447,9 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_deallocate_key req;
-       struct creq_deallocate_key_resp *resp;
+       struct creq_deallocate_key_resp resp;
        u16 cmd_flags = 0;
+       int rc;
 
        if (mrw->lkey == 0xFFFFFFFF) {
                dev_info(&res->pdev->dev,
@@ -536,27 +468,11 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
        else
                req.key = cpu_to_le32(mrw->lkey);
 
-       resp = (struct creq_deallocate_key_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR failed ");
-               dev_err(&res->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
+                                         NULL, 0);
+       if (rc)
+               return rc;
+
        /* Free the qplib's MRW memory */
        if (mrw->hwq.max_elements)
                bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
@@ -568,9 +484,10 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_allocate_mrw req;
-       struct creq_allocate_mrw_resp *resp;
+       struct creq_allocate_mrw_resp resp;
        u16 cmd_flags = 0;
        unsigned long tmp;
+       int rc;
 
        RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags);
 
@@ -584,33 +501,17 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
        tmp = (unsigned long)mrw;
        req.mrw_handle = cpu_to_le64(tmp);
 
-       resp = (struct creq_allocate_mrw_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, 0);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW send failed");
-               return -EINVAL;
-       }
-       if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
-               /* Cmd timed out */
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
+       if (rc)
+               return rc;
+
        if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1)  ||
            (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
            (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
-               mrw->rkey = le32_to_cpu(resp->xid);
+               mrw->rkey = le32_to_cpu(resp.xid);
        else
-               mrw->lkey = le32_to_cpu(resp->xid);
+               mrw->lkey = le32_to_cpu(resp.xid);
        return 0;
 }
 
@@ -619,40 +520,17 @@ int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_deregister_mr req;
-       struct creq_deregister_mr_resp *resp;
+       struct creq_deregister_mr_resp resp;
        u16 cmd_flags = 0;
        int rc;
 
        RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags);
 
        req.lkey = cpu_to_le32(mrw->lkey);
-       resp = (struct creq_deregister_mr_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, block);
-       if (!resp) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR send failed");
-               return -EINVAL;
-       }
-       if (block)
-               rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
-                                                   le16_to_cpu(req.cookie));
-       else
-               rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
-                                                  le16_to_cpu(req.cookie));
-       if (!rc) {
-               /* Cmd timed out */
-               dev_err(&res->pdev->dev, "QPLIB: SP: DEREG_MR timed out");
-               return -ETIMEDOUT;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR failed ");
-               dev_err(&rcfw->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, block);
+       if (rc)
+               return rc;
 
        /* Free the qplib's MR memory */
        if (mrw->hwq.max_elements) {
@@ -669,7 +547,7 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_register_mr req;
-       struct creq_register_mr_resp *resp;
+       struct creq_register_mr_resp resp;
        u16 cmd_flags = 0, level;
        int pg_ptrs, pages, i, rc;
        dma_addr_t **pbl_ptr;
@@ -730,36 +608,11 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
        req.key = cpu_to_le32(mr->lkey);
        req.mr_size = cpu_to_le64(mr->total_size);
 
-       resp = (struct creq_register_mr_resp *)
-                       bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
-                                                    NULL, block);
-       if (!resp) {
-               dev_err(&res->pdev->dev, "SP: REG_MR send failed");
-               rc = -EINVAL;
-               goto fail;
-       }
-       if (block)
-               rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
-                                                   le16_to_cpu(req.cookie));
-       else
-               rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
-                                                  le16_to_cpu(req.cookie));
-       if (!rc) {
-               /* Cmd timed out */
-               dev_err(&res->pdev->dev, "SP: REG_MR timed out");
-               rc = -ETIMEDOUT;
-               goto fail;
-       }
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&res->pdev->dev, "QPLIB: SP: REG_MR failed ");
-               dev_err(&res->pdev->dev,
-                       "QPLIB: SP: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               rc = -EINVAL;
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, block);
+       if (rc)
                goto fail;
-       }
+
        return 0;
 
 fail:
@@ -804,35 +657,15 @@ int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
 {
        struct bnxt_qplib_rcfw *rcfw = res->rcfw;
        struct cmdq_map_tc_to_cos req;
-       struct creq_map_tc_to_cos_resp *resp;
+       struct creq_map_tc_to_cos_resp resp;
        u16 cmd_flags = 0;
-       int tleft;
+       int rc = 0;
 
        RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags);
        req.cos0 = cpu_to_le16(cids[0]);
        req.cos1 = cpu_to_le16(cids[1]);
 
-       resp = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, 0);
-       if (!resp) {
-               dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS send failed");
-               return -EINVAL;
-       }
-
-       tleft = bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie));
-       if (!tleft) {
-               dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS timed out");
-               return -ETIMEDOUT;
-       }
-
-       if (resp->status ||
-           le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
-               dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS failed ");
-               dev_err(&res->pdev->dev,
-                       "QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
-                       resp->status, le16_to_cpu(req.cookie),
-                       le16_to_cpu(resp->cookie));
-               return -EINVAL;
-       }
-
+       rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
+                                         (void *)&resp, NULL, 0);
        return 0;
 }
index 1442a617e968e1d367a9fd9e69a0540da645ce6f..a543f959098bd11972383a9d907725c08497a8f4 100644 (file)
@@ -40,6 +40,8 @@
 #ifndef __BNXT_QPLIB_SP_H__
 #define __BNXT_QPLIB_SP_H__
 
+#define BNXT_QPLIB_RESERVED_QP_WRS     128
+
 struct bnxt_qplib_dev_attr {
        char                            fw_ver[32];
        u16                             max_sgid;
index b6fe45924c6ed5a3a835c89f00b9265a940e57ef..0910faf3587b547e873bc4e5572e7defd93623b3 100644 (file)
@@ -488,6 +488,7 @@ static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
 
        ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
        release_ep_resources(ep);
+       kfree_skb(skb);
        return 0;
 }
 
@@ -498,6 +499,7 @@ static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
        ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
        c4iw_put_ep(&ep->parent_ep->com);
        release_ep_resources(ep);
+       kfree_skb(skb);
        return 0;
 }
 
@@ -569,11 +571,13 @@ static void abort_arp_failure(void *handle, struct sk_buff *skb)
 
        pr_debug("%s rdev %p\n", __func__, rdev);
        req->cmd = CPL_ABORT_NO_RST;
+       skb_get(skb);
        ret = c4iw_ofld_send(rdev, skb);
        if (ret) {
                __state_set(&ep->com, DEAD);
                queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE);
-       }
+       } else
+               kfree_skb(skb);
 }
 
 static int send_flowc(struct c4iw_ep *ep)
@@ -2517,7 +2521,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
 
-       hdrs = sizeof(struct iphdr) + sizeof(struct tcphdr) +
+       hdrs = ((iptype == 4) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)) +
+              sizeof(struct tcphdr) +
               ((enable_tcp_timestamps && req->tcpopt.tstamp) ? 12 : 0);
        if (peer_mss && child_ep->mtu > (peer_mss + hdrs))
                child_ep->mtu = peer_mss + hdrs;
index 329fb65e8fb0edfafd19d6fbea17196f810f29d5..ae0b79aeea2ec141ebc83b9960f59718035eb1bf 100644 (file)
@@ -767,7 +767,7 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
                kfree(entry);
        }
 
-       list_for_each_safe(pos, nxt, &uctx->qpids) {
+       list_for_each_safe(pos, nxt, &uctx->cqids) {
                entry = list_entry(pos, struct c4iw_qid_list, entry);
                list_del_init(&entry->entry);
                kfree(entry);
@@ -880,13 +880,15 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
        rdev->free_workq = create_singlethread_workqueue("iw_cxgb4_free");
        if (!rdev->free_workq) {
                err = -ENOMEM;
-               goto err_free_status_page;
+               goto err_free_status_page_and_wr_log;
        }
 
        rdev->status_page->db_off = 0;
 
        return 0;
-err_free_status_page:
+err_free_status_page_and_wr_log:
+       if (c4iw_wr_log && rdev->wr_log)
+               kfree(rdev->wr_log);
        free_page((unsigned long)rdev->status_page);
 destroy_ocqp_pool:
        c4iw_ocqp_pool_destroy(rdev);
@@ -903,9 +905,11 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
 {
        destroy_workqueue(rdev->free_workq);
        kfree(rdev->wr_log);
+       c4iw_release_dev_ucontext(rdev, &rdev->uctx);
        free_page((unsigned long)rdev->status_page);
        c4iw_pblpool_destroy(rdev);
        c4iw_rqtpool_destroy(rdev);
+       c4iw_ocqp_pool_destroy(rdev);
        c4iw_destroy_resource(&rdev->resource);
 }
 
@@ -971,7 +975,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
                 devp->rdev.lldi.sge_egrstatuspagesize);
 
        devp->rdev.hw_queue.t4_eq_status_entries =
-               devp->rdev.lldi.sge_ingpadboundary > 64 ? 2 : 1;
+               devp->rdev.lldi.sge_egrstatuspagesize / 64;
        devp->rdev.hw_queue.t4_max_eq_size = 65520;
        devp->rdev.hw_queue.t4_max_iq_size = 65520;
        devp->rdev.hw_queue.t4_max_rq_size = 8192 -
index 5d6b1eeaa9a0a14c1088655cd5f049b5d3defa91..2ba00b89df6a046bba536cfe889c373d9063ced0 100644 (file)
@@ -6312,25 +6312,38 @@ static void handle_8051_request(struct hfi1_pportdata *ppd)
        }
 }
 
-static void write_global_credit(struct hfi1_devdata *dd,
-                               u8 vau, u16 total, u16 shared)
+/*
+ * Set up allocation unit vaulue.
+ */
+void set_up_vau(struct hfi1_devdata *dd, u8 vau)
 {
-       write_csr(dd, SEND_CM_GLOBAL_CREDIT,
-                 ((u64)total <<
-                  SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT) |
-                 ((u64)shared <<
-                  SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT) |
-                 ((u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT));
+       u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT);
+
+       /* do not modify other values in the register */
+       reg &= ~SEND_CM_GLOBAL_CREDIT_AU_SMASK;
+       reg |= (u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT;
+       write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg);
 }
 
 /*
  * Set up initial VL15 credits of the remote.  Assumes the rest of
- * the CM credit registers are zero from a previous global or credit reset .
+ * the CM credit registers are zero from a previous global or credit reset.
+ * Shared limit for VL15 will always be 0.
  */
-void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf)
+void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf)
 {
-       /* leave shared count at zero for both global and VL15 */
-       write_global_credit(dd, vau, vl15buf, 0);
+       u64 reg = read_csr(dd, SEND_CM_GLOBAL_CREDIT);
+
+       /* set initial values for total and shared credit limit */
+       reg &= ~(SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SMASK |
+                SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SMASK);
+
+       /*
+        * Set total limit to be equal to VL15 credits.
+        * Leave shared limit at 0.
+        */
+       reg |= (u64)vl15buf << SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT;
+       write_csr(dd, SEND_CM_GLOBAL_CREDIT, reg);
 
        write_csr(dd, SEND_CM_CREDIT_VL15, (u64)vl15buf
                  << SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT);
@@ -6348,9 +6361,11 @@ void reset_link_credits(struct hfi1_devdata *dd)
        for (i = 0; i < TXE_NUM_DATA_VL; i++)
                write_csr(dd, SEND_CM_CREDIT_VL + (8 * i), 0);
        write_csr(dd, SEND_CM_CREDIT_VL15, 0);
-       write_global_credit(dd, 0, 0, 0);
+       write_csr(dd, SEND_CM_GLOBAL_CREDIT, 0);
        /* reset the CM block */
        pio_send_control(dd, PSC_CM_RESET);
+       /* reset cached value */
+       dd->vl15buf_cached = 0;
 }
 
 /* convert a vCU to a CU */
@@ -6839,24 +6854,35 @@ void handle_link_up(struct work_struct *work)
 {
        struct hfi1_pportdata *ppd = container_of(work, struct hfi1_pportdata,
                                                  link_up_work);
+       struct hfi1_devdata *dd = ppd->dd;
+
        set_link_state(ppd, HLS_UP_INIT);
 
        /* cache the read of DC_LCB_STS_ROUND_TRIP_LTP_CNT */
-       read_ltp_rtt(ppd->dd);
+       read_ltp_rtt(dd);
        /*
         * OPA specifies that certain counters are cleared on a transition
         * to link up, so do that.
         */
-       clear_linkup_counters(ppd->dd);
+       clear_linkup_counters(dd);
        /*
         * And (re)set link up default values.
         */
        set_linkup_defaults(ppd);
 
+       /*
+        * Set VL15 credits. Use cached value from verify cap interrupt.
+        * In case of quick linkup or simulator, vl15 value will be set by
+        * handle_linkup_change. VerifyCap interrupt handler will not be
+        * called in those scenarios.
+        */
+       if (!(quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR))
+               set_up_vl15(dd, dd->vl15buf_cached);
+
        /* enforce link speed enabled */
        if ((ppd->link_speed_active & ppd->link_speed_enabled) == 0) {
                /* oops - current speed is not enabled, bounce */
-               dd_dev_err(ppd->dd,
+               dd_dev_err(dd,
                           "Link speed active 0x%x is outside enabled 0x%x, downing link\n",
                           ppd->link_speed_active, ppd->link_speed_enabled);
                set_link_down_reason(ppd, OPA_LINKDOWN_REASON_SPEED_POLICY, 0,
@@ -7357,7 +7383,14 @@ void handle_verify_cap(struct work_struct *work)
         */
        if (vau == 0)
                vau = 1;
-       set_up_vl15(dd, vau, vl15buf);
+       set_up_vau(dd, vau);
+
+       /*
+        * Set VL15 credits to 0 in global credit register. Cache remote VL15
+        * credits value and wait for link-up interrupt ot set it.
+        */
+       set_up_vl15(dd, 0);
+       dd->vl15buf_cached = vl15buf;
 
        /* set up the LCB CRC mode */
        crc_mask = ppd->port_crc_mode_enabled & partner_supported_crc;
index 5bfa839d1c48bc14939f680e74b696ac43105119..793514f1d15fb4a82357ba755dd97c7855f076ad 100644 (file)
 #define SEND_CM_CTRL_FORCE_CREDIT_MODE_SMASK 0x8ull
 #define SEND_CM_CTRL_RESETCSR 0x0000000000000020ull
 #define SEND_CM_GLOBAL_CREDIT (TXE + 0x000000000508)
+#define SEND_CM_GLOBAL_CREDIT_AU_MASK 0x7ull
 #define SEND_CM_GLOBAL_CREDIT_AU_SHIFT 16
+#define SEND_CM_GLOBAL_CREDIT_AU_SMASK 0x70000ull
 #define SEND_CM_GLOBAL_CREDIT_RESETCSR 0x0000094000030000ull
 #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_MASK 0xFFFFull
 #define SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT 0
index da322e6668cc5893262c3316486147cac6df1ca9..414a04a481c2abab3b3fe44d3949d591e684c065 100644 (file)
@@ -1045,6 +1045,14 @@ struct hfi1_devdata {
        /* initial vl15 credits to use */
        u16 vl15_init;
 
+       /*
+        * Cached value for vl15buf, read during verify cap interrupt. VL15
+        * credits are to be kept at 0 and set when handling the link-up
+        * interrupt. This removes the possibility of receiving VL15 MAD
+        * packets before this HFI is ready.
+        */
+       u16 vl15buf_cached;
+
        /* Misc small ints */
        u8 n_krcv_queues;
        u8 qos_shift;
@@ -1598,7 +1606,8 @@ int hfi1_rcvbuf_validate(u32 size, u8 type, u16 *encode);
 int fm_get_table(struct hfi1_pportdata *ppd, int which, void *t);
 int fm_set_table(struct hfi1_pportdata *ppd, int which, void *t);
 
-void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf);
+void set_up_vau(struct hfi1_devdata *dd, u8 vau);
+void set_up_vl15(struct hfi1_devdata *dd, u16 vl15buf);
 void reset_link_credits(struct hfi1_devdata *dd);
 void assign_remote_cm_au_table(struct hfi1_devdata *dd, u8 vcu);
 
index ba265d0ae93b4a96d6c29364f30b34c6046c335b..04a5082d5ac55259d992db8843cd361797b2992c 100644 (file)
@@ -130,7 +130,8 @@ void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup)
                 * the remote values.  Both sides must be using the values.
                 */
                if (quick_linkup || dd->icode == ICODE_FUNCTIONAL_SIMULATOR) {
-                       set_up_vl15(dd, dd->vau, dd->vl15_init);
+                       set_up_vau(dd, dd->vau);
+                       set_up_vl15(dd, dd->vl15_init);
                        assign_remote_cm_au_table(dd, dd->vcu);
                }
 
index 93faf86d54b620fb2cc621844932d811c17868dd..6a9f6f9819e1a326b0ed5f15f831d10cec2620a6 100644 (file)
@@ -207,8 +207,8 @@ int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev)
        /*
         * Save BARs and command to rewrite after device reset.
         */
-       dd->pcibar0 = addr;
-       dd->pcibar1 = addr >> 32;
+       pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_0, &dd->pcibar0);
+       pci_read_config_dword(dd->pcidev, PCI_BASE_ADDRESS_1, &dd->pcibar1);
        pci_read_config_dword(dd->pcidev, PCI_ROM_ADDRESS, &dd->pci_rom);
        pci_read_config_word(dd->pcidev, PCI_COMMAND, &dd->pci_command);
        pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &dd->pcie_devctl);
index 069bdaf061ab923cbc8b123ab182806fdb3c4dac..1080778a1f7c4a38816ce02058f63baae862d89e 100644 (file)
@@ -2159,8 +2159,11 @@ send_last:
                ret = hfi1_rvt_get_rwqe(qp, 1);
                if (ret < 0)
                        goto nack_op_err;
-               if (!ret)
+               if (!ret) {
+                       /* peer will send again */
+                       rvt_put_ss(&qp->r_sge);
                        goto rnr_nak;
+               }
                wc.ex.imm_data = ohdr->u.rc.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
                goto send_last;
index 50d140d25e38fa3cce8b4512b86099c633f1bc6c..2f3bbcac1e3492ff6cfeb5d92ebef73bda8b59fd 100644 (file)
@@ -196,7 +196,8 @@ static const struct sysfs_ops port_cc_sysfs_ops = {
 };
 
 static struct attribute *port_cc_default_attributes[] = {
-       &cc_prescan_attr.attr
+       &cc_prescan_attr.attr,
+       NULL
 };
 
 static struct kobj_type port_cc_ktype = {
index f3bc01bce483fe5d81ba08e2a60212e4f0f32b98..6ae98aa7f74ebb14f4ce2e9e3cee7c629270253f 100644 (file)
@@ -784,7 +784,6 @@ static void i40iw_build_mpa_v2(struct i40iw_cm_node *cm_node,
        }
 
        ctrl_ird |= IETF_PEER_TO_PEER;
-       ctrl_ird |= IETF_FLPDU_ZERO_LEN;
 
        switch (mpa_key) {
        case MPA_KEY_REQUEST:
@@ -2446,8 +2445,8 @@ static void i40iw_handle_rcv_mpa(struct i40iw_cm_node *cm_node,
                } else {
                        type = I40IW_CM_EVENT_CONNECTED;
                        cm_node->state = I40IW_CM_STATE_OFFLOADED;
-                       i40iw_send_ack(cm_node);
                }
+               i40iw_send_ack(cm_node);
                break;
        default:
                pr_err("%s wrong cm_node state =%d\n", __func__, cm_node->state);
index f82483b3d1e7dc205fa2f6a5e8037fd4d6866eab..a027e2072477aef12a230fdc79a1a1d6668bf15c 100644 (file)
@@ -285,28 +285,20 @@ void i40iw_change_l2params(struct i40iw_sc_vsi *vsi, struct i40iw_l2params *l2pa
        struct i40iw_sc_dev *dev = vsi->dev;
        struct i40iw_sc_qp *qp = NULL;
        bool qs_handle_change = false;
-       bool mss_change = false;
        unsigned long flags;
        u16 qs_handle;
        int i;
 
-       if (vsi->mss != l2params->mss) {
-               mss_change = true;
-               vsi->mss = l2params->mss;
-       }
+       vsi->mss = l2params->mss;
 
        i40iw_fill_qos_list(l2params->qs_handle_list);
        for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
                qs_handle = l2params->qs_handle_list[i];
                if (vsi->qos[i].qs_handle != qs_handle)
                        qs_handle_change = true;
-               else if (!mss_change)
-                       continue;       /* no MSS nor qs handle change */
                spin_lock_irqsave(&vsi->qos[i].lock, flags);
                qp = i40iw_get_qp(&vsi->qos[i].qplist, qp);
                while (qp) {
-                       if (mss_change)
-                               i40iw_qp_mss_modify(dev, qp);
                        if (qs_handle_change) {
                                qp->qs_handle = qs_handle;
                                /* issue cqp suspend command */
@@ -2395,7 +2387,6 @@ static enum i40iw_status_code i40iw_sc_qp_modify(
 
        set_64bit_val(wqe,
                      8,
-                     LS_64(info->new_mss, I40IW_CQPSQ_QP_NEWMSS) |
                      LS_64(term_len, I40IW_CQPSQ_QP_TERMLEN));
 
        set_64bit_val(wqe, 16, qp->hw_host_ctx_pa);
@@ -2410,7 +2401,6 @@ static enum i40iw_status_code i40iw_sc_qp_modify(
                 LS_64(info->cq_num_valid, I40IW_CQPSQ_QP_CQNUMVALID) |
                 LS_64(info->force_loopback, I40IW_CQPSQ_QP_FORCELOOPBACK) |
                 LS_64(qp->qp_type, I40IW_CQPSQ_QP_QPTYPE) |
-                LS_64(info->mss_change, I40IW_CQPSQ_QP_MSSCHANGE) |
                 LS_64(info->static_rsrc, I40IW_CQPSQ_QP_STATRSRC) |
                 LS_64(info->remove_hash_idx, I40IW_CQPSQ_QP_REMOVEHASHENTRY) |
                 LS_64(term_actions, I40IW_CQPSQ_QP_TERMACT) |
index 2728af3103ce9ae285ab8c0b88980e716a1cb5e4..a3f18a22f5ed1787794031eb8a1765ab2804cdc4 100644 (file)
@@ -1319,13 +1319,13 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev,
        status = i40iw_obj_aligned_mem(iwdev, &mem, I40IW_QUERY_FPM_BUF_SIZE,
                                       I40IW_FPM_QUERY_BUF_ALIGNMENT_MASK);
        if (status)
-               goto exit;
+               goto error;
        info.fpm_query_buf_pa = mem.pa;
        info.fpm_query_buf = mem.va;
        status = i40iw_obj_aligned_mem(iwdev, &mem, I40IW_COMMIT_FPM_BUF_SIZE,
                                       I40IW_FPM_COMMIT_BUF_ALIGNMENT_MASK);
        if (status)
-               goto exit;
+               goto error;
        info.fpm_commit_buf_pa = mem.pa;
        info.fpm_commit_buf = mem.va;
        info.hmc_fn_id = ldev->fid;
@@ -1347,11 +1347,9 @@ static enum i40iw_status_code i40iw_initialize_dev(struct i40iw_device *iwdev,
        info.exception_lan_queue = 1;
        info.vchnl_send = i40iw_virtchnl_send;
        status = i40iw_device_init(&iwdev->sc_dev, &info);
-exit:
-       if (status) {
-               kfree(iwdev->hmc_info_mem);
-               iwdev->hmc_info_mem = NULL;
-       }
+
+       if (status)
+               goto error;
        memset(&vsi_info, 0, sizeof(vsi_info));
        vsi_info.dev = &iwdev->sc_dev;
        vsi_info.back_vsi = (void *)iwdev;
@@ -1362,11 +1360,19 @@ exit:
                memset(&stats_info, 0, sizeof(stats_info));
                stats_info.fcn_id = ldev->fid;
                stats_info.pestat = kzalloc(sizeof(*stats_info.pestat), GFP_KERNEL);
+               if (!stats_info.pestat) {
+                       status = I40IW_ERR_NO_MEMORY;
+                       goto error;
+               }
                stats_info.stats_initialize = true;
                if (stats_info.pestat)
                        i40iw_vsi_stats_init(&iwdev->vsi, &stats_info);
        }
        return status;
+error:
+       kfree(iwdev->hmc_info_mem);
+       iwdev->hmc_info_mem = NULL;
+       return status;
 }
 
 /**
index aa66c1c63dfa4b0879eecfdb4a46f58f3279de98..f27be3e7830bb438f5543d88ef35eae1c4d93586 100644 (file)
@@ -199,7 +199,6 @@ void i40iw_cqp_spawn_worker(struct i40iw_sc_dev *dev,
                            struct i40iw_virtchnl_work_info *work_info, u32 iw_vf_idx);
 void *i40iw_remove_head(struct list_head *list);
 void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, bool suspend);
-void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
 
 void i40iw_term_modify_qp(struct i40iw_sc_qp *qp, u8 next_state, u8 term, u8 term_len);
 void i40iw_terminate_done(struct i40iw_sc_qp *qp, int timeout_occurred);
index 7b76259752b0062e5cf16f7bc097f5cd4b66098e..959ec81fba99ca6499f2e8d7d68f0cb073c86646 100644 (file)
@@ -541,7 +541,6 @@ struct i40iw_create_qp_info {
 struct i40iw_modify_qp_info {
        u64 rx_win0;
        u64 rx_win1;
-       u16 new_mss;
        u8 next_iwarp_state;
        u8 termlen;
        bool ord_valid;
@@ -554,7 +553,6 @@ struct i40iw_modify_qp_info {
        bool dont_send_term;
        bool dont_send_fin;
        bool cached_var_valid;
-       bool mss_change;
        bool force_loopback;
 };
 
index 409a3781e735db6f2072bde350815beed380425e..56d986924a4c1708216684f776f4705451a65f79 100644 (file)
@@ -756,23 +756,6 @@ void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, b
                i40iw_pr_err("CQP-OP QP Suspend/Resume fail");
 }
 
-/**
- * i40iw_qp_mss_modify - modify mss for qp
- * @dev: hardware control device structure
- * @qp: hardware control qp
- */
-void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
-{
-       struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
-       struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
-       struct i40iw_modify_qp_info info;
-
-       memset(&info, 0, sizeof(info));
-       info.mss_change = true;
-       info.new_mss = qp->vsi->mss;
-       i40iw_hw_modify_qp(iwdev, iwqp, &info, false);
-}
-
 /**
  * i40iw_term_modify_qp - modify qp for term message
  * @qp: hardware control qp
index f4d13683a403a6369c61d40d0a19cc4e5124334d..48fd327f876b08b5b246b41425ff997e64cf861d 100644 (file)
@@ -443,10 +443,7 @@ enum i40iw_status_code i40iw_vchnl_recv_pf(struct i40iw_sc_dev *dev,
        if (!dev->vchnl_up)
                return I40IW_ERR_NOT_READY;
        if (vchnl_msg->iw_op_code == I40IW_VCHNL_OP_GET_VER) {
-               if (vchnl_msg->iw_op_ver != I40IW_VCHNL_OP_GET_VER_V0)
-                       vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg);
-               else
-                       vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg);
+               vchnl_pf_send_get_ver_resp(dev, vf_id, vchnl_msg);
                return I40IW_SUCCESS;
        }
        for (iw_vf_idx = 0; iw_vf_idx < I40IW_MAX_PE_ENABLED_VF_COUNT; iw_vf_idx++) {
index b4694717f6f301f4a2d6b407f18b2c42614ee24e..21d31cb1325f5fc0271f093e5ec069641b8b9ffe 100644 (file)
@@ -1578,6 +1578,7 @@ static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc
        if (port < 0)
                return;
        ah.av.ib.port_pd = cpu_to_be32(port << 24 | (be32_to_cpu(ah.av.ib.port_pd) & 0xffffff));
+       ah.ibah.type = rdma_ah_find_type(&dev->ib_dev, port);
 
        mlx4_ib_query_ah(&ah.ibah, &ah_attr);
        if (rdma_ah_get_ah_flags(&ah_attr) & IB_AH_GRH)
index d45772da09635c2164f4cef8bcf5255c17fe8cff..9ecc089d4529440fa87929fb74461558db920549 100644 (file)
@@ -2979,6 +2979,18 @@ error_0:
        return ret;
 }
 
+static u8 mlx5_get_umr_fence(u8 umr_fence_cap)
+{
+       switch (umr_fence_cap) {
+       case MLX5_CAP_UMR_FENCE_NONE:
+               return MLX5_FENCE_MODE_NONE;
+       case MLX5_CAP_UMR_FENCE_SMALL:
+               return MLX5_FENCE_MODE_INITIATOR_SMALL;
+       default:
+               return MLX5_FENCE_MODE_STRONG_ORDERING;
+       }
+}
+
 static int create_dev_resources(struct mlx5_ib_resources *devr)
 {
        struct ib_srq_init_attr attr;
@@ -3680,8 +3692,10 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
        dev->ib_dev.check_mr_status     = mlx5_ib_check_mr_status;
        dev->ib_dev.get_port_immutable  = mlx5_port_immutable;
        dev->ib_dev.get_dev_fw_str      = get_dev_fw_str;
-       dev->ib_dev.alloc_rdma_netdev   = mlx5_ib_alloc_rdma_netdev;
-       dev->ib_dev.free_rdma_netdev    = mlx5_ib_free_rdma_netdev;
+       if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
+               dev->ib_dev.alloc_rdma_netdev   = mlx5_ib_alloc_rdma_netdev;
+               dev->ib_dev.free_rdma_netdev    = mlx5_ib_free_rdma_netdev;
+       }
        if (mlx5_core_is_pf(mdev)) {
                dev->ib_dev.get_vf_config       = mlx5_ib_get_vf_config;
                dev->ib_dev.set_vf_link_state   = mlx5_ib_set_vf_link_state;
@@ -3693,6 +3707,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 
        mlx5_ib_internal_fill_odp_caps(dev);
 
+       dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence));
+
        if (MLX5_CAP_GEN(mdev, imaicl)) {
                dev->ib_dev.alloc_mw            = mlx5_ib_alloc_mw;
                dev->ib_dev.dealloc_mw          = mlx5_ib_dealloc_mw;
index 38c877bc45e592dbbe9670b3c9b624b90b6df30d..bdcf25410c99df7f57e280f2672eb86b8e3205fd 100644 (file)
@@ -349,7 +349,7 @@ struct mlx5_ib_qp {
        struct mlx5_ib_wq       rq;
 
        u8                      sq_signal_bits;
-       u8                      fm_cache;
+       u8                      next_fence;
        struct mlx5_ib_wq       sq;
 
        /* serialize qp state modifications
@@ -654,6 +654,7 @@ struct mlx5_ib_dev {
        struct mlx5_ib_port     *port;
        struct mlx5_sq_bfreg     bfreg;
        struct mlx5_sq_bfreg     fp_bfreg;
+       u8                              umr_fence;
 };
 
 static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
index 93959e1e43a3da5e2f71a89c8c12bdc61368e3e0..ebb6768684de372d755cff4c6f92c768edb9045b 100644 (file)
@@ -3738,24 +3738,6 @@ static void dump_wqe(struct mlx5_ib_qp *qp, int idx, int size_16)
        }
 }
 
-static u8 get_fence(u8 fence, struct ib_send_wr *wr)
-{
-       if (unlikely(wr->opcode == IB_WR_LOCAL_INV &&
-                    wr->send_flags & IB_SEND_FENCE))
-               return MLX5_FENCE_MODE_STRONG_ORDERING;
-
-       if (unlikely(fence)) {
-               if (wr->send_flags & IB_SEND_FENCE)
-                       return MLX5_FENCE_MODE_SMALL_AND_FENCE;
-               else
-                       return fence;
-       } 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,
                     struct mlx5_wqe_ctrl_seg **ctrl,
                     struct ib_send_wr *wr, unsigned *idx,
@@ -3784,8 +3766,7 @@ static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
 static void finish_wqe(struct mlx5_ib_qp *qp,
                       struct mlx5_wqe_ctrl_seg *ctrl,
                       u8 size, unsigned idx, u64 wr_id,
-                      int nreq, u8 fence, u8 next_fence,
-                      u32 mlx5_opcode)
+                      int nreq, u8 fence, u32 mlx5_opcode)
 {
        u8 opmod = 0;
 
@@ -3793,7 +3774,6 @@ static void finish_wqe(struct mlx5_ib_qp *qp,
                                             mlx5_opcode | ((u32)opmod << 24));
        ctrl->qpn_ds = cpu_to_be32(size | (qp->trans_qp.base.mqp.qpn << 8));
        ctrl->fm_ce_se |= fence;
-       qp->fm_cache = next_fence;
        if (unlikely(qp->wq_sig))
                ctrl->signature = wq_sig(ctrl);
 
@@ -3853,7 +3833,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        goto out;
                }
 
-               fence = qp->fm_cache;
                num_sge = wr->num_sge;
                if (unlikely(num_sge > qp->sq.max_gs)) {
                        mlx5_ib_warn(dev, "\n");
@@ -3870,6 +3849,19 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        goto out;
                }
 
+               if (wr->opcode == IB_WR_LOCAL_INV ||
+                   wr->opcode == IB_WR_REG_MR) {
+                       fence = dev->umr_fence;
+                       next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
+               } else if (wr->send_flags & IB_SEND_FENCE) {
+                       if (qp->next_fence)
+                               fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
+                       else
+                               fence = MLX5_FENCE_MODE_FENCE;
+               } else {
+                       fence = qp->next_fence;
+               }
+
                switch (ibqp->qp_type) {
                case IB_QPT_XRC_INI:
                        xrc = seg;
@@ -3896,7 +3888,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                goto out;
 
                        case IB_WR_LOCAL_INV:
-                               next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
                                qp->sq.wr_data[idx] = IB_WR_LOCAL_INV;
                                ctrl->imm = cpu_to_be32(wr->ex.invalidate_rkey);
                                set_linv_wr(qp, &seg, &size);
@@ -3904,7 +3895,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                break;
 
                        case IB_WR_REG_MR:
-                               next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
                                qp->sq.wr_data[idx] = IB_WR_REG_MR;
                                ctrl->imm = cpu_to_be32(reg_wr(wr)->key);
                                err = set_reg_wr(qp, reg_wr(wr), &seg, &size);
@@ -3927,9 +3917,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                        goto out;
                                }
 
-                               finish_wqe(qp, ctrl, size, idx, wr->wr_id,
-                                          nreq, get_fence(fence, wr),
-                                          next_fence, MLX5_OPCODE_UMR);
+                               finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
+                                          fence, MLX5_OPCODE_UMR);
                                /*
                                 * SET_PSV WQEs are not signaled and solicited
                                 * on error
@@ -3954,9 +3943,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                        goto out;
                                }
 
-                               finish_wqe(qp, ctrl, size, idx, wr->wr_id,
-                                          nreq, get_fence(fence, wr),
-                                          next_fence, MLX5_OPCODE_SET_PSV);
+                               finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
+                                          fence, MLX5_OPCODE_SET_PSV);
                                err = begin_wqe(qp, &seg, &ctrl, wr,
                                                &idx, &size, nreq);
                                if (err) {
@@ -3966,7 +3954,6 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                        goto out;
                                }
 
-                               next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
                                err = set_psv_wr(&sig_handover_wr(wr)->sig_attrs->wire,
                                                 mr->sig->psv_wire.psv_idx, &seg,
                                                 &size);
@@ -3976,9 +3963,9 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                        goto out;
                                }
 
-                               finish_wqe(qp, ctrl, size, idx, wr->wr_id,
-                                          nreq, get_fence(fence, wr),
-                                          next_fence, MLX5_OPCODE_SET_PSV);
+                               finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
+                                          fence, MLX5_OPCODE_SET_PSV);
+                               qp->next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
                                num_sge = 0;
                                goto skip_psv;
 
@@ -4089,8 +4076,8 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        }
                }
 
-               finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq,
-                          get_fence(fence, wr), next_fence,
+               qp->next_fence = next_fence;
+               finish_wqe(qp, ctrl, size, idx, wr->wr_id, nreq, fence,
                           mlx5_ib_opcode[wr->opcode]);
 skip_psv:
                if (0)
index fb983df7c157b660239983e00c85da5627863dec..30b256a2c54ec42dd97b29ff0f0cb15be6d44510 100644 (file)
@@ -610,7 +610,6 @@ static void build_mpa_v2(struct nes_cm_node *cm_node,
                ctrl_ord = cm_node->ord_size & IETF_NO_IRD_ORD;
        }
        ctrl_ird |= IETF_PEER_TO_PEER;
-       ctrl_ird |= IETF_FLPDU_ZERO_LEN;
 
        switch (mpa_key) {
        case MPA_KEY_REQUEST:
@@ -1826,7 +1825,7 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
                        type = NES_CM_EVENT_CONNECTED;
                        cm_node->state = NES_CM_STATE_TSA;
                }
-
+               send_ack(cm_node, NULL);
                break;
        default:
                WARN_ON(1);
index aa08c76a42450a2ef86d1854b45a80d7bcd4387c..d961f79b317cba526fe52ca4af6adc40c0781868 100644 (file)
 #define QEDR_MSG_QP   "  QP"
 #define QEDR_MSG_GSI  " GSI"
 
-#define QEDR_CQ_MAGIC_NUMBER   (0x11223344)
+#define QEDR_CQ_MAGIC_NUMBER   (0x11223344)
+
+#define FW_PAGE_SIZE           (RDMA_RING_PAGE_SIZE)
+#define FW_PAGE_SHIFT          (12)
 
 struct qedr_dev;
 
index 3d7705cec7705fcf334a96353e6830b554176500..d86dbe814d98fbe00adf22acb6d1ee658efc5ef5 100644 (file)
@@ -270,11 +270,13 @@ static inline int qedr_gsi_build_header(struct qedr_dev *dev,
                return rc;
        }
 
-       vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev);
-       if (vlan_id < VLAN_CFI_MASK)
-               has_vlan = true;
-       if (sgid_attr.ndev)
+       if (sgid_attr.ndev) {
+               vlan_id = rdma_vlan_dev_vlan_id(sgid_attr.ndev);
+               if (vlan_id < VLAN_CFI_MASK)
+                       has_vlan = true;
+
                dev_put(sgid_attr.ndev);
+       }
 
        if (!memcmp(&sgid, &zgid, sizeof(sgid))) {
                DP_ERR(dev, "gsi post send: GID not found GID index %d\n",
index 17685cfea6a2dcb435e659675805dcbc29139e7b..d6723c365c7fba36168bc11c227de8bc34eef862 100644 (file)
@@ -653,14 +653,15 @@ static int qedr_prepare_pbl_tbl(struct qedr_dev *dev,
 
 static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
                               struct qedr_pbl *pbl,
-                              struct qedr_pbl_info *pbl_info)
+                              struct qedr_pbl_info *pbl_info, u32 pg_shift)
 {
        int shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0;
+       u32 fw_pg_cnt, fw_pg_per_umem_pg;
        struct qedr_pbl *pbl_tbl;
        struct scatterlist *sg;
        struct regpair *pbe;
+       u64 pg_addr;
        int entry;
-       u32 addr;
 
        if (!pbl_info->num_pbes)
                return;
@@ -683,29 +684,35 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
 
        shift = umem->page_shift;
 
+       fw_pg_per_umem_pg = BIT(umem->page_shift - pg_shift);
+
        for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
                pages = sg_dma_len(sg) >> shift;
+               pg_addr = sg_dma_address(sg);
                for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) {
-                       /* store the page address in pbe */
-                       pbe->lo = cpu_to_le32(sg_dma_address(sg) +
-                                             (pg_cnt << shift));
-                       addr = upper_32_bits(sg_dma_address(sg) +
-                                            (pg_cnt << shift));
-                       pbe->hi = cpu_to_le32(addr);
-                       pbe_cnt++;
-                       total_num_pbes++;
-                       pbe++;
-
-                       if (total_num_pbes == pbl_info->num_pbes)
-                               return;
-
-                       /* If the given pbl is full storing the pbes,
-                        * move to next pbl.
-                        */
-                       if (pbe_cnt == (pbl_info->pbl_size / sizeof(u64))) {
-                               pbl_tbl++;
-                               pbe = (struct regpair *)pbl_tbl->va;
-                               pbe_cnt = 0;
+                       for (fw_pg_cnt = 0; fw_pg_cnt < fw_pg_per_umem_pg;) {
+                               pbe->lo = cpu_to_le32(pg_addr);
+                               pbe->hi = cpu_to_le32(upper_32_bits(pg_addr));
+
+                               pg_addr += BIT(pg_shift);
+                               pbe_cnt++;
+                               total_num_pbes++;
+                               pbe++;
+
+                               if (total_num_pbes == pbl_info->num_pbes)
+                                       return;
+
+                               /* If the given pbl is full storing the pbes,
+                                * move to next pbl.
+                                */
+                               if (pbe_cnt ==
+                                   (pbl_info->pbl_size / sizeof(u64))) {
+                                       pbl_tbl++;
+                                       pbe = (struct regpair *)pbl_tbl->va;
+                                       pbe_cnt = 0;
+                               }
+
+                               fw_pg_cnt++;
                        }
                }
        }
@@ -754,7 +761,7 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
                                       u64 buf_addr, size_t buf_len,
                                       int access, int dmasync)
 {
-       int page_cnt;
+       u32 fw_pages;
        int rc;
 
        q->buf_addr = buf_addr;
@@ -766,8 +773,10 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
                return PTR_ERR(q->umem);
        }
 
-       page_cnt = ib_umem_page_count(q->umem);
-       rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, page_cnt, 0);
+       fw_pages = ib_umem_page_count(q->umem) <<
+           (q->umem->page_shift - FW_PAGE_SHIFT);
+
+       rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, fw_pages, 0);
        if (rc)
                goto err0;
 
@@ -777,7 +786,8 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
                goto err0;
        }
 
-       qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info);
+               qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info,
+                                  FW_PAGE_SHIFT);
 
        return 0;
 
@@ -2226,7 +2236,7 @@ struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
                goto err1;
 
        qedr_populate_pbls(dev, mr->umem, mr->info.pbl_table,
-                          &mr->info.pbl_info);
+                          &mr->info.pbl_info, mr->umem->page_shift);
 
        rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
        if (rc) {
@@ -3209,6 +3219,10 @@ static int process_req(struct qedr_dev *dev, struct qedr_qp *qp,
                case IB_WC_REG_MR:
                        qp->wqe_wr_id[qp->sq.cons].mr->info.completed++;
                        break;
+               case IB_WC_RDMA_READ:
+               case IB_WC_SEND:
+                       wc->byte_len = qp->wqe_wr_id[qp->sq.cons].bytes_len;
+                       break;
                default:
                        break;
                }
index fc8b88514da52bc380ce51066e0a2665ff18a2be..4ddbcac5eabe6834f90ecac5885b75495493264a 100644 (file)
@@ -1956,8 +1956,10 @@ send_last:
                ret = qib_get_rwqe(qp, 1);
                if (ret < 0)
                        goto nack_op_err;
-               if (!ret)
+               if (!ret) {
+                       rvt_put_ss(&qp->r_sge);
                        goto rnr_nak;
+               }
                wc.ex.imm_data = ohdr->u.rc.imm_data;
                hdrsize += 4;
                wc.wc_flags = IB_WC_WITH_IMM;
index ecdba2fce0837675f4a9ae6cddb80c7b1c1c0a3d..1ac5b8551a4d37325e782e5dc438ed4915d7243f 100644 (file)
@@ -68,6 +68,7 @@
 static inline u32 rxe_crc32(struct rxe_dev *rxe,
                            u32 crc, void *next, size_t len)
 {
+       u32 retval;
        int err;
 
        SHASH_DESC_ON_STACK(shash, rxe->tfm);
@@ -81,7 +82,9 @@ static inline u32 rxe_crc32(struct rxe_dev *rxe,
                return crc32_le(crc, next, len);
        }
 
-       return *(u32 *)shash_desc_ctx(shash);
+       retval = *(u32 *)shash_desc_ctx(shash);
+       barrier_data(shash_desc_ctx(shash));
+       return retval;
 }
 
 int rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);
index 83d709e74dfb87ab0dcec30c87f0e49cd57022d2..073e66783f1dd8a4b62f9fc59a84319b507b51b8 100644 (file)
@@ -740,13 +740,8 @@ static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr,
 
                sge = ibwr->sg_list;
                for (i = 0; i < num_sge; i++, sge++) {
-                       if (qp->is_user && copy_from_user(p, (__user void *)
-                                           (uintptr_t)sge->addr, sge->length))
-                               return -EFAULT;
-
-                       else if (!qp->is_user)
-                               memcpy(p, (void *)(uintptr_t)sge->addr,
-                                      sge->length);
+                       memcpy(p, (void *)(uintptr_t)sge->addr,
+                                       sge->length);
 
                        p += sge->length;
                }
index 874b24366e4dd744cc9ddf1c4b561a5a050641d1..7871379342f48fa77b2e6e8279ca774b4c49ad2f 100644 (file)
@@ -178,7 +178,7 @@ static inline int ib_speed_enum_to_int(int speed)
 static int ipoib_get_link_ksettings(struct net_device *netdev,
                                    struct ethtool_link_ksettings *cmd)
 {
-       struct ipoib_dev_priv *priv = netdev_priv(netdev);
+       struct ipoib_dev_priv *priv = ipoib_priv(netdev);
        struct ib_port_attr attr;
        int ret, speed, width;
 
index 0060b2f9f659d7ad1ee9a1767d0029dc8529ff4c..efe7402f48852195efae4fc70cf843d0398dda30 100644 (file)
@@ -863,7 +863,6 @@ dev_stop:
        set_bit(IPOIB_STOP_REAPER, &priv->flags);
        cancel_delayed_work(&priv->ah_reap_task);
        set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
-       napi_enable(&priv->napi);
        ipoib_ib_dev_stop(dev);
        return -1;
 }
index 2869d1adb1decdab20a19145536fc978344aba78..1015a63de6aed6f3a8b88f3816dc5720a2d24092 100644 (file)
@@ -1590,12 +1590,14 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)
        wait_for_completion(&priv->ntbl.deleted);
 }
 
-void ipoib_dev_uninit_default(struct net_device *dev)
+static void ipoib_dev_uninit_default(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = ipoib_priv(dev);
 
        ipoib_transport_dev_cleanup(dev);
 
+       netif_napi_del(&priv->napi);
+
        ipoib_cm_dev_cleanup(dev);
 
        kfree(priv->rx_ring);
@@ -1649,6 +1651,7 @@ out_rx_ring_cleanup:
        kfree(priv->rx_ring);
 
 out:
+       netif_napi_del(&priv->napi);
        return -ENOMEM;
 }
 
@@ -2237,6 +2240,7 @@ event_failed:
 
 device_init_failed:
        free_netdev(priv->dev);
+       kfree(priv);
 
 alloc_mem_failed:
        return ERR_PTR(result);
@@ -2277,7 +2281,7 @@ static void ipoib_add_one(struct ib_device *device)
 
 static void ipoib_remove_one(struct ib_device *device, void *client_data)
 {
-       struct ipoib_dev_priv *priv, *tmp;
+       struct ipoib_dev_priv *priv, *tmp, *cpriv, *tcpriv;
        struct list_head *dev_list = client_data;
 
        if (!dev_list)
@@ -2300,7 +2304,14 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
                flush_workqueue(priv->wq);
 
                unregister_netdev(priv->dev);
-               free_netdev(priv->dev);
+               if (device->free_rdma_netdev)
+                       device->free_rdma_netdev(priv->dev);
+               else
+                       free_netdev(priv->dev);
+
+               list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
+                       kfree(cpriv);
+
                kfree(priv);
        }
 
index 36dc4fcaa3cdbcd2516d44fb9360c5dcccce1404..081b33deff1bcbf6f381c9993af174a3dc5e90b4 100644 (file)
@@ -133,13 +133,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
        snprintf(intf_name, sizeof intf_name, "%s.%04x",
                 ppriv->dev->name, pkey);
 
+       if (!rtnl_trylock())
+               return restart_syscall();
+
        priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
        if (!priv)
                return -ENOMEM;
 
-       if (!rtnl_trylock())
-               return restart_syscall();
-
        down_write(&ppriv->vlan_rwsem);
 
        /*
@@ -167,8 +167,10 @@ out:
 
        rtnl_unlock();
 
-       if (result)
+       if (result) {
                free_netdev(priv->dev);
+               kfree(priv);
+       }
 
        return result;
 }
@@ -209,6 +211,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 
        if (dev) {
                free_netdev(dev);
+               kfree(priv);
                return 0;
        }
 
index def723a5df29fa72342ed5e52ec7fa35fa54375c..2354c742caa12d69ef761ecbc7ca8af311bb8aa5 100644 (file)
@@ -320,7 +320,7 @@ static int srp_new_cm_id(struct srp_rdma_ch *ch)
        ch->path.sgid = target->sgid;
        ch->path.dgid = target->orig_dgid;
        ch->path.pkey = target->pkey;
-       sa_path_set_service_id(&ch->path, target->service_id);
+       ch->path.service_id = target->service_id;
 
        return 0;
 }
@@ -575,7 +575,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
        return 0;
 
 err_qp:
-       srp_destroy_qp(ch, qp);
+       ib_destroy_qp(qp);
 
 err_send_cq:
        ib_free_cq(send_cq);
index 485900f953e088ca91d0b1b538be6f6cc3ad6794..abc266e40e1710e034d05077ebbe7dc33ce42903 100644 (file)
@@ -213,7 +213,7 @@ static int tm2_touchkey_probe(struct i2c_client *client,
        /* led device */
        touchkey->led_dev.name = TM2_TOUCHKEY_DEV_NAME;
        touchkey->led_dev.brightness = LED_FULL;
-       touchkey->led_dev.max_brightness = LED_FULL;
+       touchkey->led_dev.max_brightness = LED_ON;
        touchkey->led_dev.brightness_set = tm2_touchkey_led_brightness_set;
 
        error = devm_led_classdev_register(&client->dev, &touchkey->led_dev);
index f11807db69792a1c19661b6921caceee247fbaf5..400869e61a0663be592e723f8f9de4f3596aaf3d 100644 (file)
@@ -256,6 +256,42 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
        return 0;
 }
 
+#ifdef CONFIG_ACPI
+static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek,
+                                            struct platform_device *pdev)
+{
+       unsigned long long hrv = 0;
+       acpi_status status;
+
+       if (IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY) &&
+           axp20x_pek->axp20x->variant == AXP288_ID) {
+               status = acpi_evaluate_integer(ACPI_HANDLE(pdev->dev.parent),
+                                              "_HRV", NULL, &hrv);
+               if (ACPI_FAILURE(status))
+                       dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n");
+
+               /*
+                * On Cherry Trail platforms (hrv == 3), do not register the
+                * input device if there is an "INTCFD9" or "ACPI0011" gpio
+                * button ACPI device, as that handles the power button too,
+                * and otherwise we end up reporting all presses twice.
+                */
+               if (hrv == 3 && (acpi_dev_present("INTCFD9", NULL, -1) ||
+                                acpi_dev_present("ACPI0011", NULL, -1)))
+                       return false;
+
+       }
+
+       return true;
+}
+#else
+static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek,
+                                            struct platform_device *pdev)
+{
+       return true;
+}
+#endif
+
 static int axp20x_pek_probe(struct platform_device *pdev)
 {
        struct axp20x_pek *axp20x_pek;
@@ -268,13 +304,7 @@ static int axp20x_pek_probe(struct platform_device *pdev)
 
        axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);
 
-       /*
-        * Do not register the input device if there is an "INTCFD9"
-        * gpio button ACPI device, that handles the power button too,
-        * and otherwise we end up reporting all presses twice.
-        */
-       if (!acpi_dev_found("INTCFD9") ||
-           !IS_ENABLED(CONFIG_INPUT_SOC_BUTTON_ARRAY)) {
+       if (axp20x_pek_should_register_input(axp20x_pek, pdev)) {
                error = axp20x_pek_probe_input_device(axp20x_pek, pdev);
                if (error)
                        return error;
index e37d37273182097d412f30a3878ea0303f9f7a5b..f600f3a7a3c685488e1ede36058439c59f0703dc 100644 (file)
@@ -248,7 +248,8 @@ static struct soc_button_info *soc_button_get_button_info(struct device *dev)
 
        if (!btns_desc) {
                dev_err(dev, "ACPI Button Descriptors not found\n");
-               return ERR_PTR(-ENODEV);
+               button_info = ERR_PTR(-ENODEV);
+               goto out;
        }
 
        /* The first package describes the collection */
@@ -264,24 +265,31 @@ static struct soc_button_info *soc_button_get_button_info(struct device *dev)
        }
        if (collection_uid == -1) {
                dev_err(dev, "Invalid Button Collection Descriptor\n");
-               return ERR_PTR(-ENODEV);
+               button_info = ERR_PTR(-ENODEV);
+               goto out;
        }
 
        /* There are package.count - 1 buttons + 1 terminating empty entry */
        button_info = devm_kcalloc(dev, btns_desc->package.count,
                                   sizeof(*button_info), GFP_KERNEL);
-       if (!button_info)
-               return ERR_PTR(-ENOMEM);
+       if (!button_info) {
+               button_info = ERR_PTR(-ENOMEM);
+               goto out;
+       }
 
        /* Parse the button descriptors */
        for (i = 1, btn = 0; i < btns_desc->package.count; i++, btn++) {
                if (soc_button_parse_btn_desc(dev,
                                              &btns_desc->package.elements[i],
                                              collection_uid,
-                                             &button_info[btn]))
-                       return ERR_PTR(-ENODEV);
+                                             &button_info[btn])) {
+                       button_info = ERR_PTR(-ENODEV);
+                       goto out;
+               }
        }
 
+out:
+       kfree(buf.pointer);
        return button_info;
 }
 
index a679e56c44cd49ddea4361aebdb97d4fe7f1e12e..f431da07f861e50fa86574954f7e4b0c2c1e57c3 100644 (file)
@@ -554,32 +554,34 @@ static int elan_i2c_finish_fw_update(struct i2c_client *client,
                                     struct completion *completion)
 {
        struct device *dev = &client->dev;
-       long ret;
        int error;
        int len;
-       u8 buffer[ETP_I2C_INF_LENGTH];
+       u8 buffer[ETP_I2C_REPORT_LEN];
+
+       len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN);
+       if (len != ETP_I2C_REPORT_LEN) {
+               error = len < 0 ? len : -EIO;
+               dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n",
+                       error, len);
+       }
 
        reinit_completion(completion);
        enable_irq(client->irq);
 
        error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET);
-       if (!error)
-               ret = wait_for_completion_interruptible_timeout(completion,
-                                                       msecs_to_jiffies(300));
-       disable_irq(client->irq);
-
        if (error) {
                dev_err(dev, "device reset failed: %d\n", error);
-               return error;
-       } else if (ret == 0) {
+       } else if (!wait_for_completion_timeout(completion,
+                                               msecs_to_jiffies(300))) {
                dev_err(dev, "timeout waiting for device reset\n");
-               return -ETIMEDOUT;
-       } else if (ret < 0) {
-               error = ret;
-               dev_err(dev, "error waiting for device reset: %d\n", error);
-               return error;
+               error = -ETIMEDOUT;
        }
 
+       disable_irq(client->irq);
+
+       if (error)
+               return error;
+
        len = i2c_master_recv(client, buffer, ETP_I2C_INF_LENGTH);
        if (len != ETP_I2C_INF_LENGTH) {
                error = len < 0 ? len : -EIO;
index e73d968023f7ce7de418dcf1315b7c554773d604..f1fa1f172107722ef13d8c98e0c2d539d096c2aa 100644 (file)
@@ -1118,8 +1118,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
+ * Fujitsu LIFEBOOK E546   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E554   0x570f01        40, 14, 0c      2 hw buttons
+ * Fujitsu LIFEBOOK E557   0x570f01        40, 14, 0c      2 hw buttons
  * Fujitsu T725            0x470f01        05, 12, 09      2 hw buttons
  * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
  * Gigabyte U2442          0x450f01        58, 17, 0c      2 hw buttons
@@ -1524,6 +1526,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E544"),
                },
        },
+       {
+               /* Fujitsu LIFEBOOK E546  does not work with crc_enabled == 0 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E546"),
+               },
+       },
        {
                /* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */
                .matches = {
@@ -1545,6 +1554,13 @@ static const struct dmi_system_id elantech_dmi_force_crc_enabled[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E556"),
                },
        },
+       {
+               /* Fujitsu LIFEBOOK E557 does not work with crc_enabled == 0 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E557"),
+               },
+       },
        {
                /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
                .matches = {
index 131df9d3660f0e4866b9ffc849ca0d6ce1d4e906..16c30460ef041b13686db7f6efe36860b725a4bd 100644 (file)
@@ -176,6 +176,12 @@ static const char * const smbus_pnp_ids[] = {
        NULL
 };
 
+static const char * const forcepad_pnp_ids[] = {
+       "SYN300D",
+       "SYN3014",
+       NULL
+};
+
 /*
  * Send a command to the synpatics touchpad by special commands
  */
@@ -397,6 +403,8 @@ static int synaptics_query_hardware(struct psmouse *psmouse,
 {
        int error;
 
+       memset(info, 0, sizeof(*info));
+
        error = synaptics_identify(psmouse, info);
        if (error)
                return error;
@@ -480,13 +488,6 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
        { }
 };
 
-/* This list has been kindly provided by Synaptics. */
-static const char * const forcepad_pnp_ids[] = {
-       "SYN300D",
-       "SYN3014",
-       NULL
-};
-
 /*****************************************************************************
  *     Synaptics communications functions
  ****************************************************************************/
@@ -1687,7 +1688,8 @@ enum {
        SYNAPTICS_INTERTOUCH_ON,
 };
 
-static int synaptics_intertouch = SYNAPTICS_INTERTOUCH_NOT_SET;
+static int synaptics_intertouch = IS_ENABLED(CONFIG_RMI4_SMB) ?
+               SYNAPTICS_INTERTOUCH_NOT_SET : SYNAPTICS_INTERTOUCH_OFF;
 module_param_named(synaptics_intertouch, synaptics_intertouch, int, 0644);
 MODULE_PARM_DESC(synaptics_intertouch, "Use a secondary bus for the Synaptics device.");
 
@@ -1737,8 +1739,16 @@ static int synaptics_setup_intertouch(struct psmouse *psmouse,
 
        if (synaptics_intertouch == SYNAPTICS_INTERTOUCH_NOT_SET) {
                if (!psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
-                   !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids))
+                   !psmouse_matches_pnp_id(psmouse, smbus_pnp_ids)) {
+
+                       if (!psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids))
+                               psmouse_info(psmouse,
+                                            "Your touchpad (%s) says it can support a different bus. "
+                                            "If i2c-hid and hid-rmi are not used, you might want to try setting psmouse.synaptics_intertouch to 1 and report this to linux-input@vger.kernel.org.\n",
+                                            psmouse->ps2dev.serio->firmware_id);
+
                        return -ENXIO;
+               }
        }
 
        psmouse_info(psmouse, "Trying to set up SMBus access\n");
@@ -1810,6 +1820,15 @@ int synaptics_init(struct psmouse *psmouse)
        }
 
        if (SYN_CAP_INTERTOUCH(info.ext_cap_0c)) {
+               if ((!IS_ENABLED(CONFIG_RMI4_SMB) ||
+                    !IS_ENABLED(CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS)) &&
+                   /* Forcepads need F21, which is not ready */
+                   !psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids)) {
+                       psmouse_warn(psmouse,
+                                    "The touchpad can support a better bus than the too old PS/2 protocol. "
+                                    "Make sure MOUSE_PS2_SYNAPTICS_SMBUS and RMI4_SMB are enabled to get a better touchpad experience.\n");
+               }
+
                error = synaptics_setup_intertouch(psmouse, &info, true);
                if (!error)
                        return PSMOUSE_SYNAPTICS_SMBUS;
index 77dad045a4683026460dca491419112d730897d7..ad71a5e768dc46432b18b84fb344a7bb514bb56c 100644 (file)
@@ -146,7 +146,7 @@ static int rmi_f03_register_pt(struct f03_data *f03)
        if (!serio)
                return -ENOMEM;
 
-       serio->id.type = SERIO_8042;
+       serio->id.type = SERIO_PS_PSTHRU;
        serio->write = rmi_f03_pt_write;
        serio->port_data = f03;
 
index dea63e2db3e6213f5e83d6067870a16cc5707e6d..f5206e2c767ebf3579c2468b2a2956cc4bff3dcc 100644 (file)
@@ -31,9 +31,6 @@
 #define F54_GET_REPORT          1
 #define F54_FORCE_CAL           2
 
-/* Fixed sizes of reports */
-#define F54_QUERY_LEN                  27
-
 /* F54 capabilities */
 #define F54_CAP_BASELINE       (1 << 2)
 #define F54_CAP_IMAGE8         (1 << 3)
@@ -95,7 +92,6 @@ struct rmi_f54_reports {
 struct f54_data {
        struct rmi_function *fn;
 
-       u8 qry[F54_QUERY_LEN];
        u8 num_rx_electrodes;
        u8 num_tx_electrodes;
        u8 capabilities;
@@ -632,22 +628,23 @@ static int rmi_f54_detect(struct rmi_function *fn)
 {
        int error;
        struct f54_data *f54;
+       u8 buf[6];
 
        f54 = dev_get_drvdata(&fn->dev);
 
        error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
-                              &f54->qry, sizeof(f54->qry));
+                              buf, sizeof(buf));
        if (error) {
                dev_err(&fn->dev, "%s: Failed to query F54 properties\n",
                        __func__);
                return error;
        }
 
-       f54->num_rx_electrodes = f54->qry[0];
-       f54->num_tx_electrodes = f54->qry[1];
-       f54->capabilities = f54->qry[2];
-       f54->clock_rate = f54->qry[3] | (f54->qry[4] << 8);
-       f54->family = f54->qry[5];
+       f54->num_rx_electrodes = buf[0];
+       f54->num_tx_electrodes = buf[1];
+       f54->capabilities = buf[2];
+       f54->clock_rate = buf[3] | (buf[4] << 8);
+       f54->family = buf[5];
 
        rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F54 num_rx_electrodes: %d\n",
                f54->num_rx_electrodes);
index 09720d950686c844b49f1d7f32710e160d21624a..f932a83b4990210d8daeb25c1d2482b958c3719e 100644 (file)
@@ -723,6 +723,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
                },
        },
+       {
+               /* Fujitsu UH554 laptop */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+               },
+       },
        { }
 };
 
index 2302aef2b2d403d47f8384c0127ad91104788ef5..dd042a9b0aaacc208056376b27a5fd7bf5755f6c 100644 (file)
@@ -350,6 +350,7 @@ static bool mxt_object_readable(unsigned int type)
        case MXT_TOUCH_KEYARRAY_T15:
        case MXT_TOUCH_PROXIMITY_T23:
        case MXT_TOUCH_PROXKEY_T52:
+       case MXT_TOUCH_MULTITOUCHSCREEN_T100:
        case MXT_PROCI_GRIPFACE_T20:
        case MXT_PROCG_NOISE_T22:
        case MXT_PROCI_ONETOUCH_T24:
index 8cf8d8d5d4ef4f82b45cc5ecbb959c92be95b699..f872817e81e46ba6d962a5edc207302e9bd25f3f 100644 (file)
@@ -471,7 +471,7 @@ static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
 static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
                M09_REGISTER_OFFSET, 0, 31);
 static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
-               M09_REGISTER_THRESHOLD, 20, 80);
+               M09_REGISTER_THRESHOLD, 0, 80);
 static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
                NO_REGISTER, 3, 14);
 
index 813dd68a5c82478f4636652fe6e5dec05ec1fd37..0dbcf105f7db348773592f54d4b85beb9b7ba4a3 100644 (file)
@@ -526,6 +526,7 @@ static int __maybe_unused silead_ts_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
 
+       disable_irq(client->irq);
        silead_ts_set_power(client, SILEAD_POWER_OFF);
        return 0;
 }
@@ -551,6 +552,8 @@ static int __maybe_unused silead_ts_resume(struct device *dev)
                return -ENODEV;
        }
 
+       enable_irq(client->irq);
+
        return 0;
 }
 
index 63cacf5d6cf23ab5611ba4219207a47c00662226..0f1219fa85617bc72b39c8f450ee4edfed2f364f 100644 (file)
@@ -3879,11 +3879,9 @@ static void irte_ga_prepare(void *entry,
                            u8 vector, u32 dest_apicid, int devid)
 {
        struct irte_ga *irte = (struct irte_ga *) entry;
-       struct iommu_dev_data *dev_data = search_dev_data(devid);
 
        irte->lo.val                      = 0;
        irte->hi.val                      = 0;
-       irte->lo.fields_remap.guest_mode  = dev_data ? dev_data->use_vapic : 0;
        irte->lo.fields_remap.int_type    = delivery_mode;
        irte->lo.fields_remap.dm          = dest_mode;
        irte->hi.fields.vector            = vector;
@@ -3939,10 +3937,10 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
        struct irte_ga *irte = (struct irte_ga *) entry;
        struct iommu_dev_data *dev_data = search_dev_data(devid);
 
-       if (!dev_data || !dev_data->use_vapic) {
+       if (!dev_data || !dev_data->use_vapic ||
+           !irte->lo.fields_remap.guest_mode) {
                irte->hi.fields.vector = vector;
                irte->lo.fields_remap.destination = dest_apicid;
-               irte->lo.fields_remap.guest_mode = 0;
                modify_irte_ga(devid, index, irte, NULL);
        }
 }
index 8348f366ddd1a651817361cb9b8874ebdd3bc2bd..62618e77bedc9e2e8bf9ae241fcf127383735a73 100644 (file)
@@ -396,13 +396,13 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
                dma_addr_t iova, size_t size)
 {
        struct iova_domain *iovad = &cookie->iovad;
-       unsigned long shift = iova_shift(iovad);
 
        /* The MSI case is only ever cleaning up its most recent allocation */
        if (cookie->type == IOMMU_DMA_MSI_COOKIE)
                cookie->msi_iova -= size;
        else
-               free_iova_fast(iovad, iova >> shift, size >> shift);
+               free_iova_fast(iovad, iova_pfn(iovad, iova),
+                               size >> iova_shift(iovad));
 }
 
 static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr,
@@ -617,11 +617,14 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
-       struct iova_domain *iovad = &cookie->iovad;
-       size_t iova_off = iova_offset(iovad, phys);
+       size_t iova_off = 0;
        dma_addr_t iova;
 
-       size = iova_align(iovad, size + iova_off);
+       if (cookie->type == IOMMU_DMA_IOVA_COOKIE) {
+               iova_off = iova_offset(&cookie->iovad, phys);
+               size = iova_align(&cookie->iovad, size + iova_off);
+       }
+
        iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
        if (!iova)
                return DMA_ERROR_CODE;
index 90ab0115d78e8dcc4512a6ab2efb27ac45a86c54..fc2765ccdb57496e257a0da0fd2177431a1c8713 100644 (file)
@@ -2055,11 +2055,14 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
        if (context_copied(context)) {
                u16 did_old = context_domain_id(context);
 
-               if (did_old >= 0 && did_old < cap_ndoms(iommu->cap))
+               if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) {
                        iommu->flush.flush_context(iommu, did_old,
                                                   (((u16)bus) << 8) | devfn,
                                                   DMA_CCMD_MASK_NOBIT,
                                                   DMA_CCMD_DEVICE_INVL);
+                       iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
+                                                DMA_TLB_DSI_FLUSH);
+               }
        }
 
        pgd = domain->pgd;
index a27ef570c328d194d3528e81a64ea4f986e31ca6..bc1efbfb9ddf0f121a213f9919f7e3ea0fa957ca 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
index 9f44ee8ea1bc8a10a6ff4c0dad297b78b8c2f57a..19779b88a47973eef332b88b05d1ac76193f788d 100644 (file)
@@ -118,6 +118,7 @@ static const struct iommu_ops
 
        ops = iommu_ops_from_fwnode(fwnode);
        if ((ops && !ops->of_xlate) ||
+           !of_device_is_available(iommu_spec->np) ||
            (!ops && !of_iommu_driver_present(iommu_spec->np)))
                return NULL;
 
@@ -236,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
                        ops = ERR_PTR(err);
        }
 
+       /* Ignore all other errors apart from EPROBE_DEFER */
+       if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
+               dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
+               ops = NULL;
+       }
+
        return ops;
 }
 
index d2306c821ebb594398d102433dcc66efcb2bf573..31d6b5a582d28a2b4fdd0d0c0f0bf9e6113a9e4d 100644 (file)
@@ -106,10 +106,7 @@ static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
 static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
                                        u32 *mask, u32 *addr)
 {
-       unsigned int ofst;
-
-       hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
-       ofst = hwirq / 32 * 4;
+       unsigned int ofst = (hwirq / 32) * 4;
 
        *mask = 1 << (hwirq % 32);
        *addr = ofst + REG_MBIGEN_CLEAR_OFFSET;
@@ -337,9 +334,15 @@ static int mbigen_device_probe(struct platform_device *pdev)
        mgn_chip->pdev = pdev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mgn_chip->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(mgn_chip->base))
-               return PTR_ERR(mgn_chip->base);
+       if (!res)
+               return -EINVAL;
+
+       mgn_chip->base = devm_ioremap(&pdev->dev, res->start,
+                                     resource_size(res));
+       if (!mgn_chip->base) {
+               dev_err(&pdev->dev, "failed to ioremap %pR\n", res);
+               return -ENOMEM;
+       }
 
        if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
                err = mbigen_of_create_domain(pdev, mgn_chip);
index eb7fbe15996304fc9eecca11a2b71b70bffd284d..929f8558bf1c0fe247d5c0ab99e40dfaaea094bd 100644 (file)
@@ -140,7 +140,7 @@ static inline void gic_map_to_vpe(unsigned int intr, unsigned int vpe)
 }
 
 #ifdef CONFIG_CLKSRC_MIPS_GIC
-u64 gic_read_count(void)
+u64 notrace gic_read_count(void)
 {
        unsigned int hi, hi2, lo;
 
@@ -167,7 +167,7 @@ unsigned int gic_get_count_width(void)
        return bits;
 }
 
-void gic_write_compare(u64 cnt)
+void notrace gic_write_compare(u64 cnt)
 {
        if (mips_cm_is64) {
                gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE), cnt);
@@ -179,7 +179,7 @@ void gic_write_compare(u64 cnt)
        }
 }
 
-void gic_write_cpu_compare(u64 cnt, int cpu)
+void notrace gic_write_cpu_compare(u64 cnt, int cpu)
 {
        unsigned long flags;
 
index bb3ac5fe5846b9e2d27b71bea9bf0bff9bcb8e2d..72a391e01011c8356474765cde4ab18d2f997f10 100644 (file)
@@ -142,7 +142,7 @@ static struct irq_chip xtensa_mx_irq_chip = {
 int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
 {
        struct irq_domain *root_domain =
-               irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+               irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
                                &xtensa_mx_irq_domain_ops,
                                &xtensa_mx_irq_chip);
        irq_set_default_host(root_domain);
index 472ae17709647201606a10344fd741d77e81e988..f728755fa2922019e6b117105f3a9b9dfe0fc3e9 100644 (file)
@@ -89,7 +89,7 @@ static struct irq_chip xtensa_irq_chip = {
 int __init xtensa_pic_init_legacy(struct device_node *interrupt_parent)
 {
        struct irq_domain *root_domain =
-               irq_domain_add_legacy(NULL, NR_IRQS, 0, 0,
+               irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
                                &xtensa_irq_domain_ops, &xtensa_irq_chip);
        irq_set_default_host(root_domain);
        return 0;
index d07dd5196ffca59c11532051fb88e2ecdc7326c9..8aa158a091806fd7d3107ed56b8550198be7b9a0 100644 (file)
@@ -2364,7 +2364,7 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
                       id);
                return NULL;
        } else {
-               rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+               rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC);
                if (!rs)
                        return NULL;
                rs->state = CCPResetIdle;
index 8b7faea2ddf88b718c252dc049e5d1b8b5e8357b..422dced7c90ac26dcf0d366fedb32ab9edf44207 100644 (file)
@@ -75,7 +75,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb)
                if (sk->sk_state != MISDN_BOUND)
                        continue;
                if (!cskb)
-                       cskb = skb_copy(skb, GFP_KERNEL);
+                       cskb = skb_copy(skb, GFP_ATOMIC);
                if (!cskb) {
                        printk(KERN_WARNING "%s no skb\n", __func__);
                        break;
index 1548259297c185e8cfefb4f6df7127b97755da2b..2cfd9389ee96f8cc69a40681374a19a31aa174ed 100644 (file)
@@ -242,7 +242,7 @@ static int bcm6328_hwled(struct device *dev, struct device_node *nc, u32 reg,
 
                spin_lock_irqsave(lock, flags);
                val = bcm6328_led_read(addr);
-               val |= (BIT(reg) << (((sel % 4) * 4) + 16));
+               val |= (BIT(reg % 4) << (((sel % 4) * 4) + 16));
                bcm6328_led_write(addr, val);
                spin_unlock_irqrestore(lock, flags);
        }
@@ -269,7 +269,7 @@ static int bcm6328_hwled(struct device *dev, struct device_node *nc, u32 reg,
 
                spin_lock_irqsave(lock, flags);
                val = bcm6328_led_read(addr);
-               val |= (BIT(reg) << ((sel % 4) * 4));
+               val |= (BIT(reg % 4) << ((sel % 4) * 4));
                bcm6328_led_write(addr, val);
                spin_unlock_irqrestore(lock, flags);
        }
index 78a7ce816a4792c7b1ddc101cece8c265084e630..9a873118ea5fcf4ff7adae18e03b3a351936df16 100644 (file)
@@ -285,7 +285,7 @@ static int pca955x_probe(struct i2c_client *client,
                        "slave address 0x%02x\n",
                        client->name, chip->bits, client->addr);
 
-       if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -EIO;
 
        if (pdata) {
index afa3b40992140b2cf194ef971502a517b1cc9bd2..e95ea65380c864b5aef90c9eec0bb000b4b51086 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/sched/loadavg.h>
 #include <linux/leds.h>
 #include <linux/reboot.h>
-#include <linux/suspend.h>
 #include "../leds.h"
 
 static int panic_heartbeats;
@@ -163,30 +162,6 @@ 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)
 {
@@ -201,10 +176,6 @@ 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,
 };
@@ -221,14 +192,12 @@ 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 bf7419a56454e3834ea2c2034d3170591f1ad97f..f4eace5ea184095eb0c170c4f3f1647f72b8c537 100644 (file)
@@ -485,10 +485,10 @@ void bitmap_print_sb(struct bitmap *bitmap)
        pr_debug("         magic: %08x\n", le32_to_cpu(sb->magic));
        pr_debug("       version: %d\n", le32_to_cpu(sb->version));
        pr_debug("          uuid: %08x.%08x.%08x.%08x\n",
-                *(__u32 *)(sb->uuid+0),
-                *(__u32 *)(sb->uuid+4),
-                *(__u32 *)(sb->uuid+8),
-                *(__u32 *)(sb->uuid+12));
+                le32_to_cpu(*(__u32 *)(sb->uuid+0)),
+                le32_to_cpu(*(__u32 *)(sb->uuid+4)),
+                le32_to_cpu(*(__u32 *)(sb->uuid+8)),
+                le32_to_cpu(*(__u32 *)(sb->uuid+12)));
        pr_debug("        events: %llu\n",
                 (unsigned long long) le64_to_cpu(sb->events));
        pr_debug("events cleared: %llu\n",
index 5db11a40512940df04d0dc871498830ec45f03ee..840c1496b2b138ef504bde4c441b1082df183473 100644 (file)
@@ -218,7 +218,7 @@ static DEFINE_SPINLOCK(param_spinlock);
  * Buffers are freed after this timeout
  */
 static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
-static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
+static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
 
 static unsigned long dm_bufio_peak_allocated;
 static unsigned long dm_bufio_allocated_kmem_cache;
@@ -1334,7 +1334,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c)
 {
        struct dm_io_request io_req = {
                .bi_op = REQ_OP_WRITE,
-               .bi_op_flags = REQ_PREFLUSH,
+               .bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
                .mem.type = DM_IO_KMEM,
                .mem.ptr.addr = NULL,
                .client = c->dm_io,
@@ -1558,10 +1558,10 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp)
        return true;
 }
 
-static unsigned get_retain_buffers(struct dm_bufio_client *c)
+static unsigned long get_retain_buffers(struct dm_bufio_client *c)
 {
-        unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
-        return retain_bytes / c->block_size;
+        unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
+        return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT);
 }
 
 static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
@@ -1571,7 +1571,7 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
        struct dm_buffer *b, *tmp;
        unsigned long freed = 0;
        unsigned long count = nr_to_scan;
-       unsigned retain_target = get_retain_buffers(c);
+       unsigned long retain_target = get_retain_buffers(c);
 
        for (l = 0; l < LIST_SIZE; l++) {
                list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) {
@@ -1794,8 +1794,8 @@ static bool older_than(struct dm_buffer *b, unsigned long age_hz)
 static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz)
 {
        struct dm_buffer *b, *tmp;
-       unsigned retain_target = get_retain_buffers(c);
-       unsigned count;
+       unsigned long retain_target = get_retain_buffers(c);
+       unsigned long count;
        LIST_HEAD(write_list);
 
        dm_bufio_lock(c);
@@ -1955,7 +1955,7 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
 module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
 
-module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR);
+module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory");
 
 module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
index 9b1afdfb13f0f9510183ab916e642206023a60c5..70723389129163146666664e053d03e4263d677a 100644 (file)
@@ -33,6 +33,11 @@ struct background_tracker *btracker_create(unsigned max_work)
 {
        struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL);
 
+       if (!b) {
+               DMERR("couldn't create background_tracker");
+               return NULL;
+       }
+
        b->max_work = max_work;
        atomic_set(&b->pending_promotes, 0);
        atomic_set(&b->pending_writebacks, 0);
index 72479bd61e118e51c4bada036901ebe1bc4b1091..e5eb9c9b4bc8e8265c90debdc3d86eea98f08d96 100644 (file)
@@ -1120,8 +1120,6 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
         * Cache entries may not be populated.  So we cannot rely on the
         * size of the clean queue.
         */
-       unsigned nr_clean;
-
        if (idle) {
                /*
                 * We'd like to clean everything.
@@ -1129,18 +1127,16 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
                return q_size(&mq->dirty) == 0u;
        }
 
-       nr_clean = from_cblock(mq->cache_size) - q_size(&mq->dirty);
-       return (nr_clean + btracker_nr_writebacks_queued(mq->bg_work)) >=
-               percent_to_target(mq, CLEAN_TARGET);
+       /*
+        * If we're busy we don't worry about cleaning at all.
+        */
+       return true;
 }
 
-static bool free_target_met(struct smq_policy *mq, bool idle)
+static bool free_target_met(struct smq_policy *mq)
 {
        unsigned nr_free;
 
-       if (!idle)
-               return true;
-
        nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated;
        return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >=
                percent_to_target(mq, FREE_TARGET);
@@ -1190,9 +1186,9 @@ static void queue_demotion(struct smq_policy *mq)
        if (unlikely(WARN_ON_ONCE(!mq->migrations_allowed)))
                return;
 
-       e = q_peek(&mq->clean, mq->clean.nr_levels, true);
+       e = q_peek(&mq->clean, mq->clean.nr_levels / 2, true);
        if (!e) {
-               if (!clean_target_met(mq, false))
+               if (!clean_target_met(mq, true))
                        queue_writeback(mq);
                return;
        }
@@ -1220,7 +1216,7 @@ static void queue_promotion(struct smq_policy *mq, dm_oblock_t oblock,
                 * We always claim to be 'idle' to ensure some demotions happen
                 * with continuous loads.
                 */
-               if (!free_target_met(mq, true))
+               if (!free_target_met(mq))
                        queue_demotion(mq);
                return;
        }
@@ -1421,14 +1417,10 @@ static int smq_get_background_work(struct dm_cache_policy *p, bool idle,
        spin_lock_irqsave(&mq->lock, flags);
        r = btracker_issue(mq->bg_work, result);
        if (r == -ENODATA) {
-               /* find some writeback work to do */
-               if (mq->migrations_allowed && !free_target_met(mq, idle))
-                       queue_demotion(mq);
-
-               else if (!clean_target_met(mq, idle))
+               if (!clean_target_met(mq, idle)) {
                        queue_writeback(mq);
-
-               r = btracker_issue(mq->bg_work, result);
+                       r = btracker_issue(mq->bg_work, result);
+               }
        }
        spin_unlock_irqrestore(&mq->lock, flags);
 
@@ -1452,6 +1444,7 @@ static void __complete_background_work(struct smq_policy *mq,
                clear_pending(mq, e);
                if (success) {
                        e->oblock = work->oblock;
+                       e->level = NR_CACHE_LEVELS - 1;
                        push(mq, e);
                        // h, q, a
                } else {
index 1db375f50a1321aae81492d1b3ac6392c52a00c2..d682a0511381aad0cadb7ab1f4eae9f815639aa1 100644 (file)
@@ -94,6 +94,9 @@ static void iot_io_begin(struct io_tracker *iot, sector_t len)
 
 static void __iot_io_end(struct io_tracker *iot, sector_t len)
 {
+       if (!len)
+               return;
+
        iot->in_flight -= len;
        if (!iot->in_flight)
                iot->idle_time = jiffies;
@@ -474,7 +477,7 @@ struct cache {
        spinlock_t invalidation_lock;
        struct list_head invalidation_requests;
 
-       struct io_tracker origin_tracker;
+       struct io_tracker tracker;
 
        struct work_struct commit_ws;
        struct batcher committer;
@@ -901,8 +904,7 @@ static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio)
 
 static bool accountable_bio(struct cache *cache, struct bio *bio)
 {
-       return ((bio->bi_bdev == cache->origin_dev->bdev) &&
-               bio_op(bio) != REQ_OP_DISCARD);
+       return bio_op(bio) != REQ_OP_DISCARD;
 }
 
 static void accounted_begin(struct cache *cache, struct bio *bio)
@@ -912,7 +914,7 @@ static void accounted_begin(struct cache *cache, struct bio *bio)
 
        if (accountable_bio(cache, bio)) {
                pb->len = bio_sectors(bio);
-               iot_io_begin(&cache->origin_tracker, pb->len);
+               iot_io_begin(&cache->tracker, pb->len);
        }
 }
 
@@ -921,7 +923,7 @@ static void accounted_complete(struct cache *cache, struct bio *bio)
        size_t pb_data_size = get_per_bio_data_size(cache);
        struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
-       iot_io_end(&cache->origin_tracker, pb->len);
+       iot_io_end(&cache->tracker, pb->len);
 }
 
 static void accounted_request(struct cache *cache, struct bio *bio)
@@ -1716,20 +1718,19 @@ static int invalidate_start(struct cache *cache, dm_cblock_t cblock,
 
 enum busy {
        IDLE,
-       MODERATE,
        BUSY
 };
 
 static enum busy spare_migration_bandwidth(struct cache *cache)
 {
-       bool idle = iot_idle_for(&cache->origin_tracker, HZ);
+       bool idle = iot_idle_for(&cache->tracker, HZ);
        sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) *
                cache->sectors_per_block;
 
-       if (current_volume <= cache->migration_threshold)
-               return idle ? IDLE : MODERATE;
+       if (idle && current_volume <= cache->migration_threshold)
+               return IDLE;
        else
-               return idle ? MODERATE : BUSY;
+               return BUSY;
 }
 
 static void inc_hit_counter(struct cache *cache, struct bio *bio)
@@ -2045,8 +2046,6 @@ static void check_migrations(struct work_struct *ws)
 
        for (;;) {
                b = spare_migration_bandwidth(cache);
-               if (b == BUSY)
-                       break;
 
                r = policy_get_background_work(cache->policy, b == IDLE, &op);
                if (r == -ENODATA)
@@ -2717,7 +2716,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
        batcher_init(&cache->committer, commit_op, cache,
                     issue_op, cache, cache->wq);
-       iot_init(&cache->origin_tracker);
+       iot_init(&cache->tracker);
 
        init_rwsem(&cache->background_work_lock);
        prevent_background_work(cache);
@@ -2941,7 +2940,7 @@ static void cache_postsuspend(struct dm_target *ti)
 
        cancel_delayed_work(&cache->waker);
        flush_workqueue(cache->wq);
-       WARN_ON(cache->origin_tracker.in_flight);
+       WARN_ON(cache->tracker.in_flight);
 
        /*
         * If it's a flush suspend there won't be any deferred bios, so this
index c7f7c8d7657670850adedceb505538e1b9cdb2ce..93b18108816813bd4d49e0ba3e6eb57be7ae3d9f 100644 (file)
@@ -783,7 +783,8 @@ static void write_journal(struct dm_integrity_c *ic, unsigned commit_start, unsi
                        for (i = 0; i < commit_sections; i++)
                                rw_section_mac(ic, commit_start + i, true);
                }
-               rw_journal(ic, REQ_OP_WRITE, REQ_FUA, commit_start, commit_sections, &io_comp);
+               rw_journal(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, commit_start,
+                          commit_sections, &io_comp);
        } else {
                unsigned to_end;
                io_comp.in_flight = (atomic_t)ATOMIC_INIT(2);
@@ -1104,10 +1105,13 @@ static void schedule_autocommit(struct dm_integrity_c *ic)
 static void submit_flush_bio(struct dm_integrity_c *ic, struct dm_integrity_io *dio)
 {
        struct bio *bio;
-       spin_lock_irq(&ic->endio_wait.lock);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ic->endio_wait.lock, flags);
        bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
        bio_list_add(&ic->flush_bio_list, bio);
-       spin_unlock_irq(&ic->endio_wait.lock);
+       spin_unlock_irqrestore(&ic->endio_wait.lock, flags);
+
        queue_work(ic->commit_wq, &ic->commit_work);
 }
 
@@ -2374,21 +2378,6 @@ static void dm_integrity_set(struct dm_target *ti, struct dm_integrity_c *ic)
        blk_queue_max_integrity_segments(disk->queue, UINT_MAX);
 }
 
-/* FIXME: use new kvmalloc */
-static void *dm_integrity_kvmalloc(size_t size, gfp_t gfp)
-{
-       void *ptr = NULL;
-
-       if (size <= PAGE_SIZE)
-               ptr = kmalloc(size, GFP_KERNEL | gfp);
-       if (!ptr && size <= KMALLOC_MAX_SIZE)
-               ptr = kmalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | gfp);
-       if (!ptr)
-               ptr = __vmalloc(size, GFP_KERNEL | gfp, PAGE_KERNEL);
-
-       return ptr;
-}
-
 static void dm_integrity_free_page_list(struct dm_integrity_c *ic, struct page_list *pl)
 {
        unsigned i;
@@ -2407,7 +2396,7 @@ static struct page_list *dm_integrity_alloc_page_list(struct dm_integrity_c *ic)
        struct page_list *pl;
        unsigned i;
 
-       pl = dm_integrity_kvmalloc(page_list_desc_size, __GFP_ZERO);
+       pl = kvmalloc(page_list_desc_size, GFP_KERNEL | __GFP_ZERO);
        if (!pl)
                return NULL;
 
@@ -2437,7 +2426,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
        struct scatterlist **sl;
        unsigned i;
 
-       sl = dm_integrity_kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), __GFP_ZERO);
+       sl = kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), GFP_KERNEL | __GFP_ZERO);
        if (!sl)
                return NULL;
 
@@ -2453,7 +2442,7 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
 
                n_pages = (end_index - start_index + 1);
 
-               s = dm_integrity_kvmalloc(n_pages * sizeof(struct scatterlist), 0);
+               s = kvmalloc(n_pages * sizeof(struct scatterlist), GFP_KERNEL);
                if (!s) {
                        dm_integrity_free_journal_scatterlist(ic, sl);
                        return NULL;
@@ -2617,7 +2606,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                goto bad;
                        }
 
-                       sg = dm_integrity_kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), 0);
+                       sg = kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), GFP_KERNEL);
                        if (!sg) {
                                *error = "Unable to allocate sg list";
                                r = -ENOMEM;
@@ -2673,7 +2662,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                                r = -ENOMEM;
                                goto bad;
                        }
-                       ic->sk_requests = dm_integrity_kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), __GFP_ZERO);
+                       ic->sk_requests = kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), GFP_KERNEL | __GFP_ZERO);
                        if (!ic->sk_requests) {
                                *error = "Unable to allocate sk requests";
                                r = -ENOMEM;
@@ -2740,7 +2729,7 @@ retest_commit_id:
                r = -ENOMEM;
                goto bad;
        }
-       ic->journal_tree = dm_integrity_kvmalloc(journal_tree_size, 0);
+       ic->journal_tree = kvmalloc(journal_tree_size, GFP_KERNEL);
        if (!ic->journal_tree) {
                *error = "Could not allocate memory for journal tree";
                r = -ENOMEM;
@@ -3054,6 +3043,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                ti->error = "The device is too small";
                goto bad;
        }
+       if (ti->len > ic->provided_data_sectors) {
+               r = -EINVAL;
+               ti->error = "Not enough provided sectors for requested mapping size";
+               goto bad;
+       }
 
        if (!buffer_sectors)
                buffer_sectors = 1;
index 3702e502466d37a902c64a74a1f5ad7b516770bb..8d5ca30f655123611b5dcd2ba3d35b52e9c6c447 100644 (file)
@@ -317,8 +317,8 @@ static void do_region(int op, int op_flags, unsigned region,
        else if (op == REQ_OP_WRITE_SAME)
                special_cmd_max_sectors = q->limits.max_write_same_sectors;
        if ((op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES ||
-            op == REQ_OP_WRITE_SAME)  &&
-           special_cmd_max_sectors == 0) {
+            op == REQ_OP_WRITE_SAME) && special_cmd_max_sectors == 0) {
+               atomic_inc(&io->count);
                dec_count(io, region, -EOPNOTSUPP);
                return;
        }
index 0555b4410e0598a6096642f10978ad6798bc5f98..41852ae287a58c29e675dd4b794f1670f9dc53e8 100644 (file)
@@ -1710,12 +1710,13 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
        }
 
        /*
-        * Try to avoid low memory issues when a device is suspended.
+        * Use __GFP_HIGH to avoid low memory issues when a device is
+        * suspended and the ioctl is needed to resume it.
         * Use kmalloc() rather than vmalloc() when we can.
         */
        dmi = NULL;
        noio_flag = memalloc_noio_save();
-       dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL);
+       dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL | __GFP_HIGH);
        memalloc_noio_restore(noio_flag);
 
        if (!dmi) {
index 926a6bcb32c8600118696119fd8ebe521cadbe5e..3df056b73b6610927a57058394a5bbe08f1b3404 100644 (file)
@@ -447,7 +447,7 @@ failed:
  * it has been invoked.
  */
 #define dm_report_EIO(m)                                               \
-({                                                                     \
+do {                                                                   \
        struct mapped_device *md = dm_table_get_md((m)->ti->table);     \
                                                                        \
        pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \
@@ -455,8 +455,7 @@ failed:
                 test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags),        \
                 test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags),  \
                 dm_noflush_suspending((m)->ti));                       \
-       -EIO;                                                           \
-})
+} while (0)
 
 /*
  * Map cloned requests (request-based multipath)
@@ -481,7 +480,8 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
        if (!pgpath) {
                if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
                        return DM_MAPIO_DELAY_REQUEUE;
-               return dm_report_EIO(m);        /* Failed */
+               dm_report_EIO(m);       /* Failed */
+               return DM_MAPIO_KILL;
        } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
                   test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) {
                if (pg_init_all_paths(m))
@@ -558,7 +558,8 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
        if (!pgpath) {
                if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
                        return DM_MAPIO_REQUEUE;
-               return dm_report_EIO(m);
+               dm_report_EIO(m);
+               return -EIO;
        }
 
        mpio->pgpath = pgpath;
@@ -1493,7 +1494,7 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
                if (atomic_read(&m->nr_valid_paths) == 0 &&
                    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
                        if (error == -EIO)
-                               error = dm_report_EIO(m);
+                               dm_report_EIO(m);
                        /* complete with the original error */
                        r = DM_ENDIO_DONE;
                }
@@ -1524,8 +1525,10 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
                fail_path(mpio->pgpath);
 
        if (atomic_read(&m->nr_valid_paths) == 0 &&
-           !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
-               return dm_report_EIO(m);
+           !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
+               dm_report_EIO(m);
+               return -EIO;
+       }
 
        /* Queue for the daemon to resubmit */
        dm_bio_restore(get_bio_details_from_bio(clone), clone);
index 7d893228c40f50dd7d0017fca004b504fa27f567..b4b75dad816ad95c0028f1b64b2be73e8993caac 100644 (file)
@@ -1927,7 +1927,7 @@ struct dm_raid_superblock {
        /********************************************************************
         * BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
         *
-        * FEATURE_FLAG_SUPPORTS_V190 in the features member indicates that those exist
+        * FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
         */
 
        __le32 flags; /* Flags defining array states for reshaping */
@@ -2092,6 +2092,11 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
        sb->layout = cpu_to_le32(mddev->layout);
        sb->stripe_sectors = cpu_to_le32(mddev->chunk_sectors);
 
+       /********************************************************************
+        * BELOW FOLLOW V1.9.0 EXTENSIONS TO THE PRISTINE SUPERBLOCK FORMAT!!!
+        *
+        * FEATURE_FLAG_SUPPORTS_V190 in the compat_features member indicates that those exist
+        */
        sb->new_level = cpu_to_le32(mddev->new_level);
        sb->new_layout = cpu_to_le32(mddev->new_layout);
        sb->new_stripe_sectors = cpu_to_le32(mddev->new_chunk_sectors);
@@ -2438,8 +2443,14 @@ static int super_validate(struct raid_set *rs, struct md_rdev *rdev)
        mddev->bitmap_info.default_offset = mddev->bitmap_info.offset;
 
        if (!test_and_clear_bit(FirstUse, &rdev->flags)) {
-               /* Retrieve device size stored in superblock to be prepared for shrink */
-               rdev->sectors = le64_to_cpu(sb->sectors);
+               /*
+                * Retrieve rdev size stored in superblock to be prepared for shrink.
+                * Check extended superblock members are present otherwise the size
+                * will not be set!
+                */
+               if (le32_to_cpu(sb->compat_features) & FEATURE_FLAG_SUPPORTS_V190)
+                       rdev->sectors = le64_to_cpu(sb->sectors);
+
                rdev->recovery_offset = le64_to_cpu(sb->disk_recovery_offset);
                if (rdev->recovery_offset == MaxSector)
                        set_bit(In_sync, &rdev->flags);
index a95cbb80fb34444144bad346b3e769c625e8c788..4da8858856fb3019c16d5681c241f8733dca21ec 100644 (file)
@@ -145,6 +145,7 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
 
 struct dm_raid1_bio_record {
        struct mirror *m;
+       /* if details->bi_bdev == NULL, details were not saved */
        struct dm_bio_details details;
        region_t write_region;
 };
@@ -260,7 +261,7 @@ static int mirror_flush(struct dm_target *ti)
        struct mirror *m;
        struct dm_io_request io_req = {
                .bi_op = REQ_OP_WRITE,
-               .bi_op_flags = REQ_PREFLUSH,
+               .bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
                .mem.type = DM_IO_KMEM,
                .mem.ptr.addr = NULL,
                .client = ms->io_client,
@@ -1198,6 +1199,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
        struct dm_raid1_bio_record *bio_record =
          dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
 
+       bio_record->details.bi_bdev = NULL;
+
        if (rw == WRITE) {
                /* Save region for mirror_end_io() handler */
                bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
@@ -1256,12 +1259,22 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
        }
 
        if (error == -EOPNOTSUPP)
-               return error;
+               goto out;
 
        if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
-               return error;
+               goto out;
 
        if (unlikely(error)) {
+               if (!bio_record->details.bi_bdev) {
+                       /*
+                        * There wasn't enough memory to record necessary
+                        * information for a retry or there was no other
+                        * mirror in-sync.
+                        */
+                       DMERR_LIMIT("Mirror read failed.");
+                       return -EIO;
+               }
+
                m = bio_record->m;
 
                DMERR("Mirror read failed from %s. Trying alternative device.",
@@ -1277,6 +1290,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
                        bd = &bio_record->details;
 
                        dm_bio_restore(bd, bio);
+                       bio_record->details.bi_bdev = NULL;
                        bio->bi_error = 0;
 
                        queue_bio(ms, bio, rw);
@@ -1285,6 +1299,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
                DMERR("All replicated volumes dead, failing I/O");
        }
 
+out:
+       bio_record->details.bi_bdev = NULL;
+
        return error;
 }
 
index 2af27026aa2edd7ec0683c0d6f92ac3612eff0d4..b639fa7246eebec191aa8a084333391ab0435dfa 100644 (file)
@@ -507,6 +507,7 @@ static int map_request(struct dm_rq_target_io *tio)
        case DM_MAPIO_KILL:
                /* The target wants to complete the I/O */
                dm_kill_unmapped_request(rq, -EIO);
+               break;
        default:
                DMWARN("unimplemented target map return value: %d", r);
                BUG();
index b93476c3ba3f9767fb133fed977e7a888cc0698e..c5534d294773fc0267a1b4c7438a3316e74d417a 100644 (file)
@@ -741,7 +741,8 @@ static void persistent_commit_exception(struct dm_exception_store *store,
        /*
         * Commit exceptions to disk.
         */
-       if (ps->valid && area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA))
+       if (ps->valid && area_io(ps, REQ_OP_WRITE,
+                                REQ_PREFLUSH | REQ_FUA | REQ_SYNC))
                ps->valid = 0;
 
        /*
index 0f0251d0d337fff94b1e41d11940d658874eda17..d31d18d9727c69d555d7971e53ddde6b6c401bf3 100644 (file)
@@ -484,11 +484,11 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
        if (r < 0)
                return r;
 
-       r = save_sm_roots(pmd);
+       r = dm_tm_pre_commit(pmd->tm);
        if (r < 0)
                return r;
 
-       r = dm_tm_pre_commit(pmd->tm);
+       r = save_sm_roots(pmd);
        if (r < 0)
                return r;
 
index 17ad50daed08ef5022b8648ef2e8701208c85a9d..28808e5ec0fd68346609eb33ac552359f5cff760 100644 (file)
@@ -1094,6 +1094,19 @@ static void process_prepared_discard_passdown_pt1(struct dm_thin_new_mapping *m)
                return;
        }
 
+       /*
+        * Increment the unmapped blocks.  This prevents a race between the
+        * passdown io and reallocation of freed blocks.
+        */
+       r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
+       if (r) {
+               metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
+               bio_io_error(m->bio);
+               cell_defer_no_holder(tc, m->cell);
+               mempool_free(m, pool->mapping_pool);
+               return;
+       }
+
        discard_parent = bio_alloc(GFP_NOIO, 1);
        if (!discard_parent) {
                DMWARN("%s: unable to allocate top level discard bio for passdown. Skipping passdown.",
@@ -1114,19 +1127,6 @@ static void process_prepared_discard_passdown_pt1(struct dm_thin_new_mapping *m)
                        end_discard(&op, r);
                }
        }
-
-       /*
-        * Increment the unmapped blocks.  This prevents a race between the
-        * passdown io and reallocation of freed blocks.
-        */
-       r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
-       if (r) {
-               metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
-               bio_io_error(m->bio);
-               cell_defer_no_holder(tc, m->cell);
-               mempool_free(m, pool->mapping_pool);
-               return;
-       }
 }
 
 static void process_prepared_discard_passdown_pt2(struct dm_thin_new_mapping *m)
index 97de961a3bfc80d11497c5ac2558ce7ad7a57a7e..1ec9b2c51c076d99ba6003f90eae608d9c9e35af 100644 (file)
@@ -166,7 +166,7 @@ static int verity_hash_init(struct dm_verity *v, struct ahash_request *req,
                return r;
        }
 
-       if (likely(v->version >= 1))
+       if (likely(v->salt_size && (v->version >= 1)))
                r = verity_hash_update(v, req, v->salt, v->salt_size, res);
 
        return r;
@@ -177,7 +177,7 @@ static int verity_hash_final(struct dm_verity *v, struct ahash_request *req,
 {
        int r;
 
-       if (unlikely(!v->version)) {
+       if (unlikely(v->salt_size && (!v->version))) {
                r = verity_hash_update(v, req, v->salt, v->salt_size, res);
 
                if (r < 0) {
index 6ef9500226c0c7d789ed78e6876195f73ef9d6b7..37ccd73c79ecf2eeb4f33b5bc597f88ca5750d4b 100644 (file)
@@ -1657,7 +1657,7 @@ static struct mapped_device *alloc_dev(int minor)
 
        bio_init(&md->flush_bio, NULL, 0);
        md->flush_bio.bi_bdev = md->bdev;
-       md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+       md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC;
 
        dm_stats_init(&md->stats);
 
index 7299ce2f08a810555a0407a423a512a0f59f190c..03082e17c65cc87af2a44a8020bda6cbdb8b0262 100644 (file)
@@ -1311,8 +1311,10 @@ static int add_new_disk(struct mddev *mddev, struct md_rdev *rdev)
        cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
        lock_comm(cinfo, 1);
        ret = __sendmsg(cinfo, &cmsg);
-       if (ret)
+       if (ret) {
+               unlock_comm(cinfo);
                return ret;
+       }
        cinfo->no_new_dev_lockres->flags |= DLM_LKF_NOQUEUE;
        ret = dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_EX);
        cinfo->no_new_dev_lockres->flags &= ~DLM_LKF_NOQUEUE;
index 82f798be964fc51d8c1d2d5b8cf5fc88392814ee..87edc342ccb3d5c51bb45313f1218f9839528917 100644 (file)
@@ -765,7 +765,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
            test_bit(FailFast, &rdev->flags) &&
            !test_bit(LastDev, &rdev->flags))
                ff = MD_FAILFAST;
-       bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA | ff;
+       bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH | REQ_FUA | ff;
 
        atomic_inc(&mddev->pending_writes);
        submit_bio(bio);
@@ -5174,6 +5174,18 @@ static void mddev_delayed_delete(struct work_struct *ws)
 
 static void no_op(struct percpu_ref *r) {}
 
+int mddev_init_writes_pending(struct mddev *mddev)
+{
+       if (mddev->writes_pending.percpu_count_ptr)
+               return 0;
+       if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0)
+               return -ENOMEM;
+       /* We want to start with the refcount at zero */
+       percpu_ref_put(&mddev->writes_pending);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mddev_init_writes_pending);
+
 static int md_alloc(dev_t dev, char *name)
 {
        /*
@@ -5239,10 +5251,6 @@ static int md_alloc(dev_t dev, char *name)
        blk_queue_make_request(mddev->queue, md_make_request);
        blk_set_stacking_limits(&mddev->queue->limits);
 
-       if (percpu_ref_init(&mddev->writes_pending, no_op, 0, GFP_KERNEL) < 0)
-               goto abort;
-       /* We want to start with the refcount at zero */
-       percpu_ref_put(&mddev->writes_pending);
        disk = alloc_disk(1 << shift);
        if (!disk) {
                blk_cleanup_queue(mddev->queue);
@@ -8022,18 +8030,15 @@ EXPORT_SYMBOL(md_write_end);
  * may proceed without blocking.  It is important to call this before
  * attempting a GFP_KERNEL allocation while holding the mddev lock.
  * Must be called with mddev_lock held.
- *
- * In the ->external case MD_SB_CHANGE_PENDING can not be cleared until mddev->lock
- * is dropped, so return -EAGAIN after notifying userspace.
  */
-int md_allow_write(struct mddev *mddev)
+void md_allow_write(struct mddev *mddev)
 {
        if (!mddev->pers)
-               return 0;
+               return;
        if (mddev->ro)
-               return 0;
+               return;
        if (!mddev->pers->sync_request)
-               return 0;
+               return;
 
        spin_lock(&mddev->lock);
        if (mddev->in_sync) {
@@ -8046,13 +8051,12 @@ int md_allow_write(struct mddev *mddev)
                spin_unlock(&mddev->lock);
                md_update_sb(mddev, 0);
                sysfs_notify_dirent_safe(mddev->sysfs_state);
+               /* wait for the dirty state to be recorded in the metadata */
+               wait_event(mddev->sb_wait,
+                          !test_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags) &&
+                          !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
        } else
                spin_unlock(&mddev->lock);
-
-       if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
-               return -EAGAIN;
-       else
-               return 0;
 }
 EXPORT_SYMBOL_GPL(md_allow_write);
 
index 4e75d121bfcc5671640421769476c85d2843e7c9..0fa1de42c42bcb328276a42fc56809d53217a285 100644 (file)
@@ -648,6 +648,7 @@ extern void md_unregister_thread(struct md_thread **threadp);
 extern void md_wakeup_thread(struct md_thread *thread);
 extern void md_check_recovery(struct mddev *mddev);
 extern void md_reap_sync_thread(struct mddev *mddev);
+extern int mddev_init_writes_pending(struct mddev *mddev);
 extern void md_write_start(struct mddev *mddev, struct bio *bi);
 extern void md_write_inc(struct mddev *mddev, struct bio *bi);
 extern void md_write_end(struct mddev *mddev);
@@ -665,7 +666,7 @@ extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
                        bool metadata_op);
 extern void md_do_sync(struct md_thread *thread);
 extern void md_new_event(struct mddev *mddev);
-extern int md_allow_write(struct mddev *mddev);
+extern void md_allow_write(struct mddev *mddev);
 extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
 extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
 extern int md_check_no_bitmap(struct mddev *mddev);
index ebb280a14325e1d937986926b40592c3b1847168..32adf6b4a9c7097e12796f8b396f80bfc8867c0a 100644 (file)
@@ -142,10 +142,23 @@ static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
 
 static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
 {
+       int r;
+       uint32_t old_count;
        enum allocation_event ev;
        struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-       return sm_ll_dec(&smd->ll, b, &ev);
+       r = sm_ll_dec(&smd->ll, b, &ev);
+       if (!r && (ev == SM_FREE)) {
+               /*
+                * It's only free if it's also free in the last
+                * transaction.
+                */
+               r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+               if (!r && !old_count)
+                       smd->nr_allocated_this_transaction--;
+       }
+
+       return r;
 }
 
 static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
index 84e58596594db79f0dde1f789de9a200fb1f0e8c..d6c0bc76e837dff8636253f4daaea0aa16ce4d89 100644 (file)
@@ -385,7 +385,7 @@ static int raid0_run(struct mddev *mddev)
                blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
                blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
                blk_queue_max_write_zeroes_sectors(mddev->queue, mddev->chunk_sectors);
-               blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
+               blk_queue_max_discard_sectors(mddev->queue, UINT_MAX);
 
                blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
                blk_queue_io_opt(mddev->queue,
@@ -459,6 +459,95 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev,
        }
 }
 
+static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
+{
+       struct r0conf *conf = mddev->private;
+       struct strip_zone *zone;
+       sector_t start = bio->bi_iter.bi_sector;
+       sector_t end;
+       unsigned int stripe_size;
+       sector_t first_stripe_index, last_stripe_index;
+       sector_t start_disk_offset;
+       unsigned int start_disk_index;
+       sector_t end_disk_offset;
+       unsigned int end_disk_index;
+       unsigned int disk;
+
+       zone = find_zone(conf, &start);
+
+       if (bio_end_sector(bio) > zone->zone_end) {
+               struct bio *split = bio_split(bio,
+                       zone->zone_end - bio->bi_iter.bi_sector, GFP_NOIO,
+                       mddev->bio_set);
+               bio_chain(split, bio);
+               generic_make_request(bio);
+               bio = split;
+               end = zone->zone_end;
+       } else
+               end = bio_end_sector(bio);
+
+       if (zone != conf->strip_zone)
+               end = end - zone[-1].zone_end;
+
+       /* Now start and end is the offset in zone */
+       stripe_size = zone->nb_dev * mddev->chunk_sectors;
+
+       first_stripe_index = start;
+       sector_div(first_stripe_index, stripe_size);
+       last_stripe_index = end;
+       sector_div(last_stripe_index, stripe_size);
+
+       start_disk_index = (int)(start - first_stripe_index * stripe_size) /
+               mddev->chunk_sectors;
+       start_disk_offset = ((int)(start - first_stripe_index * stripe_size) %
+               mddev->chunk_sectors) +
+               first_stripe_index * mddev->chunk_sectors;
+       end_disk_index = (int)(end - last_stripe_index * stripe_size) /
+               mddev->chunk_sectors;
+       end_disk_offset = ((int)(end - last_stripe_index * stripe_size) %
+               mddev->chunk_sectors) +
+               last_stripe_index * mddev->chunk_sectors;
+
+       for (disk = 0; disk < zone->nb_dev; disk++) {
+               sector_t dev_start, dev_end;
+               struct bio *discard_bio = NULL;
+               struct md_rdev *rdev;
+
+               if (disk < start_disk_index)
+                       dev_start = (first_stripe_index + 1) *
+                               mddev->chunk_sectors;
+               else if (disk > start_disk_index)
+                       dev_start = first_stripe_index * mddev->chunk_sectors;
+               else
+                       dev_start = start_disk_offset;
+
+               if (disk < end_disk_index)
+                       dev_end = (last_stripe_index + 1) * mddev->chunk_sectors;
+               else if (disk > end_disk_index)
+                       dev_end = last_stripe_index * mddev->chunk_sectors;
+               else
+                       dev_end = end_disk_offset;
+
+               if (dev_end <= dev_start)
+                       continue;
+
+               rdev = conf->devlist[(zone - conf->strip_zone) *
+                       conf->strip_zone[0].nb_dev + disk];
+               if (__blkdev_issue_discard(rdev->bdev,
+                       dev_start + zone->dev_start + rdev->data_offset,
+                       dev_end - dev_start, GFP_NOIO, 0, &discard_bio) ||
+                   !discard_bio)
+                       continue;
+               bio_chain(discard_bio, bio);
+               if (mddev->gendisk)
+                       trace_block_bio_remap(bdev_get_queue(rdev->bdev),
+                               discard_bio, disk_devt(mddev->gendisk),
+                               bio->bi_iter.bi_sector);
+               generic_make_request(discard_bio);
+       }
+       bio_endio(bio);
+}
+
 static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 {
        struct strip_zone *zone;
@@ -473,6 +562,11 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
                return;
        }
 
+       if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
+               raid0_handle_discard(mddev, bio);
+               return;
+       }
+
        bio_sector = bio->bi_iter.bi_sector;
        sector = bio_sector;
        chunk_sects = mddev->chunk_sectors;
@@ -498,19 +592,13 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
        bio->bi_iter.bi_sector = sector + zone->dev_start +
                tmp_dev->data_offset;
 
-       if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
-                    !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
-               /* Just ignore it */
-               bio_endio(bio);
-       } else {
-               if (mddev->gendisk)
-                       trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
-                                             bio, disk_devt(mddev->gendisk),
-                                             bio_sector);
-               mddev_check_writesame(mddev, bio);
-               mddev_check_write_zeroes(mddev, bio);
-               generic_make_request(bio);
-       }
+       if (mddev->gendisk)
+               trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
+                                     bio, disk_devt(mddev->gendisk),
+                                     bio_sector);
+       mddev_check_writesame(mddev, bio);
+       mddev_check_write_zeroes(mddev, bio);
+       generic_make_request(bio);
 }
 
 static void raid0_status(struct seq_file *seq, struct mddev *mddev)
index 7ed59351fe972d60a8bf2bb22d20f4abaa718710..e1a7e3d4c5e4f17d0dedb4f171ad3bd47ff70022 100644 (file)
@@ -666,8 +666,11 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
                                        break;
                        }
                        continue;
-               } else
+               } else {
+                       if ((sectors > best_good_sectors) && (best_disk >= 0))
+                               best_disk = -1;
                        best_good_sectors = sectors;
+               }
 
                if (best_disk >= 0)
                        /* At least two disks to choose from so failfast is OK */
@@ -1529,17 +1532,16 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
                        plug = container_of(cb, struct raid1_plug_cb, cb);
                else
                        plug = NULL;
-               spin_lock_irqsave(&conf->device_lock, flags);
                if (plug) {
                        bio_list_add(&plug->pending, mbio);
                        plug->pending_cnt++;
                } else {
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        bio_list_add(&conf->pending_bio_list, mbio);
                        conf->pending_count++;
-               }
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!plug)
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
                        md_wakeup_thread(mddev->thread);
+               }
        }
 
        r1_bio_write_done(r1_bio);
@@ -3061,6 +3063,8 @@ static int raid1_run(struct mddev *mddev)
                        mdname(mddev));
                return -EIO;
        }
+       if (mddev_init_writes_pending(mddev) < 0)
+               return -ENOMEM;
        /*
         * copy the already verified devices into our private RAID1
         * bookkeeping area. [whatever we allocate in run(),
@@ -3197,7 +3201,7 @@ static int raid1_reshape(struct mddev *mddev)
        struct r1conf *conf = mddev->private;
        int cnt, raid_disks;
        unsigned long flags;
-       int d, d2, err;
+       int d, d2;
 
        /* Cannot change chunk_size, layout, or level */
        if (mddev->chunk_sectors != mddev->new_chunk_sectors ||
@@ -3209,11 +3213,8 @@ static int raid1_reshape(struct mddev *mddev)
                return -EINVAL;
        }
 
-       if (!mddev_is_clustered(mddev)) {
-               err = md_allow_write(mddev);
-               if (err)
-                       return err;
-       }
+       if (!mddev_is_clustered(mddev))
+               md_allow_write(mddev);
 
        raid_disks = mddev->raid_disks + mddev->delta_disks;
 
index 6b86a0032cf86683834c1ce82fcda6e6bd6b8e80..797ed60abd5e27cd2f32d0f80d36c660ed1e4419 100644 (file)
@@ -1282,17 +1282,16 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
                plug = container_of(cb, struct raid10_plug_cb, cb);
        else
                plug = NULL;
-       spin_lock_irqsave(&conf->device_lock, flags);
        if (plug) {
                bio_list_add(&plug->pending, mbio);
                plug->pending_cnt++;
        } else {
+               spin_lock_irqsave(&conf->device_lock, flags);
                bio_list_add(&conf->pending_bio_list, mbio);
                conf->pending_count++;
-       }
-       spin_unlock_irqrestore(&conf->device_lock, flags);
-       if (!plug)
+               spin_unlock_irqrestore(&conf->device_lock, flags);
                md_wakeup_thread(mddev->thread);
+       }
 }
 
 static void raid10_write_request(struct mddev *mddev, struct bio *bio,
@@ -3612,6 +3611,9 @@ static int raid10_run(struct mddev *mddev)
        int first = 1;
        bool discard_supported = false;
 
+       if (mddev_init_writes_pending(mddev) < 0)
+               return -ENOMEM;
+
        if (mddev->private == NULL) {
                conf = setup_conf(mddev);
                if (IS_ERR(conf))
index 26ba09282e7c9691bdc352c5fb4b75b9f6e29821..0a7af8b0a80a031a99a7af1742e2d64e6df0d106 100644 (file)
@@ -24,6 +24,7 @@
 #include "md.h"
 #include "raid5.h"
 #include "bitmap.h"
+#include "raid5-log.h"
 
 /*
  * metadata/data stored in disk with 4k size unit (a block) regardless
@@ -622,20 +623,30 @@ static void r5l_do_submit_io(struct r5l_log *log, struct r5l_io_unit *io)
        __r5l_set_io_unit_state(io, IO_UNIT_IO_START);
        spin_unlock_irqrestore(&log->io_list_lock, flags);
 
+       /*
+        * In case of journal device failures, submit_bio will get error
+        * and calls endio, then active stripes will continue write
+        * process. Therefore, it is not necessary to check Faulty bit
+        * of journal device here.
+        *
+        * We can't check split_bio after current_bio is submitted. If
+        * io->split_bio is null, after current_bio is submitted, current_bio
+        * might already be completed and the io_unit is freed. We submit
+        * split_bio first to avoid the issue.
+        */
+       if (io->split_bio) {
+               if (io->has_flush)
+                       io->split_bio->bi_opf |= REQ_PREFLUSH;
+               if (io->has_fua)
+                       io->split_bio->bi_opf |= REQ_FUA;
+               submit_bio(io->split_bio);
+       }
+
        if (io->has_flush)
                io->current_bio->bi_opf |= REQ_PREFLUSH;
        if (io->has_fua)
                io->current_bio->bi_opf |= REQ_FUA;
        submit_bio(io->current_bio);
-
-       if (!io->split_bio)
-               return;
-
-       if (io->has_flush)
-               io->split_bio->bi_opf |= REQ_PREFLUSH;
-       if (io->has_fua)
-               io->split_bio->bi_opf |= REQ_FUA;
-       submit_bio(io->split_bio);
 }
 
 /* deferred io_unit will be dispatched here */
@@ -670,6 +681,11 @@ static void r5c_disable_writeback_async(struct work_struct *work)
                return;
        pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n",
                mdname(mddev));
+
+       /* wait superblock change before suspend */
+       wait_event(mddev->sb_wait,
+                  !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
+
        mddev_suspend(mddev);
        log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
        mddev_resume(mddev);
@@ -1766,7 +1782,7 @@ static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos,
        mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum,
                                             mb, PAGE_SIZE));
        if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE,
-                         REQ_FUA, false)) {
+                         REQ_SYNC | REQ_FUA, false)) {
                __free_page(page);
                return -EIO;
        }
@@ -2372,7 +2388,7 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
                mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum,
                                                     mb, PAGE_SIZE));
                sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page,
-                            REQ_OP_WRITE, REQ_FUA, false);
+                            REQ_OP_WRITE, REQ_SYNC | REQ_FUA, false);
                sh->log_start = ctx->pos;
                list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
                atomic_inc(&log->stripe_in_journal_count);
@@ -2621,8 +2637,11 @@ int r5c_try_caching_write(struct r5conf *conf,
         * When run in degraded mode, array is set to write-through mode.
         * This check helps drain pending write safely in the transition to
         * write-through mode.
+        *
+        * When a stripe is syncing, the write is also handled in write
+        * through mode.
         */
-       if (s->failed) {
+       if (s->failed || test_bit(STRIPE_SYNCING, &sh->state)) {
                r5c_make_stripe_write_out(sh);
                return -EAGAIN;
        }
@@ -2825,6 +2844,9 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
        }
 
        r5l_append_flush_payload(log, sh->sector);
+       /* stripe is flused to raid disks, we can do resync now */
+       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
+               set_bit(STRIPE_HANDLE, &sh->state);
 }
 
 int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
@@ -2973,7 +2995,7 @@ ioerr:
        return ret;
 }
 
-void r5c_update_on_rdev_error(struct mddev *mddev)
+void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
 {
        struct r5conf *conf = mddev->private;
        struct r5l_log *log = conf->log;
@@ -2981,7 +3003,8 @@ void r5c_update_on_rdev_error(struct mddev *mddev)
        if (!log)
                return;
 
-       if (raid5_calc_degraded(conf) > 0 &&
+       if ((raid5_calc_degraded(conf) > 0 ||
+            test_bit(Journal, &rdev->flags)) &&
            conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
                schedule_work(&log->disable_writeback_work);
 }
index 27097101cccac90b739ce5564145114df2417f6b..328d67aedda49dcf2a7c93d1d188d77108794647 100644 (file)
@@ -28,7 +28,8 @@ extern void r5c_flush_cache(struct r5conf *conf, int num);
 extern void r5c_check_stripe_cache_usage(struct r5conf *conf);
 extern void r5c_check_cached_full_stripe(struct r5conf *conf);
 extern struct md_sysfs_entry r5c_journal_mode;
-extern void r5c_update_on_rdev_error(struct mddev *mddev);
+extern void r5c_update_on_rdev_error(struct mddev *mddev,
+                                    struct md_rdev *rdev);
 extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
 
 extern struct dma_async_tx_descriptor *
index 5d25bebf3328e4967334465916aca3e3c750e447..ccce92e68d7fa5d8258bb7f2ca2bfa1bcd545709 100644 (file)
@@ -907,8 +907,8 @@ static int ppl_write_empty_header(struct ppl_log *log)
        pplhdr->checksum = cpu_to_le32(~crc32c_le(~0, pplhdr, PAGE_SIZE));
 
        if (!sync_page_io(rdev, rdev->ppl.sector - rdev->data_offset,
-                         PPL_HEADER_SIZE, page, REQ_OP_WRITE | REQ_FUA, 0,
-                         false)) {
+                         PPL_HEADER_SIZE, page, REQ_OP_WRITE | REQ_SYNC |
+                         REQ_FUA, 0, false)) {
                md_error(rdev->mddev, rdev);
                ret = -EIO;
        }
index 2e38cfac5b1dc5a318f66b4bb6e2e2195797ad53..ec0f951ae19fbc8fa392306b7c6c45a38f3eb0e4 100644 (file)
@@ -103,8 +103,7 @@ static inline void unlock_device_hash_lock(struct r5conf *conf, int hash)
 static inline void lock_all_device_hash_locks_irq(struct r5conf *conf)
 {
        int i;
-       local_irq_disable();
-       spin_lock(conf->hash_locks);
+       spin_lock_irq(conf->hash_locks);
        for (i = 1; i < NR_STRIPE_HASH_LOCKS; i++)
                spin_lock_nest_lock(conf->hash_locks + i, conf->hash_locks);
        spin_lock(&conf->device_lock);
@@ -114,9 +113,9 @@ static inline void unlock_all_device_hash_locks_irq(struct r5conf *conf)
 {
        int i;
        spin_unlock(&conf->device_lock);
-       for (i = NR_STRIPE_HASH_LOCKS; i; i--)
-               spin_unlock(conf->hash_locks + i - 1);
-       local_irq_enable();
+       for (i = NR_STRIPE_HASH_LOCKS - 1; i; i--)
+               spin_unlock(conf->hash_locks + i);
+       spin_unlock_irq(conf->hash_locks);
 }
 
 /* Find first data disk in a raid6 stripe */
@@ -234,11 +233,15 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh,
                        if (test_bit(R5_InJournal, &sh->dev[i].flags))
                                injournal++;
        /*
-        * When quiesce in r5c write back, set STRIPE_HANDLE for stripes with
-        * data in journal, so they are not released to cached lists
+        * In the following cases, the stripe cannot be released to cached
+        * lists. Therefore, we make the stripe write out and set
+        * STRIPE_HANDLE:
+        *   1. when quiesce in r5c write back;
+        *   2. when resync is requested fot the stripe.
         */
-       if (conf->quiesce && r5c_is_writeback(conf->log) &&
-           !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0) {
+       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) ||
+           (conf->quiesce && r5c_is_writeback(conf->log) &&
+            !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0)) {
                if (test_bit(STRIPE_R5C_CACHING, &sh->state))
                        r5c_make_stripe_write_out(sh);
                set_bit(STRIPE_HANDLE, &sh->state);
@@ -714,12 +717,11 @@ static bool is_full_stripe_write(struct stripe_head *sh)
 
 static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
 {
-       local_irq_disable();
        if (sh1 > sh2) {
-               spin_lock(&sh2->stripe_lock);
+               spin_lock_irq(&sh2->stripe_lock);
                spin_lock_nested(&sh1->stripe_lock, 1);
        } else {
-               spin_lock(&sh1->stripe_lock);
+               spin_lock_irq(&sh1->stripe_lock);
                spin_lock_nested(&sh2->stripe_lock, 1);
        }
 }
@@ -727,8 +729,7 @@ static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
 static void unlock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
 {
        spin_unlock(&sh1->stripe_lock);
-       spin_unlock(&sh2->stripe_lock);
-       local_irq_enable();
+       spin_unlock_irq(&sh2->stripe_lock);
 }
 
 /* Only freshly new full stripe normal write stripe can be added to a batch list */
@@ -2312,14 +2313,12 @@ static int resize_stripes(struct r5conf *conf, int newsize)
        struct stripe_head *osh, *nsh;
        LIST_HEAD(newstripes);
        struct disk_info *ndisks;
-       int err;
+       int err = 0;
        struct kmem_cache *sc;
        int i;
        int hash, cnt;
 
-       err = md_allow_write(conf->mddev);
-       if (err)
-               return err;
+       md_allow_write(conf->mddev);
 
        /* Step 1 */
        sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
@@ -2694,7 +2693,7 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
                bdevname(rdev->bdev, b),
                mdname(mddev),
                conf->raid_disks - mddev->degraded);
-       r5c_update_on_rdev_error(mddev);
+       r5c_update_on_rdev_error(mddev, rdev);
 }
 
 /*
@@ -3055,6 +3054,11 @@ sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous)
  *      When LOG_CRITICAL, stripes with injournal == 0 will be sent to
  *      no_space_stripes list.
  *
+ *   3. during journal failure
+ *      In journal failure, we try to flush all cached data to raid disks
+ *      based on data in stripe cache. The array is read-only to upper
+ *      layers, so we would skip all pending writes.
+ *
  */
 static inline bool delay_towrite(struct r5conf *conf,
                                 struct r5dev *dev,
@@ -3068,6 +3072,9 @@ static inline bool delay_towrite(struct r5conf *conf,
        if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
            s->injournal > 0)
                return true;
+       /* case 3 above */
+       if (s->log_failed && s->injournal)
+               return true;
        return false;
 }
 
@@ -4078,10 +4085,15 @@ static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
                        set_bit(STRIPE_INSYNC, &sh->state);
                else {
                        atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches);
-                       if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+                       if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) {
                                /* don't try to repair!! */
                                set_bit(STRIPE_INSYNC, &sh->state);
-                       else {
+                               pr_warn_ratelimited("%s: mismatch sector in range "
+                                                   "%llu-%llu\n", mdname(conf->mddev),
+                                                   (unsigned long long) sh->sector,
+                                                   (unsigned long long) sh->sector +
+                                                   STRIPE_SECTORS);
+                       } else {
                                sh->check_state = check_state_compute_run;
                                set_bit(STRIPE_COMPUTE_RUN, &sh->state);
                                set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request);
@@ -4230,10 +4242,15 @@ static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
                        }
                } else {
                        atomic64_add(STRIPE_SECTORS, &conf->mddev->resync_mismatches);
-                       if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+                       if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) {
                                /* don't try to repair!! */
                                set_bit(STRIPE_INSYNC, &sh->state);
-                       else {
+                               pr_warn_ratelimited("%s: mismatch sector in range "
+                                                   "%llu-%llu\n", mdname(conf->mddev),
+                                                   (unsigned long long) sh->sector,
+                                                   (unsigned long long) sh->sector +
+                                                   STRIPE_SECTORS);
+                       } else {
                                int *target = &sh->ops.target;
 
                                sh->ops.target = -1;
@@ -4653,8 +4670,13 @@ static void handle_stripe(struct stripe_head *sh)
 
        if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) && !sh->batch_head) {
                spin_lock(&sh->stripe_lock);
-               /* Cannot process 'sync' concurrently with 'discard' */
-               if (!test_bit(STRIPE_DISCARD, &sh->state) &&
+               /*
+                * Cannot process 'sync' concurrently with 'discard'.
+                * Flush data in r5cache before 'sync'.
+                */
+               if (!test_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state) &&
+                   !test_bit(STRIPE_R5C_FULL_STRIPE, &sh->state) &&
+                   !test_bit(STRIPE_DISCARD, &sh->state) &&
                    test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
                        set_bit(STRIPE_SYNCING, &sh->state);
                        clear_bit(STRIPE_INSYNC, &sh->state);
@@ -4701,10 +4723,15 @@ static void handle_stripe(struct stripe_head *sh)
               " to_write=%d failed=%d failed_num=%d,%d\n",
               s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
               s.failed_num[0], s.failed_num[1]);
-       /* check if the array has lost more than max_degraded devices and,
+       /*
+        * check if the array has lost more than max_degraded devices and,
         * if so, some requests might need to be failed.
+        *
+        * When journal device failed (log_failed), we will only process
+        * the stripe if there is data need write to raid disks
         */
-       if (s.failed > conf->max_degraded || s.log_failed) {
+       if (s.failed > conf->max_degraded ||
+           (s.log_failed && s.injournal == 0)) {
                sh->check_state = 0;
                sh->reconstruct_state = 0;
                break_stripe_batch_list(sh, 0);
@@ -5277,8 +5304,10 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group)
        struct stripe_head *sh, *tmp;
        struct list_head *handle_list = NULL;
        struct r5worker_group *wg;
-       bool second_try = !r5c_is_writeback(conf->log);
-       bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state);
+       bool second_try = !r5c_is_writeback(conf->log) &&
+               !r5l_log_disk_error(conf);
+       bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state) ||
+               r5l_log_disk_error(conf);
 
 again:
        wg = NULL;
@@ -6313,7 +6342,6 @@ int
 raid5_set_cache_size(struct mddev *mddev, int size)
 {
        struct r5conf *conf = mddev->private;
-       int err;
 
        if (size <= 16 || size > 32768)
                return -EINVAL;
@@ -6325,10 +6353,7 @@ raid5_set_cache_size(struct mddev *mddev, int size)
                ;
        mutex_unlock(&conf->cache_size_mutex);
 
-
-       err = md_allow_write(mddev);
-       if (err)
-               return err;
+       md_allow_write(mddev);
 
        mutex_lock(&conf->cache_size_mutex);
        while (size > conf->max_nr_stripes)
@@ -7093,6 +7118,9 @@ static int raid5_run(struct mddev *mddev)
        long long min_offset_diff = 0;
        int first = 1;
 
+       if (mddev_init_writes_pending(mddev) < 0)
+               return -ENOMEM;
+
        if (mddev->recovery_cp != MaxSector)
                pr_notice("md/raid:%s: not clean -- starting background reconstruction\n",
                          mdname(mddev));
@@ -7530,7 +7558,9 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                 * neilb: there is no locking about new writes here,
                 * so this cannot be safe.
                 */
-               if (atomic_read(&conf->active_stripes)) {
+               if (atomic_read(&conf->active_stripes) ||
+                   atomic_read(&conf->r5c_cached_full_stripes) ||
+                   atomic_read(&conf->r5c_cached_partial_stripes)) {
                        return -EBUSY;
                }
                log_exit(conf);
index b72edd27f880fbe99641cd36b44005c6ad9252c6..55d9c2b82b7eab11268d88f7d8e5cf586f910985 100644 (file)
@@ -2,6 +2,12 @@
 # Multimedia device configuration
 #
 
+config CEC_CORE
+       tristate
+
+config CEC_NOTIFIER
+       bool
+
 menuconfig MEDIA_SUPPORT
        tristate "Multimedia support"
        depends on HAS_IOMEM
index 523fea3648ad71749009fc9f7d0f543d36734128..044503aa8801744785da9c637bda4c020bfac766 100644 (file)
@@ -4,8 +4,6 @@
 
 media-objs     := media-device.o media-devnode.o media-entity.o
 
-obj-$(CONFIG_CEC_CORE) += cec/
-
 #
 # I2C drivers should come before other drivers, otherwise they'll fail
 # when compiled as builtin drivers
@@ -26,6 +24,8 @@ obj-$(CONFIG_DVB_CORE)  += dvb-core/
 # There are both core and drivers at RC subtree - merge before drivers
 obj-y += rc/
 
+obj-$(CONFIG_CEC_CORE) += cec/
+
 #
 # Finally, merge the drivers that require the core
 #
index f944d93e3167f4e338a1e9cb607af32311136b50..43428cec3a01cde9ca4deb920ceb1fde47289076 100644 (file)
@@ -1,19 +1,6 @@
-config CEC_CORE
-       tristate
-       depends on MEDIA_CEC_SUPPORT
-       default y
-
-config MEDIA_CEC_NOTIFIER
-       bool
-
 config MEDIA_CEC_RC
        bool "HDMI CEC RC integration"
        depends on CEC_CORE && RC_CORE
+       depends on CEC_CORE=m || RC_CORE=y
        ---help---
          Pass on CEC remote control messages to the RC framework.
-
-config MEDIA_CEC_DEBUG
-       bool "HDMI CEC debugfs interface"
-       depends on CEC_CORE && DEBUG_FS
-       ---help---
-         Turns on the DebugFS interface for CEC devices.
index 402a6c62a3e8b9bb4857ac553e1b9a14c6babc16..eaf408e646697adcb8cc95b95c8425574715bdee 100644 (file)
@@ -1,6 +1,6 @@
 cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o
 
-ifeq ($(CONFIG_MEDIA_CEC_NOTIFIER),y)
+ifeq ($(CONFIG_CEC_NOTIFIER),y)
   cec-objs += cec-notifier.o
 endif
 
index f5fe01c9da8af17906805668b8448cd6aaf9da1e..9dfc79800c7191964557afe729603afa5cf2b5df 100644 (file)
@@ -1864,7 +1864,7 @@ void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
                WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
 }
 
-#ifdef CONFIG_MEDIA_CEC_DEBUG
+#ifdef CONFIG_DEBUG_FS
 /*
  * Log the current state of the CEC adapter.
  * Very useful for debugging.
index 0860fb458757df3871ccab290867fcf7c4d5c11e..999926f731c88827802029ba2a928ee457e49ffb 100644 (file)
@@ -271,16 +271,10 @@ static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh,
                        bool block, struct cec_msg __user *parg)
 {
        struct cec_msg msg = {};
-       long err = 0;
+       long err;
 
        if (copy_from_user(&msg, parg, sizeof(msg)))
                return -EFAULT;
-       mutex_lock(&adap->lock);
-       if (!adap->is_configured && fh->mode_follower < CEC_MODE_MONITOR)
-               err = -ENONET;
-       mutex_unlock(&adap->lock);
-       if (err)
-               return err;
 
        err = cec_receive_msg(fh, &msg, block);
        if (err)
index f9ebff90f8ebc08b77088c8f1901d8aa7077b99f..2f87748ba4fceea377284be6a1c35b6478ca4788 100644 (file)
@@ -187,7 +187,7 @@ static void cec_devnode_unregister(struct cec_devnode *devnode)
        put_device(&devnode->dev);
 }
 
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#ifdef CONFIG_CEC_NOTIFIER
 static void cec_cec_notify(struct cec_adapter *adap, u16 pa)
 {
        cec_s_phys_addr(adap, pa, false);
@@ -323,7 +323,7 @@ int cec_register_adapter(struct cec_adapter *adap,
        }
 
        dev_set_drvdata(&adap->devnode.dev, adap);
-#ifdef CONFIG_MEDIA_CEC_DEBUG
+#ifdef CONFIG_DEBUG_FS
        if (!top_cec_dir)
                return 0;
 
@@ -355,7 +355,7 @@ void cec_unregister_adapter(struct cec_adapter *adap)
        adap->rc = NULL;
 #endif
        debugfs_remove_recursive(adap->cec_dir);
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#ifdef CONFIG_CEC_NOTIFIER
        if (adap->notifier)
                cec_notifier_unregister(adap->notifier);
 #endif
@@ -395,7 +395,7 @@ static int __init cec_devnode_init(void)
                return ret;
        }
 
-#ifdef CONFIG_MEDIA_CEC_DEBUG
+#ifdef CONFIG_DEBUG_FS
        top_cec_dir = debugfs_create_dir("cec", NULL);
        if (IS_ERR_OR_NULL(top_cec_dir)) {
                pr_warn("cec: Failed to create debugfs cec dir\n");
index fd181c99ce117fc44c16ded99d50abe9a655b4f8..aaa9471c7d117eae0a00e4bbbf4ed20e3ca65b36 100644 (file)
@@ -220,7 +220,8 @@ config VIDEO_ADV7604
 
 config VIDEO_ADV7604_CEC
        bool "Enable Analog Devices ADV7604 CEC support"
-       depends on VIDEO_ADV7604 && CEC_CORE
+       depends on VIDEO_ADV7604
+       select CEC_CORE
        ---help---
          When selected the adv7604 will support the optional
          HDMI CEC feature.
@@ -240,7 +241,8 @@ config VIDEO_ADV7842
 
 config VIDEO_ADV7842_CEC
        bool "Enable Analog Devices ADV7842 CEC support"
-       depends on VIDEO_ADV7842 && CEC_CORE
+       depends on VIDEO_ADV7842
+       select CEC_CORE
        ---help---
          When selected the adv7842 will support the optional
          HDMI CEC feature.
@@ -478,7 +480,8 @@ config VIDEO_ADV7511
 
 config VIDEO_ADV7511_CEC
        bool "Enable Analog Devices ADV7511 CEC support"
-       depends on VIDEO_ADV7511 && CEC_CORE
+       depends on VIDEO_ADV7511
+       select CEC_CORE
        ---help---
          When selected the adv7511 will support the optional
          HDMI CEC feature.
index acef4eca269f1c1f3f1e36d6ca8c76e1523cd9b6..3251cba89e8f63052091aa5b1bdaf7f2bb74afc3 100644 (file)
@@ -223,7 +223,7 @@ static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val)
 static void i2c_wr8_and_or(struct v4l2_subdev *sd, u16 reg,
                u8 mask, u8 val)
 {
-       i2c_wrreg(sd, reg, (i2c_rdreg(sd, reg, 2) & mask) | val, 2);
+       i2c_wrreg(sd, reg, (i2c_rdreg(sd, reg, 1) & mask) | val, 1);
 }
 
 static u16 i2c_rd16(struct v4l2_subdev *sd, u16 reg)
index ac026ee1ca07484ffa6b0c51632d1c9958c0d3cd..041cb80a26b1ff22f049abaed44b0a62c9b91a9c 100644 (file)
@@ -501,8 +501,9 @@ if CEC_PLATFORM_DRIVERS
 
 config VIDEO_SAMSUNG_S5P_CEC
        tristate "Samsung S5P CEC driver"
-       depends on CEC_CORE && (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST)
-       select MEDIA_CEC_NOTIFIER
+       depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
+       select CEC_CORE
+       select CEC_NOTIFIER
        ---help---
          This is a driver for Samsung S5P HDMI CEC interface. It uses the
          generic CEC framework interface.
@@ -511,8 +512,9 @@ config VIDEO_SAMSUNG_S5P_CEC
 
 config VIDEO_STI_HDMI_CEC
        tristate "STMicroelectronics STiH4xx HDMI CEC driver"
-       depends on CEC_CORE && (ARCH_STI || COMPILE_TEST)
-       select MEDIA_CEC_NOTIFIER
+       depends on ARCH_STI || COMPILE_TEST
+       select CEC_CORE
+       select CEC_NOTIFIER
        ---help---
          This is a driver for STIH4xx HDMI CEC interface. It uses the
          generic CEC framework interface.
index 57a842ff309747382a928998d0209072476da421..b7731b18ecae1741ebee3be1bf9188659bfeb398 100644 (file)
@@ -493,10 +493,10 @@ static int vdec_h264_get_param(unsigned long h_vdec,
 }
 
 static struct vdec_common_if vdec_h264_if = {
-       vdec_h264_init,
-       vdec_h264_decode,
-       vdec_h264_get_param,
-       vdec_h264_deinit,
+       .init           = vdec_h264_init,
+       .decode         = vdec_h264_decode,
+       .get_param      = vdec_h264_get_param,
+       .deinit         = vdec_h264_deinit,
 };
 
 struct vdec_common_if *get_h264_dec_comm_if(void);
index 6e7a62ae0842c2e69bb65e31bb1fa80e7c9ce44c..b9fad6a488799ebc7fad8b12b6990b9c33d7c60b 100644 (file)
@@ -620,10 +620,10 @@ static void vdec_vp8_deinit(unsigned long h_vdec)
 }
 
 static struct vdec_common_if vdec_vp8_if = {
-       vdec_vp8_init,
-       vdec_vp8_decode,
-       vdec_vp8_get_param,
-       vdec_vp8_deinit,
+       .init           = vdec_vp8_init,
+       .decode         = vdec_vp8_decode,
+       .get_param      = vdec_vp8_get_param,
+       .deinit         = vdec_vp8_deinit,
 };
 
 struct vdec_common_if *get_vp8_dec_comm_if(void);
index 5539b1853f166a611ed678bc1274f55e48f1347c..1daee1207469b3ea9e740676aa80765a4280c118 100644 (file)
@@ -979,10 +979,10 @@ static int vdec_vp9_get_param(unsigned long h_vdec,
 }
 
 static struct vdec_common_if vdec_vp9_if = {
-       vdec_vp9_init,
-       vdec_vp9_decode,
-       vdec_vp9_get_param,
-       vdec_vp9_deinit,
+       .init           = vdec_vp9_init,
+       .decode         = vdec_vp9_decode,
+       .get_param      = vdec_vp9_get_param,
+       .deinit         = vdec_vp9_deinit,
 };
 
 struct vdec_common_if *get_vp9_dec_comm_if(void);
index b36ac19dc6e48d60afbc4053fb848d9439dfcd5d..154de92dd809e74ff3d7539787856fef631229fc 100644 (file)
@@ -26,7 +26,8 @@ config VIDEO_VIVID
 
 config VIDEO_VIVID_CEC
        bool "Enable CEC emulation support"
-       depends on VIDEO_VIVID && CEC_CORE
+       depends on VIDEO_VIVID
+       select CEC_CORE
        ---help---
          When selected the vivid module will emulate the optional
          HDMI CEC feature.
index 90f66dc7c0d74dbed7cf370f652546eadc563bf8..a2fc1a1d58b0e317539a1a679e32f96c12d3b00f 100644 (file)
@@ -211,7 +211,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
  */
 void ir_raw_event_handle(struct rc_dev *dev)
 {
-       if (!dev->raw)
+       if (!dev->raw || !dev->raw->thread)
                return;
 
        wake_up_process(dev->raw->thread);
@@ -490,6 +490,7 @@ int ir_raw_event_register(struct rc_dev *dev)
 {
        int rc;
        struct ir_raw_handler *handler;
+       struct task_struct *thread;
 
        if (!dev)
                return -EINVAL;
@@ -507,13 +508,15 @@ int ir_raw_event_register(struct rc_dev *dev)
         * because the event is coming from userspace
         */
        if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
-               dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
-                                              "rc%u", dev->minor);
+               thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u",
+                                    dev->minor);
 
-               if (IS_ERR(dev->raw->thread)) {
-                       rc = PTR_ERR(dev->raw->thread);
+               if (IS_ERR(thread)) {
+                       rc = PTR_ERR(thread);
                        goto out;
                }
+
+               dev->raw->thread = thread;
        }
 
        mutex_lock(&ir_raw_handler_lock);
index e12ec50bf0bf7531cb76ef129149d77f531fa525..90a5f8fd5eea68d6e1f007843c6bb67f7c8790b2 100644 (file)
@@ -183,9 +183,15 @@ static irqreturn_t sir_interrupt(int irq, void *dev_id)
        static unsigned long delt;
        unsigned long deltintr;
        unsigned long flags;
+       int counter = 0;
        int iir, lsr;
 
        while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) {
+               if (++counter > 256) {
+                       dev_err(&sir_ir_dev->dev, "Trapped in interrupt");
+                       break;
+               }
+
                switch (iir & UART_IIR_ID) { /* FIXME toto treba preriedit */
                case UART_IIR_MSI:
                        (void)inb(io + UART_MSR);
index 8937f3986a01f1c89e3fcc5b6825cb6b754ddf20..18ead44824ba2bd02d27480e0f04ac69f39182fd 100644 (file)
@@ -1,6 +1,7 @@
 config USB_PULSE8_CEC
        tristate "Pulse Eight HDMI CEC"
-       depends on USB_ACM && CEC_CORE
+       depends on USB_ACM
+       select CEC_CORE
        select SERIO
        select SERIO_SERPORT
        ---help---
index 3eb86607efb8f627566af1ff374053d7f6b980ec..030ef01b1ff04137ede4a84ddf0357afe943343d 100644 (file)
@@ -1,6 +1,7 @@
 config USB_RAINSHADOW_CEC
        tristate "RainShadow Tech HDMI CEC"
-       depends on USB_ACM && CEC_CORE
+       depends on USB_ACM
+       select CEC_CORE
        select SERIO
        select SERIO_SERPORT
        ---help---
index 541ca543f71f4efe7e29e7c22bce114c2b18fc3d..4126552c90556ede32ec1bf2aee53c4d3afc3811 100644 (file)
@@ -119,7 +119,7 @@ static void rain_irq_work_handler(struct work_struct *work)
 
        while (true) {
                unsigned long flags;
-               bool exit_loop;
+               bool exit_loop = false;
                char data;
 
                spin_lock_irqsave(&rain->buf_lock, flags);
@@ -336,6 +336,7 @@ static int rain_connect(struct serio *serio, struct serio_driver *drv)
        serio_set_drvdata(serio, rain);
        INIT_WORK(&rain->work, rain_irq_work_handler);
        mutex_init(&rain->write_lock);
+       spin_lock_init(&rain->buf_lock);
 
        err = serio_open(serio, drv);
        if (err)
index 94afbbf928072ba6c24c850bdc41c3ab0820a96d..c0175ea7e7ad186d7d62c352c917cb3d14e28649 100644 (file)
@@ -868,7 +868,7 @@ EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
 
 void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
 {
-       if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
+       if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
                return NULL;
 
        return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
index 35910f945bfad02823f7146c0746feb90aa2cda9..99e644cda4d13db301b713a5752788c0f646dfa1 100644 (file)
@@ -581,7 +581,7 @@ static int atmel_ebi_probe(struct platform_device *pdev)
        return of_platform_populate(np, NULL, NULL, dev);
 }
 
-static int atmel_ebi_resume(struct device *dev)
+static __maybe_unused int atmel_ebi_resume(struct device *dev)
 {
        struct atmel_ebi *ebi = dev_get_drvdata(dev);
        struct atmel_ebi_dev *ebid;
index bf0fe0137dfed2c893001abb8cfe8b83861dae08..6d1b4b707cc287034c0d8fd225c4f7fc18e796ad 100644 (file)
@@ -512,7 +512,7 @@ static void gpmc_cs_show_timings(int cs, const char *desc)
        pr_info("gpmc cs%i access configuration:\n", cs);
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1,  4,  4, "time-para-granularity");
        GPMC_GET_RAW(GPMC_CS_CONFIG1,  8,  9, "mux-add-data");
-       GPMC_GET_RAW_MAX(GPMC_CS_CONFIG1, 12, 13,
+       GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 12, 13, 1,
                         GPMC_CONFIG1_DEVICESIZE_MAX, "device-width");
        GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write");
index 75488e65cd96cf6484e300d47280df77f1eec77a..8d46e3ad9529d46a2b2e27229668e517ef38552f 100644 (file)
@@ -245,8 +245,7 @@ static int arizona_poll_reg(struct arizona *arizona,
        int ret;
 
        ret = regmap_read_poll_timeout(arizona->regmap,
-                                      ARIZONA_INTERRUPT_RAW_STATUS_5, val,
-                                      ((val & mask) == target),
+                                      reg, val, ((val & mask) == target),
                                       ARIZONA_REG_POLL_DELAY_US,
                                       timeout_ms * 1000);
        if (ret)
index 2cba76e6fa3cb0bd8b2148bdd472c44f5abaf0d7..07bbd4cc18526514a2f1029b3d12b4d1b4724613 100644 (file)
@@ -492,6 +492,7 @@ config ASPEED_LPC_CTRL
 
 config PCI_ENDPOINT_TEST
        depends on PCI
+       select CRC32
        tristate "PCI Endpoint Test driver"
        ---help---
            Enable this configuration option to enable the host side test driver
index 4472ce11f98d74e03fb50c5bab8302274535d423..8c32040b9c09f988274ac8cc9354e4b56419787f 100644 (file)
@@ -45,7 +45,7 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
        mutex_init(&ctx->mapping_lock);
        ctx->mapping = NULL;
 
-       if (cxl_is_psl8(afu)) {
+       if (cxl_is_power8()) {
                spin_lock_init(&ctx->sste_lock);
 
                /*
@@ -189,7 +189,7 @@ int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma)
                if (start + len > ctx->afu->adapter->ps_size)
                        return -EINVAL;
 
-               if (cxl_is_psl9(ctx->afu)) {
+               if (cxl_is_power9()) {
                        /*
                         * Make sure there is a valid problem state
                         * area space for this AFU.
@@ -324,7 +324,7 @@ static void reclaim_ctx(struct rcu_head *rcu)
 {
        struct cxl_context *ctx = container_of(rcu, struct cxl_context, rcu);
 
-       if (cxl_is_psl8(ctx->afu))
+       if (cxl_is_power8())
                free_page((u64)ctx->sstp);
        if (ctx->ff_page)
                __free_page(ctx->ff_page);
index c8568ea7c5186745dd36774ec16cf909c4b6f996..a03f8e7535e58fe77d899b7a40e86e780792f50c 100644 (file)
@@ -357,6 +357,7 @@ static const cxl_p2n_reg_t CXL_PSL_WED_An     = {0x0A0};
 #define CXL_PSL9_DSISR_An_PF_RGP  0x0000000000000090ULL  /* PTE not found (Radix Guest (parent)) 0b10010000 */
 #define CXL_PSL9_DSISR_An_PF_HRH  0x0000000000000094ULL  /* PTE not found (HPT/Radix Host)       0b10010100 */
 #define CXL_PSL9_DSISR_An_PF_STEG 0x000000000000009CULL  /* PTE not found (STEG VA)              0b10011100 */
+#define CXL_PSL9_DSISR_An_URTCH   0x00000000000000B4ULL  /* Unsupported Radix Tree Configuration 0b10110100 */
 
 /****** CXL_PSL_TFC_An ******************************************************/
 #define CXL_PSL_TFC_An_A  (1ull << (63-28)) /* Acknowledge non-translation fault */
@@ -844,24 +845,15 @@ static inline bool cxl_is_power8(void)
 
 static inline bool cxl_is_power9(void)
 {
-       /* intermediate solution */
-       if (!cxl_is_power8() &&
-          (cpu_has_feature(CPU_FTRS_POWER9) ||
-           cpu_has_feature(CPU_FTR_POWER9_DD1)))
+       if (pvr_version_is(PVR_POWER9))
                return true;
        return false;
 }
 
-static inline bool cxl_is_psl8(struct cxl_afu *afu)
+static inline bool cxl_is_power9_dd1(void)
 {
-       if (afu->adapter->caia_major == 1)
-               return true;
-       return false;
-}
-
-static inline bool cxl_is_psl9(struct cxl_afu *afu)
-{
-       if (afu->adapter->caia_major == 2)
+       if ((pvr_version_is(PVR_POWER9)) &&
+           cpu_has_feature(CPU_FTR_POWER9_DD1))
                return true;
        return false;
 }
index 5344448f514e16ac7b8b50a68b6173461a66783c..c79e39bad7a42673ed0a2273236519c654120f57 100644 (file)
@@ -187,7 +187,7 @@ static struct mm_struct *get_mem_context(struct cxl_context *ctx)
 
 static bool cxl_is_segment_miss(struct cxl_context *ctx, u64 dsisr)
 {
-       if ((cxl_is_psl8(ctx->afu)) && (dsisr & CXL_PSL_DSISR_An_DS))
+       if ((cxl_is_power8() && (dsisr & CXL_PSL_DSISR_An_DS)))
                return true;
 
        return false;
@@ -195,16 +195,23 @@ static bool cxl_is_segment_miss(struct cxl_context *ctx, u64 dsisr)
 
 static bool cxl_is_page_fault(struct cxl_context *ctx, u64 dsisr)
 {
-       if ((cxl_is_psl8(ctx->afu)) && (dsisr & CXL_PSL_DSISR_An_DM))
-               return true;
+       u64 crs; /* Translation Checkout Response Status */
 
-       if ((cxl_is_psl9(ctx->afu)) &&
-          ((dsisr & CXL_PSL9_DSISR_An_CO_MASK) &
-               (CXL_PSL9_DSISR_An_PF_SLR | CXL_PSL9_DSISR_An_PF_RGC |
-                CXL_PSL9_DSISR_An_PF_RGP | CXL_PSL9_DSISR_An_PF_HRH |
-                CXL_PSL9_DSISR_An_PF_STEG)))
+       if ((cxl_is_power8()) && (dsisr & CXL_PSL_DSISR_An_DM))
                return true;
 
+       if (cxl_is_power9()) {
+               crs = (dsisr & CXL_PSL9_DSISR_An_CO_MASK);
+               if ((crs == CXL_PSL9_DSISR_An_PF_SLR) ||
+                   (crs == CXL_PSL9_DSISR_An_PF_RGC) ||
+                   (crs == CXL_PSL9_DSISR_An_PF_RGP) ||
+                   (crs == CXL_PSL9_DSISR_An_PF_HRH) ||
+                   (crs == CXL_PSL9_DSISR_An_PF_STEG) ||
+                   (crs == CXL_PSL9_DSISR_An_URTCH)) {
+                       return true;
+               }
+       }
+
        return false;
 }
 
index 17b433f1ce23b7deeb2e3f35139d3bef57ef20d0..0761271d68c5613b23152c03522f6a388950ea86 100644 (file)
@@ -159,11 +159,8 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
 
        /* Do this outside the status_mutex to avoid a circular dependency with
         * the locking in cxl_mmap_fault() */
-       if (copy_from_user(&work, uwork,
-                          sizeof(struct cxl_ioctl_start_work))) {
-               rc = -EFAULT;
-               goto out;
-       }
+       if (copy_from_user(&work, uwork, sizeof(work)))
+               return -EFAULT;
 
        mutex_lock(&ctx->status_mutex);
        if (ctx->status != OPENED) {
index 1703655072b1ed312fc9970d0f71eb5fb75baf46..c1ba0d42cbc865467334c25a0b62a3f1f8932a21 100644 (file)
@@ -329,8 +329,15 @@ static int __init init_cxl(void)
 
        cxl_debugfs_init();
 
-       if ((rc = register_cxl_calls(&cxl_calls)))
-               goto err;
+       /*
+        * we don't register the callback on P9. slb callack is only
+        * used for the PSL8 MMU and CX4.
+        */
+       if (cxl_is_power8()) {
+               rc = register_cxl_calls(&cxl_calls);
+               if (rc)
+                       goto err;
+       }
 
        if (cpu_has_feature(CPU_FTR_HVMODE)) {
                cxl_ops = &cxl_native_ops;
@@ -347,7 +354,8 @@ static int __init init_cxl(void)
 
        return 0;
 err1:
-       unregister_cxl_calls(&cxl_calls);
+       if (cxl_is_power8())
+               unregister_cxl_calls(&cxl_calls);
 err:
        cxl_debugfs_exit();
        cxl_file_exit();
@@ -366,7 +374,8 @@ static void exit_cxl(void)
 
        cxl_debugfs_exit();
        cxl_file_exit();
-       unregister_cxl_calls(&cxl_calls);
+       if (cxl_is_power8())
+               unregister_cxl_calls(&cxl_calls);
        idr_destroy(&cxl_adapter_idr);
 }
 
index 871a2f09c71845b2803bab920618c36de634e4fc..2b2f8894149df307b04a8cd17b2309873e962fc3 100644 (file)
@@ -105,11 +105,16 @@ static int native_afu_reset(struct cxl_afu *afu)
                           CXL_AFU_Cntl_An_RS_MASK | CXL_AFU_Cntl_An_ES_MASK,
                           false);
 
-       /* Re-enable any masked interrupts */
-       serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
-       serr &= ~CXL_PSL_SERR_An_IRQ_MASKS;
-       cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
-
+       /*
+        * Re-enable any masked interrupts when the AFU is not
+        * activated to avoid side effects after attaching a process
+        * in dedicated mode.
+        */
+       if (afu->current_mode == 0) {
+               serr = cxl_p1n_read(afu, CXL_PSL_SERR_An);
+               serr &= ~CXL_PSL_SERR_An_IRQ_MASKS;
+               cxl_p1n_write(afu, CXL_PSL_SERR_An, serr);
+       }
 
        return rc;
 }
@@ -139,9 +144,9 @@ int cxl_psl_purge(struct cxl_afu *afu)
 
        pr_devel("PSL purge request\n");
 
-       if (cxl_is_psl8(afu))
+       if (cxl_is_power8())
                trans_fault = CXL_PSL_DSISR_TRANS;
-       if (cxl_is_psl9(afu))
+       if (cxl_is_power9())
                trans_fault = CXL_PSL9_DSISR_An_TF;
 
        if (!cxl_ops->link_ok(afu->adapter, afu)) {
@@ -603,7 +608,7 @@ static u64 calculate_sr(struct cxl_context *ctx)
                if (!test_tsk_thread_flag(current, TIF_32BIT))
                        sr |= CXL_PSL_SR_An_SF;
        }
-       if (cxl_is_psl9(ctx->afu)) {
+       if (cxl_is_power9()) {
                if (radix_enabled())
                        sr |= CXL_PSL_SR_An_XLAT_ror;
                else
@@ -1117,10 +1122,10 @@ static irqreturn_t native_handle_psl_slice_error(struct cxl_context *ctx,
 
 static bool cxl_is_translation_fault(struct cxl_afu *afu, u64 dsisr)
 {
-       if ((cxl_is_psl8(afu)) && (dsisr & CXL_PSL_DSISR_TRANS))
+       if ((cxl_is_power8()) && (dsisr & CXL_PSL_DSISR_TRANS))
                return true;
 
-       if ((cxl_is_psl9(afu)) && (dsisr & CXL_PSL9_DSISR_An_TF))
+       if ((cxl_is_power9()) && (dsisr & CXL_PSL9_DSISR_An_TF))
                return true;
 
        return false;
@@ -1194,10 +1199,10 @@ static void native_irq_wait(struct cxl_context *ctx)
                if (ph != ctx->pe)
                        return;
                dsisr = cxl_p2n_read(ctx->afu, CXL_PSL_DSISR_An);
-               if (cxl_is_psl8(ctx->afu) &&
+               if (cxl_is_power8() &&
                   ((dsisr & CXL_PSL_DSISR_PENDING) == 0))
                        return;
-               if (cxl_is_psl9(ctx->afu) &&
+               if (cxl_is_power9() &&
                   ((dsisr & CXL_PSL9_DSISR_PENDING) == 0))
                        return;
                /*
@@ -1302,13 +1307,16 @@ int cxl_native_register_psl_err_irq(struct cxl *adapter)
 
 void cxl_native_release_psl_err_irq(struct cxl *adapter)
 {
-       if (adapter->native->err_virq != irq_find_mapping(NULL, adapter->native->err_hwirq))
+       if (adapter->native->err_virq == 0 ||
+           adapter->native->err_virq !=
+           irq_find_mapping(NULL, adapter->native->err_hwirq))
                return;
 
        cxl_p1_write(adapter, CXL_PSL_ErrIVTE, 0x0000000000000000);
        cxl_unmap_irq(adapter->native->err_virq, adapter);
        cxl_ops->release_one_irq(adapter, adapter->native->err_hwirq);
        kfree(adapter->irq_name);
+       adapter->native->err_virq = 0;
 }
 
 int cxl_native_register_serr_irq(struct cxl_afu *afu)
@@ -1346,13 +1354,15 @@ int cxl_native_register_serr_irq(struct cxl_afu *afu)
 
 void cxl_native_release_serr_irq(struct cxl_afu *afu)
 {
-       if (afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
+       if (afu->serr_virq == 0 ||
+           afu->serr_virq != irq_find_mapping(NULL, afu->serr_hwirq))
                return;
 
        cxl_p1n_write(afu, CXL_PSL_SERR_An, 0x0000000000000000);
        cxl_unmap_irq(afu->serr_virq, afu);
        cxl_ops->release_one_irq(afu->adapter, afu->serr_hwirq);
        kfree(afu->err_irq_name);
+       afu->serr_virq = 0;
 }
 
 int cxl_native_register_psl_irq(struct cxl_afu *afu)
@@ -1375,12 +1385,15 @@ int cxl_native_register_psl_irq(struct cxl_afu *afu)
 
 void cxl_native_release_psl_irq(struct cxl_afu *afu)
 {
-       if (afu->native->psl_virq != irq_find_mapping(NULL, afu->native->psl_hwirq))
+       if (afu->native->psl_virq == 0 ||
+           afu->native->psl_virq !=
+           irq_find_mapping(NULL, afu->native->psl_hwirq))
                return;
 
        cxl_unmap_irq(afu->native->psl_virq, afu);
        cxl_ops->release_one_irq(afu->adapter, afu->native->psl_hwirq);
        kfree(afu->psl_irq_name);
+       afu->native->psl_virq = 0;
 }
 
 static void recover_psl_err(struct cxl_afu *afu, u64 errstat)
index 6dc1ee5b92c97121c86cbe12f0f46dab77a7c957..1eb9859809bff6ae367f849afc76fc21d8fc844d 100644 (file)
@@ -436,7 +436,7 @@ static int init_implementation_adapter_regs_psl9(struct cxl *adapter, struct pci
        /* nMMU_ID Defaults to: b’000001001’*/
        xsl_dsnctl |= ((u64)0x09 << (63-28));
 
-       if (cxl_is_power9() && !cpu_has_feature(CPU_FTR_POWER9_DD1)) {
+       if (!(cxl_is_power9_dd1())) {
                /*
                 * Used to identify CAPI packets which should be sorted into
                 * the Non-Blocking queues by the PHB. This field should match
@@ -491,7 +491,7 @@ static int init_implementation_adapter_regs_psl9(struct cxl *adapter, struct pci
        cxl_p1_write(adapter, CXL_PSL9_APCDEDTYPE, 0x40000003FFFF0000ULL);
 
        /* Disable vc dd1 fix */
-       if ((cxl_is_power9() && cpu_has_feature(CPU_FTR_POWER9_DD1)))
+       if (cxl_is_power9_dd1())
                cxl_p1_write(adapter, CXL_PSL9_GP_CT, 0x0400000000000001ULL);
 
        return 0;
@@ -1439,8 +1439,7 @@ int cxl_pci_reset(struct cxl *adapter)
         * The adapter is about to be reset, so ignore errors.
         * Not supported on P9 DD1
         */
-       if ((cxl_is_power8()) ||
-           ((cxl_is_power9() && !cpu_has_feature(CPU_FTR_POWER9_DD1))))
+       if ((cxl_is_power8()) || (!(cxl_is_power9_dd1())))
                cxl_data_cache_flush(adapter);
 
        /* pcie_warm_reset requests a fundamental pci reset which includes a
@@ -1750,7 +1749,6 @@ static const struct cxl_service_layer_ops psl9_ops = {
        .debugfs_add_adapter_regs = cxl_debugfs_add_adapter_regs_psl9,
        .debugfs_add_afu_regs = cxl_debugfs_add_afu_regs_psl9,
        .psl_irq_dump_registers = cxl_native_irq_dump_regs_psl9,
-       .err_irq_dump_registers = cxl_native_err_irq_dump_regs,
        .debugfs_stop_trace = cxl_stop_trace_psl9,
        .write_timebase_ctrl = write_timebase_ctrl_psl9,
        .timebase_read = timebase_read_psl9,
@@ -1889,8 +1887,7 @@ static void cxl_pci_remove_adapter(struct cxl *adapter)
         * Flush adapter datacache as its about to be removed.
         * Not supported on P9 DD1.
         */
-       if ((cxl_is_power8()) ||
-           ((cxl_is_power9() && !cpu_has_feature(CPU_FTR_POWER9_DD1))))
+       if ((cxl_is_power8()) || (!(cxl_is_power9_dd1())))
                cxl_data_cache_flush(adapter);
 
        cxl_deconfigure_adapter(adapter);
index d1928fdd0f435630609c92056a66ad1af000a4ae..07aad85763348b0a7ec85ccf85ab21eb0031b43a 100644 (file)
@@ -763,8 +763,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
 {
        struct mei_cl_device *cldev = to_mei_cl_device(dev);
        const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+       u8 version = mei_me_cl_ver(cldev->me_cl);
 
-       return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:", cldev->name, uuid);
+       return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
+                        cldev->name, uuid, version);
 }
 static DEVICE_ATTR_RO(modalias);
 
index c862cd4583cc93694747e191f5e3537e5767bfa5..b8069eec18cb44ef335535789f0e2a61ffaf4bd1 100644 (file)
@@ -309,6 +309,9 @@ static inline enum xp_retval
 xpc_send(short partid, int ch_number, u32 flags, void *payload,
         u16 payload_size)
 {
+       if (!xpc_interface.send)
+               return xpNotLoaded;
+
        return xpc_interface.send(partid, ch_number, flags, payload,
                                  payload_size);
 }
@@ -317,6 +320,9 @@ static inline enum xp_retval
 xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
                u16 payload_size, xpc_notify_func func, void *key)
 {
+       if (!xpc_interface.send_notify)
+               return xpNotLoaded;
+
        return xpc_interface.send_notify(partid, ch_number, flags, payload,
                                         payload_size, func, key);
 }
@@ -324,12 +330,16 @@ xpc_send_notify(short partid, int ch_number, u32 flags, void *payload,
 static inline void
 xpc_received(short partid, int ch_number, void *payload)
 {
-       return xpc_interface.received(partid, ch_number, payload);
+       if (xpc_interface.received)
+               xpc_interface.received(partid, ch_number, payload);
 }
 
 static inline enum xp_retval
 xpc_partid_to_nasids(short partid, void *nasids)
 {
+       if (!xpc_interface.partid_to_nasids)
+               return xpNotLoaded;
+
        return xpc_interface.partid_to_nasids(partid, nasids);
 }
 
index 01be66d02ca8ce52c84b809fa55a7aeb6b219bc2..6d7f557fd1c1a1e885eb3dad64886b3e0afe32fe 100644 (file)
@@ -69,23 +69,9 @@ struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
 EXPORT_SYMBOL_GPL(xpc_registrations);
 
 /*
- * Initialize the XPC interface to indicate that XPC isn't loaded.
+ * Initialize the XPC interface to NULL to indicate that XPC isn't loaded.
  */
-static enum xp_retval
-xpc_notloaded(void)
-{
-       return xpNotLoaded;
-}
-
-struct xpc_interface xpc_interface = {
-       (void (*)(int))xpc_notloaded,
-       (void (*)(int))xpc_notloaded,
-       (enum xp_retval(*)(short, int, u32, void *, u16))xpc_notloaded,
-       (enum xp_retval(*)(short, int, u32, void *, u16, xpc_notify_func,
-                          void *))xpc_notloaded,
-       (void (*)(short, int, void *))xpc_notloaded,
-       (enum xp_retval(*)(short, void *))xpc_notloaded
-};
+struct xpc_interface xpc_interface = { };
 EXPORT_SYMBOL_GPL(xpc_interface);
 
 /*
@@ -115,17 +101,7 @@ EXPORT_SYMBOL_GPL(xpc_set_interface);
 void
 xpc_clear_interface(void)
 {
-       xpc_interface.connect = (void (*)(int))xpc_notloaded;
-       xpc_interface.disconnect = (void (*)(int))xpc_notloaded;
-       xpc_interface.send = (enum xp_retval(*)(short, int, u32, void *, u16))
-           xpc_notloaded;
-       xpc_interface.send_notify = (enum xp_retval(*)(short, int, u32, void *,
-                                                      u16, xpc_notify_func,
-                                                      void *))xpc_notloaded;
-       xpc_interface.received = (void (*)(short, int, void *))
-           xpc_notloaded;
-       xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *))
-           xpc_notloaded;
+       memset(&xpc_interface, 0, sizeof(xpc_interface));
 }
 EXPORT_SYMBOL_GPL(xpc_clear_interface);
 
@@ -188,7 +164,8 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
 
        mutex_unlock(&registration->mutex);
 
-       xpc_interface.connect(ch_number);
+       if (xpc_interface.connect)
+               xpc_interface.connect(ch_number);
 
        return xpSuccess;
 }
@@ -237,7 +214,8 @@ xpc_disconnect(int ch_number)
        registration->assigned_limit = 0;
        registration->idle_limit = 0;
 
-       xpc_interface.disconnect(ch_number);
+       if (xpc_interface.disconnect)
+               xpc_interface.disconnect(ch_number);
 
        mutex_unlock(&registration->mutex);
 
index 1304160de16828f402dad6ff1f970af70764c3b2..13ef162cf066a63363106e40a513f3317205d10d 100644 (file)
@@ -27,6 +27,7 @@ struct mmc_pwrseq_simple {
        struct mmc_pwrseq pwrseq;
        bool clk_enabled;
        u32 post_power_on_delay_ms;
+       u32 power_off_delay_us;
        struct clk *ext_clk;
        struct gpio_descs *reset_gpios;
 };
@@ -78,6 +79,10 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
 
        mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
 
+       if (pwrseq->power_off_delay_us)
+               usleep_range(pwrseq->power_off_delay_us,
+                       2 * pwrseq->power_off_delay_us);
+
        if (!IS_ERR(pwrseq->ext_clk) && pwrseq->clk_enabled) {
                clk_disable_unprepare(pwrseq->ext_clk);
                pwrseq->clk_enabled = false;
@@ -119,6 +124,8 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
 
        device_property_read_u32(dev, "post-power-on-delay-ms",
                                 &pwrseq->post_power_on_delay_ms);
+       device_property_read_u32(dev, "power-off-delay-us",
+                                &pwrseq->power_off_delay_us);
 
        pwrseq->pwrseq.dev = dev;
        pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
index 772d0900026d0efbd6e59911f93ef9cc8930b38a..951d2cdd7888b0d68f9994298572759162277682 100644 (file)
@@ -108,7 +108,7 @@ static void octeon_mmc_release_bus(struct cvm_mmc_host *host)
 static void octeon_mmc_int_enable(struct cvm_mmc_host *host, u64 val)
 {
        writeq(val, host->base + MIO_EMM_INT(host));
-       if (!host->dma_active || (host->dma_active && !host->has_ciu3))
+       if (!host->has_ciu3)
                writeq(val, host->base + MIO_EMM_INT_EN(host));
 }
 
@@ -267,7 +267,7 @@ static int octeon_mmc_probe(struct platform_device *pdev)
        }
 
        host->global_pwr_gpiod = devm_gpiod_get_optional(&pdev->dev,
-                                                        "power-gpios",
+                                                        "power",
                                                         GPIOD_OUT_HIGH);
        if (IS_ERR(host->global_pwr_gpiod)) {
                dev_err(&pdev->dev, "Invalid power GPIO\n");
@@ -288,11 +288,20 @@ static int octeon_mmc_probe(struct platform_device *pdev)
                if (ret) {
                        dev_err(&pdev->dev, "Error populating slots\n");
                        octeon_mmc_set_shared_power(host, 0);
-                       return ret;
+                       goto error;
                }
                i++;
        }
        return 0;
+
+error:
+       for (i = 0; i < CAVIUM_MAX_MMC; i++) {
+               if (host->slot[i])
+                       cvm_mmc_of_slot_remove(host->slot[i]);
+               if (host->slot_pdev[i])
+                       of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
+       }
+       return ret;
 }
 
 static int octeon_mmc_remove(struct platform_device *pdev)
index fe3d77267cd6b7803ae287d8b6fc5fc308f95a87..b9cc9599879978972b4c8c96f9dbddc26caebb2f 100644 (file)
@@ -146,6 +146,12 @@ static int thunder_mmc_probe(struct pci_dev *pdev,
        return 0;
 
 error:
+       for (i = 0; i < CAVIUM_MAX_MMC; i++) {
+               if (host->slot[i])
+                       cvm_mmc_of_slot_remove(host->slot[i]);
+               if (host->slot_pdev[i])
+                       of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL);
+       }
        clk_disable_unprepare(host->clk);
        return ret;
 }
index 58b51ba6aabd2de7773209d42aa758cb493c2500..b8aaf0fdb77cf52bf89cd3000a98b77536a6f5a4 100644 (file)
@@ -839,14 +839,14 @@ static void cvm_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                cvm_mmc_reset_bus(slot);
                if (host->global_pwr_gpiod)
                        host->set_shared_power(host, 0);
-               else
+               else if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
                break;
 
        case MMC_POWER_UP:
                if (host->global_pwr_gpiod)
                        host->set_shared_power(host, 1);
-               else
+               else if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
                break;
        }
@@ -968,20 +968,15 @@ static int cvm_mmc_of_parse(struct device *dev, struct cvm_mmc_slot *slot)
                return -EINVAL;
        }
 
-       mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc");
-       if (IS_ERR(mmc->supply.vmmc)) {
-               if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-               /*
-                * Legacy Octeon firmware has no regulator entry, fall-back to
-                * a hard-coded voltage to get a sane OCR.
-                */
+       ret = mmc_regulator_get_supply(mmc);
+       if (ret == -EPROBE_DEFER)
+               return ret;
+       /*
+        * Legacy Octeon firmware has no regulator entry, fall-back to
+        * a hard-coded voltage to get a sane OCR.
+        */
+       if (IS_ERR(mmc->supply.vmmc))
                mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       } else {
-               ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
-               if (ret > 0)
-                       mmc->ocr_avail = ret;
-       }
 
        /* Common MMC bindings */
        ret = mmc_of_parse(mmc);
index 1842ed341af10e38902f1178f409d645b7301679..de962c2d5e000a834bc40064be3bbe426e55bf5a 100644 (file)
@@ -210,6 +210,15 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,
        int i;
        bool use_desc_chain_mode = true;
 
+       /*
+        * Broken SDIO with AP6255-based WiFi on Khadas VIM Pro has been
+        * reported. For some strange reason this occurs in descriptor
+        * chain mode only. So let's fall back to bounce buffer mode
+        * for command SD_IO_RW_EXTENDED.
+        */
+       if (mrq->cmd->opcode == SD_IO_RW_EXTENDED)
+               return;
+
        for_each_sg(data->sg, sg, data->sg_len, i)
                /* check for 8 byte alignment */
                if (sg->offset & 7) {
index 3275d49958120857d899384237bc905ad5fd17a5..61666d2697713a7665191b848084846142644457 100644 (file)
@@ -187,7 +187,8 @@ static const struct sdhci_iproc_data iproc_cygnus_data = {
 };
 
 static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
-       .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+       .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+                 SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
        .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
        .ops = &sdhci_iproc_ops,
 };
index 6356781f1cca78190bff46e5225606e0f2113cc7..f7e26b031e768d871ed465cde982005295066e82 100644 (file)
@@ -787,14 +787,6 @@ int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios)
        return ret;
 }
 
-void xenon_clean_phy(struct sdhci_host *host)
-{
-       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
-
-       kfree(priv->phy_params);
-}
-
 static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
                         const char *phy_name)
 {
@@ -819,11 +811,7 @@ static int xenon_add_phy(struct device_node *np, struct sdhci_host *host,
        if (ret)
                return ret;
 
-       ret = xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params);
-       if (ret)
-               xenon_clean_phy(host);
-
-       return ret;
+       return xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params);
 }
 
 int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host)
index 67246655315b02b005b00153abfaa60c67fca7a5..bc1781bb070b7b8b83c0132abb114f6905ffddfb 100644 (file)
@@ -486,7 +486,7 @@ static int xenon_probe(struct platform_device *pdev)
 
        err = xenon_sdhc_prepare(host);
        if (err)
-               goto clean_phy_param;
+               goto err_clk;
 
        err = sdhci_add_host(host);
        if (err)
@@ -496,8 +496,6 @@ static int xenon_probe(struct platform_device *pdev)
 
 remove_sdhc:
        xenon_sdhc_unprepare(host);
-clean_phy_param:
-       xenon_clean_phy(host);
 err_clk:
        clk_disable_unprepare(pltfm_host->clk);
 free_pltfm:
@@ -510,8 +508,6 @@ static int xenon_remove(struct platform_device *pdev)
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 
-       xenon_clean_phy(host);
-
        sdhci_remove_host(host, 0);
 
        xenon_sdhc_unprepare(host);
index 6e6523ea01ce50389f3b77f52b467efb11305831..73debb42dc2f9991356f59668d18ebd09296f927 100644 (file)
@@ -93,7 +93,6 @@ struct xenon_priv {
 };
 
 int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios);
-void xenon_clean_phy(struct sdhci_host *host);
 int xenon_phy_parse_dt(struct device_node *np,
                       struct sdhci_host *host);
 void xenon_soc_pad_ctrl(struct sdhci_host *host,
index d474378ed810b3c3ab19d8a4e85e77e0eb15511c..b1dd12729f19b29ea8f35886aba02cc986990661 100644 (file)
@@ -202,7 +202,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
        return 0;
 }
 
-const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
+static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
        .ecc = nand_ooblayout_ecc_lp_hamming,
        .free = nand_ooblayout_free_lp_hamming,
 };
@@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
        /* Initialize the ->data_interface field. */
        ret = nand_init_data_interface(chip);
        if (ret)
-               return ret;
+               goto err_nand_init;
 
        /*
         * Setup the data interface correctly on the chip and controller side.
@@ -4373,7 +4373,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
         */
        ret = nand_setup_data_interface(chip);
        if (ret)
-               return ret;
+               goto err_nand_init;
 
        nand_maf_id = chip->id.data[0];
        nand_dev_id = chip->id.data[1];
@@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
        mtd->size = i * chip->chipsize;
 
        return 0;
+
+err_nand_init:
+       /* Free manufacturer priv data. */
+       nand_manufacturer_cleanup(chip);
+
+       return ret;
 }
 EXPORT_SYMBOL(nand_scan_ident);
 
@@ -4574,18 +4580,23 @@ int nand_scan_tail(struct mtd_info *mtd)
 
        /* New bad blocks should be marked in OOB, flash-based BBT, or both */
        if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
-                  !(chip->bbt_options & NAND_BBT_USE_FLASH)))
-               return -EINVAL;
+                  !(chip->bbt_options & NAND_BBT_USE_FLASH))) {
+               ret = -EINVAL;
+               goto err_ident;
+       }
 
        if (invalid_ecc_page_accessors(chip)) {
                pr_err("Invalid ECC page accessors setup\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_ident;
        }
 
        if (!(chip->options & NAND_OWN_BUFFERS)) {
                nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
-               if (!nbuf)
-                       return -ENOMEM;
+               if (!nbuf) {
+                       ret = -ENOMEM;
+                       goto err_ident;
+               }
 
                nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
                if (!nbuf->ecccalc) {
@@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd)
 
                chip->buffers = nbuf;
        } else {
-               if (!chip->buffers)
-                       return -ENOMEM;
+               if (!chip->buffers) {
+                       ret = -ENOMEM;
+                       goto err_ident;
+               }
        }
 
        /* Set the internal oob buffer location, just after the page data */
@@ -4842,7 +4855,11 @@ int nand_scan_tail(struct mtd_info *mtd)
                return 0;
 
        /* Build bad block table */
-       return chip->scan_bbt(mtd);
+       ret = chip->scan_bbt(mtd);
+       if (ret)
+               goto err_free;
+       return 0;
+
 err_free:
        if (nbuf) {
                kfree(nbuf->databuf);
@@ -4850,6 +4867,13 @@ err_free:
                kfree(nbuf->ecccalc);
                kfree(nbuf);
        }
+
+err_ident:
+       /* Clean up nand_scan_ident(). */
+
+       /* Free manufacturer priv data. */
+       nand_manufacturer_cleanup(chip);
+
        return ret;
 }
 EXPORT_SYMBOL(nand_scan_tail);
index 9d5ca0e540b5bc5c9e3be9a6a3b476624e63be14..92e2cf8e9ff9066860973caaf60ecb95e2d4a599 100644 (file)
@@ -6,7 +6,6 @@
  * published by the Free Software Foundation.
  *
  */
-#include <linux/module.h>
 #include <linux/mtd/nand.h>
 #include <linux/sizes.h>
 
index 9cfc4035a420a3eae2d2a451c97f5300f8bc8b80..1e0755997762aa23ee953ad20f2a88d24dc7139c 100644 (file)
@@ -84,6 +84,9 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
                        case 7:
                                chip->ecc_strength_ds = 60;
                                break;
+                       default:
+                               WARN(1, "Could not decode ECC info");
+                               chip->ecc_step_ds = 0;
                        }
                }
        } else {
index 05b6e106520331ddd48f619f798d21c4cfeb2059..49b286c6c10fc85e5ee7e75f4dd10d231c86c73f 100644 (file)
  * byte 1 for other packets in the page (PKT_N, for N > 0)
  * ERR_COUNT_PKT_N is the max error count over all but the first packet.
  */
-#define DECODE_OK_PKT_0(v)     ((v) & BIT(7))
-#define DECODE_OK_PKT_N(v)     ((v) & BIT(15))
 #define ERR_COUNT_PKT_0(v)     (((v) >> 0) & 0x3f)
 #define ERR_COUNT_PKT_N(v)     (((v) >> 8) & 0x3f)
+#define DECODE_FAIL_PKT_0(v)   (((v) & BIT(7)) == 0)
+#define DECODE_FAIL_PKT_N(v)   (((v) & BIT(15)) == 0)
 
 /* Offsets relative to pbus_base */
 #define PBUS_CS_CTRL   0x83c
@@ -193,6 +193,8 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
                                                  chip->ecc.strength);
                if (res < 0)
                        mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += res;
 
                bitflips = max(res, bitflips);
                buf += pkt_size;
@@ -202,9 +204,11 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
        return bitflips;
 }
 
-static int decode_error_report(struct tango_nfc *nfc)
+static int decode_error_report(struct nand_chip *chip)
 {
        u32 status, res;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct tango_nfc *nfc = to_tango_nfc(chip->controller);
 
        status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS);
        if (status & PAGE_IS_EMPTY)
@@ -212,10 +216,14 @@ static int decode_error_report(struct tango_nfc *nfc)
 
        res = readl_relaxed(nfc->mem_base + ERROR_REPORT);
 
-       if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res))
-               return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
+       if (DECODE_FAIL_PKT_0(res) || DECODE_FAIL_PKT_N(res))
+               return -EBADMSG;
+
+       /* ERR_COUNT_PKT_N is max, not sum, but that's all we have */
+       mtd->ecc_stats.corrected +=
+               ERR_COUNT_PKT_0(res) + ERR_COUNT_PKT_N(res);
 
-       return -EBADMSG;
+       return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
 }
 
 static void tango_dma_callback(void *arg)
@@ -282,7 +290,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
        if (err)
                return err;
 
-       res = decode_error_report(nfc);
+       res = decode_error_report(chip);
        if (res < 0) {
                chip->ecc.read_oob_raw(mtd, chip, page);
                res = check_erased_page(chip, buf);
@@ -663,6 +671,7 @@ static const struct of_device_id tango_nand_ids[] = {
        { .compatible = "sigma,smp8758-nand" },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, tango_nand_ids);
 
 static struct platform_driver tango_nand_driver = {
        .probe  = tango_nand_probe,
index 62ee439d58829574d732e84b8afba738871a43e5..53a1cb551defabe29e763e578632c33ac851547f 100644 (file)
@@ -756,6 +756,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
        struct net_device *dev = dev_id;
        struct arcnet_local *lp;
        int recbuf, status, diagstatus, didsomething, boguscount;
+       unsigned long flags;
        int retval = IRQ_NONE;
 
        arc_printk(D_DURING, dev, "\n");
@@ -765,7 +766,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
        lp = netdev_priv(dev);
        BUG_ON(!lp);
 
-       spin_lock(&lp->lock);
+       spin_lock_irqsave(&lp->lock, flags);
 
        /* RESET flag was enabled - if device is not running, we must
         * clear it right away (but nothing else).
@@ -774,7 +775,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
                if (lp->hw.status(dev) & RESETflag)
                        lp->hw.command(dev, CFLAGScmd | RESETclear);
                lp->hw.intmask(dev, 0);
-               spin_unlock(&lp->lock);
+               spin_unlock_irqrestore(&lp->lock, flags);
                return retval;
        }
 
@@ -998,7 +999,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
        udelay(1);
        lp->hw.intmask(dev, lp->intmask);
 
-       spin_unlock(&lp->lock);
+       spin_unlock_irqrestore(&lp->lock, flags);
        return retval;
 }
 EXPORT_SYMBOL(arcnet_interrupt);
index 2056878fb087d6d3bc3bf6564220065f30322283..4fa2e46b48d3e561e3883fdc1a023493bc39ed30 100644 (file)
@@ -212,7 +212,7 @@ static int ack_tx(struct net_device *dev, int acked)
        ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */
        ackpkt->soft.cap.mes.ack = acked;
 
-       arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n",
+       arc_printk(D_PROTO, dev, "Acknowledge for cap packet %x.\n",
                   *((int *)&ackpkt->soft.cap.cookie[0]));
 
        ackskb->protocol = cpu_to_be16(ETH_P_ARCNET);
index 239de38fbd6a588bbb0e90e3452ea60ca1e5a161..47f80b83dcf42a47666f05a688a680b7690251cf 100644 (file)
@@ -135,6 +135,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
        for (i = 0; i < ci->devcount; i++) {
                struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
                struct com20020_dev *card;
+               int dev_id_mask = 0xf;
 
                dev = alloc_arcdev(device);
                if (!dev) {
@@ -166,6 +167,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
                arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
                arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
 
+               SET_NETDEV_DEV(dev, &pdev->dev);
                dev->base_addr = ioaddr;
                dev->dev_addr[0] = node;
                dev->irq = pdev->irq;
@@ -179,8 +181,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
 
                /* Get the dev_id from the PLX rotary coder */
                if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
-                       dev->dev_id = 0xc;
-               dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4;
+                       dev_id_mask = 0x3;
+               dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
 
                snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
 
index 13d9ad4b3f5c977e99f3ac2f38d3f244de3ae203..78043a9c5981e5a0b8d562879de0f77e0763aa75 100644 (file)
@@ -246,8 +246,6 @@ int com20020_found(struct net_device *dev, int shared)
                return -ENODEV;
        }
 
-       dev->base_addr = ioaddr;
-
        arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
                   lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
 
index c5fd4259da331b27503644938ab22787e2eea8ae..e5386ab706ec7fa394162b338c6ff4ad1de8944c 100644 (file)
@@ -90,10 +90,13 @@ enum ad_link_speed_type {
        AD_LINK_SPEED_100MBPS,
        AD_LINK_SPEED_1000MBPS,
        AD_LINK_SPEED_2500MBPS,
+       AD_LINK_SPEED_5000MBPS,
        AD_LINK_SPEED_10000MBPS,
+       AD_LINK_SPEED_14000MBPS,
        AD_LINK_SPEED_20000MBPS,
        AD_LINK_SPEED_25000MBPS,
        AD_LINK_SPEED_40000MBPS,
+       AD_LINK_SPEED_50000MBPS,
        AD_LINK_SPEED_56000MBPS,
        AD_LINK_SPEED_100000MBPS,
 };
@@ -259,10 +262,13 @@ static inline int __check_agg_selection_timer(struct port *port)
  *     %AD_LINK_SPEED_100MBPS,
  *     %AD_LINK_SPEED_1000MBPS,
  *     %AD_LINK_SPEED_2500MBPS,
+ *     %AD_LINK_SPEED_5000MBPS,
  *     %AD_LINK_SPEED_10000MBPS
+ *     %AD_LINK_SPEED_14000MBPS,
  *     %AD_LINK_SPEED_20000MBPS
  *     %AD_LINK_SPEED_25000MBPS
  *     %AD_LINK_SPEED_40000MBPS
+ *     %AD_LINK_SPEED_50000MBPS
  *     %AD_LINK_SPEED_56000MBPS
  *     %AD_LINK_SPEED_100000MBPS
  */
@@ -296,10 +302,18 @@ static u16 __get_link_speed(struct port *port)
                        speed = AD_LINK_SPEED_2500MBPS;
                        break;
 
+               case SPEED_5000:
+                       speed = AD_LINK_SPEED_5000MBPS;
+                       break;
+
                case SPEED_10000:
                        speed = AD_LINK_SPEED_10000MBPS;
                        break;
 
+               case SPEED_14000:
+                       speed = AD_LINK_SPEED_14000MBPS;
+                       break;
+
                case SPEED_20000:
                        speed = AD_LINK_SPEED_20000MBPS;
                        break;
@@ -312,6 +326,10 @@ static u16 __get_link_speed(struct port *port)
                        speed = AD_LINK_SPEED_40000MBPS;
                        break;
 
+               case SPEED_50000:
+                       speed = AD_LINK_SPEED_50000MBPS;
+                       break;
+
                case SPEED_56000:
                        speed = AD_LINK_SPEED_56000MBPS;
                        break;
@@ -707,9 +725,15 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                case AD_LINK_SPEED_2500MBPS:
                        bandwidth = nports * 2500;
                        break;
+               case AD_LINK_SPEED_5000MBPS:
+                       bandwidth = nports * 5000;
+                       break;
                case AD_LINK_SPEED_10000MBPS:
                        bandwidth = nports * 10000;
                        break;
+               case AD_LINK_SPEED_14000MBPS:
+                       bandwidth = nports * 14000;
+                       break;
                case AD_LINK_SPEED_20000MBPS:
                        bandwidth = nports * 20000;
                        break;
@@ -719,6 +743,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                case AD_LINK_SPEED_40000MBPS:
                        bandwidth = nports * 40000;
                        break;
+               case AD_LINK_SPEED_50000MBPS:
+                       bandwidth = nports * 50000;
+                       break;
                case AD_LINK_SPEED_56000MBPS:
                        bandwidth = nports * 56000;
                        break;
@@ -2577,7 +2604,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
                return -1;
 
        ad_info->aggregator_id = aggregator->aggregator_identifier;
-       ad_info->ports = aggregator->num_of_ports;
+       ad_info->ports = __agg_active_ports(aggregator);
        ad_info->actor_key = aggregator->actor_oper_aggregator_key;
        ad_info->partner_key = aggregator->partner_oper_aggregator_key;
        ether_addr_copy(ad_info->partner_system,
index 2be78807fd6e1318487961708394caead76af268..8ab6bdbe16820dd3e56ec517838903bedda515de 100644 (file)
@@ -2612,11 +2612,13 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
        bond_for_each_slave_rcu(bond, slave, iter) {
                unsigned long trans_start = dev_trans_start(slave->dev);
 
+               slave->new_link = BOND_LINK_NOCHANGE;
+
                if (slave->link != BOND_LINK_UP) {
                        if (bond_time_in_interval(bond, trans_start, 1) &&
                            bond_time_in_interval(bond, slave->last_rx, 1)) {
 
-                               slave->link  = BOND_LINK_UP;
+                               slave->new_link = BOND_LINK_UP;
                                slave_state_changed = 1;
 
                                /* primary_slave has no meaning in round-robin
@@ -2643,7 +2645,7 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
                        if (!bond_time_in_interval(bond, trans_start, 2) ||
                            !bond_time_in_interval(bond, slave->last_rx, 2)) {
 
-                               slave->link  = BOND_LINK_DOWN;
+                               slave->new_link = BOND_LINK_DOWN;
                                slave_state_changed = 1;
 
                                if (slave->link_failure_count < UINT_MAX)
@@ -2674,6 +2676,11 @@ static void bond_loadbalance_arp_mon(struct bonding *bond)
                if (!rtnl_trylock())
                        goto re_arm;
 
+               bond_for_each_slave(bond, slave, iter) {
+                       if (slave->new_link != BOND_LINK_NOCHANGE)
+                               slave->link = slave->new_link;
+               }
+
                if (slave_state_changed) {
                        bond_slave_state_change(bond);
                        if (BOND_MODE(bond) == BOND_MODE_XOR)
@@ -4185,7 +4192,6 @@ static void bond_destructor(struct net_device *bond_dev)
        struct bonding *bond = netdev_priv(bond_dev);
        if (bond->wq)
                destroy_workqueue(bond->wq);
-       free_netdev(bond_dev);
 }
 
 void bond_setup(struct net_device *bond_dev)
@@ -4205,7 +4211,8 @@ void bond_setup(struct net_device *bond_dev)
        bond_dev->netdev_ops = &bond_netdev_ops;
        bond_dev->ethtool_ops = &bond_ethtool_ops;
 
-       bond_dev->destructor = bond_destructor;
+       bond_dev->needs_free_netdev = true;
+       bond_dev->priv_destructor = bond_destructor;
 
        SET_NETDEV_DEVTYPE(bond_dev, &bond_type);
 
@@ -4271,10 +4278,10 @@ static int bond_check_params(struct bond_params *params)
        int arp_validate_value, fail_over_mac_value, primary_reselect_value, i;
        struct bond_opt_value newval;
        const struct bond_opt_value *valptr;
-       int arp_all_targets_value;
+       int arp_all_targets_value = 0;
        u16 ad_actor_sys_prio = 0;
        u16 ad_user_port_key = 0;
-       __be32 arp_target[BOND_MAX_ARP_TARGETS];
+       __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0 };
        int arp_ip_count;
        int bond_mode   = BOND_MODE_ROUNDROBIN;
        int xmit_hashtype = BOND_XMIT_POLICY_LAYER2;
@@ -4501,7 +4508,6 @@ static int bond_check_params(struct bond_params *params)
                arp_validate_value = 0;
        }
 
-       arp_all_targets_value = 0;
        if (arp_all_targets) {
                bond_opt_initstr(&newval, arp_all_targets);
                valptr = bond_opt_parse(bond_opt_get(BOND_OPT_ARP_ALL_TARGETS),
@@ -4730,7 +4736,7 @@ int bond_create(struct net *net, const char *name)
 
        rtnl_unlock();
        if (res < 0)
-               bond_destructor(bond_dev);
+               free_netdev(bond_dev);
        return res;
 }
 
index ddabce7594565232a5e903c23248ea884995c149..71a7c3b44fdde3c3a7ede652a7dab681d577e6ce 100644 (file)
@@ -1121,7 +1121,7 @@ static void cfhsi_setup(struct net_device *dev)
        dev->flags = IFF_POINTOPOINT | IFF_NOARP;
        dev->mtu = CFHSI_MAX_CAIF_FRAME_SZ;
        dev->priv_flags |= IFF_NO_QUEUE;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        dev->netdev_ops = &cfhsi_netdevops;
        for (i = 0; i < CFHSI_PRIO_LAST; ++i)
                skb_queue_head_init(&cfhsi->qhead[i]);
index c2dea4916e5d720bb29814153f302ec364fe4f61..76e1d3545105e8abb9e2ef644e03fab0d2f5b243 100644 (file)
@@ -428,7 +428,7 @@ static void caifdev_setup(struct net_device *dev)
        dev->flags = IFF_POINTOPOINT | IFF_NOARP;
        dev->mtu = CAIF_MAX_MTU;
        dev->priv_flags |= IFF_NO_QUEUE;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        skb_queue_head_init(&serdev->head);
        serdev->common.link_select = CAIF_LINK_LOW_LATENCY;
        serdev->common.use_frag = true;
index 3a529fbe539fb6ee098f0b85515a49bdc1b64d90..fc21afe852b9817a2bdd242fc371834c515213dd 100644 (file)
@@ -712,7 +712,7 @@ static void cfspi_setup(struct net_device *dev)
        dev->flags = IFF_NOARP | IFF_POINTOPOINT;
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->mtu = SPI_MAX_PAYLOAD_SIZE;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        skb_queue_head_init(&cfspi->qhead);
        skb_queue_head_init(&cfspi->chead);
        cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
index 6122768c86444ec5b9c5fa67d7a63aa2690ba2f5..1794ea0420b794e76c75fafdede7e1a73ca86868 100644 (file)
@@ -617,7 +617,7 @@ static void cfv_netdev_setup(struct net_device *netdev)
        netdev->tx_queue_len = 100;
        netdev->flags = IFF_POINTOPOINT | IFF_NOARP;
        netdev->mtu = CFV_DEF_MTU_SIZE;
-       netdev->destructor = free_netdev;
+       netdev->needs_free_netdev = true;
 }
 
 /* Create debugfs counters for the device */
index 611d16a7061de5cb45f5e7bf7903b45472657965..ae4ed03dc6420d2e8eb0c6c0267982ab6ca58780 100644 (file)
@@ -391,6 +391,9 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,
        can_update_state_error_stats(dev, new_state);
        priv->state = new_state;
 
+       if (!cf)
+               return;
+
        if (unlikely(new_state == CAN_STATE_BUS_OFF)) {
                cf->can_id |= CAN_ERR_BUSOFF;
                return;
index 0d57be5ea97bafb2e9a119d28429549a91b80012..85268be0c913df5f5dc595405ade48efbd8add0a 100644 (file)
@@ -489,7 +489,7 @@ int peak_canfd_handle_msgs_list(struct peak_canfd_priv *priv,
                                struct pucan_rx_msg *msg_list, int msg_count)
 {
        void *msg_ptr = msg_list;
-       int i, msg_size;
+       int i, msg_size = 0;
 
        for (i = 0; i < msg_count; i++) {
                msg_size = peak_canfd_handle_msg(priv, msg_ptr);
index eb7173713bbcb0c339ae6ccbf99fc8014fb17133..6a6e896e52fa09415ae72715602fd4713e28f899 100644 (file)
@@ -417,7 +417,7 @@ static int slc_open(struct net_device *dev)
 static void slc_free_netdev(struct net_device *dev)
 {
        int i = dev->base_addr;
-       free_netdev(dev);
+
        slcan_devs[i] = NULL;
 }
 
@@ -436,7 +436,8 @@ static const struct net_device_ops slc_netdev_ops = {
 static void slc_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &slc_netdev_ops;
-       dev->destructor         = slc_free_netdev;
+       dev->needs_free_netdev  = true;
+       dev->priv_destructor    = slc_free_netdev;
 
        dev->hard_header_len    = 0;
        dev->addr_len           = 0;
@@ -761,8 +762,6 @@ static void __exit slcan_exit(void)
                if (sl->tty) {
                        printk(KERN_ERR "%s: tty discipline still running\n",
                               dev->name);
-                       /* Intentionally leak the control block. */
-                       dev->destructor = NULL;
                }
 
                unregister_netdev(dev);
index eecee7f8dfb70763aa0e7c3f90f85ae66ff85385..afcc1312dbaf8f67bce640e17dbc20c06592dc45 100644 (file)
@@ -265,6 +265,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev)
                             sizeof(*dm),
                             1000);
 
+       kfree(dm);
+
        return rc;
 }
 
index 57913dbbae0a970f5f28051d10f064792d69333c..1ca76e03e965ce0b1185c3220a86cb306d89e3e5 100644 (file)
@@ -908,8 +908,6 @@ static int peak_usb_probe(struct usb_interface *intf,
        const struct peak_usb_adapter *peak_usb_adapter = NULL;
        int i, err = -ENOMEM;
 
-       usb_dev = interface_to_usbdev(intf);
-
        /* get corresponding PCAN-USB adapter */
        for (i = 0; i < ARRAY_SIZE(peak_usb_adapters_list); i++)
                if (peak_usb_adapters_list[i]->device_id == usb_id_product) {
@@ -920,7 +918,7 @@ static int peak_usb_probe(struct usb_interface *intf,
        if (!peak_usb_adapter) {
                /* should never come except device_id bad usage in this file */
                pr_err("%s: didn't find device id. 0x%x in devices list\n",
-                       PCAN_USB_DRIVER_NAME, usb_dev->descriptor.idProduct);
+                       PCAN_USB_DRIVER_NAME, usb_id_product);
                return -ENODEV;
        }
 
index facca33d53e9fd24b996dc6dfd38c925b8128fdb..a8cb33264ff1ef32e9f9d44955e07f768f1cc543 100644 (file)
@@ -152,7 +152,7 @@ static const struct net_device_ops vcan_netdev_ops = {
 static void vcan_setup(struct net_device *dev)
 {
        dev->type               = ARPHRD_CAN;
-       dev->mtu                = CAN_MTU;
+       dev->mtu                = CANFD_MTU;
        dev->hard_header_len    = 0;
        dev->addr_len           = 0;
        dev->tx_queue_len       = 0;
@@ -163,7 +163,7 @@ static void vcan_setup(struct net_device *dev)
                dev->flags |= IFF_ECHO;
 
        dev->netdev_ops         = &vcan_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 }
 
 static struct rtnl_link_ops vcan_link_ops __read_mostly = {
index 7fbb2479568160b3b57fedb187429618937d2248..cfe889e8f1723823d5a3b9db71e9ba438624a9a2 100644 (file)
@@ -150,13 +150,13 @@ static const struct net_device_ops vxcan_netdev_ops = {
 static void vxcan_setup(struct net_device *dev)
 {
        dev->type               = ARPHRD_CAN;
-       dev->mtu                = CAN_MTU;
+       dev->mtu                = CANFD_MTU;
        dev->hard_header_len    = 0;
        dev->addr_len           = 0;
        dev->tx_queue_len       = 0;
        dev->flags              = (IFF_NOARP|IFF_ECHO);
        dev->netdev_ops         = &vxcan_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 }
 
 /* forward declaration for rtnl_create_link() */
index 19581d783d8ec7dc9ed9e5fd5a2891e8f2d22135..d034d8cd7d22dcde187f0becb24afd45480271f3 100644 (file)
@@ -849,6 +849,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
                mv88e6xxx_g1_stats_read(chip, reg, &low);
                if (s->sizeof_stat == 8)
                        mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
+               break;
+       default:
+               return UINT64_MAX;
        }
        value = (((u64)high) << 16) | low;
        return value;
index 96046bb12ca17333530f237fddb46438c3298dea..14c0be98e0a4d449aa4122c2db6e9ef6af007c84 100644 (file)
@@ -114,13 +114,13 @@ static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
        return -EOPNOTSUPP;
 }
 
-int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip, int src_dev,
-                          int src_port, u16 data)
+static inline int mv88e6xxx_g2_pvt_write(struct mv88e6xxx_chip *chip,
+                                        int src_dev, int src_port, u16 data)
 {
        return -EOPNOTSUPP;
 }
 
-int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
+static inline int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
 {
        return -EOPNOTSUPP;
 }
index 149244aac20aa765551b93ca25d78018b28f17f9..9905b52fe293c221b1ae9852d72016191ebbadda 100644 (file)
@@ -328,7 +328,6 @@ static void dummy_free_netdev(struct net_device *dev)
        struct dummy_priv *priv = netdev_priv(dev);
 
        kfree(priv->vfinfo);
-       free_netdev(dev);
 }
 
 static void dummy_setup(struct net_device *dev)
@@ -338,7 +337,8 @@ static void dummy_setup(struct net_device *dev)
        /* Initialize the device structure. */
        dev->netdev_ops = &dummy_netdev_ops;
        dev->ethtool_ops = &dummy_ethtool_ops;
-       dev->destructor = dummy_free_netdev;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = dummy_free_netdev;
 
        /* Fill in device structure with ethernet-generic values. */
        dev->flags |= IFF_NOARP;
index b0a3b85fc6f8d346f3a7d421b094b491d022dd12..db02bc2fb4b2d634ed454cedfcf57692e9b941c0 100644 (file)
@@ -748,13 +748,13 @@ static int ax_init_dev(struct net_device *dev)
 
        ret = ax_mii_init(dev);
        if (ret)
-               goto out_irq;
+               goto err_out;
 
        ax_NS8390_init(dev, 0);
 
        ret = register_netdev(dev);
        if (ret)
-               goto out_irq;
+               goto err_out;
 
        netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
                    ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
@@ -762,9 +762,6 @@ static int ax_init_dev(struct net_device *dev)
 
        return 0;
 
- out_irq:
-       /* cleanup irq */
-       free_irq(dev->irq, dev);
  err_out:
        return ret;
 }
index 08d11cede9c972596ee683c5d255fe143b76b9b8..f5b237e0bd60e2f0e2e6fd5a95d78515285629b1 100644 (file)
@@ -61,6 +61,8 @@
 
 #define ENA_MMIO_READ_TIMEOUT 0xFFFFFFFF
 
+#define ENA_REGS_ADMIN_INTR_MASK 1
+
 /*****************************************************************************/
 /*****************************************************************************/
 /*****************************************************************************/
@@ -232,11 +234,9 @@ static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queu
        tail_masked = admin_queue->sq.tail & queue_size_mask;
 
        /* In case of queue FULL */
-       cnt = admin_queue->sq.tail - admin_queue->sq.head;
+       cnt = atomic_read(&admin_queue->outstanding_cmds);
        if (cnt >= admin_queue->q_depth) {
-               pr_debug("admin queue is FULL (tail %d head %d depth: %d)\n",
-                        admin_queue->sq.tail, admin_queue->sq.head,
-                        admin_queue->q_depth);
+               pr_debug("admin queue is full.\n");
                admin_queue->stats.out_of_space++;
                return ERR_PTR(-ENOSPC);
        }
@@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status)
 static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx,
                                                     struct ena_com_admin_queue *admin_queue)
 {
-       unsigned long flags;
-       u32 start_time;
+       unsigned long flags, timeout;
        int ret;
 
-       start_time = ((u32)jiffies_to_usecs(jiffies));
+       timeout = jiffies + ADMIN_CMD_TIMEOUT_US;
+
+       while (1) {
+               spin_lock_irqsave(&admin_queue->q_lock, flags);
+               ena_com_handle_admin_completion(admin_queue);
+               spin_unlock_irqrestore(&admin_queue->q_lock, flags);
+
+               if (comp_ctx->status != ENA_CMD_SUBMITTED)
+                       break;
 
-       while (comp_ctx->status == ENA_CMD_SUBMITTED) {
-               if ((((u32)jiffies_to_usecs(jiffies)) - start_time) >
-                   ADMIN_CMD_TIMEOUT_US) {
+               if (time_is_before_jiffies(timeout)) {
                        pr_err("Wait for completion (polling) timeout\n");
                        /* ENA didn't have any completion */
                        spin_lock_irqsave(&admin_queue->q_lock, flags);
@@ -528,10 +533,6 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c
                        goto err;
                }
 
-               spin_lock_irqsave(&admin_queue->q_lock, flags);
-               ena_com_handle_admin_completion(admin_queue);
-               spin_unlock_irqrestore(&admin_queue->q_lock, flags);
-
                msleep(100);
        }
 
@@ -1455,6 +1456,12 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev)
 
 void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling)
 {
+       u32 mask_value = 0;
+
+       if (polling)
+               mask_value = ENA_REGS_ADMIN_INTR_MASK;
+
+       writel(mask_value, ena_dev->reg_bar + ENA_REGS_INTR_MASK_OFF);
        ena_dev->admin_queue.polling = polling;
 }
 
index 67b2338f8fb34100df983fc11727d4e661548b24..3ee55e2fd69465e12603890bce1b530be551a2d9 100644 (file)
@@ -80,7 +80,6 @@ static const struct ena_stats ena_stats_tx_strings[] = {
        ENA_STAT_TX_ENTRY(tx_poll),
        ENA_STAT_TX_ENTRY(doorbells),
        ENA_STAT_TX_ENTRY(prepare_ctx_err),
-       ENA_STAT_TX_ENTRY(missing_tx_comp),
        ENA_STAT_TX_ENTRY(bad_req_id),
 };
 
@@ -94,6 +93,7 @@ static const struct ena_stats ena_stats_rx_strings[] = {
        ENA_STAT_RX_ENTRY(dma_mapping_err),
        ENA_STAT_RX_ENTRY(bad_desc_num),
        ENA_STAT_RX_ENTRY(rx_copybreak_pkt),
+       ENA_STAT_RX_ENTRY(empty_rx_ring),
 };
 
 static const struct ena_stats ena_stats_ena_com_strings[] = {
index 7c1214d7885566ded4dfc05e85c2ee86b8d3c949..4f16ed38bcf3a267f84894177da1f89713a0eb3e 100644 (file)
@@ -190,6 +190,7 @@ static void ena_init_io_rings(struct ena_adapter *adapter)
                rxr->sgl_size = adapter->max_rx_sgl_size;
                rxr->smoothed_interval =
                        ena_com_get_nonadaptive_moderation_interval_rx(ena_dev);
+               rxr->empty_rx_queue = 0;
        }
 }
 
@@ -1078,6 +1079,26 @@ inline void ena_adjust_intr_moderation(struct ena_ring *rx_ring,
        rx_ring->per_napi_bytes = 0;
 }
 
+static inline void ena_unmask_interrupt(struct ena_ring *tx_ring,
+                                       struct ena_ring *rx_ring)
+{
+       struct ena_eth_io_intr_reg intr_reg;
+
+       /* Update intr register: rx intr delay,
+        * tx intr delay and interrupt unmask
+        */
+       ena_com_update_intr_reg(&intr_reg,
+                               rx_ring->smoothed_interval,
+                               tx_ring->smoothed_interval,
+                               true);
+
+       /* It is a shared MSI-X.
+        * Tx and Rx CQ have pointer to it.
+        * So we use one of them to reach the intr reg
+        */
+       ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+}
+
 static inline void ena_update_ring_numa_node(struct ena_ring *tx_ring,
                                             struct ena_ring *rx_ring)
 {
@@ -1108,7 +1129,6 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
 {
        struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);
        struct ena_ring *tx_ring, *rx_ring;
-       struct ena_eth_io_intr_reg intr_reg;
 
        u32 tx_work_done;
        u32 rx_work_done;
@@ -1149,22 +1169,9 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
                        if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev))
                                ena_adjust_intr_moderation(rx_ring, tx_ring);
 
-                       /* Update intr register: rx intr delay,
-                        * tx intr delay and interrupt unmask
-                        */
-                       ena_com_update_intr_reg(&intr_reg,
-                                               rx_ring->smoothed_interval,
-                                               tx_ring->smoothed_interval,
-                                               true);
-
-                       /* It is a shared MSI-X.
-                        * Tx and Rx CQ have pointer to it.
-                        * So we use one of them to reach the intr reg
-                        */
-                       ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+                       ena_unmask_interrupt(tx_ring, rx_ring);
                }
 
-
                ena_update_ring_numa_node(tx_ring, rx_ring);
 
                ret = rx_work_done;
@@ -1485,6 +1492,11 @@ static int ena_up_complete(struct ena_adapter *adapter)
 
        ena_napi_enable_all(adapter);
 
+       /* Enable completion queues interrupt */
+       for (i = 0; i < adapter->num_queues; i++)
+               ena_unmask_interrupt(&adapter->tx_ring[i],
+                                    &adapter->rx_ring[i]);
+
        /* schedule napi in case we had pending packets
         * from the last time we disable napi
         */
@@ -1532,6 +1544,7 @@ static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid)
                          "Failed to get TX queue handlers. TX queue num %d rc: %d\n",
                          qid, rc);
                ena_com_destroy_io_queue(ena_dev, ena_qid);
+               return rc;
        }
 
        ena_com_update_numa_node(tx_ring->ena_com_io_cq, ctx.numa_node);
@@ -1596,6 +1609,7 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid)
                          "Failed to get RX queue handlers. RX queue num %d rc: %d\n",
                          qid, rc);
                ena_com_destroy_io_queue(ena_dev, ena_qid);
+               return rc;
        }
 
        ena_com_update_numa_node(rx_ring->ena_com_io_cq, ctx.numa_node);
@@ -1981,6 +1995,7 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_info->tx_descs = nb_hw_desc;
        tx_info->last_jiffies = jiffies;
+       tx_info->print_once = 0;
 
        tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use,
                tx_ring->ring_size);
@@ -2550,13 +2565,44 @@ err:
                "Reset attempt failed. Can not reset the device\n");
 }
 
-static void check_for_missing_tx_completions(struct ena_adapter *adapter)
+static int check_missing_comp_in_queue(struct ena_adapter *adapter,
+                                      struct ena_ring *tx_ring)
 {
        struct ena_tx_buffer *tx_buf;
        unsigned long last_jiffies;
+       u32 missed_tx = 0;
+       int i;
+
+       for (i = 0; i < tx_ring->ring_size; i++) {
+               tx_buf = &tx_ring->tx_buffer_info[i];
+               last_jiffies = tx_buf->last_jiffies;
+               if (unlikely(last_jiffies &&
+                            time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) {
+                       if (!tx_buf->print_once)
+                               netif_notice(adapter, tx_err, adapter->netdev,
+                                            "Found a Tx that wasn't completed on time, qid %d, index %d.\n",
+                                            tx_ring->qid, i);
+
+                       tx_buf->print_once = 1;
+                       missed_tx++;
+
+                       if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) {
+                               netif_err(adapter, tx_err, adapter->netdev,
+                                         "The number of lost tx completions is above the threshold (%d > %d). Reset the device\n",
+                                         missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS);
+                               set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
+                               return -EIO;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void check_for_missing_tx_completions(struct ena_adapter *adapter)
+{
        struct ena_ring *tx_ring;
-       int i, j, budget;
-       u32 missed_tx;
+       int i, budget, rc;
 
        /* Make sure the driver doesn't turn the device in other process */
        smp_rmb();
@@ -2572,31 +2618,9 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter)
        for (i = adapter->last_monitored_tx_qid; i < adapter->num_queues; i++) {
                tx_ring = &adapter->tx_ring[i];
 
-               for (j = 0; j < tx_ring->ring_size; j++) {
-                       tx_buf = &tx_ring->tx_buffer_info[j];
-                       last_jiffies = tx_buf->last_jiffies;
-                       if (unlikely(last_jiffies && time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) {
-                               netif_notice(adapter, tx_err, adapter->netdev,
-                                            "Found a Tx that wasn't completed on time, qid %d, index %d.\n",
-                                            tx_ring->qid, j);
-
-                               u64_stats_update_begin(&tx_ring->syncp);
-                               missed_tx = tx_ring->tx_stats.missing_tx_comp++;
-                               u64_stats_update_end(&tx_ring->syncp);
-
-                               /* Clear last jiffies so the lost buffer won't
-                                * be counted twice.
-                                */
-                               tx_buf->last_jiffies = 0;
-
-                               if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) {
-                                       netif_err(adapter, tx_err, adapter->netdev,
-                                                 "The number of lost tx completion is above the threshold (%d > %d). Reset the device\n",
-                                                 missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS);
-                                       set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
-                               }
-                       }
-               }
+               rc = check_missing_comp_in_queue(adapter, tx_ring);
+               if (unlikely(rc))
+                       return;
 
                budget--;
                if (!budget)
@@ -2606,6 +2630,58 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter)
        adapter->last_monitored_tx_qid = i % adapter->num_queues;
 }
 
+/* trigger napi schedule after 2 consecutive detections */
+#define EMPTY_RX_REFILL 2
+/* For the rare case where the device runs out of Rx descriptors and the
+ * napi handler failed to refill new Rx descriptors (due to a lack of memory
+ * for example).
+ * This case will lead to a deadlock:
+ * The device won't send interrupts since all the new Rx packets will be dropped
+ * The napi handler won't allocate new Rx descriptors so the device will be
+ * able to send new packets.
+ *
+ * This scenario can happen when the kernel's vm.min_free_kbytes is too small.
+ * It is recommended to have at least 512MB, with a minimum of 128MB for
+ * constrained environment).
+ *
+ * When such a situation is detected - Reschedule napi
+ */
+static void check_for_empty_rx_ring(struct ena_adapter *adapter)
+{
+       struct ena_ring *rx_ring;
+       int i, refill_required;
+
+       if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags))
+               return;
+
+       if (test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))
+               return;
+
+       for (i = 0; i < adapter->num_queues; i++) {
+               rx_ring = &adapter->rx_ring[i];
+
+               refill_required =
+                       ena_com_sq_empty_space(rx_ring->ena_com_io_sq);
+               if (unlikely(refill_required == (rx_ring->ring_size - 1))) {
+                       rx_ring->empty_rx_queue++;
+
+                       if (rx_ring->empty_rx_queue >= EMPTY_RX_REFILL) {
+                               u64_stats_update_begin(&rx_ring->syncp);
+                               rx_ring->rx_stats.empty_rx_ring++;
+                               u64_stats_update_end(&rx_ring->syncp);
+
+                               netif_err(adapter, drv, adapter->netdev,
+                                         "trigger refill for ring %d\n", i);
+
+                               napi_schedule(rx_ring->napi);
+                               rx_ring->empty_rx_queue = 0;
+                       }
+               } else {
+                       rx_ring->empty_rx_queue = 0;
+               }
+       }
+}
+
 /* Check for keep alive expiration */
 static void check_for_missing_keep_alive(struct ena_adapter *adapter)
 {
@@ -2660,6 +2736,8 @@ static void ena_timer_service(unsigned long data)
 
        check_for_missing_tx_completions(adapter);
 
+       check_for_empty_rx_ring(adapter);
+
        if (debug_area)
                ena_dump_stats_to_buf(adapter, debug_area);
 
@@ -2840,6 +2918,11 @@ static void ena_release_bars(struct ena_com_dev *ena_dev, struct pci_dev *pdev)
 {
        int release_bars;
 
+       if (ena_dev->mem_bar)
+               devm_iounmap(&pdev->dev, ena_dev->mem_bar);
+
+       devm_iounmap(&pdev->dev, ena_dev->reg_bar);
+
        release_bars = pci_select_bars(pdev, IORESOURCE_MEM) & ENA_BAR_MASK;
        pci_release_selected_regions(pdev, release_bars);
 }
@@ -2927,8 +3010,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_free_ena_dev;
        }
 
-       ena_dev->reg_bar = ioremap(pci_resource_start(pdev, ENA_REG_BAR),
-                                  pci_resource_len(pdev, ENA_REG_BAR));
+       ena_dev->reg_bar = devm_ioremap(&pdev->dev,
+                                       pci_resource_start(pdev, ENA_REG_BAR),
+                                       pci_resource_len(pdev, ENA_REG_BAR));
        if (!ena_dev->reg_bar) {
                dev_err(&pdev->dev, "failed to remap regs bar\n");
                rc = -EFAULT;
@@ -2948,8 +3032,9 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        ena_set_push_mode(pdev, ena_dev, &get_feat_ctx);
 
        if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
-               ena_dev->mem_bar = ioremap_wc(pci_resource_start(pdev, ENA_MEM_BAR),
-                                             pci_resource_len(pdev, ENA_MEM_BAR));
+               ena_dev->mem_bar = devm_ioremap_wc(&pdev->dev,
+                                                  pci_resource_start(pdev, ENA_MEM_BAR),
+                                                  pci_resource_len(pdev, ENA_MEM_BAR));
                if (!ena_dev->mem_bar) {
                        rc = -EFAULT;
                        goto err_device_destroy;
index 0e22bce6239d0e06c73a366e0d98a2348a9b7fa9..a4d3d5e2106885b093424dc2ae3856c002653d06 100644 (file)
@@ -45,7 +45,7 @@
 
 #define DRV_MODULE_VER_MAJOR   1
 #define DRV_MODULE_VER_MINOR   1
-#define DRV_MODULE_VER_SUBMINOR 2
+#define DRV_MODULE_VER_SUBMINOR 7
 
 #define DRV_MODULE_NAME                "ena"
 #ifndef DRV_MODULE_VERSION
@@ -146,7 +146,18 @@ struct ena_tx_buffer {
        u32 tx_descs;
        /* num of buffers used by this skb */
        u32 num_of_bufs;
-       /* Save the last jiffies to detect missing tx packets */
+
+       /* Used for detect missing tx packets to limit the number of prints */
+       u32 print_once;
+       /* Save the last jiffies to detect missing tx packets
+        *
+        * sets to non zero value on ena_start_xmit and set to zero on
+        * napi and timer_Service_routine.
+        *
+        * while this value is not protected by lock,
+        * a given packet is not expected to be handled by ena_start_xmit
+        * and by napi/timer_service at the same time.
+        */
        unsigned long last_jiffies;
        struct ena_com_buf bufs[ENA_PKT_MAX_BUFS];
 } ____cacheline_aligned;
@@ -170,7 +181,6 @@ struct ena_stats_tx {
        u64 napi_comp;
        u64 tx_poll;
        u64 doorbells;
-       u64 missing_tx_comp;
        u64 bad_req_id;
 };
 
@@ -184,6 +194,7 @@ struct ena_stats_rx {
        u64 dma_mapping_err;
        u64 bad_desc_num;
        u64 rx_copybreak_pkt;
+       u64 empty_rx_ring;
 };
 
 struct ena_ring {
@@ -231,6 +242,7 @@ struct ena_ring {
                struct ena_stats_tx tx_stats;
                struct ena_stats_rx rx_stats;
        };
+       int empty_rx_queue;
 } ____cacheline_aligned;
 
 struct ena_stats_dev {
index b3bc87fe3764e397e4a9ce19518866cb97530771..0a98c369df2045ccbb9fbf7a55af848530a5f464 100644 (file)
@@ -324,7 +324,7 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
                              struct xgbe_ring *ring,
                              struct xgbe_ring_data *rdata)
 {
-       int order, ret;
+       int ret;
 
        if (!ring->rx_hdr_pa.pages) {
                ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0);
@@ -333,9 +333,8 @@ static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
        }
 
        if (!ring->rx_buf_pa.pages) {
-               order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0);
                ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC,
-                                      order);
+                                      PAGE_ALLOC_COSTLY_ORDER);
                if (ret)
                        return ret;
        }
index 4ee15ff06a448b72dbd6763427d9d02dfadad268..faeb4935ef3e3af5c998ef701e1e7cd2f5d739c8 100644 (file)
@@ -200,29 +200,18 @@ err_exit:
 static int hw_atl_a0_hw_offload_set(struct aq_hw_s *self,
                                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
-
        /* TX checksums offloads*/
        tpo_ipv4header_crc_offload_en_set(self, 1);
        tpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* RX checksums offloads*/
        rpo_ipv4header_crc_offload_en_set(self, 1);
        rpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* LSO offloads*/
        tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
-       if (err < 0)
-               goto err_exit;
-
-       err = aq_hw_err_from_flags(self);
 
-err_exit:
-       return err;
+       return aq_hw_err_from_flags(self);
 }
 
 static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self)
index 42150708191dbf67d91b33218a2a275e9b5fd45d..1bceb7358e5ca3a4455badf55bc091d3705dc89d 100644 (file)
@@ -200,25 +200,18 @@ err_exit:
 static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
                                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
        unsigned int i;
 
        /* TX checksums offloads*/
        tpo_ipv4header_crc_offload_en_set(self, 1);
        tpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* RX checksums offloads*/
        rpo_ipv4header_crc_offload_en_set(self, 1);
        rpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* LSO offloads*/
        tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
-       if (err < 0)
-               goto err_exit;
 
 /* LRO offloads */
        {
@@ -245,10 +238,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
 
                rpo_lro_en_set(self, aq_nic_cfg->is_lro ? 0xFFFFFFFFU : 0U);
        }
-       err = aq_hw_err_from_flags(self);
-
-err_exit:
-       return err;
+       return aq_hw_err_from_flags(self);
 }
 
 static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self)
index b8e3d88f08790a2e16ae3fc6b5edb8bedaaadf2f..a66aee51ab5b049c4e9f6367aebdd57cbbf5fc5a 100644 (file)
@@ -193,9 +193,6 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
                             struct aq_hw_caps_s *aq_hw_caps,
                             u32 *regs_buff);
 
-int hw_atl_utils_hw_get_settings(struct aq_hw_s *self,
-                                struct ethtool_cmd *cmd);
-
 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
                              unsigned int power_state);
 
index 63f2deec2a52994684fa7a58763f68502265542e..77a1c03255defa77f2c662650d41a1ffc68eb7bb 100644 (file)
@@ -1353,6 +1353,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) &&
                pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
                printk(KERN_ERR "atl2: No usable DMA configuration, aborting\n");
+               err = -EIO;
                goto err_dma;
        }
 
@@ -1366,10 +1367,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * pcibios_set_master to do the needed arch specific settings */
        pci_set_master(pdev);
 
-       err = -ENOMEM;
        netdev = alloc_etherdev(sizeof(struct atl2_adapter));
-       if (!netdev)
+       if (!netdev) {
+               err = -ENOMEM;
                goto err_alloc_etherdev;
+       }
 
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
@@ -1408,8 +1410,6 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto err_sw_init;
 
-       err = -EIO;
-
        netdev->hw_features = NETIF_F_HW_VLAN_CTAG_RX;
        netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX);
 
index 099b374c1b17bbd8e9cabe68cdc7cd991a258737..5274501428e4fb05850bada0d4ff3cd8a346f59f 100644 (file)
@@ -2026,9 +2026,12 @@ static int bcm_sysport_probe(struct platform_device *pdev)
        priv->num_rx_desc_words = params->num_rx_desc_words;
 
        priv->irq0 = platform_get_irq(pdev, 0);
-       if (!priv->is_lite)
+       if (!priv->is_lite) {
                priv->irq1 = platform_get_irq(pdev, 1);
-       priv->wol_irq = platform_get_irq(pdev, 2);
+               priv->wol_irq = platform_get_irq(pdev, 2);
+       } else {
+               priv->wol_irq = platform_get_irq(pdev, 1);
+       }
        if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) {
                dev_err(&pdev->dev, "invalid interrupts\n");
                ret = -EINVAL;
index eccb3d1b6abb748c14567d0efcdc28a405b64fb5..f619c4cac51f0f3a8a6631091c8e022de087a719 100644 (file)
@@ -1926,7 +1926,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb,
        }
 
        /* select a non-FCoE queue */
-       return fallback(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
+       return fallback(dev, skb) % (BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos);
 }
 
 void bnx2x_set_num_queues(struct bnx2x *bp)
@@ -3883,15 +3883,26 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                /* when transmitting in a vf, start bd must hold the ethertype
                 * for fw to enforce it
                 */
+               u16 vlan_tci = 0;
 #ifndef BNX2X_STOP_ON_ERROR
-               if (IS_VF(bp))
+               if (IS_VF(bp)) {
 #endif
-                       tx_start_bd->vlan_or_ethertype =
-                               cpu_to_le16(ntohs(eth->h_proto));
+                       /* Still need to consider inband vlan for enforced */
+                       if (__vlan_get_tag(skb, &vlan_tci)) {
+                               tx_start_bd->vlan_or_ethertype =
+                                       cpu_to_le16(ntohs(eth->h_proto));
+                       } else {
+                               tx_start_bd->bd_flags.as_bitfield |=
+                                       (X_ETH_INBAND_VLAN <<
+                                        ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT);
+                               tx_start_bd->vlan_or_ethertype =
+                                       cpu_to_le16(vlan_tci);
+                       }
 #ifndef BNX2X_STOP_ON_ERROR
-               else
+               } else {
                        /* used by FW for packet accounting */
                        tx_start_bd->vlan_or_ethertype = cpu_to_le16(pkt_prod);
+               }
 #endif
        }
 
index a851f95c307a3331a889972bc3c60273219f8a7b..349a46593abff6e4ea80ddd3a79301dac9cca517 100644 (file)
@@ -12729,7 +12729,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
        } else {
                /* If no mc addresses are required, flush the configuration */
                rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
-               if (rc)
+               if (rc < 0)
                        BNX2X_ERR("Failed to clear multicast configuration %d\n",
                                  rc);
        }
index bdfd53b46bc568286ac9debc70bb14563329040b..9ca994d0bab66eeec49c53275d5257350a5f4f8e 100644 (file)
@@ -901,6 +901,8 @@ static void bnx2x_vf_flr(struct bnx2x *bp, struct bnx2x_virtf *vf)
        /* release VF resources */
        bnx2x_vf_free_resc(bp, vf);
 
+       vf->malicious = false;
+
        /* re-open the mailbox */
        bnx2x_vf_enable_mbx(bp, vf->abs_vfid);
        return;
@@ -1822,9 +1824,11 @@ get_vf:
                   vf->abs_vfid, qidx);
                bnx2x_vf_handle_rss_update_eqe(bp, vf);
        case EVENT_RING_OPCODE_VF_FLR:
-       case EVENT_RING_OPCODE_MALICIOUS_VF:
                /* Do nothing for now */
                return 0;
+       case EVENT_RING_OPCODE_MALICIOUS_VF:
+               vf->malicious = true;
+               return 0;
        }
 
        return 0;
@@ -1905,6 +1909,13 @@ void bnx2x_iov_adjust_stats_req(struct bnx2x *bp)
                        continue;
                }
 
+               if (vf->malicious) {
+                       DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
+                              "vf %d malicious so no stats for it\n",
+                              vf->abs_vfid);
+                       continue;
+               }
+
                DP_AND((BNX2X_MSG_IOV | BNX2X_MSG_STATS),
                       "add addresses for vf %d\n", vf->abs_vfid);
                for_each_vfq(vf, j) {
@@ -3042,7 +3053,7 @@ void bnx2x_vf_pci_dealloc(struct bnx2x *bp)
 {
        BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->vf2pf_mbox_mapping,
                       sizeof(struct bnx2x_vf_mbx_msg));
-       BNX2X_PCI_FREE(bp->vf2pf_mbox, bp->pf2vf_bulletin_mapping,
+       BNX2X_PCI_FREE(bp->pf2vf_bulletin, bp->pf2vf_bulletin_mapping,
                       sizeof(union pf_vf_bulletin));
 }
 
index 888d0b6632e86f2f7ab7e2f9e605be87fa4c7061..53466f6cebabc4cd3089a0b45fdaa74e8bd9d905 100644 (file)
@@ -141,6 +141,7 @@ struct bnx2x_virtf {
 #define VF_RESET       3       /* VF FLR'd, pending cleanup */
 
        bool flr_clnup_stage;   /* true during flr cleanup */
+       bool malicious;         /* true if FW indicated so, until FLR */
 
        /* dma */
        dma_addr_t fw_stat_map;
index b56c54d68d5e3d6d8748a23b014ca4177c7d6dee..74e8e215524d72029a4a48dfc18897a9bf369f6b 100644 (file)
@@ -1301,10 +1301,11 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
                cp_cons = NEXT_CMP(cp_cons);
        }
 
-       if (unlikely(agg_bufs > MAX_SKB_FRAGS)) {
+       if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) {
                bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
-               netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
-                           agg_bufs, (int)MAX_SKB_FRAGS);
+               if (agg_bufs > MAX_SKB_FRAGS)
+                       netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
+                                   agg_bufs, (int)MAX_SKB_FRAGS);
                return NULL;
        }
 
@@ -1562,6 +1563,45 @@ next_rx_no_prod:
        return rc;
 }
 
+/* In netpoll mode, if we are using a combined completion ring, we need to
+ * discard the rx packets and recycle the buffers.
+ */
+static int bnxt_force_rx_discard(struct bnxt *bp, struct bnxt_napi *bnapi,
+                                u32 *raw_cons, u8 *event)
+{
+       struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+       u32 tmp_raw_cons = *raw_cons;
+       struct rx_cmp_ext *rxcmp1;
+       struct rx_cmp *rxcmp;
+       u16 cp_cons;
+       u8 cmp_type;
+
+       cp_cons = RING_CMP(tmp_raw_cons);
+       rxcmp = (struct rx_cmp *)
+                       &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+
+       tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons);
+       cp_cons = RING_CMP(tmp_raw_cons);
+       rxcmp1 = (struct rx_cmp_ext *)
+                       &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
+
+       if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
+               return -EBUSY;
+
+       cmp_type = RX_CMP_TYPE(rxcmp);
+       if (cmp_type == CMP_TYPE_RX_L2_CMP) {
+               rxcmp1->rx_cmp_cfa_code_errors_v2 |=
+                       cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR);
+       } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
+               struct rx_tpa_end_cmp_ext *tpa_end1;
+
+               tpa_end1 = (struct rx_tpa_end_cmp_ext *)rxcmp1;
+               tpa_end1->rx_tpa_end_cmp_errors_v2 |=
+                       cpu_to_le32(RX_TPA_END_CMP_ERRORS);
+       }
+       return bnxt_rx_pkt(bp, bnapi, raw_cons, event);
+}
+
 #define BNXT_GET_EVENT_PORT(data)      \
        ((data) &                       \
         ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
@@ -1744,7 +1784,11 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
                        if (unlikely(tx_pkts > bp->tx_wake_thresh))
                                rx_pkts = budget;
                } else if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
-                       rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event);
+                       if (likely(budget))
+                               rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event);
+                       else
+                               rc = bnxt_force_rx_discard(bp, bnapi, &raw_cons,
+                                                          &event);
                        if (likely(rc >= 0))
                                rx_pkts += rc;
                        else if (rc == -EBUSY)  /* partial completion */
@@ -6663,12 +6707,11 @@ static void bnxt_poll_controller(struct net_device *dev)
        struct bnxt *bp = netdev_priv(dev);
        int i;
 
-       for (i = 0; i < bp->cp_nr_rings; i++) {
-               struct bnxt_irq *irq = &bp->irq_tbl[i];
+       /* Only process tx rings/combined rings in netpoll mode. */
+       for (i = 0; i < bp->tx_nr_rings; i++) {
+               struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
 
-               disable_irq(irq->vector);
-               irq->handler(irq->vector, bp->bnapi[i]);
-               enable_irq(irq->vector);
+               napi_schedule(&txr->bnapi->napi);
        }
 }
 #endif
@@ -7630,8 +7673,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->min_mtu = ETH_ZLEN;
        dev->max_mtu = BNXT_MAX_MTU;
 
-       bnxt_dcb_init(bp);
-
 #ifdef CONFIG_BNXT_SRIOV
        init_waitqueue_head(&bp->sriov_cfg_wait);
 #endif
@@ -7669,6 +7710,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        bnxt_hwrm_func_qcfg(bp);
        bnxt_hwrm_port_led_qcaps(bp);
        bnxt_ethtool_init(bp);
+       bnxt_dcb_init(bp);
 
        bnxt_set_rx_skb_mode(bp, false);
        bnxt_set_tpa_flags(bp);
index 3ef42dbc63273f756bb7e52fe7da65ba1968eea4..d46a85041083c3708860b71cb661afe9123028d0 100644 (file)
@@ -374,12 +374,16 @@ struct rx_tpa_end_cmp_ext {
 
        __le32 rx_tpa_end_cmp_errors_v2;
        #define RX_TPA_END_CMP_V2                               (0x1 << 0)
-       #define RX_TPA_END_CMP_ERRORS                           (0x7fff << 1)
+       #define RX_TPA_END_CMP_ERRORS                           (0x3 << 1)
        #define RX_TPA_END_CMPL_ERRORS_SHIFT                     1
 
        u32 rx_tpa_end_cmp_start_opaque;
 };
 
+#define TPA_END_ERRORS(rx_tpa_end_ext)                                 \
+       ((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 &                   \
+        cpu_to_le32(RX_TPA_END_CMP_ERRORS))
+
 #define DB_IDX_MASK                                            0xffffff
 #define DB_IDX_VALID                                           (0x1 << 26)
 #define DB_IRQ_DIS                                             (0x1 << 27)
index 46de2f8ff024aad59341ecf5963ccbd9082dae9e..5c6dd0ce209f627e4c5bd74efa1ef581d1eb46ad 100644 (file)
@@ -553,8 +553,10 @@ static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
        if ((mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE))
                return 1;
 
-       if ((mode & DCB_CAP_DCBX_HOST) && BNXT_VF(bp))
-               return 1;
+       if (mode & DCB_CAP_DCBX_HOST) {
+               if (BNXT_VF(bp) || (bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
+                       return 1;
+       }
 
        if (mode == bp->dcbx_cap)
                return 0;
index 38a5c6764bb50f45124c212db37e11d2cc777076..53309f659951042ca6301c95e110910414031e70 100644 (file)
@@ -2171,9 +2171,10 @@ static int cxgb_up(struct adapter *adap)
 {
        int err;
 
+       mutex_lock(&uld_mutex);
        err = setup_sge_queues(adap);
        if (err)
-               goto out;
+               goto rel_lock;
        err = setup_rss(adap);
        if (err)
                goto freeq;
@@ -2196,23 +2197,28 @@ static int cxgb_up(struct adapter *adap)
                if (err)
                        goto irq_err;
        }
+
        enable_rx(adap);
        t4_sge_start(adap);
        t4_intr_enable(adap);
        adap->flags |= FULL_INIT_DONE;
+       mutex_unlock(&uld_mutex);
+
        notify_ulds(adap, CXGB4_STATE_UP);
 #if IS_ENABLED(CONFIG_IPV6)
        update_clip(adap);
 #endif
        /* Initialize hash mac addr list*/
        INIT_LIST_HEAD(&adap->mac_hlist);
- out:
        return err;
+
  irq_err:
        dev_err(adap->pdev_dev, "request_irq failed, err %d\n", err);
  freeq:
        t4_free_sge_resources(adap);
-       goto out;
+ rel_lock:
+       mutex_unlock(&uld_mutex);
+       return err;
 }
 
 static void cxgb_down(struct adapter *adapter)
@@ -2771,6 +2777,9 @@ void t4_fatal_err(struct adapter *adap)
 {
        int port;
 
+       if (pci_channel_offline(adap->pdev))
+               return;
+
        /* Disable the SGE since ULDs are going to free resources that
         * could be exposed to the adapter.  RDMA MWs for example...
         */
@@ -3882,9 +3891,10 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev,
        spin_lock(&adap->stats_lock);
        for_each_port(adap, i) {
                struct net_device *dev = adap->port[i];
-
-               netif_device_detach(dev);
-               netif_carrier_off(dev);
+               if (dev) {
+                       netif_device_detach(dev);
+                       netif_carrier_off(dev);
+               }
        }
        spin_unlock(&adap->stats_lock);
        disable_interrupts(adap);
@@ -3963,12 +3973,13 @@ static void eeh_resume(struct pci_dev *pdev)
        rtnl_lock();
        for_each_port(adap, i) {
                struct net_device *dev = adap->port[i];
-
-               if (netif_running(dev)) {
-                       link_start(dev);
-                       cxgb_set_rxmode(dev);
+               if (dev) {
+                       if (netif_running(dev)) {
+                               link_start(dev);
+                               cxgb_set_rxmode(dev);
+                       }
+                       netif_device_attach(dev);
                }
-               netif_device_attach(dev);
        }
        rtnl_unlock();
 }
@@ -4516,7 +4527,7 @@ static void dummy_setup(struct net_device *dev)
        /* Initialize the device structure. */
        dev->netdev_ops = &cxgb4_mgmt_netdev_ops;
        dev->ethtool_ops = &cxgb4_mgmt_ethtool_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
 }
 
 static int config_mgmt_dev(struct pci_dev *pdev)
index aded42b96f6d966ba7e814c0a89c738968a655b6..3a34aa629f7dd81a56e6b5c1c63bfdeb685c3f25 100644 (file)
@@ -4557,8 +4557,13 @@ void t4_intr_enable(struct adapter *adapter)
  */
 void t4_intr_disable(struct adapter *adapter)
 {
-       u32 whoami = t4_read_reg(adapter, PL_WHOAMI_A);
-       u32 pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
+       u32 whoami, pf;
+
+       if (pci_channel_offline(adapter->pdev))
+               return;
+
+       whoami = t4_read_reg(adapter, PL_WHOAMI_A);
+       pf = CHELSIO_CHIP_VERSION(adapter->params.chip) <= CHELSIO_T5 ?
                        SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
 
        t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE_A), 0);
index fa376444e57c5668fc4c1ff027e56fdcc11bb55a..f2d623a7aee04e21f1e4e52645d66788a59341ab 100644 (file)
@@ -37,7 +37,7 @@
 
 #define T4FW_VERSION_MAJOR 0x01
 #define T4FW_VERSION_MINOR 0x10
-#define T4FW_VERSION_MICRO 0x21
+#define T4FW_VERSION_MICRO 0x2D
 #define T4FW_VERSION_BUILD 0x00
 
 #define T4FW_MIN_VERSION_MAJOR 0x01
@@ -46,7 +46,7 @@
 
 #define T5FW_VERSION_MAJOR 0x01
 #define T5FW_VERSION_MINOR 0x10
-#define T5FW_VERSION_MICRO 0x21
+#define T5FW_VERSION_MICRO 0x2D
 #define T5FW_VERSION_BUILD 0x00
 
 #define T5FW_MIN_VERSION_MAJOR 0x00
@@ -55,7 +55,7 @@
 
 #define T6FW_VERSION_MAJOR 0x01
 #define T6FW_VERSION_MINOR 0x10
-#define T6FW_VERSION_MICRO 0x21
+#define T6FW_VERSION_MICRO 0x2D
 #define T6FW_VERSION_BUILD 0x00
 
 #define T6FW_MIN_VERSION_MAJOR 0x00
index f3a09ab559004b80106e957674cb0d6acbf3ea65..4eee18ce9be46b5e1dc35167b51af634a2070e60 100644 (file)
@@ -5078,9 +5078,11 @@ static netdev_features_t be_features_check(struct sk_buff *skb,
        struct be_adapter *adapter = netdev_priv(dev);
        u8 l4_hdr = 0;
 
-       /* The code below restricts offload features for some tunneled packets.
+       /* The code below restricts offload features for some tunneled and
+        * Q-in-Q packets.
         * Offload features for normal (non tunnel) packets are unchanged.
         */
+       features = vlan_features_check(skb, features);
        if (!skb->encapsulation ||
            !(adapter->flags & BE_FLAGS_VXLAN_OFFLOADS))
                return features;
index e863ba74d005d7f255931b336825df2abadd2fc8..8bb0db990c8fcf8258201f1af5fcf3fa9976b5f9 100644 (file)
@@ -739,6 +739,8 @@ static int ethoc_open(struct net_device *dev)
        if (ret)
                return ret;
 
+       napi_enable(&priv->napi);
+
        ethoc_init_ring(priv, dev->mem_start);
        ethoc_reset(priv);
 
@@ -754,7 +756,6 @@ static int ethoc_open(struct net_device *dev)
        priv->old_duplex = -1;
 
        phy_start(dev->phydev);
-       napi_enable(&priv->napi);
 
        if (netif_msg_ifup(priv)) {
                dev_info(&dev->dev, "I/O: %08lx Memory: %08lx-%08lx\n",
index 6ac336b546e6c226b1951c239a52b362052c04aa..1536356e2ea89ffaaf52974f1ed46b97ea861ae6 100644 (file)
@@ -1174,11 +1174,17 @@ static int ftmac100_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id ftmac100_of_ids[] = {
+       { .compatible = "andestech,atmac100" },
+       { }
+};
+
 static struct platform_driver ftmac100_driver = {
        .probe          = ftmac100_probe,
        .remove         = ftmac100_remove,
        .driver         = {
                .name   = DRV_NAME,
+               .of_match_table = ftmac100_of_ids
        },
 };
 
@@ -1202,3 +1208,4 @@ module_exit(ftmac100_exit);
 MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
 MODULE_DESCRIPTION("FTMAC100 driver");
 MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, ftmac100_of_ids);
index 9a520e4f0df9a0d47b75f71f01557414ba3d4eab..290ad0563320d6bd9f59212d0cd70b765336441d 100644 (file)
@@ -2647,7 +2647,7 @@ static int dpaa_eth_probe(struct platform_device *pdev)
        priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */
 
        /* device used for DMA mapping */
-       arch_setup_dma_ops(dev, 0, 0, NULL, false);
+       set_dma_ops(dev, get_dma_ops(&pdev->dev));
        err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
        if (err) {
                dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
index 56a563f90b0bf51d189dac8eb7da14791cc2b078..f7c8649fd28f695a1ff0519a85491bf85ec11f0b 100644 (file)
@@ -3192,7 +3192,7 @@ static int fec_reset_phy(struct platform_device *pdev)
 {
        int err, phy_reset;
        bool active_high = false;
-       int msec = 1;
+       int msec = 1, phy_post_delay = 0;
        struct device_node *np = pdev->dev.of_node;
 
        if (!np)
@@ -3209,6 +3209,11 @@ static int fec_reset_phy(struct platform_device *pdev)
        else if (!gpio_is_valid(phy_reset))
                return 0;
 
+       err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay);
+       /* valid reset duration should be less than 1s */
+       if (!err && phy_post_delay > 1000)
+               return -EINVAL;
+
        active_high = of_property_read_bool(np, "phy-reset-active-high");
 
        err = devm_gpio_request_one(&pdev->dev, phy_reset,
@@ -3226,6 +3231,15 @@ static int fec_reset_phy(struct platform_device *pdev)
 
        gpio_set_value_cansleep(phy_reset, !active_high);
 
+       if (!phy_post_delay)
+               return 0;
+
+       if (phy_post_delay > 20)
+               msleep(phy_post_delay);
+       else
+               usleep_range(phy_post_delay * 1000,
+                            phy_post_delay * 1000 + 1000);
+
        return 0;
 }
 #else /* CONFIG_OF */
index dc0850b3b517b9b02e3cd9a42cf98425a55d0df3..8870a9a798ca4e0245e6b05ac8d4ee2cf8499b46 100644 (file)
@@ -2,6 +2,7 @@ config FSL_FMAN
        tristate "FMan support"
        depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
        select GENERIC_ALLOCATOR
+       depends on HAS_DMA
        select PHYLIB
        default n
        help
index 0b31f8502adae2e86c292fb99437ee943c0794bf..6e67d22fd0d54f69e5ee3358717e7ed539fad952 100644 (file)
@@ -623,6 +623,8 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,
                goto no_mem;
        }
 
+       set_dma_ops(&pdev->dev, get_dma_ops(priv->dev));
+
        ret = platform_device_add_data(pdev, &data, sizeof(data));
        if (ret)
                goto err;
index 446c7b374ff5c36712d5813cf94b4e9b4ca0b01e..a10de1e9c157d2590eb19122f27fd5dda1a4816b 100644 (file)
@@ -381,7 +381,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
 {
        const struct of_device_id *id =
                of_match_device(fsl_pq_mdio_match, &pdev->dev);
-       const struct fsl_pq_mdio_data *data = id->data;
+       const struct fsl_pq_mdio_data *data;
        struct device_node *np = pdev->dev.of_node;
        struct resource res;
        struct device_node *tbi;
@@ -389,6 +389,13 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
        struct mii_bus *new_bus;
        int err;
 
+       if (!id) {
+               dev_err(&pdev->dev, "Failed to match device\n");
+               return -ENODEV;
+       }
+
+       data = id->data;
+
        dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible);
 
        new_bus = mdiobus_alloc_size(sizeof(*priv));
index b8fab149690f880394f0d973560aecca69d1171e..e95795b3c84160c6dd567c3a725d66f7886fe6fe 100644 (file)
@@ -288,9 +288,15 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
 
                /* Force 1000M Link, Default is 0x0200 */
                phy_write(phy_dev, 7, 0x20C);
-               phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
 
-               /* Enable PHY loop-back */
+               /* Powerup Fiber */
+               phy_write(phy_dev, HNS_PHY_PAGE_REG, 1);
+               val = phy_read(phy_dev, COPPER_CONTROL_REG);
+               val &= ~PHY_POWER_DOWN;
+               phy_write(phy_dev, COPPER_CONTROL_REG, val);
+
+               /* Enable Phy Loopback */
+               phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
                val = phy_read(phy_dev, COPPER_CONTROL_REG);
                val |= PHY_LOOP_BACK;
                val &= ~PHY_POWER_DOWN;
@@ -299,6 +305,12 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
                phy_write(phy_dev, HNS_PHY_PAGE_REG, 0xFA);
                phy_write(phy_dev, 1, 0x400);
                phy_write(phy_dev, 7, 0x200);
+
+               phy_write(phy_dev, HNS_PHY_PAGE_REG, 1);
+               val = phy_read(phy_dev, COPPER_CONTROL_REG);
+               val |= PHY_POWER_DOWN;
+               phy_write(phy_dev, COPPER_CONTROL_REG, val);
+
                phy_write(phy_dev, HNS_PHY_PAGE_REG, 0);
                phy_write(phy_dev, 9, 0xF00);
 
index 508923f39ccfe0cbc39ed23305af46860eef32c9..259e69a52ec52acde37849b9858c9953029679af 100644 (file)
@@ -343,6 +343,7 @@ static int emac_reset(struct emac_instance *dev)
 {
        struct emac_regs __iomem *p = dev->emacp;
        int n = 20;
+       bool __maybe_unused try_internal_clock = false;
 
        DBG(dev, "reset" NL);
 
@@ -355,6 +356,7 @@ static int emac_reset(struct emac_instance *dev)
        }
 
 #ifdef CONFIG_PPC_DCR_NATIVE
+do_retry:
        /*
         * PPC460EX/GT Embedded Processor Advanced User's Manual
         * section 28.10.1 Mode Register 0 (EMACx_MR0) states:
@@ -362,10 +364,19 @@ static int emac_reset(struct emac_instance *dev)
         * of the EMAC. If none is present, select the internal clock
         * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1).
         * After a soft reset, select the external clock.
+        *
+        * The AR8035-A PHY Meraki MR24 does not provide a TX Clk if the
+        * ethernet cable is not attached. This causes the reset to timeout
+        * and the PHY detection code in emac_init_phy() is unable to
+        * communicate and detect the AR8035-A PHY. As a result, the emac
+        * driver bails out early and the user has no ethernet.
+        * In order to stay compatible with existing configurations, the
+        * driver will temporarily switch to the internal clock, after
+        * the first reset fails.
         */
        if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
-               if (dev->phy_address == 0xffffffff &&
-                   dev->phy_map == 0xffffffff) {
+               if (try_internal_clock || (dev->phy_address == 0xffffffff &&
+                                          dev->phy_map == 0xffffffff)) {
                        /* No PHY: select internal loop clock before reset */
                        dcri_clrset(SDR0, SDR0_ETH_CFG,
                                    0, SDR0_ETH_CFG_ECS << dev->cell_index);
@@ -383,8 +394,15 @@ static int emac_reset(struct emac_instance *dev)
 
 #ifdef CONFIG_PPC_DCR_NATIVE
        if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) {
-               if (dev->phy_address == 0xffffffff &&
-                   dev->phy_map == 0xffffffff) {
+               if (!n && !try_internal_clock) {
+                       /* first attempt has timed out. */
+                       n = 20;
+                       try_internal_clock = true;
+                       goto do_retry;
+               }
+
+               if (try_internal_clock || (dev->phy_address == 0xffffffff &&
+                                          dev->phy_map == 0xffffffff)) {
                        /* No PHY: restore external clock source after reset */
                        dcri_clrset(SDR0, SDR0_ETH_CFG,
                                    SDR0_ETH_CFG_ECS << dev->cell_index, 0);
@@ -2460,20 +2478,24 @@ static int emac_mii_bus_reset(struct mii_bus *bus)
        return emac_reset(dev);
 }
 
+static int emac_mdio_phy_start_aneg(struct mii_phy *phy,
+                                   struct phy_device *phy_dev)
+{
+       phy_dev->autoneg = phy->autoneg;
+       phy_dev->speed = phy->speed;
+       phy_dev->duplex = phy->duplex;
+       phy_dev->advertising = phy->advertising;
+       return phy_start_aneg(phy_dev);
+}
+
 static int emac_mdio_setup_aneg(struct mii_phy *phy, u32 advertise)
 {
        struct net_device *ndev = phy->dev;
        struct emac_instance *dev = netdev_priv(ndev);
 
-       dev->phy.autoneg = AUTONEG_ENABLE;
-       dev->phy.speed = SPEED_1000;
-       dev->phy.duplex = DUPLEX_FULL;
-       dev->phy.advertising = advertise;
        phy->autoneg = AUTONEG_ENABLE;
-       phy->speed = dev->phy.speed;
-       phy->duplex = dev->phy.duplex;
        phy->advertising = advertise;
-       return phy_start_aneg(dev->phy_dev);
+       return emac_mdio_phy_start_aneg(phy, dev->phy_dev);
 }
 
 static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)
@@ -2481,13 +2503,10 @@ static int emac_mdio_setup_forced(struct mii_phy *phy, int speed, int fd)
        struct net_device *ndev = phy->dev;
        struct emac_instance *dev = netdev_priv(ndev);
 
-       dev->phy.autoneg =  AUTONEG_DISABLE;
-       dev->phy.speed = speed;
-       dev->phy.duplex = fd;
        phy->autoneg = AUTONEG_DISABLE;
        phy->speed = speed;
        phy->duplex = fd;
-       return phy_start_aneg(dev->phy_dev);
+       return emac_mdio_phy_start_aneg(phy, dev->phy_dev);
 }
 
 static int emac_mdio_poll_link(struct mii_phy *phy)
@@ -2509,16 +2528,17 @@ static int emac_mdio_read_link(struct mii_phy *phy)
 {
        struct net_device *ndev = phy->dev;
        struct emac_instance *dev = netdev_priv(ndev);
+       struct phy_device *phy_dev = dev->phy_dev;
        int res;
 
-       res = phy_read_status(dev->phy_dev);
+       res = phy_read_status(phy_dev);
        if (res)
                return res;
 
-       dev->phy.speed = phy->speed;
-       dev->phy.duplex = phy->duplex;
-       dev->phy.pause = phy->pause;
-       dev->phy.asym_pause = phy->asym_pause;
+       phy->speed = phy_dev->speed;
+       phy->duplex = phy_dev->duplex;
+       phy->pause = phy_dev->pause;
+       phy->asym_pause = phy_dev->asym_pause;
        return 0;
 }
 
@@ -2528,13 +2548,6 @@ static int emac_mdio_init_phy(struct mii_phy *phy)
        struct emac_instance *dev = netdev_priv(ndev);
 
        phy_start(dev->phy_dev);
-       dev->phy.autoneg = phy->autoneg;
-       dev->phy.speed = phy->speed;
-       dev->phy.duplex = phy->duplex;
-       dev->phy.advertising = phy->advertising;
-       dev->phy.pause = phy->pause;
-       dev->phy.asym_pause = phy->asym_pause;
-
        return phy_init_hw(dev->phy_dev);
 }
 
index 4f2d329dba998308eeb2ddaed52733cb3059f605..c0fbeb387db46627bed908e8f4cb145ed0bcfe4b 100644 (file)
@@ -81,7 +81,7 @@
 static const char ibmvnic_driver_name[] = "ibmvnic";
 static const char ibmvnic_driver_string[] = "IBM System i/p Virtual NIC Driver";
 
-MODULE_AUTHOR("Santiago Leon <santi_leon@yahoo.com>");
+MODULE_AUTHOR("Santiago Leon");
 MODULE_DESCRIPTION("IBM System i/p Virtual NIC Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IBMVNIC_DRIVER_VERSION);
@@ -1468,6 +1468,11 @@ static void ibmvnic_netpoll_controller(struct net_device *dev)
 }
 #endif
 
+static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       return -EOPNOTSUPP;
+}
+
 static const struct net_device_ops ibmvnic_netdev_ops = {
        .ndo_open               = ibmvnic_open,
        .ndo_stop               = ibmvnic_close,
@@ -1479,6 +1484,7 @@ static const struct net_device_ops ibmvnic_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ibmvnic_netpoll_controller,
 #endif
+       .ndo_change_mtu         = ibmvnic_change_mtu,
 };
 
 /* ethtool functions */
index cdde3cc28fb59f16234fe5aaf501f569abb62dc4..44d9610f7a15d739c3b8b9312cd81bd9a8dc0ed0 100644 (file)
@@ -399,6 +399,7 @@ struct i40e_pf {
 #define I40E_FLAG_RX_CSUM_ENABLED              BIT_ULL(1)
 #define I40E_FLAG_MSI_ENABLED                  BIT_ULL(2)
 #define I40E_FLAG_MSIX_ENABLED                 BIT_ULL(3)
+#define I40E_FLAG_HW_ATR_EVICT_ENABLED         BIT_ULL(4)
 #define I40E_FLAG_RSS_ENABLED                  BIT_ULL(6)
 #define I40E_FLAG_VMDQ_ENABLED                 BIT_ULL(7)
 #define I40E_FLAG_IWARP_ENABLED                        BIT_ULL(10)
index 7a8eb486b9ea554421fc7f62929a973b9c6efad4..894c8e57ba004398c5a86981930504ace9027a29 100644 (file)
@@ -224,7 +224,7 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
        I40E_PRIV_FLAG("LinkPolling", I40E_FLAG_LINK_POLLING_ENABLED, 0),
        I40E_PRIV_FLAG("flow-director-atr", I40E_FLAG_FD_ATR_ENABLED, 0),
        I40E_PRIV_FLAG("veb-stats", I40E_FLAG_VEB_STATS_ENABLED, 0),
-       I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_CAPABLE, 0),
+       I40E_PRIV_FLAG("hw-atr-eviction", I40E_FLAG_HW_ATR_EVICT_ENABLED, 0),
        I40E_PRIV_FLAG("legacy-rx", I40E_FLAG_LEGACY_RX, 0),
 };
 
@@ -4092,7 +4092,7 @@ flags_complete:
 
        /* Only allow ATR evict on hardware that is capable of handling it */
        if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
-               pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+               pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_ENABLED;
 
        if (changed_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT) {
                u16 sw_flags = 0, valid_flags = 0;
index d5c9c9e06ff57e21c1e28d09b9eea18af6e22f1a..a7a4b28b4144c62c35982dba952f7e77a5809f2e 100644 (file)
@@ -295,7 +295,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
  **/
 void i40e_service_event_schedule(struct i40e_pf *pf)
 {
-       if (!test_bit(__I40E_VSI_DOWN, pf->state) &&
+       if (!test_bit(__I40E_DOWN, pf->state) &&
            !test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
                queue_work(i40e_wq, &pf->service_task);
 }
@@ -3611,7 +3611,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
                 * this is not a performance path and napi_schedule()
                 * can deal with rescheduling.
                 */
-               if (!test_bit(__I40E_VSI_DOWN, pf->state))
+               if (!test_bit(__I40E_DOWN, pf->state))
                        napi_schedule_irqoff(&q_vector->napi);
        }
 
@@ -3687,7 +3687,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
 enable_intr:
        /* re-enable interrupt causes */
        wr32(hw, I40E_PFINT_ICR0_ENA, ena_mask);
-       if (!test_bit(__I40E_VSI_DOWN, pf->state)) {
+       if (!test_bit(__I40E_DOWN, pf->state)) {
                i40e_service_event_schedule(pf);
                i40e_irq_dynamic_enable_icr0(pf, false);
        }
@@ -6203,7 +6203,7 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
 {
 
        /* if interface is down do nothing */
-       if (test_bit(__I40E_VSI_DOWN, pf->state))
+       if (test_bit(__I40E_DOWN, pf->state))
                return;
 
        if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
@@ -6344,7 +6344,7 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf)
        int i;
 
        /* if interface is down do nothing */
-       if (test_bit(__I40E_VSI_DOWN, pf->state) ||
+       if (test_bit(__I40E_DOWN, pf->state) ||
            test_bit(__I40E_CONFIG_BUSY, pf->state))
                return;
 
@@ -6399,9 +6399,9 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
                reset_flags |= BIT(__I40E_GLOBAL_RESET_REQUESTED);
                clear_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state);
        }
-       if (test_bit(__I40E_VSI_DOWN_REQUESTED, pf->state)) {
-               reset_flags |= BIT(__I40E_VSI_DOWN_REQUESTED);
-               clear_bit(__I40E_VSI_DOWN_REQUESTED, pf->state);
+       if (test_bit(__I40E_DOWN_REQUESTED, pf->state)) {
+               reset_flags |= BIT(__I40E_DOWN_REQUESTED);
+               clear_bit(__I40E_DOWN_REQUESTED, pf->state);
        }
 
        /* If there's a recovery already waiting, it takes
@@ -6415,7 +6415,7 @@ static void i40e_reset_subtask(struct i40e_pf *pf)
 
        /* If we're already down or resetting, just bail */
        if (reset_flags &&
-           !test_bit(__I40E_VSI_DOWN, pf->state) &&
+           !test_bit(__I40E_DOWN, pf->state) &&
            !test_bit(__I40E_CONFIG_BUSY, pf->state)) {
                rtnl_lock();
                i40e_do_reset(pf, reset_flags, true);
@@ -7002,7 +7002,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
        u32 val;
        int v;
 
-       if (test_bit(__I40E_VSI_DOWN, pf->state))
+       if (test_bit(__I40E_DOWN, pf->state))
                goto clear_recovery;
        dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
 
@@ -8821,11 +8821,12 @@ static int i40e_sw_init(struct i40e_pf *pf)
                    (pf->hw.aq.api_min_ver > 4))) {
                /* Supported in FW API version higher than 1.4 */
                pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
-               pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
-       } else {
-               pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
        }
 
+       /* Enable HW ATR eviction if possible */
+       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
+               pf->flags |= I40E_FLAG_HW_ATR_EVICT_ENABLED;
+
        pf->eeprom_version = 0xDEAD;
        pf->lan_veb = I40E_NO_VEB;
        pf->lan_vsi = I40E_NO_VSI;
@@ -9767,7 +9768,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
                return -ENODEV;
        }
        if (vsi == pf->vsi[pf->lan_vsi] &&
-           !test_bit(__I40E_VSI_DOWN, pf->state)) {
+           !test_bit(__I40E_DOWN, pf->state)) {
                dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
                return -ENODEV;
        }
@@ -11003,7 +11004,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        pf->next_vsi = 0;
        pf->pdev = pdev;
-       set_bit(__I40E_VSI_DOWN, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
 
        hw = &pf->hw;
        hw->back = pf;
@@ -11293,7 +11294,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         * before setting up the misc vector or we get a race and the vector
         * ends up disabled forever.
         */
-       clear_bit(__I40E_VSI_DOWN, pf->state);
+       clear_bit(__I40E_DOWN, pf->state);
 
        /* In case of MSIX we are going to setup the misc vector right here
         * to handle admin queue events etc. In case of legacy and MSI
@@ -11448,7 +11449,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* Unwind what we've done if something failed in the setup */
 err_vsis:
-       set_bit(__I40E_VSI_DOWN, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
        i40e_clear_interrupt_scheme(pf);
        kfree(pf->vsi);
 err_switch_setup:
@@ -11500,7 +11501,7 @@ static void i40e_remove(struct pci_dev *pdev)
 
        /* no more scheduling of any task */
        set_bit(__I40E_SUSPENDED, pf->state);
-       set_bit(__I40E_VSI_DOWN, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
        if (pf->service_timer.data)
                del_timer_sync(&pf->service_timer);
        if (pf->service_task.func)
@@ -11740,7 +11741,7 @@ static void i40e_shutdown(struct pci_dev *pdev)
        struct i40e_hw *hw = &pf->hw;
 
        set_bit(__I40E_SUSPENDED, pf->state);
-       set_bit(__I40E_VSI_DOWN, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
        rtnl_lock();
        i40e_prep_for_reset(pf, true);
        rtnl_unlock();
@@ -11789,7 +11790,7 @@ static int i40e_suspend(struct pci_dev *pdev, pm_message_t state)
        int retval = 0;
 
        set_bit(__I40E_SUSPENDED, pf->state);
-       set_bit(__I40E_VSI_DOWN, pf->state);
+       set_bit(__I40E_DOWN, pf->state);
 
        if (pf->wol_en && (pf->flags & I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE))
                i40e_enable_mc_magic_wake(pf);
@@ -11841,7 +11842,7 @@ static int i40e_resume(struct pci_dev *pdev)
 
        /* handling the reset will rebuild the device state */
        if (test_and_clear_bit(__I40E_SUSPENDED, pf->state)) {
-               clear_bit(__I40E_VSI_DOWN, pf->state);
+               clear_bit(__I40E_DOWN, pf->state);
                rtnl_lock();
                i40e_reset_and_rebuild(pf, false, true);
                rtnl_unlock();
index 29321a6167a6675757e74ab4e3cd1a100cb423b0..77115c25d96fa88e8348bd0e891d03ca964b4d12 100644 (file)
@@ -1854,7 +1854,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
 #if (PAGE_SIZE < 8192)
        unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
 #else
-       unsigned int truesize = SKB_DATA_ALIGN(size);
+       unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+                               SKB_DATA_ALIGN(I40E_SKB_PAD + size);
 #endif
        struct sk_buff *skb;
 
@@ -2340,7 +2341,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
        /* Due to lack of space, no more new filters can be programmed */
        if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
                return;
-       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) {
+       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED) {
                /* HW ATR eviction will take care of removing filters on FIN
                 * and RST packets.
                 */
@@ -2402,7 +2403,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
                        I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
                        I40E_TXD_FLTR_QW1_CNTINDEX_MASK;
 
-       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
+       if (pf->flags & I40E_FLAG_HW_ATR_EVICT_ENABLED)
                dtype_cmd |= I40E_TXD_FLTR_QW1_ATR_MASK;
 
        fdir_desc->qindex_flex_ptype_vsi = cpu_to_le32(flex_ptype);
index 95c23fbaa2113214d9cd34ddfa176a7d1cd8d89e..0fb38ca78900312c59a6cd0f0373dc6cd87ecf84 100644 (file)
@@ -3017,10 +3017,12 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,
                                           VLAN_VID_MASK));
        }
 
+       spin_unlock_bh(&vsi->mac_filter_hash_lock);
        if (vlan_id || qos)
                ret = i40e_vsi_add_pvid(vsi, vlanprio);
        else
                i40e_vsi_remove_pvid(vsi);
+       spin_lock_bh(&vsi->mac_filter_hash_lock);
 
        if (vlan_id) {
                dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
index dfe241a12ad0756d10a77b954486d2194a31c5ca..12b02e5305038d55fcee5d2109b4ab534a09b1bb 100644 (file)
@@ -1190,7 +1190,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
 #if (PAGE_SIZE < 8192)
        unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
 #else
-       unsigned int truesize = SKB_DATA_ALIGN(size);
+       unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
+                               SKB_DATA_ALIGN(I40E_SKB_PAD + size);
 #endif
        struct sk_buff *skb;
 
index 9b875d776b296d165c4ae3a994bd527a8dafb698..33c901622ed5b94aef2a0335aa4576962072d34c 100644 (file)
@@ -3719,7 +3719,7 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,
                                    dma_addr_t *dma_addr,
                                    phys_addr_t *phys_addr)
 {
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
 
        *dma_addr = mvpp2_percpu_read(priv, cpu,
                                      MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
@@ -3740,6 +3740,8 @@ static void mvpp2_bm_bufs_get_addrs(struct device *dev, struct mvpp2 *priv,
                if (sizeof(phys_addr_t) == 8)
                        *phys_addr |= (u64)phys_addr_highbits << 32;
        }
+
+       put_cpu();
 }
 
 /* Free all buffers from the pool */
@@ -3920,18 +3922,12 @@ static inline u32 mvpp2_bm_cookie_pool_set(u32 cookie, int pool)
        return bm;
 }
 
-/* Get pool number from a BM cookie */
-static inline int mvpp2_bm_cookie_pool_get(unsigned long cookie)
-{
-       return (cookie >> MVPP2_BM_COOKIE_POOL_OFFS) & 0xFF;
-}
-
 /* Release buffer to BM */
 static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
                                     dma_addr_t buf_dma_addr,
                                     phys_addr_t buf_phys_addr)
 {
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
 
        if (port->priv->hw_version == MVPP22) {
                u32 val = 0;
@@ -3958,15 +3954,15 @@ static inline void mvpp2_bm_pool_put(struct mvpp2_port *port, int pool,
                           MVPP2_BM_VIRT_RLS_REG, buf_phys_addr);
        mvpp2_percpu_write(port->priv, cpu,
                           MVPP2_BM_PHY_RLS_REG(pool), buf_dma_addr);
+
+       put_cpu();
 }
 
 /* Refill BM pool */
-static void mvpp2_pool_refill(struct mvpp2_port *port, u32 bm,
+static void mvpp2_pool_refill(struct mvpp2_port *port, int pool,
                              dma_addr_t dma_addr,
                              phys_addr_t phys_addr)
 {
-       int pool = mvpp2_bm_cookie_pool_get(bm);
-
        mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
 }
 
@@ -4186,8 +4182,6 @@ static void mvpp22_port_mii_set(struct mvpp2_port *port)
 {
        u32 val;
 
-       return;
-
        /* Only GOP port 0 has an XLG MAC */
        if (port->gop_id == 0) {
                val = readl(port->base + MVPP22_XLG_CTRL3_REG);
@@ -4515,21 +4509,6 @@ static void mvpp2_rxq_offset_set(struct mvpp2_port *port,
        mvpp2_write(port->priv, MVPP2_RXQ_CONFIG_REG(prxq), val);
 }
 
-/* Obtain BM cookie information from descriptor */
-static u32 mvpp2_bm_cookie_build(struct mvpp2_port *port,
-                                struct mvpp2_rx_desc *rx_desc)
-{
-       int cpu = smp_processor_id();
-       int pool;
-
-       pool = (mvpp2_rxdesc_status_get(port, rx_desc) &
-               MVPP2_RXD_BM_POOL_ID_MASK) >>
-               MVPP2_RXD_BM_POOL_ID_OFFS;
-
-       return ((pool & 0xFF) << MVPP2_BM_COOKIE_POOL_OFFS) |
-              ((cpu & 0xFF) << MVPP2_BM_COOKIE_CPU_OFFS);
-}
-
 /* Tx descriptors helper methods */
 
 /* Get pointer to next Tx descriptor to be processed (send) by HW */
@@ -4757,7 +4736,7 @@ static void mvpp2_txp_max_tx_size_set(struct mvpp2_port *port)
 static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
                                   struct mvpp2_rx_queue *rxq)
 {
-       int cpu = smp_processor_id();
+       int cpu = get_cpu();
 
        if (rxq->pkts_coal > MVPP2_OCCUPIED_THRESH_MASK)
                rxq->pkts_coal = MVPP2_OCCUPIED_THRESH_MASK;
@@ -4765,6 +4744,8 @@ static void mvpp2_rx_pkts_coal_set(struct mvpp2_port *port,
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_THRESH_REG,
                           rxq->pkts_coal);
+
+       put_cpu();
 }
 
 static u32 mvpp2_usec_to_cycles(u32 usec, unsigned long clk_hz)
@@ -4945,7 +4926,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
        mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
 
        /* Set Rx descriptors queue starting address - indirect access */
-       cpu = smp_processor_id();
+       cpu = get_cpu();
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);
        if (port->priv->hw_version == MVPP21)
                rxq_dma = rxq->descs_dma;
@@ -4954,6 +4935,7 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, rxq_dma);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_INDEX_REG, 0);
+       put_cpu();
 
        /* Set Offset */
        mvpp2_rxq_offset_set(port, rxq->id, NET_SKB_PAD);
@@ -4980,9 +4962,13 @@ static void mvpp2_rxq_drop_pkts(struct mvpp2_port *port,
 
        for (i = 0; i < rx_received; i++) {
                struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
-               u32 bm = mvpp2_bm_cookie_build(port, rx_desc);
+               u32 status = mvpp2_rxdesc_status_get(port, rx_desc);
+               int pool;
+
+               pool = (status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+                       MVPP2_RXD_BM_POOL_ID_OFFS;
 
-               mvpp2_pool_refill(port, bm,
+               mvpp2_pool_refill(port, pool,
                                  mvpp2_rxdesc_dma_addr_get(port, rx_desc),
                                  mvpp2_rxdesc_cookie_get(port, rx_desc));
        }
@@ -5012,10 +4998,11 @@ static void mvpp2_rxq_deinit(struct mvpp2_port *port,
         * free descriptor number
         */
        mvpp2_write(port->priv, MVPP2_RXQ_STATUS_REG(rxq->id), 0);
-       cpu = smp_processor_id();
+       cpu = get_cpu();
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_NUM_REG, rxq->id);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_ADDR_REG, 0);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_RXQ_DESC_SIZE_REG, 0);
+       put_cpu();
 }
 
 /* Create and initialize a Tx queue */
@@ -5038,7 +5025,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
        txq->last_desc = txq->size - 1;
 
        /* Set Tx descriptors queue starting address - indirect access */
-       cpu = smp_processor_id();
+       cpu = get_cpu();
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG,
                           txq->descs_dma);
@@ -5063,6 +5050,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG,
                           MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
                           MVPP2_PREF_BUF_THRESH(desc_per_txq / 2));
+       put_cpu();
 
        /* WRR / EJP configuration - indirect access */
        tx_port_num = mvpp2_egress_port(port);
@@ -5133,10 +5121,11 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
        mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0);
 
        /* Set Tx descriptors queue starting address and size */
-       cpu = smp_processor_id();
+       cpu = get_cpu();
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_ADDR_REG, 0);
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_DESC_SIZE_REG, 0);
+       put_cpu();
 }
 
 /* Cleanup Tx ports */
@@ -5146,7 +5135,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)
        int delay, pending, cpu;
        u32 val;
 
-       cpu = smp_processor_id();
+       cpu = get_cpu();
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_NUM_REG, txq->id);
        val = mvpp2_percpu_read(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG);
        val |= MVPP2_TXQ_DRAIN_EN_MASK;
@@ -5173,6 +5162,7 @@ static void mvpp2_txq_clean(struct mvpp2_port *port, struct mvpp2_tx_queue *txq)
 
        val &= ~MVPP2_TXQ_DRAIN_EN_MASK;
        mvpp2_percpu_write(port->priv, cpu, MVPP2_TXQ_PREF_BUF_REG, val);
+       put_cpu();
 
        for_each_present_cpu(cpu) {
                txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
@@ -5420,7 +5410,7 @@ static void mvpp2_rx_csum(struct mvpp2_port *port, u32 status,
 
 /* Reuse skb if possible, or allocate a new skb and add it to BM pool */
 static int mvpp2_rx_refill(struct mvpp2_port *port,
-                          struct mvpp2_bm_pool *bm_pool, u32 bm)
+                          struct mvpp2_bm_pool *bm_pool, int pool)
 {
        dma_addr_t dma_addr;
        phys_addr_t phys_addr;
@@ -5432,7 +5422,7 @@ static int mvpp2_rx_refill(struct mvpp2_port *port,
        if (!buf)
                return -ENOMEM;
 
-       mvpp2_pool_refill(port, bm, dma_addr, phys_addr);
+       mvpp2_pool_refill(port, pool, dma_addr, phys_addr);
 
        return 0;
 }
@@ -5490,7 +5480,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
                unsigned int frag_size;
                dma_addr_t dma_addr;
                phys_addr_t phys_addr;
-               u32 bm, rx_status;
+               u32 rx_status;
                int pool, rx_bytes, err;
                void *data;
 
@@ -5502,8 +5492,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
                phys_addr = mvpp2_rxdesc_cookie_get(port, rx_desc);
                data = (void *)phys_to_virt(phys_addr);
 
-               bm = mvpp2_bm_cookie_build(port, rx_desc);
-               pool = mvpp2_bm_cookie_pool_get(bm);
+               pool = (rx_status & MVPP2_RXD_BM_POOL_ID_MASK) >>
+                       MVPP2_RXD_BM_POOL_ID_OFFS;
                bm_pool = &port->priv->bm_pools[pool];
 
                /* In case of an error, release the requested buffer pointer
@@ -5516,7 +5506,7 @@ err_drop_frame:
                        dev->stats.rx_errors++;
                        mvpp2_rx_error(port, rx_desc);
                        /* Return the buffer to the pool */
-                       mvpp2_pool_refill(port, bm, dma_addr, phys_addr);
+                       mvpp2_pool_refill(port, pool, dma_addr, phys_addr);
                        continue;
                }
 
@@ -5531,7 +5521,7 @@ err_drop_frame:
                        goto err_drop_frame;
                }
 
-               err = mvpp2_rx_refill(port, bm_pool, bm);
+               err = mvpp2_rx_refill(port, bm_pool, pool);
                if (err) {
                        netdev_err(port->dev, "failed to refill BM pools\n");
                        goto err_drop_frame;
index ae5fdc2df65412afce4e72b8384c9c4b3302c56e..ffbcb27c05e55f43630a812249bab21609886dd9 100644 (file)
@@ -1562,11 +1562,6 @@ static int mlx4_en_flow_replace(struct net_device *dev,
                qpn = priv->drop_qp.qpn;
        else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {
                qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);
-               if (qpn < priv->rss_map.base_qpn ||
-                   qpn >= priv->rss_map.base_qpn + priv->rx_ring_num) {
-                       en_warn(priv, "rxnfc: QP (0x%x) doesn't exist\n", qpn);
-                       return -EINVAL;
-               }
        } else {
                if (cmd->fs.ring_cookie >= priv->rx_ring_num) {
                        en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n",
index 703205475524d689cd2762f2d2ce3abfd2b6ebcb..83aab1e4c8c8c76f73a598c5bdde51e185d9121a 100644 (file)
@@ -2862,12 +2862,10 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
        int port = 0;
 
        if (msi_x) {
-               int nreq = dev->caps.num_ports * num_online_cpus() + 1;
-
-               nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
-                            nreq);
-               if (nreq > MAX_MSIX)
-                       nreq = MAX_MSIX;
+               int nreq = min3(dev->caps.num_ports *
+                               (int)num_online_cpus() + 1,
+                               dev->caps.num_eqs - dev->caps.reserved_eqs,
+                               MAX_MSIX);
 
                entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
                if (!entries)
index 1a670b68155550fe9f61fb2bc2c7a3688391249c..0710b367746468f1d4faeb5b8a8f3266ca941674 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/etherdevice.h>
 
 #include <linux/mlx4/cmd.h>
+#include <linux/mlx4/qp.h>
 #include <linux/export.h>
 
 #include "mlx4.h"
@@ -985,16 +986,21 @@ int mlx4_flow_attach(struct mlx4_dev *dev,
        if (IS_ERR(mailbox))
                return PTR_ERR(mailbox);
 
+       if (!mlx4_qp_lookup(dev, rule->qpn)) {
+               mlx4_err_rule(dev, "QP doesn't exist\n", rule);
+               ret = -EINVAL;
+               goto out;
+       }
+
        trans_rule_ctrl_to_hw(rule, mailbox->buf);
 
        size += sizeof(struct mlx4_net_trans_rule_hw_ctrl);
 
        list_for_each_entry(cur, &rule->list, list) {
                ret = parse_trans_rule(dev, cur, mailbox->buf + size);
-               if (ret < 0) {
-                       mlx4_free_cmd_mailbox(dev, mailbox);
-                       return ret;
-               }
+               if (ret < 0)
+                       goto out;
+
                size += ret;
        }
 
@@ -1021,6 +1027,7 @@ int mlx4_flow_attach(struct mlx4_dev *dev,
                }
        }
 
+out:
        mlx4_free_cmd_mailbox(dev, mailbox);
 
        return ret;
index 2d6abd4662b143612769ef9b91783249bcd2ac8b..5a310d313e94d08d035c265e6b538c27dcf957c3 100644 (file)
@@ -384,6 +384,19 @@ static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
                __mlx4_qp_free_icm(dev, qpn);
 }
 
+struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
+{
+       struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table;
+       struct mlx4_qp *qp;
+
+       spin_lock(&qp_table->lock);
+
+       qp = __mlx4_qp_lookup(dev, qpn);
+
+       spin_unlock(&qp_table->lock);
+       return qp;
+}
+
 int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp, gfp_t gfp)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
@@ -471,6 +484,12 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
        }
 
        if (attr & MLX4_UPDATE_QP_QOS_VPORT) {
+               if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QOS_VPP)) {
+                       mlx4_warn(dev, "Granular QoS per VF is not enabled\n");
+                       err = -EOPNOTSUPP;
+                       goto out;
+               }
+
                qp_mask |= 1ULL << MLX4_UPD_QP_MASK_QOS_VPP;
                cmd->qp_context.qos_vport = params->qos_vport;
        }
index 07516545474f3ac76e750aaa4af2532b6ac81207..812783865205715e8e88ad66d4ccbfe7172ec6e5 100644 (file)
@@ -5255,6 +5255,13 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
        mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
 }
 
+static void update_qos_vpp(struct mlx4_update_qp_context *ctx,
+                          struct mlx4_vf_immed_vlan_work *work)
+{
+       ctx->qp_mask |= cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_QOS_VPP);
+       ctx->qp_context.qos_vport = work->qos_vport;
+}
+
 void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
 {
        struct mlx4_vf_immed_vlan_work *work =
@@ -5369,11 +5376,10 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
                                        qp->sched_queue & 0xC7;
                                upd_context->qp_context.pri_path.sched_queue |=
                                        ((work->qos & 0x7) << 3);
-                               upd_context->qp_mask |=
-                                       cpu_to_be64(1ULL <<
-                                                   MLX4_UPD_QP_MASK_QOS_VPP);
-                               upd_context->qp_context.qos_vport =
-                                       work->qos_vport;
+
+                               if (dev->caps.flags2 &
+                                   MLX4_DEV_CAP_FLAG2_QOS_VPP)
+                                       update_qos_vpp(upd_context, work);
                        }
 
                        err = mlx4_cmd(dev, mailbox->dma,
index fc52d742b7f7a52885bc78cfcb23acbd738bc552..27251a78075ccba1c4e151b54387aa987dc17210 100644 (file)
@@ -13,7 +13,7 @@ config MLX5_CORE
 
 config MLX5_CORE_EN
        bool "Mellanox Technologies ConnectX-4 Ethernet support"
-       depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
+       depends on NETDEVICES && ETHERNET && INET && PCI && MLX5_CORE
        depends on IPV6=y || IPV6=n || MLX5_CORE=m
        imply PTP_1588_CLOCK
        default n
index 5bdaf3d545b2fc656a318d5b562f940e14ecd9d9..10d282841f5be16c0957c72111c68baf6a452ca9 100644 (file)
@@ -774,7 +774,7 @@ static void cb_timeout_handler(struct work_struct *work)
        mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
                       mlx5_command_str(msg_to_opcode(ent->in)),
                       msg_to_opcode(ent->in));
-       mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+       mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
 }
 
 static void cmd_work_handler(struct work_struct *work)
@@ -804,6 +804,7 @@ static void cmd_work_handler(struct work_struct *work)
        }
 
        cmd->ent_arr[ent->idx] = ent;
+       set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
        lay = get_inst(cmd, ent->idx);
        ent->lay = lay;
        memset(lay, 0, sizeof(*lay));
@@ -825,6 +826,20 @@ static void cmd_work_handler(struct work_struct *work)
        if (ent->callback)
                schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
 
+       /* Skip sending command to fw if internal error */
+       if (pci_channel_offline(dev->pdev) ||
+           dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+               u8 status = 0;
+               u32 drv_synd;
+
+               ent->ret = mlx5_internal_err_ret_value(dev, msg_to_opcode(ent->in), &drv_synd, &status);
+               MLX5_SET(mbox_out, ent->out, status, status);
+               MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
+
+               mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+               return;
+       }
+
        /* ring doorbell after the descriptor is valid */
        mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
        wmb();
@@ -835,7 +850,7 @@ static void cmd_work_handler(struct work_struct *work)
                poll_timeout(ent);
                /* make sure we read the descriptor after ownership is SW */
                rmb();
-               mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+               mlx5_cmd_comp_handler(dev, 1UL << ent->idx, (ent->ret == -ETIMEDOUT));
        }
 }
 
@@ -879,7 +894,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
                wait_for_completion(&ent->done);
        } else if (!wait_for_completion_timeout(&ent->done, timeout)) {
                ent->ret = -ETIMEDOUT;
-               mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+               mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
        }
 
        err = ent->ret;
@@ -1375,7 +1390,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
        }
 }
 
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced)
 {
        struct mlx5_cmd *cmd = &dev->cmd;
        struct mlx5_cmd_work_ent *ent;
@@ -1395,6 +1410,19 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
                        struct semaphore *sem;
 
                        ent = cmd->ent_arr[i];
+
+                       /* if we already completed the command, ignore it */
+                       if (!test_and_clear_bit(MLX5_CMD_ENT_STATE_PENDING_COMP,
+                                               &ent->state)) {
+                               /* only real completion can free the cmd slot */
+                               if (!forced) {
+                                       mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n",
+                                                     ent->idx);
+                                       free_ent(cmd, ent->idx);
+                               }
+                               continue;
+                       }
+
                        if (ent->callback)
                                cancel_delayed_work(&ent->cb_timeout_work);
                        if (ent->page_queue)
@@ -1417,7 +1445,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec)
                                mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",
                                              ent->ret, deliv_status_to_str(ent->status), ent->status);
                        }
-                       free_ent(cmd, ent->idx);
+
+                       /* only real completion will free the entry slot */
+                       if (!forced)
+                               free_ent(cmd, ent->idx);
 
                        if (ent->callback) {
                                ds = ent->ts2 - ent->ts1;
index 0099a3e397bcf8758388b44e0e44888b35468920..944fc17424642189d82b5540aaa3751e7ea2c9e2 100644 (file)
@@ -458,13 +458,15 @@ struct mlx5e_mpw_info {
 
 struct mlx5e_rx_am_stats {
        int ppms; /* packets per msec */
+       int bpms; /* bytes per msec */
        int epms; /* events per msec */
 };
 
 struct mlx5e_rx_am_sample {
-       ktime_t         time;
-       unsigned int    pkt_ctr;
-       u16             event_ctr;
+       ktime_t time;
+       u32     pkt_ctr;
+       u32     byte_ctr;
+       u16     event_ctr;
 };
 
 struct mlx5e_rx_am { /* Adaptive Moderation */
@@ -1003,7 +1005,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv);
 void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv);
 void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt);
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn);
+int mlx5e_create_ttc_table(struct mlx5e_priv *priv);
 void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);
 
 int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
index ce7b09d72ff68b1850f6df3845f2fd9ae7f57bbd..16486dff14933807d47b2a99f970ffbe3996b3a2 100644 (file)
@@ -794,7 +794,6 @@ static void get_supported(u32 eth_proto_cap,
        ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
        ptys2ethtool_supported_link(supported, eth_proto_cap);
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
-       ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Asym_Pause);
 }
 
 static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
@@ -804,7 +803,7 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
        unsigned long *advertising = link_ksettings->link_modes.advertising;
 
        ptys2ethtool_adver_link(advertising, eth_proto_cap);
-       if (tx_pause)
+       if (rx_pause)
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
        if (tx_pause ^ rx_pause)
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
@@ -849,6 +848,8 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        struct mlx5e_priv *priv    = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
        u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
+       u32 rx_pause = 0;
+       u32 tx_pause = 0;
        u32 eth_proto_cap;
        u32 eth_proto_admin;
        u32 eth_proto_lp;
@@ -871,11 +872,13 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
        an_status        = MLX5_GET(ptys_reg, out, an_status);
 
+       mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
+
        ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
        ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
 
        get_supported(eth_proto_cap, link_ksettings);
-       get_advertising(eth_proto_admin, 0, 0, link_ksettings);
+       get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings);
        get_speed_duplex(netdev, eth_proto_oper, link_ksettings);
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
@@ -1239,11 +1242,11 @@ static int mlx5e_get_ts_info(struct net_device *dev,
                                 SOF_TIMESTAMPING_RX_HARDWARE |
                                 SOF_TIMESTAMPING_RAW_HARDWARE;
 
-       info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) |
-                        (BIT(1) << HWTSTAMP_TX_ON);
+       info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+                        BIT(HWTSTAMP_TX_ON);
 
-       info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) |
-                          (BIT(1) << HWTSTAMP_FILTER_ALL);
+       info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+                          BIT(HWTSTAMP_FILTER_ALL);
 
        return 0;
 }
index 576d6787b484b6387c55a172a65fa838b50e198a..53ed58320a24aef89e40230c67728ea01bd086ac 100644 (file)
@@ -800,7 +800,7 @@ void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
        mlx5e_destroy_flow_table(&ttc->ft);
 }
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)
+int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
 {
        struct mlx5e_ttc_table *ttc = &priv->fs.ttc;
        struct mlx5_flow_table_attr ft_attr = {};
@@ -810,7 +810,6 @@ int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)
        ft_attr.max_fte = MLX5E_TTC_TABLE_SIZE;
        ft_attr.level = MLX5E_TTC_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
-       ft_attr.underlay_qpn = underlay_qpn;
 
        ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
        if (IS_ERR(ft->t)) {
@@ -1147,7 +1146,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv, 0);
+       err = mlx5e_create_ttc_table(priv);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
index a61b71b6fff30358e43602b1f84e16c697e3140f..277f4de303751d6328a6bcf3282f28e6d5565e5d 100644 (file)
@@ -2976,7 +2976,7 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
        new_channels.params = priv->channels.params;
        new_channels.params.num_tc = tc ? tc : 1;
 
-       if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+       if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                priv->channels.params = new_channels.params;
                goto out;
        }
@@ -4241,7 +4241,8 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
        return netdev;
 
 err_cleanup_nic:
-       profile->cleanup(priv);
+       if (profile->cleanup)
+               profile->cleanup(priv);
        free_netdev(netdev);
 
        return NULL;
index 79462c0368a0781ca7a38354726ed628097c0c89..46984a52a94bb7fad172704b177bdf1c81ef27b8 100644 (file)
@@ -791,6 +791,8 @@ static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
        params->tx_max_inline         = mlx5e_get_max_inline_cap(mdev);
        params->num_tc                = 1;
        params->lro_wqe_sz            = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
+
+       mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
 }
 
 static void mlx5e_build_rep_netdev(struct net_device *netdev)
index 7b1566f0ae58c7c64e3313ed4f6f3fb83bafee5c..66b5fec1531349d14b5324f68a28746cecdf1918 100644 (file)
@@ -1041,6 +1041,8 @@ void mlx5e_free_xdpsq_descs(struct mlx5e_xdpsq *sq)
 #define MLX5_IB_GRH_BYTES       40
 #define MLX5_IPOIB_ENCAP_LEN    4
 #define MLX5_GID_SIZE           16
+#define MLX5_IPOIB_PSEUDO_LEN   20
+#define MLX5_IPOIB_HARD_LEN     (MLX5_IPOIB_PSEUDO_LEN + MLX5_IPOIB_ENCAP_LEN)
 
 static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
                                         struct mlx5_cqe64 *cqe,
@@ -1048,6 +1050,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
                                         struct sk_buff *skb)
 {
        struct net_device *netdev = rq->netdev;
+       char *pseudo_header;
        u8 *dgid;
        u8 g;
 
@@ -1076,8 +1079,11 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
        if (likely(netdev->features & NETIF_F_RXHASH))
                mlx5e_skb_set_hash(cqe, skb);
 
+       /* 20 bytes of ipoib header and 4 for encap existing */
+       pseudo_header = skb_push(skb, MLX5_IPOIB_PSEUDO_LEN);
+       memset(pseudo_header, 0, MLX5_IPOIB_PSEUDO_LEN);
        skb_reset_mac_header(skb);
-       skb_pull(skb, MLX5_IPOIB_ENCAP_LEN);
+       skb_pull(skb, MLX5_IPOIB_HARD_LEN);
 
        skb->dev = netdev;
 
index 02dd3a95ed8f013d0d4795d5054bd79ae4ca1201..acf32fe952cdef6f994e2937433ac4b1b7962e84 100644 (file)
@@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct mlx5e_rx_am *am)
        mlx5e_am_step(am);
 }
 
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+       (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
 static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,
                                  struct mlx5e_rx_am_stats *prev)
 {
-       int diff;
-
-       if (!prev->ppms)
-               return curr->ppms ? MLX5E_AM_STATS_BETTER :
+       if (!prev->bpms)
+               return curr->bpms ? MLX5E_AM_STATS_BETTER :
                                    MLX5E_AM_STATS_SAME;
 
-       diff = curr->ppms - prev->ppms;
-       if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */
-               return (diff > 0) ? MLX5E_AM_STATS_BETTER :
-                                   MLX5E_AM_STATS_WORSE;
+       if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+               return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER :
+                                                  MLX5E_AM_STATS_WORSE;
 
-       if (!prev->epms)
-               return curr->epms ? MLX5E_AM_STATS_WORSE :
-                                   MLX5E_AM_STATS_SAME;
+       if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+               return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER :
+                                                  MLX5E_AM_STATS_WORSE;
 
-       diff = curr->epms - prev->epms;
-       if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */
-               return (diff < 0) ? MLX5E_AM_STATS_BETTER :
-                                   MLX5E_AM_STATS_WORSE;
+       if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+               return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER :
+                                                  MLX5E_AM_STATS_WORSE;
 
        return MLX5E_AM_STATS_SAME;
 }
@@ -266,10 +265,13 @@ static void mlx5e_am_sample(struct mlx5e_rq *rq,
 {
        s->time      = ktime_get();
        s->pkt_ctr   = rq->stats.packets;
+       s->byte_ctr  = rq->stats.bytes;
        s->event_ctr = rq->cq.event_ctr;
 }
 
 #define MLX5E_AM_NEVENTS 64
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
 
 static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
                                struct mlx5e_rx_am_sample *end,
@@ -277,13 +279,17 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
 {
        /* u32 holds up to 71 minutes, should be enough */
        u32 delta_us = ktime_us_delta(end->time, start->time);
-       unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
+       u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
+       u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
+                            start->byte_ctr);
 
        if (!delta_us)
                return;
 
-       curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us;
-       curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
+       curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+       curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+       curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC,
+                                       delta_us);
 }
 
 void mlx5e_rx_am_work(struct work_struct *work)
@@ -308,7 +314,8 @@ void mlx5e_rx_am(struct mlx5e_rq *rq)
 
        switch (am->state) {
        case MLX5E_AM_MEASURE_IN_PROGRESS:
-               nevents = rq->cq.event_ctr - am->start_sample.event_ctr;
+               nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr,
+                                 am->start_sample.event_ctr);
                if (nevents < MLX5E_AM_NEVENTS)
                        break;
                mlx5e_am_sample(rq, &end_sample);
index 53e4992d6511f578c5bb31e993afb0986789a979..f81c3aa60b469bef9223fd4313b9d136803ff2b1 100644 (file)
@@ -417,20 +417,13 @@ struct mlx5e_stats {
 };
 
 static const struct counter_desc mlx5e_pme_status_desc[] = {
-       { "module_plug", 0 },
        { "module_unplug", 8 },
 };
 
 static const struct counter_desc mlx5e_pme_error_desc[] = {
-       { "module_pwr_budget_exd", 0 },  /* power budget exceed */
-       { "module_long_range", 8 },      /* long range for non MLNX cable */
-       { "module_bus_stuck", 16 },      /* bus stuck (I2C or data shorted) */
-       { "module_no_eeprom", 24 },      /* no eeprom/retry time out */
-       { "module_enforce_part", 32 },   /* enforce part number list */
-       { "module_unknown_id", 40 },     /* unknown identifier */
-       { "module_high_temp", 48 },      /* high temperature */
+       { "module_bus_stuck", 16 },       /* bus stuck (I2C or data shorted) */
+       { "module_high_temp", 48 },       /* high temperature */
        { "module_bad_shorted", 56 },    /* bad or shorted cable/module */
-       { "module_unknown_status", 64 },
 };
 
 #endif /* __MLX5_EN_STATS_H__ */
index 11c27e4fadf6e09400a432c5498749df73265477..9df9fc0d26f5b89457b1406198fa5c51d50536b3 100644 (file)
@@ -43,6 +43,7 @@
 #include <net/tc_act/tc_vlan.h>
 #include <net/tc_act/tc_tunnel_key.h>
 #include <net/tc_act/tc_pedit.h>
+#include <net/tc_act/tc_csum.h>
 #include <net/vxlan.h>
 #include <net/arp.h>
 #include "en.h"
@@ -384,7 +385,7 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
                if (e->flags & MLX5_ENCAP_ENTRY_VALID)
                        mlx5_encap_dealloc(priv->mdev, e->encap_id);
 
-               hlist_del_rcu(&e->encap_hlist);
+               hash_del_rcu(&e->encap_hlist);
                kfree(e->encap_header);
                kfree(e);
        }
@@ -894,7 +895,6 @@ static struct mlx5_fields fields[] = {
        {MLX5_ACTION_IN_FIELD_OUT_SMAC_15_0,  2, offsetof(struct pedit_headers, eth.h_source[4])},
        {MLX5_ACTION_IN_FIELD_OUT_ETHERTYPE,  2, offsetof(struct pedit_headers, eth.h_proto)},
 
-       {MLX5_ACTION_IN_FIELD_OUT_IP_DSCP, 1, offsetof(struct pedit_headers, ip4.tos)},
        {MLX5_ACTION_IN_FIELD_OUT_IP_TTL,  1, offsetof(struct pedit_headers, ip4.ttl)},
        {MLX5_ACTION_IN_FIELD_OUT_SIPV4,   4, offsetof(struct pedit_headers, ip4.saddr)},
        {MLX5_ACTION_IN_FIELD_OUT_DIPV4,   4, offsetof(struct pedit_headers, ip4.daddr)},
@@ -925,11 +925,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                                struct mlx5e_tc_flow_parse_attr *parse_attr)
 {
        struct pedit_headers *set_masks, *add_masks, *set_vals, *add_vals;
-       int i, action_size, nactions, max_actions, first, last;
+       int i, action_size, nactions, max_actions, first, last, first_z;
        void *s_masks_p, *a_masks_p, *vals_p;
-       u32 s_mask, a_mask, val;
        struct mlx5_fields *f;
        u8 cmd, field_bsize;
+       u32 s_mask, a_mask;
        unsigned long mask;
        void *action;
 
@@ -946,7 +946,8 @@ static int offload_pedit_fields(struct pedit_headers *masks,
        for (i = 0; i < ARRAY_SIZE(fields); i++) {
                f = &fields[i];
                /* avoid seeing bits set from previous iterations */
-               s_mask = a_mask = mask = val = 0;
+               s_mask = 0;
+               a_mask = 0;
 
                s_masks_p = (void *)set_masks + f->offset;
                a_masks_p = (void *)add_masks + f->offset;
@@ -981,12 +982,12 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                        memset(a_masks_p, 0, f->size);
                }
 
-               memcpy(&val, vals_p, f->size);
-
                field_bsize = f->size * BITS_PER_BYTE;
+
+               first_z = find_first_zero_bit(&mask, field_bsize);
                first = find_first_bit(&mask, field_bsize);
                last  = find_last_bit(&mask, field_bsize);
-               if (first > 0 || last != (field_bsize - 1)) {
+               if (first > 0 || last != (field_bsize - 1) || first_z < last) {
                        printk(KERN_WARNING "mlx5: partial rewrite (mask %lx) is currently not offloaded\n",
                               mask);
                        return -EOPNOTSUPP;
@@ -1002,11 +1003,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
                }
 
                if (field_bsize == 32)
-                       MLX5_SET(set_action_in, action, data, ntohl(val));
+                       MLX5_SET(set_action_in, action, data, ntohl(*(__be32 *)vals_p));
                else if (field_bsize == 16)
-                       MLX5_SET(set_action_in, action, data, ntohs(val));
+                       MLX5_SET(set_action_in, action, data, ntohs(*(__be16 *)vals_p));
                else if (field_bsize == 8)
-                       MLX5_SET(set_action_in, action, data, val);
+                       MLX5_SET(set_action_in, action, data, *(u8 *)vals_p);
 
                action += action_size;
                nactions++;
@@ -1109,6 +1110,28 @@ out_err:
        return err;
 }
 
+static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 update_flags)
+{
+       u32 prot_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR | TCA_CSUM_UPDATE_FLAG_TCP |
+                        TCA_CSUM_UPDATE_FLAG_UDP;
+
+       /*  The HW recalcs checksums only if re-writing headers */
+       if (!(action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)) {
+               netdev_warn(priv->netdev,
+                           "TC csum action is only offloaded with pedit\n");
+               return false;
+       }
+
+       if (update_flags & ~prot_flags) {
+               netdev_warn(priv->netdev,
+                           "can't offload TC csum action for some header/s - flags %#x\n",
+                           update_flags);
+               return false;
+       }
+
+       return true;
+}
+
 static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                                struct mlx5e_tc_flow_parse_attr *parse_attr,
                                struct mlx5e_tc_flow *flow)
@@ -1149,6 +1172,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        continue;
                }
 
+               if (is_tcf_csum(a)) {
+                       if (csum_offload_supported(priv, attr->action,
+                                                  tcf_csum_update_flags(a)))
+                               continue;
+
+                       return -EOPNOTSUPP;
+               }
+
                if (is_tcf_skbedit_mark(a)) {
                        u32 mark = tcf_skbedit_mark(a);
 
@@ -1651,6 +1682,14 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                        continue;
                }
 
+               if (is_tcf_csum(a)) {
+                       if (csum_offload_supported(priv, attr->action,
+                                                  tcf_csum_update_flags(a)))
+                               continue;
+
+                       return -EOPNOTSUPP;
+               }
+
                if (is_tcf_mirred_egress_redirect(a)) {
                        int ifindex = tcf_mirred_ifindex(a);
                        struct net_device *out_dev, *encap_dev = NULL;
index ea5d8d37a75c465cf022a4c29d89918802f97bbb..33eae5ad2fb09efe302e2b892c3c9e30d4b117f5 100644 (file)
@@ -422,7 +422,7 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr)
                        break;
 
                case MLX5_EVENT_TYPE_CMD:
-                       mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector));
+                       mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false);
                        break;
 
                case MLX5_EVENT_TYPE_PORT_CHANGE:
index f991f669047e5df2531f043c3934d248bf3099b8..a53e982a68634b5129324fb5af58776804fc5853 100644 (file)
@@ -906,21 +906,34 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
        return 0;
 }
 
-int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
+static int mlx5_devlink_eswitch_check(struct devlink *devlink)
 {
-       struct mlx5_core_dev *dev;
-       u16 cur_mlx5_mode, mlx5_mode = 0;
+       struct mlx5_core_dev *dev = devlink_priv(devlink);
 
-       dev = devlink_priv(devlink);
+       if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
+               return -EOPNOTSUPP;
 
        if (!MLX5_CAP_GEN(dev, vport_group_manager))
                return -EOPNOTSUPP;
 
-       cur_mlx5_mode = dev->priv.eswitch->mode;
-
-       if (cur_mlx5_mode == SRIOV_NONE)
+       if (dev->priv.eswitch->mode == SRIOV_NONE)
                return -EOPNOTSUPP;
 
+       return 0;
+}
+
+int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
+{
+       struct mlx5_core_dev *dev = devlink_priv(devlink);
+       u16 cur_mlx5_mode, mlx5_mode = 0;
+       int err;
+
+       err = mlx5_devlink_eswitch_check(devlink);
+       if (err)
+               return err;
+
+       cur_mlx5_mode = dev->priv.eswitch->mode;
+
        if (esw_mode_from_devlink(mode, &mlx5_mode))
                return -EINVAL;
 
@@ -937,15 +950,12 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
 
 int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
 {
-       struct mlx5_core_dev *dev;
-
-       dev = devlink_priv(devlink);
-
-       if (!MLX5_CAP_GEN(dev, vport_group_manager))
-               return -EOPNOTSUPP;
+       struct mlx5_core_dev *dev = devlink_priv(devlink);
+       int err;
 
-       if (dev->priv.eswitch->mode == SRIOV_NONE)
-               return -EOPNOTSUPP;
+       err = mlx5_devlink_eswitch_check(devlink);
+       if (err)
+               return err;
 
        return esw_mode_to_devlink(dev->priv.eswitch->mode, mode);
 }
@@ -954,15 +964,12 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
 {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
        struct mlx5_eswitch *esw = dev->priv.eswitch;
-       int num_vports = esw->enabled_vports;
        int err, vport;
        u8 mlx5_mode;
 
-       if (!MLX5_CAP_GEN(dev, vport_group_manager))
-               return -EOPNOTSUPP;
-
-       if (esw->mode == SRIOV_NONE)
-               return -EOPNOTSUPP;
+       err = mlx5_devlink_eswitch_check(devlink);
+       if (err)
+               return err;
 
        switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
        case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
@@ -985,7 +992,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
        if (err)
                goto out;
 
-       for (vport = 1; vport < num_vports; vport++) {
+       for (vport = 1; vport < esw->enabled_vports; vport++) {
                err = mlx5_modify_nic_vport_min_inline(dev, vport, mlx5_mode);
                if (err) {
                        esw_warn(dev, "Failed to set min inline on vport %d\n",
@@ -1010,12 +1017,11 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
 {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
        struct mlx5_eswitch *esw = dev->priv.eswitch;
+       int err;
 
-       if (!MLX5_CAP_GEN(dev, vport_group_manager))
-               return -EOPNOTSUPP;
-
-       if (esw->mode == SRIOV_NONE)
-               return -EOPNOTSUPP;
+       err = mlx5_devlink_eswitch_check(devlink);
+       if (err)
+               return err;
 
        return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
 }
@@ -1062,11 +1068,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap)
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        int err;
 
-       if (!MLX5_CAP_GEN(dev, vport_group_manager))
-               return -EOPNOTSUPP;
-
-       if (esw->mode == SRIOV_NONE)
-               return -EOPNOTSUPP;
+       err = mlx5_devlink_eswitch_check(devlink);
+       if (err)
+               return err;
 
        if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&
            (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) ||
@@ -1105,12 +1109,11 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, u8 *encap)
 {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
        struct mlx5_eswitch *esw = dev->priv.eswitch;
+       int err;
 
-       if (!MLX5_CAP_GEN(dev, vport_group_manager))
-               return -EOPNOTSUPP;
-
-       if (esw->mode == SRIOV_NONE)
-               return -EOPNOTSUPP;
+       err = mlx5_devlink_eswitch_check(devlink);
+       if (err)
+               return err;
 
        *encap = esw->offloads.encap;
        return 0;
index 19e3d2fc2099e09a987d0d475629580c72cd37c0..fcec7bedd3cd348f78ec25703d4e77a6e005f596 100644 (file)
 #include "eswitch.h"
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
-                           struct mlx5_flow_table *ft)
+                           struct mlx5_flow_table *ft, u32 underlay_qpn)
 {
        u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {0};
        u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};
 
        if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
-           ft->underlay_qpn == 0)
+           underlay_qpn == 0)
                return 0;
 
        MLX5_SET(set_flow_table_root_in, in, opcode,
                 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
        MLX5_SET(set_flow_table_root_in, in, table_type, ft->type);
        MLX5_SET(set_flow_table_root_in, in, table_id, ft->id);
+       MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn);
        if (ft->vport) {
                MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport);
                MLX5_SET(set_flow_table_root_in, in, other_vport, 1);
        }
 
-       if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
-           ft->underlay_qpn != 0)
-               MLX5_SET(set_flow_table_root_in, in, underlay_qpn, ft->underlay_qpn);
-
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
 
index 8fad806885362dce727791213422b7a9c0d5b897..0f98a7cf4877d8103ef03989e15d05eda570fdb2 100644 (file)
@@ -71,7 +71,8 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,
                        unsigned int index);
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
-                           struct mlx5_flow_table *ft);
+                           struct mlx5_flow_table *ft,
+                           u32 underlay_qpn);
 
 int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id);
 int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id);
index b8a176503d384f863de75cacf7bd81d1f40ad9d8..8f5125ccd8d4f430a2c0e5d60273e7002ca527bd 100644 (file)
@@ -650,7 +650,7 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
        if (ft->level >= min_level)
                return 0;
 
-       err = mlx5_cmd_update_root_ft(root->dev, ft);
+       err = mlx5_cmd_update_root_ft(root->dev, ft, root->underlay_qpn);
        if (err)
                mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
                               ft->id);
@@ -818,8 +818,6 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
                goto unlock_root;
        }
 
-       ft->underlay_qpn = ft_attr->underlay_qpn;
-
        tree_init_node(&ft->node, 1, del_flow_table);
        log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
        next_ft = find_next_chained_ft(fs_prio);
@@ -864,7 +862,7 @@ struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace
        ft_attr.level   = level;
        ft_attr.prio    = prio;
 
-       return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, 0);
+       return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_NORMAL, vport);
 }
 
 struct mlx5_flow_table*
@@ -1489,7 +1487,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)
 
        new_root_ft = find_next_ft(ft);
        if (new_root_ft) {
-               int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft);
+               int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft,
+                                                 root->underlay_qpn);
 
                if (err) {
                        mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
@@ -2062,3 +2061,21 @@ err:
        mlx5_cleanup_fs(dev);
        return err;
 }
+
+int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
+{
+       struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
+
+       root->underlay_qpn = underlay_qpn;
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn);
+
+int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
+{
+       struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
+
+       root->underlay_qpn = 0;
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn);
index 81eafc7b9dd93fc4c8411aa8ad473299ca6c623e..990acee6fb091f102e7412c499df8df44eb806db 100644 (file)
@@ -118,7 +118,6 @@ struct mlx5_flow_table {
        /* FWD rules that point on this flow table */
        struct list_head                fwd_rules;
        u32                             flags;
-       u32                             underlay_qpn;
 };
 
 struct mlx5_fc_cache {
@@ -195,6 +194,7 @@ struct mlx5_flow_root_namespace {
        struct mlx5_flow_table          *root_ft;
        /* Should be held when chaining flow tables */
        struct mutex                    chain_lock;
+       u32                             underlay_qpn;
 };
 
 int mlx5_init_fc_stats(struct mlx5_core_dev *dev);
index d0515391d33bbc57961311f648ed5ef25f457c28..f27f84ffbc850487557ad0184960d7c872abb160 100644 (file)
@@ -90,7 +90,7 @@ static void trigger_cmd_completions(struct mlx5_core_dev *dev)
        spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 
        mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
-       mlx5_cmd_comp_handler(dev, vector);
+       mlx5_cmd_comp_handler(dev, vector, true);
        return;
 
 no_trig:
@@ -275,10 +275,8 @@ static void poll_health(unsigned long data)
        struct mlx5_core_health *health = &dev->priv.health;
        u32 count;
 
-       if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
-               mod_timer(&health->timer, get_next_poll_jiffies());
-               return;
-       }
+       if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+               goto out;
 
        count = ioread32be(health->health_counter);
        if (count == health->prev)
@@ -290,8 +288,6 @@ static void poll_health(unsigned long data)
        if (health->miss_counter == MAX_MISSES) {
                dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n");
                print_health_info(dev);
-       } else {
-               mod_timer(&health->timer, get_next_poll_jiffies());
        }
 
        if (in_fatal(dev) && !health->sick) {
@@ -305,6 +301,9 @@ static void poll_health(unsigned long data)
                                "new health works are not permitted at this stage\n");
                spin_unlock(&health->wq_lock);
        }
+
+out:
+       mod_timer(&health->timer, get_next_poll_jiffies());
 }
 
 void mlx5_start_health_poll(struct mlx5_core_dev *dev)
index 019c230da498f4d540cfb253a5c5f06edffeee05..cc1858752e70818650ca86a00795b3bb48668fb6 100644 (file)
@@ -66,6 +66,10 @@ static void mlx5i_init(struct mlx5_core_dev *mdev,
 
        mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev));
 
+       /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */
+       mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST);
+       priv->channels.params.lro_en = false;
+
        mutex_init(&priv->state_lock);
 
        netdev->hw_features    |= NETIF_F_SG;
@@ -156,6 +160,8 @@ out:
 
 static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp)
 {
+       mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn);
+
        mlx5_core_destroy_qp(mdev, qp);
 }
 
@@ -170,6 +176,8 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv)
                return err;
        }
 
+       mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn);
+
        err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]);
        if (err) {
                mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err);
@@ -189,7 +197,6 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
 
 static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 {
-       struct mlx5i_priv *ipriv = priv->ppriv;
        int err;
 
        priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
@@ -205,7 +212,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv, ipriv->qp.qpn);
+       err = mlx5e_create_ttc_table(priv);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
index 0c123d571b4cf52a0eb3b833208156766b5de6be..13be264587f135737887688005ed7ba872b54157 100644 (file)
@@ -175,8 +175,9 @@ static struct mlx5_profile profile[] = {
        },
 };
 
-#define FW_INIT_TIMEOUT_MILI   2000
-#define FW_INIT_WAIT_MS                2
+#define FW_INIT_TIMEOUT_MILI           2000
+#define FW_INIT_WAIT_MS                        2
+#define FW_PRE_INIT_TIMEOUT_MILI       10000
 
 static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
 {
@@ -537,8 +538,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
        /* disable cmdif checksum */
        MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0);
 
-       /* If the HCA supports 4K UARs use it */
-       if (MLX5_CAP_GEN_MAX(dev, uar_4k))
+       /* Enable 4K UAR only when HCA supports it and page size is bigger
+        * than 4K.
+        */
+       if (MLX5_CAP_GEN_MAX(dev, uar_4k) && PAGE_SIZE > 4096)
                MLX5_SET(cmd_hca_cap, set_hca_cap, uar_4k, 1);
 
        MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12);
@@ -612,7 +615,6 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
        struct mlx5_priv *priv  = &mdev->priv;
        struct msix_entry *msix = priv->msix_arr;
        int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
-       int err;
 
        if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
                mlx5_core_warn(mdev, "zalloc_cpumask_var failed");
@@ -622,18 +624,11 @@ static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
        cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
                        priv->irq_info[i].mask);
 
-       err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
-       if (err) {
-               mlx5_core_warn(mdev, "irq_set_affinity_hint failed,irq 0x%.4x",
-                              irq);
-               goto err_clear_mask;
-       }
+       if (IS_ENABLED(CONFIG_SMP) &&
+           irq_set_affinity_hint(irq, priv->irq_info[i].mask))
+               mlx5_core_warn(mdev, "irq_set_affinity_hint failed, irq 0x%.4x", irq);
 
        return 0;
-
-err_clear_mask:
-       free_cpumask_var(priv->irq_info[i].mask);
-       return err;
 }
 
 static void mlx5_irq_clear_affinity_hint(struct mlx5_core_dev *mdev, int i)
@@ -1019,6 +1014,15 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
         */
        dev->state = MLX5_DEVICE_STATE_UP;
 
+       /* wait for firmware to accept initialization segments configurations
+        */
+       err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
+       if (err) {
+               dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
+                       FW_PRE_INIT_TIMEOUT_MILI);
+               goto out;
+       }
+
        err = mlx5_cmd_init(dev);
        if (err) {
                dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
index ea56f6ade6b429585f35a2f72dae20f8d51d4a0f..5f0a7bc692a4b8e3efae2f8a3c8a55f5c448346d 100644 (file)
@@ -199,10 +199,11 @@ static int mlxsw_sp_erif_entry_get(struct mlxsw_sp *mlxsw_sp,
 
        entry->counter_valid = false;
        entry->counter = 0;
+       entry->index = mlxsw_sp_rif_index(rif);
+
        if (!counters_enabled)
                return 0;
 
-       entry->index = mlxsw_sp_rif_index(rif);
        err = mlxsw_sp_rif_counter_value_get(mlxsw_sp, rif,
                                             MLXSW_SP_RIF_COUNTER_EGRESS,
                                             &cnt);
index 33cec1cc164259ad9d7dd022a811e957447a61ff..0744452a0b188190a1da2fe0e14651aad31748de 100644 (file)
@@ -206,6 +206,9 @@ void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,
 {
        unsigned int *p_counter_index;
 
+       if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
+               return;
+
        p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
        if (WARN_ON(!p_counter_index))
                return;
@@ -3331,6 +3334,9 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
        u16 vid = vlan_dev_vlan_id(vlan_dev);
 
+       if (netif_is_bridge_port(vlan_dev))
+               return 0;
+
        if (mlxsw_sp_port_dev_check(real_dev))
                return mlxsw_sp_inetaddr_vport_event(vlan_dev, real_dev, event,
                                                     vid);
index 0d8411f1f954c5668bc3bd26f721589f2ccf205d..f4bb0c0b7c1d2689a884d64010fde0f0dfd4053c 100644 (file)
@@ -1497,8 +1497,7 @@ do_fdb_op:
        err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,
                                      adding, true);
        if (err) {
-               if (net_ratelimit())
-                       netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n");
                return;
        }
 
@@ -1558,8 +1557,7 @@ do_fdb_op:
        err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
                                          adding, true);
        if (err) {
-               if (net_ratelimit())
-                       netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n");
                return;
        }
 
index b8d5270359cd8a7109226c0be1731cbafa6d1423..e306765155290a31e390f5ddcf88b4f0aa8f973c 100644 (file)
@@ -247,7 +247,7 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
        cmd.req.arg3 = 0;
 
        if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
-               netxen_issue_cmd(adapter, &cmd);
+               rcode = netxen_issue_cmd(adapter, &cmd);
 
        if (rcode != NX_RCODE_SUCCESS)
                return -EIO;
index 483241b4b05db2add64ff928ccc9419fe733355a..a672f6a860dc4e7a49b2175283d2720c610d4453 100644 (file)
@@ -2956,7 +2956,7 @@ static u32 qed_grc_dump_ctx_data(struct qed_hwfn *p_hwfn,
                                qed_wr(p_hwfn,
                                       p_ptt,
                                       s_storm_defs[storm_id].cm_ctx_wr_addr,
-                                      BIT(9) | lid);
+                                      (i << 9) | lid);
                                *(dump_buf + offset) = qed_rd(p_hwfn,
                                                              p_ptt,
                                                              rd_reg_addr);
index 67200c5498ab01d3911735f25e6ccea05aed200e..0a8fde6299919b3c1e0d7382ac90be30631644e3 100644 (file)
@@ -983,7 +983,7 @@ void qed_set_rfs_mode_disable(struct qed_hwfn *p_hwfn,
        memset(&camline, 0, sizeof(union gft_cam_line_union));
        qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id,
               camline.cam_line_mapped.camline);
-       memset(&ramline, 0, sizeof(union gft_cam_line_union));
+       memset(&ramline, 0, sizeof(ramline));
 
        for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) {
                u32 hw_addr = PRS_REG_GFT_PROFILE_MASK_RAM;
index 537d1236a4fec0a2973d52ed34cf7f73d8a4b052..715b3aaf83ac4d65cdea4eb15f6f2089e402c469 100644 (file)
@@ -1730,7 +1730,8 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
                qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);
                break;
        default:
-               DP_ERR(cdev, "Invalid protocol type = %d\n", type);
+               DP_VERBOSE(cdev, QED_MSG_SP,
+                          "Invalid protocol type = %d\n", type);
                return;
        }
 }
index 49bad00a0f8f994837b0554f3250d5ca0811bff7..81312924df1407092fd1dd43cc0555d16976160b 100644 (file)
@@ -37,8 +37,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 65
-#define QLCNIC_LINUX_VERSIONID  "5.3.65"
+#define _QLCNIC_LINUX_SUBVERSION 66
+#define QLCNIC_LINUX_VERSIONID  "5.3.66"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -1824,22 +1824,44 @@ struct qlcnic_hardware_ops {
        u32 (*get_cap_size)(void *, int);
        void (*set_sys_info)(void *, int, u32);
        void (*store_cap_mask)(void *, u32);
+       bool (*encap_rx_offload) (struct qlcnic_adapter *adapter);
+       bool (*encap_tx_offload) (struct qlcnic_adapter *adapter);
 };
 
 extern struct qlcnic_nic_template qlcnic_vf_ops;
 
-static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter)
+static inline bool qlcnic_83xx_encap_tx_offload(struct qlcnic_adapter *adapter)
 {
        return adapter->ahw->extra_capability[0] &
               QLCNIC_83XX_FW_CAPAB_ENCAP_TX_OFFLOAD;
 }
 
-static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter)
+static inline bool qlcnic_83xx_encap_rx_offload(struct qlcnic_adapter *adapter)
 {
        return adapter->ahw->extra_capability[0] &
               QLCNIC_83XX_FW_CAPAB_ENCAP_RX_OFFLOAD;
 }
 
+static inline bool qlcnic_82xx_encap_tx_offload(struct qlcnic_adapter *adapter)
+{
+       return false;
+}
+
+static inline bool qlcnic_82xx_encap_rx_offload(struct qlcnic_adapter *adapter)
+{
+        return false;
+}
+
+static inline bool qlcnic_encap_rx_offload(struct qlcnic_adapter *adapter)
+{
+        return adapter->ahw->hw_ops->encap_rx_offload(adapter);
+}
+
+static inline bool qlcnic_encap_tx_offload(struct qlcnic_adapter *adapter)
+{
+        return adapter->ahw->hw_ops->encap_tx_offload(adapter);
+}
+
 static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter)
 {
        return adapter->nic_ops->start_firmware(adapter);
index 718bf58a7da66284e121f3aab8e79de7a6221c67..f7080d0ab8746263c6955163640964eac2fd2cb0 100644 (file)
@@ -242,6 +242,8 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
        .get_cap_size                   = qlcnic_83xx_get_cap_size,
        .set_sys_info                   = qlcnic_83xx_set_sys_info,
        .store_cap_mask                 = qlcnic_83xx_store_cap_mask,
+       .encap_rx_offload               = qlcnic_83xx_encap_rx_offload,
+       .encap_tx_offload               = qlcnic_83xx_encap_tx_offload,
 };
 
 static struct qlcnic_nic_template qlcnic_83xx_ops = {
@@ -3168,6 +3170,40 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
        return 0;
 }
 
+void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       struct qlcnic_cmd_args cmd;
+       u32 config;
+       int err;
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
+       if (err)
+               return;
+
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err) {
+               dev_info(&adapter->pdev->dev,
+                        "Get Link Status Command failed: 0x%x\n", err);
+               goto out;
+       } else {
+               config = cmd.rsp.arg[3];
+
+               switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
+               case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
+               case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
+               case QLC_83XX_MODULE_FIBRE_1000BASE_CX:
+               case QLC_83XX_MODULE_TP_1000BASE_T:
+                       ahw->port_type = QLCNIC_GBE;
+                       break;
+               default:
+                       ahw->port_type = QLCNIC_XGBE;
+               }
+       }
+out:
+       qlcnic_free_mbx_args(&cmd);
+}
+
 int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
 {
        u8 pci_func;
index 3dfe8e27b51c68de0af32af949b096d247e3ccb0..b75a812468569de7728fd9c654b6f1c7e353729f 100644 (file)
@@ -637,6 +637,7 @@ void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
 int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *,
                               struct ethtool_pauseparam *);
 int qlcnic_83xx_test_link(struct qlcnic_adapter *);
+void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter);
 int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
 int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
 int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
index 9a869c15d8bfbfc64b48a831a2b4eb7b38160714..7f7deeaf1cf07913454a13b4f7801c7b3b07545f 100644 (file)
@@ -486,6 +486,9 @@ static int qlcnic_set_link_ksettings(struct net_device *dev,
        u32 ret = 0;
        struct qlcnic_adapter *adapter = netdev_priv(dev);
 
+       if (qlcnic_83xx_check(adapter))
+               qlcnic_83xx_get_port_type(adapter);
+
        if (adapter->ahw->port_type != QLCNIC_GBE)
                return -EOPNOTSUPP;
 
index 838cc0ceafd8d0824495206bf30cdaf53f98bc59..7848cf04b29a83f0a356b3eb5360d6a6e65871f0 100644 (file)
@@ -341,7 +341,7 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
                        }
                        return -EIO;
                }
-               usleep_range(1000, 1500);
+               udelay(1200);
        }
 
        if (id_reg)
index b6628aaa6e4a45a8eaecd9d5fc4ea8136d7a07af..1b5f7d57b6f8fed6a8b232adfdee76b2cbaff13f 100644 (file)
@@ -632,6 +632,8 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
        .get_cap_size                   = qlcnic_82xx_get_cap_size,
        .set_sys_info                   = qlcnic_82xx_set_sys_info,
        .store_cap_mask                 = qlcnic_82xx_store_cap_mask,
+       .encap_rx_offload               = qlcnic_82xx_encap_rx_offload,
+       .encap_tx_offload               = qlcnic_82xx_encap_tx_offload,
 };
 
 static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
index 2f656f395f39699e4cec53f4ff25ea7e745d1041..c58180f408448e9a86a7ce40c6fb286063a6afb0 100644 (file)
@@ -77,6 +77,8 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = {
        .free_mac_list                  = qlcnic_sriov_vf_free_mac_list,
        .enable_sds_intr                = qlcnic_83xx_enable_sds_intr,
        .disable_sds_intr               = qlcnic_83xx_disable_sds_intr,
+       .encap_rx_offload               = qlcnic_83xx_encap_rx_offload,
+       .encap_tx_offload               = qlcnic_83xx_encap_tx_offload,
 };
 
 static struct qlcnic_nic_template qlcnic_sriov_vf_ops = {
index cc065ffbe4b5584a6498237d1e4a929ff1d6ebd0..bcd4708b374574fb06faf28d9b0a6cc90bc9c56d 100644 (file)
@@ -931,7 +931,7 @@ int emac_mac_up(struct emac_adapter *adpt)
        emac_mac_config(adpt);
        emac_mac_rx_descs_refill(adpt, &adpt->rx_q);
 
-       adpt->phydev->irq = PHY_IGNORE_INTERRUPT;
+       adpt->phydev->irq = PHY_POLL;
        ret = phy_connect_direct(netdev, adpt->phydev, emac_adjust_link,
                                 PHY_INTERFACE_MODE_SGMII);
        if (ret) {
index 441c1936648993fa394e5c676b7bd9957e52efa3..18461fcb981501efd7015634999cb787041c01a7 100644 (file)
 /* Qualcomm Technologies, Inc. EMAC PHY Controller driver.
  */
 
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_net.h>
 #include <linux/of_mdio.h>
 #include <linux/phy.h>
 #include <linux/iopoll.h>
 #include <linux/acpi.h>
 #include "emac.h"
-#include "emac-mac.h"
 
 /* EMAC base register offsets */
 #define EMAC_MDIO_CTRL                                        0x001414
 
 #define MDIO_WAIT_TIMES                                           1000
 
-#define EMAC_LINK_SPEED_DEFAULT (\
-               EMAC_LINK_SPEED_10_HALF  |\
-               EMAC_LINK_SPEED_10_FULL  |\
-               EMAC_LINK_SPEED_100_HALF |\
-               EMAC_LINK_SPEED_100_FULL |\
-               EMAC_LINK_SPEED_1GB_FULL)
-
-/**
- * emac_phy_mdio_autopoll_disable() - disable mdio autopoll
- * @adpt: the emac adapter
- *
- * The autopoll feature takes over the MDIO bus.  In order for
- * the PHY driver to be able to talk to the PHY over the MDIO
- * bus, we need to temporarily disable the autopoll feature.
- */
-static int emac_phy_mdio_autopoll_disable(struct emac_adapter *adpt)
-{
-       u32 val;
-
-       /* disable autopoll */
-       emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, MDIO_AP_EN, 0);
-
-       /* wait for any mdio polling to complete */
-       if (!readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, val,
-                               !(val & MDIO_BUSY), 100, MDIO_WAIT_TIMES * 100))
-               return 0;
-
-       /* failed to disable; ensure it is enabled before returning */
-       emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN);
-
-       return -EBUSY;
-}
-
-/**
- * emac_phy_mdio_autopoll_disable() - disable mdio autopoll
- * @adpt: the emac adapter
- *
- * The EMAC has the ability to poll the external PHY on the MDIO
- * bus for link state changes.  This eliminates the need for the
- * driver to poll the phy.  If if the link state does change,
- * the EMAC issues an interrupt on behalf of the PHY.
- */
-static void emac_phy_mdio_autopoll_enable(struct emac_adapter *adpt)
-{
-       emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN);
-}
-
 static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)
 {
        struct emac_adapter *adpt = bus->priv;
        u32 reg;
-       int ret;
-
-       ret = emac_phy_mdio_autopoll_disable(adpt);
-       if (ret)
-               return ret;
 
        emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,
                          (addr << PHY_ADDR_SHFT));
@@ -122,24 +66,15 @@ static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)
        if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,
                               !(reg & (MDIO_START | MDIO_BUSY)),
                               100, MDIO_WAIT_TIMES * 100))
-               ret = -EIO;
-       else
-               ret = (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK;
+               return -EIO;
 
-       emac_phy_mdio_autopoll_enable(adpt);
-
-       return ret;
+       return (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK;
 }
 
 static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
        struct emac_adapter *adpt = bus->priv;
        u32 reg;
-       int ret;
-
-       ret = emac_phy_mdio_autopoll_disable(adpt);
-       if (ret)
-               return ret;
 
        emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,
                          (addr << PHY_ADDR_SHFT));
@@ -155,11 +90,9 @@ static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
        if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,
                               !(reg & (MDIO_START | MDIO_BUSY)), 100,
                               MDIO_WAIT_TIMES * 100))
-               ret = -EIO;
+               return -EIO;
 
-       emac_phy_mdio_autopoll_enable(adpt);
-
-       return ret;
+       return 0;
 }
 
 /* Configure the MDIO bus and connect the external PHY */
index 28a8cdc364851e56a5757a8f2970853c0a462cc4..98a326faea294eec0c59f9b0ffe15d57046ce5eb 100644 (file)
 #define DMAR_DLY_CNT_DEF                                   15
 #define DMAW_DLY_CNT_DEF                                    4
 
-#define IMR_NORMAL_MASK         (\
-               ISR_ERROR       |\
-               ISR_GPHY_LINK   |\
-               ISR_TX_PKT      |\
-               GPHY_WAKEUP_INT)
-
-#define IMR_EXTENDED_MASK       (\
-               SW_MAN_INT      |\
-               ISR_OVER        |\
-               ISR_ERROR       |\
-               ISR_GPHY_LINK   |\
-               ISR_TX_PKT      |\
-               GPHY_WAKEUP_INT)
+#define IMR_NORMAL_MASK                (ISR_ERROR | ISR_OVER | ISR_TX_PKT)
 
 #define ISR_TX_PKT      (\
        TX_PKT_INT      |\
        TX_PKT_INT2     |\
        TX_PKT_INT3)
 
-#define ISR_GPHY_LINK        (\
-       GPHY_LINK_UP_INT     |\
-       GPHY_LINK_DOWN_INT)
-
 #define ISR_OVER        (\
        RFD0_UR_INT     |\
        RFD1_UR_INT     |\
@@ -187,10 +171,6 @@ irqreturn_t emac_isr(int _irq, void *data)
        if (status & ISR_OVER)
                net_warn_ratelimited("warning: TX/RX overflow\n");
 
-       /* link event */
-       if (status & ISR_GPHY_LINK)
-               phy_mac_interrupt(adpt->phydev, !!(status & GPHY_LINK_UP_INT));
-
 exit:
        /* enable the interrupt */
        writel(irq->mask, adpt->base + EMAC_INT_MASK);
index 513e6c74e1990b6fb2c8b00ee9f5a4b70076115d..24ca7df15d07d48a4214bd5df38edcceb6d284aa 100644 (file)
@@ -296,8 +296,9 @@ qcaspi_receive(struct qcaspi *qca)
 
        /* Allocate rx SKB if we don't have one available. */
        if (!qca->rx_skb) {
-               qca->rx_skb = netdev_alloc_skb(net_dev,
-                                              net_dev->mtu + VLAN_ETH_HLEN);
+               qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
+                                                       net_dev->mtu +
+                                                       VLAN_ETH_HLEN);
                if (!qca->rx_skb) {
                        netdev_dbg(net_dev, "out of RX resources\n");
                        qca->stats.out_of_mem++;
@@ -377,7 +378,7 @@ qcaspi_receive(struct qcaspi *qca)
                                        qca->rx_skb, qca->rx_skb->dev);
                                qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
                                netif_rx_ni(qca->rx_skb);
-                               qca->rx_skb = netdev_alloc_skb(net_dev,
+                               qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
                                        net_dev->mtu + VLAN_ETH_HLEN);
                                if (!qca->rx_skb) {
                                        netdev_dbg(net_dev, "out of RX resources\n");
@@ -759,7 +760,8 @@ qcaspi_netdev_init(struct net_device *dev)
        if (!qca->rx_buffer)
                return -ENOBUFS;
 
-       qca->rx_skb = netdev_alloc_skb(dev, qca->net_dev->mtu + VLAN_ETH_HLEN);
+       qca->rx_skb = netdev_alloc_skb_ip_align(dev, qca->net_dev->mtu +
+                                               VLAN_ETH_HLEN);
        if (!qca->rx_skb) {
                kfree(qca->rx_buffer);
                netdev_info(qca->net_dev, "Failed to allocate RX sk_buff.\n");
index 3cd7989c007dfe46947e2ddb366a904f1af90198..784782da3a85b638e9e2a195fe66b15c72fe0fe5 100644 (file)
@@ -230,18 +230,6 @@ static void ravb_ring_free(struct net_device *ndev, int q)
        int ring_size;
        int i;
 
-       /* Free RX skb ringbuffer */
-       if (priv->rx_skb[q]) {
-               for (i = 0; i < priv->num_rx_ring[q]; i++)
-                       dev_kfree_skb(priv->rx_skb[q][i]);
-       }
-       kfree(priv->rx_skb[q]);
-       priv->rx_skb[q] = NULL;
-
-       /* Free aligned TX buffers */
-       kfree(priv->tx_align[q]);
-       priv->tx_align[q] = NULL;
-
        if (priv->rx_ring[q]) {
                for (i = 0; i < priv->num_rx_ring[q]; i++) {
                        struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
@@ -270,6 +258,18 @@ static void ravb_ring_free(struct net_device *ndev, int q)
                priv->tx_ring[q] = NULL;
        }
 
+       /* Free RX skb ringbuffer */
+       if (priv->rx_skb[q]) {
+               for (i = 0; i < priv->num_rx_ring[q]; i++)
+                       dev_kfree_skb(priv->rx_skb[q][i]);
+       }
+       kfree(priv->rx_skb[q]);
+       priv->rx_skb[q] = NULL;
+
+       /* Free aligned TX buffers */
+       kfree(priv->tx_align[q]);
+       priv->tx_align[q] = NULL;
+
        /* Free TX skb ringbuffer.
         * SKBs are freed by ravb_tx_free() call above.
         */
index f68c4db656eda84691b411cee940528a01a2bb62..2d686ccf971b1b6525d7ded8ec5e43b65b67ee6c 100644 (file)
@@ -3220,7 +3220,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        /* MDIO bus init */
        ret = sh_mdio_init(mdp, pd);
        if (ret) {
-               dev_err(&ndev->dev, "failed to initialise MDIO\n");
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "MDIO init failed: %d\n", ret);
                goto out_release;
        }
 
index 2ae85245478087d2d640617bd79bfbfabd5f0763..a9ce82d3e9cf4b8875474cd62f02ccbfc322bc20 100644 (file)
@@ -1505,8 +1505,8 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
                *index = entry->index;
                resolved = false;
        } else if (removing) {
-               ofdpa_neigh_del(trans, found);
                *index = found->index;
+               ofdpa_neigh_del(trans, found);
        } else if (updating) {
                ofdpa_neigh_update(found, trans, NULL, false);
                resolved = !is_zero_ether_addr(found->eth_dst);
index 78efb2822b8648c6e6f02ffa764aad89570ffbd0..78f9e43420e0df217d8f118876831e54c204f191 100644 (file)
@@ -4172,7 +4172,7 @@ found:
         * recipients
         */
        if (is_mc_recip) {
-               MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+               MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
                unsigned int depth, i;
 
                memset(inbuf, 0, sizeof(inbuf));
@@ -4320,7 +4320,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
                        efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
                } else {
                        efx_mcdi_display_error(efx, MC_CMD_FILTER_OP,
-                                              MC_CMD_FILTER_OP_IN_LEN,
+                                              MC_CMD_FILTER_OP_EXT_IN_LEN,
                                               NULL, 0, rc);
                }
        }
@@ -4453,7 +4453,7 @@ static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx,
                                      struct efx_filter_spec *spec)
 {
        struct efx_ef10_filter_table *table = efx->filter_state;
-       MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+       MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
        struct efx_filter_spec *saved_spec;
        unsigned int hash, i, depth = 1;
        bool replacing = false;
@@ -4940,7 +4940,7 @@ not_restored:
 static void efx_ef10_filter_table_remove(struct efx_nic *efx)
 {
        struct efx_ef10_filter_table *table = efx->filter_state;
-       MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
+       MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
        struct efx_filter_spec *spec;
        unsigned int filter_idx;
        int rc;
@@ -5105,6 +5105,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
 
        /* Insert/renew filters */
        for (i = 0; i < addr_count; i++) {
+               EFX_WARN_ON_PARANOID(ids[i] != EFX_EF10_FILTER_ID_INVALID);
                efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
                efx_filter_set_eth_local(&spec, vlan->vid, addr_list[i].addr);
                rc = efx_ef10_filter_insert(efx, &spec, true);
@@ -5122,11 +5123,11 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
                                }
                                return rc;
                        } else {
-                               /* mark as not inserted, and carry on */
-                               rc = EFX_EF10_FILTER_ID_INVALID;
+                               /* keep invalid ID, and carry on */
                        }
+               } else {
+                       ids[i] = efx_ef10_filter_get_unsafe_id(rc);
                }
-               ids[i] = efx_ef10_filter_get_unsafe_id(rc);
        }
 
        if (multicast && rollback) {
index b7e4345c990d55454f52cbcb9c7c4d5df66ef176..019cef1d3cf72ce2d34b3a36283cabf9227c9879 100644 (file)
@@ -661,8 +661,6 @@ restore_filters:
                up_write(&vf->efx->filter_sem);
                mutex_unlock(&vf->efx->mac_lock);
 
-               up_write(&vf->efx->filter_sem);
-
                rc2 = efx_net_open(vf->efx->net_dev);
                if (rc2)
                        goto reset_nic;
index 7b916aa21bdef18896debc4bdd7384696e50f3a3..4d7fb8af880d0f36189f8475a9859b229a7bd078 100644 (file)
 #include "mcdi.h"
 
 enum {
-       EFX_REV_SIENA_A0 = 0,
-       EFX_REV_HUNT_A0 = 1,
+       /* Revisions 0-2 were Falcon A0, A1 and B0 respectively.
+        * They are not supported by this driver but these revision numbers
+        * form part of the ethtool API for register dumping.
+        */
+       EFX_REV_SIENA_A0 = 3,
+       EFX_REV_HUNT_A0 = 4,
 };
 
 static inline int efx_nic_rev(struct efx_nic *efx)
index 489ef146201e61c629c17010f672a621642e94b3..6a9c954492f225987d5dc63713034548e7aabdbb 100644 (file)
@@ -37,6 +37,7 @@
 #define TSE_PCS_CONTROL_AN_EN_MASK                     BIT(12)
 #define TSE_PCS_CONTROL_REG                            0x00
 #define TSE_PCS_CONTROL_RESTART_AN_MASK                        BIT(9)
+#define TSE_PCS_CTRL_AUTONEG_SGMII                     0x1140
 #define TSE_PCS_IF_MODE_REG                            0x28
 #define TSE_PCS_LINK_TIMER_0_REG                       0x24
 #define TSE_PCS_LINK_TIMER_1_REG                       0x26
@@ -65,6 +66,7 @@
 #define TSE_PCS_SW_RESET_TIMEOUT                       100
 #define TSE_PCS_USE_SGMII_AN_MASK                      BIT(1)
 #define TSE_PCS_USE_SGMII_ENA                          BIT(0)
+#define TSE_PCS_IF_USE_SGMII                           0x03
 
 #define SGMII_ADAPTER_CTRL_REG                         0x00
 #define SGMII_ADAPTER_DISABLE                          0x0001
@@ -101,7 +103,9 @@ int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs)
 {
        int ret = 0;
 
-       writew(TSE_PCS_USE_SGMII_ENA, base + TSE_PCS_IF_MODE_REG);
+       writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG);
+
+       writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG);
 
        writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG);
        writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG);
index aa6476439aee7f4c65784af4a451a8ffe5173561..e0ef02f9503bae027268b1b058f9875b6c1365a7 100644 (file)
@@ -214,13 +214,13 @@ static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)
 {
        /* Context type from W/B descriptor must be zero */
        if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE)
-               return -EINVAL;
+               return 0;
 
        /* Tx Timestamp Status is 1 so des0 and des1'll have valid values */
        if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS)
-               return 0;
+               return 1;
 
-       return 1;
+       return 0;
 }
 
 static inline u64 dwmac4_get_timestamp(void *desc, u32 ats)
@@ -282,7 +282,10 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)
                }
        }
 exit:
-       return ret;
+       if (likely(ret == 0))
+               return 1;
+
+       return 0;
 }
 
 static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
index cd8c601323905a7ded2504fa69faa54a1c728066..6e4cbc6ce0efd9843a55341ec47eb76fd9932327 100644 (file)
@@ -434,14 +434,14 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
                return;
 
        /* check tx tstamp status */
-       if (!priv->hw->desc->get_tx_timestamp_status(p)) {
+       if (priv->hw->desc->get_tx_timestamp_status(p)) {
                /* get the valid tstamp */
                ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
 
                memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
                shhwtstamp.hwtstamp = ns_to_ktime(ns);
 
-               netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns);
+               netdev_dbg(priv->dev, "get valid TX hw timestamp %llu\n", ns);
                /* pass tstamp to stack */
                skb_tstamp_tx(skb, &shhwtstamp);
        }
@@ -468,19 +468,19 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
                return;
 
        /* Check if timestamp is available */
-       if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {
+       if (priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {
                /* For GMAC4, the valid timestamp is from CTX next desc. */
                if (priv->plat->has_gmac4)
                        ns = priv->hw->desc->get_timestamp(np, priv->adv_ts);
                else
                        ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
 
-               netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns);
+               netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);
                shhwtstamp = skb_hwtstamps(skb);
                memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
                shhwtstamp->hwtstamp = ns_to_ktime(ns);
        } else  {
-               netdev_err(priv->dev, "cannot get RX hw timestamp\n");
+               netdev_dbg(priv->dev, "cannot get RX hw timestamp\n");
        }
 }
 
@@ -546,7 +546,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                        /* PTP v1, UDP, any kind of event packet */
                        config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
                        /* take time stamp for all event messages */
-                       snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+                       if (priv->plat->has_gmac4)
+                               snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
+                       else
+                               snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
 
                        ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
                        ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -578,7 +581,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                        config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
                        ptp_v2 = PTP_TCR_TSVER2ENA;
                        /* take time stamp for all event messages */
-                       snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+                       if (priv->plat->has_gmac4)
+                               snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
+                       else
+                               snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
 
                        ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
                        ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -612,7 +618,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                        config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
                        ptp_v2 = PTP_TCR_TSVER2ENA;
                        /* take time stamp for all event messages */
-                       snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
+                       if (priv->plat->has_gmac4)
+                               snap_type_sel = PTP_GMAC4_TCR_SNAPTYPSEL_1;
+                       else
+                               snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
 
                        ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
                        ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
@@ -1208,7 +1217,7 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
        u32 rx_count = priv->plat->rx_queues_to_use;
        unsigned int bfsize = 0;
        int ret = -ENOMEM;
-       u32 queue;
+       int queue;
        int i;
 
        if (priv->hw->mode->set_16kib_bfsize)
@@ -2724,7 +2733,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
 
                priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size,
                        0, 1,
-                       (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE),
+                       (last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE),
                        0, 0);
 
                tmp_len -= TSO_MAX_BUFF_SIZE;
@@ -2822,7 +2831,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q->tx_skbuff_dma[first_entry].buf = des;
        tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
-       tx_q->tx_skbuff[first_entry] = skb;
 
        first->des0 = cpu_to_le32(des);
 
@@ -2856,6 +2864,14 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q->tx_skbuff_dma[tx_q->cur_tx].last_segment = true;
 
+       /* Only the last descriptor gets to point to the skb. */
+       tx_q->tx_skbuff[tx_q->cur_tx] = skb;
+
+       /* We've used all descriptors we need for this skb, however,
+        * advance cur_tx so that it references a fresh descriptor.
+        * ndo_start_xmit will fill this descriptor the next time it's
+        * called and stmmac_tx_clean may clean up to this descriptor.
+        */
        tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
 
        if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) {
@@ -2947,7 +2963,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        int i, csum_insertion = 0, is_jumbo = 0;
        u32 queue = skb_get_queue_mapping(skb);
        int nfrags = skb_shinfo(skb)->nr_frags;
-       unsigned int entry, first_entry;
+       int entry;
+       unsigned int first_entry;
        struct dma_desc *desc, *first;
        struct stmmac_tx_queue *tx_q;
        unsigned int enh_desc;
@@ -2988,8 +3005,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        first = desc;
 
-       tx_q->tx_skbuff[first_entry] = skb;
-
        enh_desc = priv->plat->enh_desc;
        /* To program the descriptors according to the size of the frame */
        if (enh_desc)
@@ -3037,8 +3052,15 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                                                skb->len);
        }
 
-       entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
+       /* Only the last descriptor gets to point to the skb. */
+       tx_q->tx_skbuff[entry] = skb;
 
+       /* We've used all descriptors we need for this skb, however,
+        * advance cur_tx so that it references a fresh descriptor.
+        * ndo_start_xmit will fill this descriptor the next time it's
+        * called and stmmac_tx_clean may clean up to this descriptor.
+        */
+       entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
        tx_q->cur_tx = entry;
 
        if (netif_msg_pktdata(priv)) {
@@ -3725,7 +3747,7 @@ static void sysfs_display_ring(void *head, int size, int extend_desc,
                        ep++;
                } else {
                        seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                                  i, (unsigned int)virt_to_phys(ep),
+                                  i, (unsigned int)virt_to_phys(p),
                                   le32_to_cpu(p->des0), le32_to_cpu(p->des1),
                                   le32_to_cpu(p->des2), le32_to_cpu(p->des3));
                        p++;
index 48fb72fc423c9f7c29aa713376867c90c32932af..f4b31d69f60eb7291191a9ae714ef4377db508bb 100644 (file)
@@ -59,7 +59,8 @@
 /* Enable Snapshot for Messages Relevant to Master */
 #define        PTP_TCR_TSMSTRENA       BIT(15)
 /* Select PTP packets for Taking Snapshots */
-#define        PTP_TCR_SNAPTYPSEL_1    GENMASK(17, 16)
+#define        PTP_TCR_SNAPTYPSEL_1    BIT(16)
+#define        PTP_GMAC4_TCR_SNAPTYPSEL_1      GENMASK(17, 16)
 /* Enable MAC address for PTP Frame Filtering */
 #define        PTP_TCR_TSENMACADDR     BIT(18)
 
index 5a90fed0626065613ba59fa7c5f8ca3c2dff6ef3..5b56c24b6ed2e0c45b5a40d32941527bb1539390 100644 (file)
@@ -411,13 +411,14 @@ static int vsw_port_remove(struct vio_dev *vdev)
 
        if (port) {
                del_timer_sync(&port->vio.timer);
+               del_timer_sync(&port->clean_timer);
 
                napi_disable(&port->napi);
+               unregister_netdev(port->dev);
 
                list_del_rcu(&port->list);
 
                synchronize_rcu();
-               del_timer_sync(&port->clean_timer);
                spin_lock_irqsave(&port->vp->lock, flags);
                sunvnet_port_rm_txq_common(port);
                spin_unlock_irqrestore(&port->vp->lock, flags);
@@ -427,7 +428,6 @@ static int vsw_port_remove(struct vio_dev *vdev)
 
                dev_set_drvdata(&vdev->dev, NULL);
 
-               unregister_netdev(port->dev);
                free_netdev(port->dev);
        }
 
index 1562ab4151e192a079fc2a54dec7f8c101bcd109..56ba411421f0a77bae5b4568fb273464472741f5 100644 (file)
@@ -90,7 +90,7 @@ int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)
        if (of_device_is_compatible(dev->of_node, "ti,dm816-emac"))
                return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
 
-       if (of_machine_is_compatible("ti,am4372"))
+       if (of_machine_is_compatible("ti,am43"))
                return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
 
        if (of_machine_is_compatible("ti,dra7"))
index 729a7da90b5bed279d58d72cfc53cfa6fc2e9c80..e6222e535019a076ea0d4cd4c902f12332f079b2 100644 (file)
@@ -1353,9 +1353,10 @@ int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe)
 
        tx_pipe->dma_channel = knav_dma_open_channel(dev,
                                tx_pipe->dma_chan_name, &config);
-       if (IS_ERR_OR_NULL(tx_pipe->dma_channel)) {
+       if (IS_ERR(tx_pipe->dma_channel)) {
                dev_err(dev, "failed opening tx chan(%s)\n",
                        tx_pipe->dma_chan_name);
+               ret = PTR_ERR(tx_pipe->dma_channel);
                goto err;
        }
 
@@ -1673,9 +1674,10 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
 
        netcp->rx_channel = knav_dma_open_channel(netcp->netcp_device->device,
                                        netcp->dma_chan_name, &config);
-       if (IS_ERR_OR_NULL(netcp->rx_channel)) {
+       if (IS_ERR(netcp->rx_channel)) {
                dev_err(netcp->ndev_dev, "failed opening rx chan(%s\n",
                        netcp->dma_chan_name);
+               ret = PTR_ERR(netcp->rx_channel);
                goto fail;
        }
 
index 897176fc5043bf0da12fe5dcb7a659c269fdf615..dd92950a4615c3aab559c6dc383a4e90ee539160 100644 (file)
@@ -2651,7 +2651,6 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
        case HWTSTAMP_FILTER_NONE:
                cpts_rx_enable(cpts, 0);
                break;
-       case HWTSTAMP_FILTER_ALL:
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
index dec5d563ab19091cdadd422eed9af8268ce5805e..199459bd69612478e596dc97248d2a40defd6db8 100644 (file)
@@ -1007,7 +1007,7 @@ static void geneve_setup(struct net_device *dev)
 
        dev->netdev_ops = &geneve_netdev_ops;
        dev->ethtool_ops = &geneve_ethtool_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
 
        SET_NETDEV_DEVTYPE(dev, &geneve_type);
 
@@ -1133,7 +1133,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
 
        /* make enough headroom for basic scenario */
        encap_len = GENEVE_BASE_HLEN + ETH_HLEN;
-       if (ip_tunnel_info_af(info) == AF_INET) {
+       if (!metadata && ip_tunnel_info_af(info) == AF_INET) {
                encap_len += sizeof(struct iphdr);
                dev->max_mtu -= sizeof(struct iphdr);
        } else {
@@ -1293,7 +1293,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
        if (nla_put_u32(skb, IFLA_GENEVE_ID, vni))
                goto nla_put_failure;
 
-       if (ip_tunnel_info_af(info) == AF_INET) {
+       if (rtnl_dereference(geneve->sock4)) {
                if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE,
                                    info->key.u.ipv4.dst))
                        goto nla_put_failure;
@@ -1302,8 +1302,10 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
                               !!(info->key.tun_flags & TUNNEL_CSUM)))
                        goto nla_put_failure;
 
+       }
+
 #if IS_ENABLED(CONFIG_IPV6)
-       } else {
+       if (rtnl_dereference(geneve->sock6)) {
                if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6,
                                     &info->key.u.ipv6.dst))
                        goto nla_put_failure;
@@ -1315,8 +1317,8 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
                if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
                               !geneve->use_udp6_rx_checksums))
                        goto nla_put_failure;
-#endif
        }
+#endif
 
        if (nla_put_u8(skb, IFLA_GENEVE_TTL, info->key.ttl) ||
            nla_put_u8(skb, IFLA_GENEVE_TOS, info->key.tos) ||
index 4fea1b3dfbb4457247c4bc98dc9378591c36ecd3..ca110cd2a4e42cdebed760bdad103627b556e2f7 100644 (file)
@@ -611,7 +611,7 @@ static const struct net_device_ops gtp_netdev_ops = {
 static void gtp_link_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &gtp_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 
        dev->hard_header_len = 0;
        dev->addr_len = 0;
@@ -873,7 +873,7 @@ static struct gtp_dev *gtp_find_dev(struct net *src_net, struct nlattr *nla[])
 
        /* Check if there's an existing gtpX device to configure */
        dev = dev_get_by_index_rcu(net, nla_get_u32(nla[GTPA_LINK]));
-       if (dev->netdev_ops == &gtp_netdev_ops)
+       if (dev && dev->netdev_ops == &gtp_netdev_ops)
                gtp = netdev_priv(dev);
 
        put_net(net);
index 922bf440e9f1cb2d20ba2d2419f73972b09714c3..021a8ec411ab8316d6080592e2469e37c912bc31 100644 (file)
@@ -311,7 +311,7 @@ static void sp_setup(struct net_device *dev)
 {
        /* Finish setting up the DEVICE info. */
        dev->netdev_ops         = &sp_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->mtu                = SIXP_MTU;
        dev->hard_header_len    = AX25_MAX_HEADER_LEN;
        dev->header_ops         = &ax25_header_ops;
index f62e7f325cf92edeca25c40a1d11e53166017049..78a6414c5fd994445c7e530065bd6cfa7e5ad213 100644 (file)
@@ -476,7 +476,7 @@ static const struct net_device_ops bpq_netdev_ops = {
 static void bpq_setup(struct net_device *dev)
 {
        dev->netdev_ops      = &bpq_netdev_ops;
-       dev->destructor      = free_netdev;
+       dev->needs_free_netdev = true;
 
        memcpy(dev->broadcast, &ax25_bcast, AX25_ADDR_LEN);
        memcpy(dev->dev_addr,  &ax25_defaddr, AX25_ADDR_LEN);
index 8c3633c1d0789718fc528b9873e8295e6ab6b09e..97e3bc60c3e7d111184f4c60ce4afe50757d1398 100644 (file)
@@ -576,6 +576,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case HDLCDRVCTL_CALIBRATE:
                if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
+               if (s->par.bitrate <= 0)
+                       return -EINVAL;
                if (bi.data.calibrate > INT_MAX / s->par.bitrate)
                        return -EINVAL;
                s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16;
index 262b2ea576a38e4bb7d1c442f2dfcbc2c40fa302..6066f1bcaf2d55e7be1708f1a96e592849611169 100644 (file)
@@ -171,6 +171,8 @@ struct rndis_device {
        spinlock_t request_lock;
        struct list_head req_list;
 
+       struct work_struct mcast_work;
+
        u8 hw_mac_adr[ETH_ALEN];
        u8 rss_key[NETVSC_HASH_KEYLEN];
        u16 ind_table[ITAB_NUM];
@@ -201,6 +203,7 @@ int rndis_filter_open(struct netvsc_device *nvdev);
 int rndis_filter_close(struct netvsc_device *nvdev);
 int rndis_filter_device_add(struct hv_device *dev,
                            struct netvsc_device_info *info);
+void rndis_filter_update(struct netvsc_device *nvdev);
 void rndis_filter_device_remove(struct hv_device *dev,
                                struct netvsc_device *nvdev);
 int rndis_filter_set_rss_param(struct rndis_device *rdev,
@@ -211,7 +214,6 @@ int rndis_filter_receive(struct net_device *ndev,
                         struct vmbus_channel *channel,
                         void *data, u32 buflen);
 
-int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
 int rndis_filter_set_device_mac(struct net_device *ndev, char *mac);
 
 void netvsc_switch_datapath(struct net_device *nv_dev, bool vf);
@@ -696,7 +698,6 @@ struct net_device_context {
        /* list protection */
        spinlock_t lock;
 
-       struct work_struct work;
        u32 msg_enable; /* debug level */
 
        u32 tx_checksum_mask;
index 4421a6d0037579bbff80ee909d42510947f77690..643c539a08badf1c723ca3460003293395945db5 100644 (file)
@@ -56,37 +56,12 @@ static int debug = -1;
 module_param(debug, int, S_IRUGO);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
-static void do_set_multicast(struct work_struct *w)
-{
-       struct net_device_context *ndevctx =
-               container_of(w, struct net_device_context, work);
-       struct hv_device *device_obj = ndevctx->device_ctx;
-       struct net_device *ndev = hv_get_drvdata(device_obj);
-       struct netvsc_device *nvdev = rcu_dereference(ndevctx->nvdev);
-       struct rndis_device *rdev;
-
-       if (!nvdev)
-               return;
-
-       rdev = nvdev->extension;
-       if (rdev == NULL)
-               return;
-
-       if (ndev->flags & IFF_PROMISC)
-               rndis_filter_set_packet_filter(rdev,
-                       NDIS_PACKET_TYPE_PROMISCUOUS);
-       else
-               rndis_filter_set_packet_filter(rdev,
-                       NDIS_PACKET_TYPE_BROADCAST |
-                       NDIS_PACKET_TYPE_ALL_MULTICAST |
-                       NDIS_PACKET_TYPE_DIRECTED);
-}
-
 static void netvsc_set_multicast_list(struct net_device *net)
 {
        struct net_device_context *net_device_ctx = netdev_priv(net);
+       struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
 
-       schedule_work(&net_device_ctx->work);
+       rndis_filter_update(nvdev);
 }
 
 static int netvsc_open(struct net_device *net)
@@ -123,8 +98,6 @@ static int netvsc_close(struct net_device *net)
 
        netif_tx_disable(net);
 
-       /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
-       cancel_work_sync(&net_device_ctx->work);
        ret = rndis_filter_close(nvdev);
        if (ret != 0) {
                netdev_err(net, "unable to close device (ret %d).\n", ret);
@@ -803,7 +776,7 @@ static int netvsc_set_channels(struct net_device *net,
            channels->rx_count || channels->tx_count || channels->other_count)
                return -EINVAL;
 
-       if (count > net->num_tx_queues || count > net->num_rx_queues)
+       if (count > net->num_tx_queues || count > VRSS_CHANNEL_MAX)
                return -EINVAL;
 
        if (!nvdev || nvdev->destroy)
@@ -1028,7 +1001,7 @@ static const struct {
 static int netvsc_get_sset_count(struct net_device *dev, int string_set)
 {
        struct net_device_context *ndc = netdev_priv(dev);
-       struct netvsc_device *nvdev = rcu_dereference(ndc->nvdev);
+       struct netvsc_device *nvdev = rtnl_dereference(ndc->nvdev);
 
        if (!nvdev)
                return -ENODEV;
@@ -1158,11 +1131,22 @@ netvsc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static void netvsc_poll_controller(struct net_device *net)
+static void netvsc_poll_controller(struct net_device *dev)
 {
-       /* As netvsc_start_xmit() works synchronous we don't have to
-        * trigger anything here.
-        */
+       struct net_device_context *ndc = netdev_priv(dev);
+       struct netvsc_device *ndev;
+       int i;
+
+       rcu_read_lock();
+       ndev = rcu_dereference(ndc->nvdev);
+       if (ndev) {
+               for (i = 0; i < ndev->num_chn; i++) {
+                       struct netvsc_channel *nvchan = &ndev->chan_table[i];
+
+                       napi_schedule(&nvchan->napi);
+               }
+       }
+       rcu_read_unlock();
 }
 #endif
 
@@ -1219,7 +1203,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
        rndis_dev = ndev->extension;
        if (indir) {
                for (i = 0; i < ITAB_NUM; i++)
-                       if (indir[i] >= dev->num_rx_queues)
+                       if (indir[i] >= VRSS_CHANNEL_MAX)
                                return -EINVAL;
 
                for (i = 0; i < ITAB_NUM; i++)
@@ -1552,7 +1536,6 @@ static int netvsc_probe(struct hv_device *dev,
        hv_set_drvdata(dev, net);
 
        INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
-       INIT_WORK(&net_device_ctx->work, do_set_multicast);
 
        spin_lock_init(&net_device_ctx->lock);
        INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
@@ -1622,7 +1605,6 @@ static int netvsc_remove(struct hv_device *dev)
        netif_device_detach(net);
 
        cancel_delayed_work_sync(&ndev_ctx->dwork);
-       cancel_work_sync(&ndev_ctx->work);
 
        /*
         * Call to the vsc driver to let it know that the device is being
index f9d5b0b8209a7ffffa07984ba6d942ddb011610b..cb79cd081f427d6a22c2d48427779593965e793c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "hyperv_net.h"
 
+static void rndis_set_multicast(struct work_struct *w);
 
 #define RNDIS_EXT_LEN PAGE_SIZE
 struct rndis_request {
@@ -76,6 +77,7 @@ static struct rndis_device *get_rndis_device(void)
        spin_lock_init(&device->request_lock);
 
        INIT_LIST_HEAD(&device->req_list);
+       INIT_WORK(&device->mcast_work, rndis_set_multicast);
 
        device->state = RNDIS_DEV_UNINITIALIZED;
 
@@ -815,7 +817,8 @@ static int rndis_filter_query_link_speed(struct rndis_device *dev)
        return ret;
 }
 
-int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
+static int rndis_filter_set_packet_filter(struct rndis_device *dev,
+                                         u32 new_filter)
 {
        struct rndis_request *request;
        struct rndis_set_request *set;
@@ -846,6 +849,28 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
        return ret;
 }
 
+static void rndis_set_multicast(struct work_struct *w)
+{
+       struct rndis_device *rdev
+               = container_of(w, struct rndis_device, mcast_work);
+
+       if (rdev->ndev->flags & IFF_PROMISC)
+               rndis_filter_set_packet_filter(rdev,
+                                              NDIS_PACKET_TYPE_PROMISCUOUS);
+       else
+               rndis_filter_set_packet_filter(rdev,
+                                              NDIS_PACKET_TYPE_BROADCAST |
+                                              NDIS_PACKET_TYPE_ALL_MULTICAST |
+                                              NDIS_PACKET_TYPE_DIRECTED);
+}
+
+void rndis_filter_update(struct netvsc_device *nvdev)
+{
+       struct rndis_device *rdev = nvdev->extension;
+
+       schedule_work(&rdev->mcast_work);
+}
+
 static int rndis_filter_init_device(struct rndis_device *dev)
 {
        struct rndis_request *request;
@@ -973,6 +998,9 @@ static int rndis_filter_close_device(struct rndis_device *dev)
        if (dev->state != RNDIS_DEV_DATAINITIALIZED)
                return 0;
 
+       /* Make sure rndis_set_multicast doesn't re-enable filter! */
+       cancel_work_sync(&dev->mcast_work);
+
        ret = rndis_filter_set_packet_filter(dev, 0);
        if (ret == -ENODEV)
                ret = 0;
index 312fce7302d3252903282599223063e7d97bb863..144ea5ae8ab4abda588cb6b23292c9f3ccf06c9c 100644 (file)
@@ -207,7 +207,6 @@ static void ifb_dev_free(struct net_device *dev)
                __skb_queue_purge(&txp->tq);
        }
        kfree(dp->tx_private);
-       free_netdev(dev);
 }
 
 static void ifb_setup(struct net_device *dev)
@@ -230,7 +229,8 @@ static void ifb_setup(struct net_device *dev)
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        netif_keep_dst(dev);
        eth_hw_addr_random(dev);
-       dev->destructor = ifb_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ifb_dev_free;
 }
 
 static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
index 618ed88fad0fc1d4e227f0e84fde74462b2bc496..7c7680c8f0e32e149167f7943dc02bdc9646da23 100644 (file)
@@ -632,7 +632,7 @@ void ipvlan_link_setup(struct net_device *dev)
        dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
        dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
        dev->netdev_ops = &ipvlan_netdev_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        dev->header_ops = &ipvlan_header_ops;
        dev->ethtool_ops = &ipvlan_ethtool_ops;
 }
index 8716b8c07febf5669b5fe21d78f1b68b4d10ea3f..6f3c805f72118b1b04b48cc501b8579caeddf37a 100644 (file)
@@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
          * are "42101001.sb" or "42101002.sb"
          */
         sprintf(stir421x_fw_name, "4210%4X.sb",
-                self->usbdev->descriptor.bcdDevice);
+               le16_to_cpu(self->usbdev->descriptor.bcdDevice));
         ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);
         if (ret < 0)
                 return ret;
index 224f65cb576bbf106a4779ef5f60b75f34903b1c..30612497643c08caa8a3bf352b13f784f729f725 100644 (file)
@@ -159,7 +159,6 @@ static void loopback_dev_free(struct net_device *dev)
 {
        dev_net(dev)->loopback_dev = NULL;
        free_percpu(dev->lstats);
-       free_netdev(dev);
 }
 
 static const struct net_device_ops loopback_ops = {
@@ -196,7 +195,8 @@ static void loopback_setup(struct net_device *dev)
        dev->ethtool_ops        = &loopback_ethtool_ops;
        dev->header_ops         = &eth_header_ops;
        dev->netdev_ops         = &loopback_ops;
-       dev->destructor         = loopback_dev_free;
+       dev->needs_free_netdev  = true;
+       dev->priv_destructor    = loopback_dev_free;
 }
 
 /* Setup and register the loopback device. */
index cdc347be68f23196d6ba820d21475260bc5bae3b..79411675f0e66376ecf2fa640b51c7172d8085d9 100644 (file)
@@ -2996,7 +2996,6 @@ static void macsec_free_netdev(struct net_device *dev)
        free_percpu(macsec->secy.tx_sc.stats);
 
        dev_put(real_dev);
-       free_netdev(dev);
 }
 
 static void macsec_setup(struct net_device *dev)
@@ -3006,7 +3005,8 @@ static void macsec_setup(struct net_device *dev)
        dev->max_mtu = ETH_MAX_MTU;
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->netdev_ops = &macsec_netdev_ops;
-       dev->destructor = macsec_free_netdev;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = macsec_free_netdev;
        SET_NETDEV_DEVTYPE(dev, &macsec_type);
 
        eth_zero_addr(dev->broadcast);
index b34eaaae03fd3f289aab4a90b11c05c587858ad2..72b801803aa4d450328a5df8c4c782fbb1d5e4cc 100644 (file)
 #define MACVLAN_HASH_SIZE      (1<<MACVLAN_HASH_BITS)
 #define MACVLAN_BC_QUEUE_LEN   1000
 
+#define MACVLAN_F_PASSTHRU     1
+#define MACVLAN_F_ADDRCHANGE   2
+
 struct macvlan_port {
        struct net_device       *dev;
        struct hlist_head       vlan_hash[MACVLAN_HASH_SIZE];
        struct list_head        vlans;
        struct sk_buff_head     bc_queue;
        struct work_struct      bc_work;
-       bool                    passthru;
+       u32                     flags;
        int                     count;
        struct hlist_head       vlan_source_hash[MACVLAN_HASH_SIZE];
        DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
+       unsigned char           perm_addr[ETH_ALEN];
 };
 
 struct macvlan_source_entry {
@@ -66,6 +70,31 @@ struct macvlan_skb_cb {
 
 static void macvlan_port_destroy(struct net_device *dev);
 
+static inline bool macvlan_passthru(const struct macvlan_port *port)
+{
+       return port->flags & MACVLAN_F_PASSTHRU;
+}
+
+static inline void macvlan_set_passthru(struct macvlan_port *port)
+{
+       port->flags |= MACVLAN_F_PASSTHRU;
+}
+
+static inline bool macvlan_addr_change(const struct macvlan_port *port)
+{
+       return port->flags & MACVLAN_F_ADDRCHANGE;
+}
+
+static inline void macvlan_set_addr_change(struct macvlan_port *port)
+{
+       port->flags |= MACVLAN_F_ADDRCHANGE;
+}
+
+static inline void macvlan_clear_addr_change(struct macvlan_port *port)
+{
+       port->flags &= ~MACVLAN_F_ADDRCHANGE;
+}
+
 /* Hash Ethernet address */
 static u32 macvlan_eth_hash(const unsigned char *addr)
 {
@@ -181,11 +210,12 @@ static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
 static bool macvlan_addr_busy(const struct macvlan_port *port,
                              const unsigned char *addr)
 {
-       /* Test to see if the specified multicast address is
+       /* Test to see if the specified address is
         * currently in use by the underlying device or
         * another macvlan.
         */
-       if (ether_addr_equal_64bits(port->dev->dev_addr, addr))
+       if (!macvlan_passthru(port) && !macvlan_addr_change(port) &&
+           ether_addr_equal_64bits(port->dev->dev_addr, addr))
                return true;
 
        if (macvlan_hash_lookup(port, addr))
@@ -445,7 +475,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
        }
 
        macvlan_forward_source(skb, port, eth->h_source);
-       if (port->passthru)
+       if (macvlan_passthru(port))
                vlan = list_first_or_null_rcu(&port->vlans,
                                              struct macvlan_dev, list);
        else
@@ -574,7 +604,7 @@ static int macvlan_open(struct net_device *dev)
        struct net_device *lowerdev = vlan->lowerdev;
        int err;
 
-       if (vlan->port->passthru) {
+       if (macvlan_passthru(vlan->port)) {
                if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC)) {
                        err = dev_set_promiscuity(lowerdev, 1);
                        if (err < 0)
@@ -649,7 +679,7 @@ static int macvlan_stop(struct net_device *dev)
        dev_uc_unsync(lowerdev, dev);
        dev_mc_unsync(lowerdev, dev);
 
-       if (vlan->port->passthru) {
+       if (macvlan_passthru(vlan->port)) {
                if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
                        dev_set_promiscuity(lowerdev, -1);
                goto hash_del;
@@ -672,6 +702,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
 {
        struct macvlan_dev *vlan = netdev_priv(dev);
        struct net_device *lowerdev = vlan->lowerdev;
+       struct macvlan_port *port = vlan->port;
        int err;
 
        if (!(dev->flags & IFF_UP)) {
@@ -682,7 +713,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
                if (macvlan_addr_busy(vlan->port, addr))
                        return -EBUSY;
 
-               if (!vlan->port->passthru) {
+               if (!macvlan_passthru(port)) {
                        err = dev_uc_add(lowerdev, addr);
                        if (err)
                                return err;
@@ -692,6 +723,15 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
 
                macvlan_hash_change_addr(vlan, addr);
        }
+       if (macvlan_passthru(port) && !macvlan_addr_change(port)) {
+               /* Since addr_change isn't set, we are here due to lower
+                * device change.  Save the lower-dev address so we can
+                * restore it later.
+                */
+               ether_addr_copy(vlan->port->perm_addr,
+                               lowerdev->dev_addr);
+       }
+       macvlan_clear_addr_change(port);
        return 0;
 }
 
@@ -703,7 +743,12 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
+       /* If the addresses are the same, this is a no-op */
+       if (ether_addr_equal(dev->dev_addr, addr->sa_data))
+               return 0;
+
        if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
+               macvlan_set_addr_change(vlan->port);
                dev_set_mac_address(vlan->lowerdev, addr);
                return 0;
        }
@@ -789,10 +834,12 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
  */
 static struct lock_class_key macvlan_netdev_addr_lock_key;
 
-#define ALWAYS_ON_FEATURES \
-       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX | \
+#define ALWAYS_ON_OFFLOADS \
+       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
         NETIF_F_GSO_ROBUST)
 
+#define ALWAYS_ON_FEATURES (ALWAYS_ON_OFFLOADS | NETIF_F_LLTX)
+
 #define MACVLAN_FEATURES \
        (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
         NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \
@@ -827,6 +874,7 @@ static int macvlan_init(struct net_device *dev)
        dev->features           |= ALWAYS_ON_FEATURES;
        dev->hw_features        |= NETIF_F_LRO;
        dev->vlan_features      = lowerdev->vlan_features & MACVLAN_FEATURES;
+       dev->vlan_features      |= ALWAYS_ON_OFFLOADS;
        dev->gso_max_size       = lowerdev->gso_max_size;
        dev->gso_max_segs       = lowerdev->gso_max_segs;
        dev->hard_header_len    = lowerdev->hard_header_len;
@@ -925,7 +973,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
        /* Support unicast filter only on passthru devices.
         * Multicast filter should be allowed on all devices.
         */
-       if (!vlan->port->passthru && is_unicast_ether_addr(addr))
+       if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))
                return -EOPNOTSUPP;
 
        if (flags & NLM_F_REPLACE)
@@ -949,7 +997,7 @@ static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
        /* Support unicast filter only on passthru devices.
         * Multicast filter should be allowed on all devices.
         */
-       if (!vlan->port->passthru && is_unicast_ether_addr(addr))
+       if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))
                return -EOPNOTSUPP;
 
        if (is_unicast_ether_addr(addr))
@@ -1089,7 +1137,7 @@ void macvlan_common_setup(struct net_device *dev)
        netif_keep_dst(dev);
        dev->priv_flags        |= IFF_UNICAST_FLT;
        dev->netdev_ops         = &macvlan_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->header_ops         = &macvlan_hard_header_ops;
        dev->ethtool_ops        = &macvlan_ethtool_ops;
 }
@@ -1117,8 +1165,8 @@ static int macvlan_port_create(struct net_device *dev)
        if (port == NULL)
                return -ENOMEM;
 
-       port->passthru = false;
        port->dev = dev;
+       ether_addr_copy(port->perm_addr, dev->dev_addr);
        INIT_LIST_HEAD(&port->vlans);
        for (i = 0; i < MACVLAN_HASH_SIZE; i++)
                INIT_HLIST_HEAD(&port->vlan_hash[i]);
@@ -1158,6 +1206,18 @@ static void macvlan_port_destroy(struct net_device *dev)
                kfree_skb(skb);
        }
 
+       /* If the lower device address has been changed by passthru
+        * macvlan, put it back.
+        */
+       if (macvlan_passthru(port) &&
+           !ether_addr_equal(port->dev->dev_addr, port->perm_addr)) {
+               struct sockaddr sa;
+
+               sa.sa_family = port->dev->type;
+               memcpy(&sa.sa_data, port->perm_addr, port->dev->addr_len);
+               dev_set_mac_address(port->dev, &sa);
+       }
+
        kfree(port);
 }
 
@@ -1323,7 +1383,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
        port = macvlan_port_get_rtnl(lowerdev);
 
        /* Only 1 macvlan device can be created in passthru mode */
-       if (port->passthru) {
+       if (macvlan_passthru(port)) {
                /* The macvlan port must be not created this time,
                 * still goto destroy_macvlan_port for readability.
                 */
@@ -1349,7 +1409,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
                        err = -EINVAL;
                        goto destroy_macvlan_port;
                }
-               port->passthru = true;
+               macvlan_set_passthru(port);
                eth_hw_addr_inherit(dev, lowerdev);
        }
 
@@ -1431,7 +1491,7 @@ static int macvlan_changelink(struct net_device *dev,
        if (data && data[IFLA_MACVLAN_FLAGS]) {
                __u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
                bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC;
-               if (vlan->port->passthru && promisc) {
+               if (macvlan_passthru(vlan->port) && promisc) {
                        int err;
 
                        if (flags & MACVLAN_FLAG_NOPROMISC)
@@ -1594,7 +1654,7 @@ static int macvlan_device_event(struct notifier_block *unused,
                }
                break;
        case NETDEV_CHANGEADDR:
-               if (!port->passthru)
+               if (!macvlan_passthru(port))
                        return NOTIFY_DONE;
 
                vlan = list_first_entry_or_null(&port->vlans,
index 06ee6395117f9df71a07d22326bc6c15c1e87f2e..0e27920c2b6b6219e70871ad13031bf56711907e 100644 (file)
@@ -358,7 +358,7 @@ static ssize_t enabled_store(struct config_item *item,
                if (err)
                        goto out_unlock;
 
-               pr_info("netconsole: network logging started\n");
+               pr_info("network logging started\n");
        } else {        /* false */
                /* We need to disable the netconsole before cleaning it up
                 * otherwise we might end up in write_msg() with
index b91603835d2680aa08911da7870ea176c5dd0792..c4b3362da4a2e33184b02dff0df3082b4d7e45e4 100644 (file)
@@ -113,7 +113,7 @@ static void nlmon_setup(struct net_device *dev)
 
        dev->netdev_ops = &nlmon_ops;
        dev->ethtool_ops = &nlmon_ethtool_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
 
        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
                        NETIF_F_HIGHDMA | NETIF_F_LLTX;
index 60ffc9da6a286272d84e8dc3f4326eb908e7961a..3ab6c58d4be6fd42812bfd783715c13ef42e13c4 100644 (file)
@@ -108,7 +108,7 @@ config MDIO_MOXART
 config MDIO_OCTEON
        tristate "Octeon and some ThunderX SOCs MDIO buses"
        depends on 64BIT
-       depends on HAS_IOMEM
+       depends on HAS_IOMEM && OF_MDIO
        select MDIO_CAVIUM
        help
          This module provides a driver for the Octeon and ThunderX MDIO
@@ -127,6 +127,7 @@ config MDIO_THUNDER
        tristate "ThunderX SOCs MDIO buses"
        depends on 64BIT
        depends on PCI
+       depends on !(MDIO_DEVICE=y && PHYLIB=m)
        select MDIO_CAVIUM
        help
          This driver supports the MDIO interfaces found on Cavium
index ed0d10f54f2607533868dfd10e6bc9d0e09050de..c3065236ffcca6839d1326e60b96ac280787d2ee 100644 (file)
@@ -908,7 +908,7 @@ static void decode_txts(struct dp83640_private *dp83640,
        if (overflow) {
                pr_debug("tx timestamp queue overflow, count %d\n", overflow);
                while (skb) {
-                       skb_complete_tx_timestamp(skb, NULL);
+                       kfree_skb(skb);
                        skb = skb_dequeue(&dp83640->tx_queue);
                }
                return;
index 272b051a019975110aa1d117da993cf18cb98816..57297ba239871c631baef1dcfc2c30a66fdf3bba 100644 (file)
@@ -255,34 +255,6 @@ static int marvell_config_aneg(struct phy_device *phydev)
 {
        int err;
 
-       /* The Marvell PHY has an errata which requires
-        * that certain registers get written in order
-        * to restart autonegotiation */
-       err = phy_write(phydev, MII_BMCR, BMCR_RESET);
-
-       if (err < 0)
-               return err;
-
-       err = phy_write(phydev, 0x1d, 0x1f);
-       if (err < 0)
-               return err;
-
-       err = phy_write(phydev, 0x1e, 0x200c);
-       if (err < 0)
-               return err;
-
-       err = phy_write(phydev, 0x1d, 0x5);
-       if (err < 0)
-               return err;
-
-       err = phy_write(phydev, 0x1e, 0);
-       if (err < 0)
-               return err;
-
-       err = phy_write(phydev, 0x1e, 0x100);
-       if (err < 0)
-               return err;
-
        err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
        if (err < 0)
                return err;
@@ -316,6 +288,42 @@ static int marvell_config_aneg(struct phy_device *phydev)
        return 0;
 }
 
+static int m88e1101_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       /* This Marvell PHY has an errata which requires
+        * that certain registers get written in order
+        * to restart autonegotiation
+        */
+       err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1d, 0x1f);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0x200c);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1d, 0x5);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0);
+       if (err < 0)
+               return err;
+
+       err = phy_write(phydev, 0x1e, 0x100);
+       if (err < 0)
+               return err;
+
+       return marvell_config_aneg(phydev);
+}
+
 static int m88e1111_config_aneg(struct phy_device *phydev)
 {
        int err;
@@ -1119,8 +1127,6 @@ static int marvell_read_status_page(struct phy_device *phydev, int page)
                if (adv < 0)
                        return adv;
 
-               lpa &= adv;
-
                if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
                        phydev->duplex = DUPLEX_FULL;
                else
@@ -1892,7 +1898,7 @@ static struct phy_driver marvell_drivers[] = {
                .flags = PHY_HAS_INTERRUPT,
                .probe = marvell_probe,
                .config_init = &marvell_config_init,
-               .config_aneg = &marvell_config_aneg,
+               .config_aneg = &m88e1101_config_aneg,
                .read_status = &genphy_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
index 963838d4fac12428e0c01f88537a72b4a2fd8703..599ce24c514f1b0eb1e8a6df1e3a0362f53bee26 100644 (file)
@@ -122,10 +122,9 @@ int mdio_mux_init(struct device *dev,
        pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
        if (pb == NULL) {
                ret_val = -ENOMEM;
-               goto err_parent_bus;
+               goto err_pb_kz;
        }
 
-
        pb->switch_data = data;
        pb->switch_fn = switch_fn;
        pb->current_child = -1;
@@ -154,6 +153,7 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus = mdiobus_alloc();
                if (!cb->mii_bus) {
                        ret_val = -ENOMEM;
+                       devm_kfree(dev, cb);
                        of_node_put(child_bus_node);
                        break;
                }
@@ -170,7 +170,6 @@ int mdio_mux_init(struct device *dev,
                        mdiobus_free(cb->mii_bus);
                        devm_kfree(dev, cb);
                } else {
-                       of_node_get(child_bus_node);
                        cb->next = pb->children;
                        pb->children = cb;
                }
@@ -181,9 +180,11 @@ int mdio_mux_init(struct device *dev,
                return 0;
        }
 
+       devm_kfree(dev, pb);
+err_pb_kz:
        /* balance the reference of_mdio_find_bus() took */
-       put_device(&pb->mii_bus->dev);
-
+       if (!mux_bus)
+               put_device(&parent_bus->dev);
 err_parent_bus:
        of_node_put(parent_bus_node);
        return ret_val;
index a898e5c4ef1b465768c3216fc1985382c23eba89..f99c21f78b639fc1e6b984a20383f62021b757eb 100644 (file)
@@ -364,9 +364,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
 
        mutex_init(&bus->mdio_lock);
 
-       if (bus->reset)
-               bus->reset(bus);
-
        /* de-assert bus level PHY GPIO resets */
        if (bus->num_reset_gpios > 0) {
                bus->reset_gpiod = devm_kcalloc(&bus->dev,
@@ -396,6 +393,9 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
                }
        }
 
+       if (bus->reset)
+               bus->reset(bus);
+
        for (i = 0; i < PHY_MAX_ADDR; i++) {
                if ((bus->phy_mask & (1 << i)) == 0) {
                        struct phy_device *phydev;
@@ -658,6 +658,18 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
        return 0;
 }
 
+static int mdio_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       int rc;
+
+       /* Some devices have extra OF data and an OF-style MODALIAS */
+       rc = of_device_uevent_modalias(dev, env);
+       if (rc != -ENODEV)
+               return rc;
+
+       return 0;
+}
+
 #ifdef CONFIG_PM
 static int mdio_bus_suspend(struct device *dev)
 {
@@ -708,6 +720,7 @@ static const struct dev_pm_ops mdio_bus_pm_ops = {
 struct bus_type mdio_bus_type = {
        .name           = "mdio_bus",
        .match          = mdio_bus_match,
+       .uevent         = mdio_uevent,
        .pm             = MDIO_BUS_PM_OPS,
 };
 EXPORT_SYMBOL(mdio_bus_type);
index 6a5fd18f062c4ea400bc8036d787a94fe5108a34..8b2038844ba96a4a86c5b42aca4fa59fe96ecca2 100644 (file)
@@ -268,23 +268,12 @@ out:
        return ret;
 }
 
-static int kszphy_config_init(struct phy_device *phydev)
+/* Some config bits need to be set again on resume, handle them here. */
+static int kszphy_config_reset(struct phy_device *phydev)
 {
        struct kszphy_priv *priv = phydev->priv;
-       const struct kszphy_type *type;
        int ret;
 
-       if (!priv)
-               return 0;
-
-       type = priv->type;
-
-       if (type->has_broadcast_disable)
-               kszphy_broadcast_disable(phydev);
-
-       if (type->has_nand_tree_disable)
-               kszphy_nand_tree_disable(phydev);
-
        if (priv->rmii_ref_clk_sel) {
                ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val);
                if (ret) {
@@ -295,11 +284,30 @@ static int kszphy_config_init(struct phy_device *phydev)
        }
 
        if (priv->led_mode >= 0)
-               kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
+               kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);
 
        return 0;
 }
 
+static int kszphy_config_init(struct phy_device *phydev)
+{
+       struct kszphy_priv *priv = phydev->priv;
+       const struct kszphy_type *type;
+
+       if (!priv)
+               return 0;
+
+       type = priv->type;
+
+       if (type->has_broadcast_disable)
+               kszphy_broadcast_disable(phydev);
+
+       if (type->has_nand_tree_disable)
+               kszphy_nand_tree_disable(phydev);
+
+       return kszphy_config_reset(phydev);
+}
+
 static int ksz8041_config_init(struct phy_device *phydev)
 {
        struct device_node *of_node = phydev->mdio.dev.of_node;
@@ -611,6 +619,8 @@ static int ksz9031_read_status(struct phy_device *phydev)
        if ((regval & 0xFF) == 0xFF) {
                phy_init_hw(phydev);
                phydev->link = 0;
+               if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
+                       phydev->drv->config_intr(phydev);
        }
 
        return 0;
@@ -700,8 +710,14 @@ static int kszphy_suspend(struct phy_device *phydev)
 
 static int kszphy_resume(struct phy_device *phydev)
 {
+       int ret;
+
        genphy_resume(phydev);
 
+       ret = kszphy_config_reset(phydev);
+       if (ret)
+               return ret;
+
        /* Enable PHY Interrupts */
        if (phy_interrupt_is_valid(phydev)) {
                phydev->interrupts = PHY_INTERRUPT_ENABLED;
index 82ab8fb82587553fefc1d05bbff06d4a76bc9679..eebb0e1c70ff51a40189fd9690217c34ce9bb4cb 100644 (file)
@@ -54,6 +54,8 @@ static const char *phy_speed_to_str(int speed)
                return "5Gbps";
        case SPEED_10000:
                return "10Gbps";
+       case SPEED_14000:
+               return "14Gbps";
        case SPEED_20000:
                return "20Gbps";
        case SPEED_25000:
@@ -241,7 +243,7 @@ static const struct phy_setting settings[] = {
  * phy_lookup_setting - lookup a PHY setting
  * @speed: speed to match
  * @duplex: duplex to match
- * @feature: allowed link modes
+ * @features: allowed link modes
  * @exact: an exact match is required
  *
  * Search the settings array for a setting that matches the speed and
index 1da31dc47f863845d50823b69e51f2abab5bf3f0..74b907206aa749d894531005716a0c6dd3d0ec1f 100644 (file)
@@ -629,7 +629,7 @@ static void sl_uninit(struct net_device *dev)
 static void sl_free_netdev(struct net_device *dev)
 {
        int i = dev->base_addr;
-       free_netdev(dev);
+
        slip_devs[i] = NULL;
 }
 
@@ -651,7 +651,8 @@ static const struct net_device_ops sl_netdev_ops = {
 static void sl_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &sl_netdev_ops;
-       dev->destructor         = sl_free_netdev;
+       dev->needs_free_netdev  = true;
+       dev->priv_destructor    = sl_free_netdev;
 
        dev->hard_header_len    = 0;
        dev->addr_len           = 0;
@@ -1369,8 +1370,6 @@ static void __exit slip_exit(void)
                if (sl->tty) {
                        printk(KERN_ERR "%s: tty discipline still running\n",
                               dev->name);
-                       /* Intentionally leak the control block. */
-                       dev->destructor = NULL;
                }
 
                unregister_netdev(dev);
index 6c5d5ef46f75aa9a9089ac80bbee30a7f579b016..fba8c136aa7c1513b288e641cfe8cd6dca304ccd 100644 (file)
@@ -1643,7 +1643,6 @@ static void team_destructor(struct net_device *dev)
        struct team *team = netdev_priv(dev);
 
        free_percpu(team->pcpu_stats);
-       free_netdev(dev);
 }
 
 static int team_open(struct net_device *dev)
@@ -2079,7 +2078,8 @@ static void team_setup(struct net_device *dev)
 
        dev->netdev_ops = &team_netdev_ops;
        dev->ethtool_ops = &team_ethtool_ops;
-       dev->destructor = team_destructor;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = team_destructor;
        dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->priv_flags |= IFF_TEAM;
index bbd707b9ef7a6a305804ed0d56c3fc0e1db7d565..9ee7d4275640919f2293182cb47dca41412975ba 100644 (file)
@@ -1560,7 +1560,6 @@ static void tun_free_netdev(struct net_device *dev)
        free_percpu(tun->pcpu_stats);
        tun_flow_uninit(tun);
        security_tun_dev_free_security(tun->security);
-       free_netdev(dev);
 }
 
 static void tun_setup(struct net_device *dev)
@@ -1571,7 +1570,8 @@ static void tun_setup(struct net_device *dev)
        tun->group = INVALID_GID;
 
        dev->ethtool_ops = &tun_ethtool_ops;
-       dev->destructor = tun_free_netdev;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = tun_free_netdev;
        /* We prefer our own queue length */
        dev->tx_queue_len = TUN_READQ_SIZE;
 }
index 51cf60092a18e33924f52c568d91a33f30828b21..4037ab27734ae76fcfedafc8ce40f74f1549fcfb 100644 (file)
@@ -1722,6 +1722,18 @@ static const struct driver_info lenovo_info = {
        .tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info belkin_info = {
+       .description = "Belkin USB Ethernet Adapter",
+       .bind   = ax88179_bind,
+       .unbind = ax88179_unbind,
+       .status = ax88179_status,
+       .link_reset = ax88179_link_reset,
+       .reset  = ax88179_reset,
+       .flags  = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = ax88179_rx_fixup,
+       .tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct usb_device_id products[] = {
 {
        /* ASIX AX88179 10/100/1000 */
@@ -1751,6 +1763,10 @@ static const struct usb_device_id products[] = {
        /* Lenovo OneLinkDock Gigabit LAN */
        USB_DEVICE(0x17ef, 0x304b),
        .driver_info = (unsigned long)&lenovo_info,
+}, {
+       /* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */
+       USB_DEVICE(0x050d, 0x0128),
+       .driver_info = (unsigned long)&belkin_info,
 },
        { },
 };
index eb52de8205f0d48044bcb6c1302ce7bda779128e..c7a350bbaaa7c881a831ec8ed7b4b59dd83c6de9 100644 (file)
@@ -298,7 +298,7 @@ static void usbpn_setup(struct net_device *dev)
        dev->addr_len           = 1;
        dev->tx_queue_len       = 3;
 
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 }
 
 /*
index f3ae88fdf332e890ac8273e3df1ca7dd53092c07..8ab281b478f23bd98d71b896a0c00c4fdba7dacc 100644 (file)
@@ -310,6 +310,26 @@ skip:
                return -ENODEV;
        }
 
+       return 0;
+
+bad_desc:
+       dev_info(&dev->udev->dev, "bad CDC descriptors\n");
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+
+
+/* like usbnet_generic_cdc_bind() but handles filter initialization
+ * correctly
+ */
+int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       int rv;
+
+       rv = usbnet_generic_cdc_bind(dev, intf);
+       if (rv < 0)
+               goto bail_out;
+
        /* Some devices don't initialise properly. In particular
         * the packet filter is not reset. There are devices that
         * don't do reset all the way. So the packet filter should
@@ -317,13 +337,10 @@ skip:
         */
        usbnet_cdc_update_filter(dev);
 
-       return 0;
-
-bad_desc:
-       dev_info(&dev->udev->dev, "bad CDC descriptors\n");
-       return -ENODEV;
+bail_out:
+       return rv;
 }
-EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);
 
 void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
@@ -417,7 +434,7 @@ int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
                        < sizeof(struct cdc_state)));
 
-       status = usbnet_generic_cdc_bind(dev, intf);
+       status = usbnet_ether_cdc_bind(dev, intf);
        if (status < 0)
                return status;
 
index c4f1c363e24b89404c6834312074f8a4451ded50..9df3c1ffff355c491ab7f0a38bdddd0276cfff92 100644 (file)
@@ -310,8 +310,8 @@ static int get_mac_address(struct usbnet *dev, unsigned char *data)
        int rd_mac_len = 0;
 
        netdev_dbg(dev->net, "get_mac_address:\n\tusbnet VID:%0x PID:%0x\n",
-                  dev->udev->descriptor.idVendor,
-                  dev->udev->descriptor.idProduct);
+                  le16_to_cpu(dev->udev->descriptor.idVendor),
+                  le16_to_cpu(dev->udev->descriptor.idProduct));
 
        memset(mac_addr, 0, sizeof(mac_addr));
        rd_mac_len = control_read(dev, REQUEST_READ, 0,
index d7165767ca9d380ed4ab03e0ac592a8ee3a69040..32a22f4e8356422ba144a3e3485810537afaad2c 100644 (file)
@@ -123,7 +123,7 @@ static void qmimux_setup(struct net_device *dev)
        dev->addr_len        = 0;
        dev->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
        dev->netdev_ops      = &qmimux_netdev_ops;
-       dev->destructor      = free_netdev;
+       dev->needs_free_netdev = true;
 }
 
 static struct net_device *qmimux_find_dev(struct usbnet *dev, u8 mux_id)
@@ -1192,10 +1192,14 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x9056, 8)},    /* Sierra Wireless Modem */
        {QMI_FIXED_INTF(0x1199, 0x9057, 8)},
        {QMI_FIXED_INTF(0x1199, 0x9061, 8)},    /* Sierra Wireless Modem */
+       {QMI_FIXED_INTF(0x1199, 0x9063, 8)},    /* Sierra Wireless EM7305 */
+       {QMI_FIXED_INTF(0x1199, 0x9063, 10)},   /* Sierra Wireless EM7305 */
        {QMI_FIXED_INTF(0x1199, 0x9071, 8)},    /* Sierra Wireless MC74xx */
        {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx */
        {QMI_FIXED_INTF(0x1199, 0x9079, 8)},    /* Sierra Wireless EM74xx */
        {QMI_FIXED_INTF(0x1199, 0x9079, 10)},   /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x907b, 8)},    /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x907b, 10)},   /* Sierra Wireless EM74xx */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
@@ -1204,6 +1208,8 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},    /* Telit ME910 */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
        {QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)}, /* Telit LE920, LE920A4 */
+       {QMI_FIXED_INTF(0x1c9e, 0x9801, 3)},    /* Telewell TW-3G HSPA+ */
+       {QMI_FIXED_INTF(0x1c9e, 0x9803, 4)},    /* Telewell TW-3G HSPA+ */
        {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},    /* XS Stick W100-2 from 4G Systems */
        {QMI_FIXED_INTF(0x0b3c, 0xc000, 4)},    /* Olivetti Olicard 100 */
        {QMI_FIXED_INTF(0x0b3c, 0xc001, 4)},    /* Olivetti Olicard 120 */
index ddc62cb69be828a730e6ed32ecc9ee951fef8d3b..1a419a45e2a2e77e07e1746c9035230da465424d 100644 (file)
@@ -4368,6 +4368,8 @@ static u8 rtl_get_version(struct usb_interface *intf)
                break;
        }
 
+       dev_dbg(&intf->dev, "Detected version 0x%04x\n", version);
+
        return version;
 }
 
index 765400b62168436b278d8a09fa0dd1fd8566bcb7..2dfca96a63b60283b89efab676932a711024a499 100644 (file)
@@ -681,7 +681,7 @@ static int smsc95xx_set_features(struct net_device *netdev,
        if (ret < 0)
                return ret;
 
-       if (features & NETIF_F_HW_CSUM)
+       if (features & NETIF_F_IP_CSUM)
                read_buf |= Tx_COE_EN_;
        else
                read_buf &= ~Tx_COE_EN_;
@@ -1279,12 +1279,19 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 
        spin_lock_init(&pdata->mac_cr_lock);
 
+       /* LAN95xx devices do not alter the computed checksum of 0 to 0xffff.
+        * RFC 2460, ipv6 UDP calculated checksum yields a result of zero must
+        * be changed to 0xffff. RFC 768, ipv4 UDP computed checksum is zero,
+        * it is transmitted as all ones. The zero transmitted checksum means
+        * transmitter generated no checksum. Hence, enable csum offload only
+        * for ipv4 packets.
+        */
        if (DEFAULT_TX_CSUM_ENABLE)
-               dev->net->features |= NETIF_F_HW_CSUM;
+               dev->net->features |= NETIF_F_IP_CSUM;
        if (DEFAULT_RX_CSUM_ENABLE)
                dev->net->features |= NETIF_F_RXCSUM;
 
-       dev->net->hw_features = NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+       dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
 
        smsc95xx_init_mac_address(dev);
 
index 38f0f03a29c8898131110a620e73da4776cb7020..364fa9d11d1a1e74c59f830fe23a9b9e5b37fcee 100644 (file)
@@ -222,7 +222,6 @@ static int veth_dev_init(struct net_device *dev)
 static void veth_dev_free(struct net_device *dev)
 {
        free_percpu(dev->vstats);
-       free_netdev(dev);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -317,7 +316,8 @@ static void veth_setup(struct net_device *dev)
                               NETIF_F_HW_VLAN_STAG_TX |
                               NETIF_F_HW_VLAN_CTAG_RX |
                               NETIF_F_HW_VLAN_STAG_RX);
-       dev->destructor = veth_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = veth_dev_free;
        dev->max_mtu = ETH_MAX_MTU;
 
        dev->hw_features = VETH_FEATURES;
@@ -383,7 +383,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
                tbp = tb;
        }
 
-       if (tbp[IFLA_IFNAME]) {
+       if (ifmp && tbp[IFLA_IFNAME]) {
                nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
                name_assign_type = NET_NAME_USER;
        } else {
@@ -402,7 +402,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
                return PTR_ERR(peer);
        }
 
-       if (tbp[IFLA_ADDRESS] == NULL)
+       if (!ifmp || !tbp[IFLA_ADDRESS])
                eth_hw_addr_random(peer);
 
        if (ifmp && (dev->ifindex != 0))
index 9320d96a1632bbebe8bd1d4a04059e0df631ac19..143d8a95a60d97b9036cd092d15b0bd8f8e361f8 100644 (file)
@@ -869,7 +869,7 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq,
        unsigned int len;
 
        len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len),
-                               rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len);
+                               rq->min_buf_len, PAGE_SIZE - hdr_len);
        return ALIGN(len, L1_CACHE_BYTES);
 }
 
@@ -1797,6 +1797,7 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
        flush_work(&vi->config_work);
 
        netif_device_detach(vi->dev);
+       netif_tx_disable(vi->dev);
        cancel_delayed_work_sync(&vi->refill);
 
        if (netif_running(vi->dev)) {
@@ -1989,6 +1990,7 @@ static const struct net_device_ops virtnet_netdev = {
        .ndo_poll_controller = virtnet_netpoll,
 #endif
        .ndo_xdp                = virtnet_xdp,
+       .ndo_features_check     = passthru_features_check,
 };
 
 static void virtnet_config_changed_work(struct work_struct *work)
@@ -2143,7 +2145,8 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
        unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len;
        unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size);
 
-       return max(min_buf_len, hdr_len);
+       return max(max(min_buf_len, hdr_len) - hdr_len,
+                  (unsigned int)GOOD_PACKET_LEN);
 }
 
 static int virtnet_find_vqs(struct virtnet_info *vi)
index 25bc764ae7dc4c4dc9a5e6cb4f17f89f62464f4c..d1c7029ded7cefef468eb035f971b969da612bf5 100644 (file)
@@ -2962,6 +2962,11 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter)
        /* we need to enable NAPI, otherwise dev_close will deadlock */
        for (i = 0; i < adapter->num_rx_queues; i++)
                napi_enable(&adapter->rx_queue[i].napi);
+       /*
+        * Need to clear the quiesce bit to ensure that vmxnet3_close
+        * can quiesce the device properly
+        */
+       clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
        dev_close(adapter->netdev);
 }
 
index ceda5861da780bc64b6070acec7f37de9a8fa3e5..022c0b5f9844242bc08b766eabf208fb41d9e03d 100644 (file)
 #include <net/addrconf.h>
 #include <net/l3mdev.h>
 #include <net/fib_rules.h>
+#include <net/netns/generic.h>
 
 #define DRV_NAME       "vrf"
 #define DRV_VERSION    "1.0"
 
 #define FIB_RULE_PREF  1000       /* default preference for FIB rules */
-static bool add_fib_rules = true;
+
+static unsigned int vrf_net_id;
 
 struct net_vrf {
        struct rtable __rcu     *rth;
@@ -989,6 +991,7 @@ static u32 vrf_fib_table(const struct net_device *dev)
 
 static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       kfree_skb(skb);
        return 0;
 }
 
@@ -998,7 +1001,7 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook,
 {
        struct net *net = dev_net(dev);
 
-       if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0)
+       if (nf_hook(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) != 1)
                skb = NULL;    /* kfree_skb(skb) handled by nf code */
 
        return skb;
@@ -1347,7 +1350,7 @@ static void vrf_setup(struct net_device *dev)
        dev->netdev_ops = &vrf_netdev_ops;
        dev->l3mdev_ops = &vrf_l3mdev_ops;
        dev->ethtool_ops = &vrf_ethtool_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
 
        /* Fill in device structure with ethernet-generic values. */
        eth_hw_addr_random(dev);
@@ -1393,6 +1396,8 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
                       struct nlattr *tb[], struct nlattr *data[])
 {
        struct net_vrf *vrf = netdev_priv(dev);
+       bool *add_fib_rules;
+       struct net *net;
        int err;
 
        if (!data || !data[IFLA_VRF_TABLE])
@@ -1408,13 +1413,15 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
        if (err)
                goto out;
 
-       if (add_fib_rules) {
+       net = dev_net(dev);
+       add_fib_rules = net_generic(net, vrf_net_id);
+       if (*add_fib_rules) {
                err = vrf_add_fib_rules(dev);
                if (err) {
                        unregister_netdevice(dev);
                        goto out;
                }
-               add_fib_rules = false;
+               *add_fib_rules = false;
        }
 
 out:
@@ -1497,16 +1504,38 @@ static struct notifier_block vrf_notifier_block __read_mostly = {
        .notifier_call = vrf_device_event,
 };
 
+/* Initialize per network namespace state */
+static int __net_init vrf_netns_init(struct net *net)
+{
+       bool *add_fib_rules = net_generic(net, vrf_net_id);
+
+       *add_fib_rules = true;
+
+       return 0;
+}
+
+static struct pernet_operations vrf_net_ops __net_initdata = {
+       .init = vrf_netns_init,
+       .id   = &vrf_net_id,
+       .size = sizeof(bool),
+};
+
 static int __init vrf_init_module(void)
 {
        int rc;
 
        register_netdevice_notifier(&vrf_notifier_block);
 
-       rc = rtnl_link_register(&vrf_link_ops);
+       rc = register_pernet_subsys(&vrf_net_ops);
        if (rc < 0)
                goto error;
 
+       rc = rtnl_link_register(&vrf_link_ops);
+       if (rc < 0) {
+               unregister_pernet_subsys(&vrf_net_ops);
+               goto error;
+       }
+
        return 0;
 
 error:
index 7f0136f2dd9d6167acc9b125fb03d8c2c5f9524d..c28bdce14fd5e32b287419227d7d33bf7835c409 100644 (file)
@@ -135,7 +135,7 @@ static void vsockmon_setup(struct net_device *dev)
 
        dev->netdev_ops = &vsockmon_ops;
        dev->ethtool_ops = &vsockmon_ethtool_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
 
        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST |
                        NETIF_F_HIGHDMA | NETIF_F_LLTX;
index 328b4712683c334bf1de66a3a3789d0a04d734c3..5fa798a5c9a695ac3796d2ee4a3c1eae59a1cf9f 100644 (file)
@@ -59,6 +59,8 @@ static const u8 all_zeros_mac[ETH_ALEN + 2];
 
 static int vxlan_sock_add(struct vxlan_dev *vxlan);
 
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan);
+
 /* per-network namespace private data for this module */
 struct vxlan_net {
        struct list_head  vxlan_list;
@@ -740,6 +742,22 @@ static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f)
        call_rcu(&f->rcu, vxlan_fdb_free);
 }
 
+static void vxlan_dst_free(struct rcu_head *head)
+{
+       struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);
+
+       dst_cache_destroy(&rd->dst_cache);
+       kfree(rd);
+}
+
+static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
+                                 struct vxlan_rdst *rd)
+{
+       list_del_rcu(&rd->list);
+       vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH);
+       call_rcu(&rd->rcu, vxlan_dst_free);
+}
+
 static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan,
                           union vxlan_addr *ip, __be16 *port, __be32 *src_vni,
                           __be32 *vni, u32 *ifindex)
@@ -864,9 +882,7 @@ static int __vxlan_fdb_delete(struct vxlan_dev *vxlan,
         * otherwise destroy the fdb entry
         */
        if (rd && !list_is_singular(&f->remotes)) {
-               list_del_rcu(&rd->list);
-               vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH);
-               kfree_rcu(rd, rcu);
+               vxlan_fdb_dst_destroy(vxlan, f, rd);
                goto out;
        }
 
@@ -1067,6 +1083,8 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
        rcu_assign_pointer(vxlan->vn4_sock, NULL);
        synchronize_net();
 
+       vxlan_vs_del_dev(vxlan);
+
        if (__vxlan_sock_release_prep(sock4)) {
                udp_tunnel_sock_release(sock4->sock);
                kfree(sock4);
@@ -2342,6 +2360,15 @@ static void vxlan_cleanup(unsigned long arg)
        mod_timer(&vxlan->age_timer, next_timer);
 }
 
+static void vxlan_vs_del_dev(struct vxlan_dev *vxlan)
+{
+       struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+
+       spin_lock(&vn->sock_lock);
+       hlist_del_init_rcu(&vxlan->hlist);
+       spin_unlock(&vn->sock_lock);
+}
+
 static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan)
 {
        struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
@@ -2584,7 +2611,7 @@ static void vxlan_setup(struct net_device *dev)
        eth_hw_addr_random(dev);
        ether_setup(dev);
 
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        SET_NETDEV_DEVTYPE(dev, &vxlan_type);
 
        dev->features   |= NETIF_F_LLTX;
@@ -3286,15 +3313,9 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
 static void vxlan_dellink(struct net_device *dev, struct list_head *head)
 {
        struct vxlan_dev *vxlan = netdev_priv(dev);
-       struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 
        vxlan_flush(vxlan, true);
 
-       spin_lock(&vn->sock_lock);
-       if (!hlist_unhashed(&vxlan->hlist))
-               hlist_del_rcu(&vxlan->hlist);
-       spin_unlock(&vn->sock_lock);
-
        gro_cells_destroy(&vxlan->gro_cells);
        list_del(&vxlan->next);
        unregister_netdevice_queue(dev, head);
index 65ee2a6f248cfcbd2761272431c37627eafaced5..a0d76f70c4289d03e7b8c25700c58b218a934bd0 100644 (file)
@@ -475,7 +475,7 @@ static void dlci_setup(struct net_device *dev)
        dev->flags              = 0;
        dev->header_ops         = &dlci_header_ops;
        dev->netdev_ops         = &dlci_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 
        dlp->receive            = dlci_receive;
 
index eb915281197efc98a0fae96cc9dcdd2691a21ee3..78596e42a3f3f27623284c86a0d791a2bf4a65b6 100644 (file)
@@ -1106,7 +1106,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
                return -EIO;
        }
 
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        *get_dev_p(pvc, type) = dev;
        if (!used) {
                state(hdlc)->dce_changed = 1;
index 9df9ed62beff0cb3b2c0be7dbe1f15e646da74de..63f749078a1f1051f3f46bec13f1f60c7c64ea5f 100644 (file)
@@ -306,7 +306,7 @@ static const struct net_device_ops lapbeth_netdev_ops = {
 static void lapbeth_setup(struct net_device *dev)
 {
        dev->netdev_ops      = &lapbeth_netdev_ops;
-       dev->destructor      = free_netdev;
+       dev->needs_free_netdev = true;
        dev->type            = ARPHRD_X25;
        dev->hard_header_len = 3;
        dev->mtu             = 1000;
index 91ee542de3d79ec0903d56f2d45463af83b01a95..b90c77ef792ef8908173aa2f762d15089dce55fd 100644 (file)
@@ -1287,7 +1287,7 @@ void init_netdev(struct net_device *dev)
        struct ath6kl *ar = ath6kl_priv(dev);
 
        dev->netdev_ops = &ath6kl_netdev_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
 
        dev->needed_headroom = ETH_HLEN;
index d5e993dc9b238c6fd306b801083346570eec8790..517a315e259b79f05f2d8d3e88c371a9f39ad9e9 100644 (file)
@@ -1271,6 +1271,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
        qcom_smem_state_put(wcn->tx_enable_state);
        qcom_smem_state_put(wcn->tx_rings_empty_state);
 
+       rpmsg_destroy_ept(wcn->smd_channel);
+
        iounmap(wcn->dxe_base);
        iounmap(wcn->ccu_base);
 
index cd1d6730eab73d514db5a1b88d442607c7834e3d..617199c0e5a0e644576b3c73be0808878d4c102b 100644 (file)
@@ -5225,7 +5225,6 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)
 
        if (vif)
                brcmf_free_vif(vif);
-       free_netdev(ndev);
 }
 
 static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
index a3d82368f1a9f9722e62920e44ef52f7ee8602ef..511d190c6cca1e864e50c7b1b6ae9caa45307e00 100644 (file)
@@ -624,7 +624,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
                if (!ndev)
                        return ERR_PTR(-ENOMEM);
 
-               ndev->destructor = brcmf_cfg80211_free_netdev;
+               ndev->needs_free_netdev = true;
+               ndev->priv_destructor = brcmf_cfg80211_free_netdev;
                ifp = netdev_priv(ndev);
                ifp->ndev = ndev;
                /* store mapping ifidx to bsscfgidx */
index c7c1e9906500fd5be3d386ea4c43848caaff6ac1..d231042f19d6462018bc10fee0c789196c51abf9 100644 (file)
@@ -442,7 +442,7 @@ struct brcmf_fw {
        const char *nvram_name;
        u16 domain_nr;
        u16 bus_nr;
-       void (*done)(struct device *dev, const struct firmware *fw,
+       void (*done)(struct device *dev, int err, const struct firmware *fw,
                     void *nvram_image, u32 nvram_len);
 };
 
@@ -477,52 +477,51 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
        if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
                goto fail;
 
-       fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
+       fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
        kfree(fwctx);
        return;
 
 fail:
        brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
        release_firmware(fwctx->code);
-       device_release_driver(fwctx->dev);
+       fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
        kfree(fwctx);
 }
 
 static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
 {
        struct brcmf_fw *fwctx = ctx;
-       int ret;
+       int ret = 0;
 
        brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
-       if (!fw)
+       if (!fw) {
+               ret = -ENOENT;
                goto fail;
-
-       /* only requested code so done here */
-       if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
-               fwctx->done(fwctx->dev, fw, NULL, 0);
-               kfree(fwctx);
-               return;
        }
+       /* only requested code so done here */
+       if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
+               goto done;
+
        fwctx->code = fw;
        ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
                                      fwctx->dev, GFP_KERNEL, fwctx,
                                      brcmf_fw_request_nvram_done);
 
-       if (!ret)
-               return;
-
-       brcmf_fw_request_nvram_done(NULL, fwctx);
+       /* pass NULL to nvram callback for bcm47xx fallback */
+       if (ret)
+               brcmf_fw_request_nvram_done(NULL, fwctx);
        return;
 
 fail:
        brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
-       device_release_driver(fwctx->dev);
+done:
+       fwctx->done(fwctx->dev, ret, fw, NULL, 0);
        kfree(fwctx);
 }
 
 int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
                                const char *code, const char *nvram,
-                               void (*fw_cb)(struct device *dev,
+                               void (*fw_cb)(struct device *dev, int err,
                                              const struct firmware *fw,
                                              void *nvram_image, u32 nvram_len),
                                u16 domain_nr, u16 bus_nr)
@@ -555,7 +554,7 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
 
 int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
                           const char *code, const char *nvram,
-                          void (*fw_cb)(struct device *dev,
+                          void (*fw_cb)(struct device *dev, int err,
                                         const struct firmware *fw,
                                         void *nvram_image, u32 nvram_len))
 {
index d3c9f0d52ae3326eb18a76aaf735bb602a211a35..8fa4b7e1ab3db71c2522aa9a275ac9e6393eb0a7 100644 (file)
@@ -73,13 +73,13 @@ void brcmf_fw_nvram_free(void *nvram);
  */
 int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
                                const char *code, const char *nvram,
-                               void (*fw_cb)(struct device *dev,
+                               void (*fw_cb)(struct device *dev, int err,
                                              const struct firmware *fw,
                                              void *nvram_image, u32 nvram_len),
                                u16 domain_nr, u16 bus_nr);
 int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
                           const char *code, const char *nvram,
-                          void (*fw_cb)(struct device *dev,
+                          void (*fw_cb)(struct device *dev, int err,
                                         const struct firmware *fw,
                                         void *nvram_image, u32 nvram_len));
 
index 72373e59308e8fe54cf14090efd135a045273f4a..f59642b2c935a503f36600f4573861a7597ad267 100644 (file)
@@ -2145,7 +2145,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
        struct brcmf_fws_info *fws = drvr_to_fws(ifp->drvr);
        struct brcmf_fws_mac_descriptor *entry;
 
-       if (!ifp->ndev || fws->fcmode == BRCMF_FWS_FCMODE_NONE)
+       if (!ifp->ndev || !brcmf_fws_queue_skbs(fws))
                return;
 
        entry = &fws->desc.iface[ifp->ifidx];
index f36b96dc6acdfc2160ba35e187a46356a3b41c28..f878706613e679515410e573eb770f1b1a28ef26 100644 (file)
@@ -1650,16 +1650,23 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = {
        .write32 = brcmf_pcie_buscore_write32,
 };
 
-static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw,
+static void brcmf_pcie_setup(struct device *dev, int ret,
+                            const struct firmware *fw,
                             void *nvram, u32 nvram_len)
 {
-       struct brcmf_bus *bus = dev_get_drvdata(dev);
-       struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie;
-       struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo;
+       struct brcmf_bus *bus;
+       struct brcmf_pciedev *pcie_bus_dev;
+       struct brcmf_pciedev_info *devinfo;
        struct brcmf_commonring **flowrings;
-       int ret;
        u32 i;
 
+       /* check firmware loading result */
+       if (ret)
+               goto fail;
+
+       bus = dev_get_drvdata(dev);
+       pcie_bus_dev = bus->bus_priv.pcie;
+       devinfo = pcie_bus_dev->devinfo;
        brcmf_pcie_attach(devinfo);
 
        /* Some of the firmwares have the size of the memory of the device
index fc64b8913aa6a11c0111fec3b9d900174dc250c3..5653d6dd38f6fe5c5132f2d7940facd31bef6549 100644 (file)
@@ -3422,7 +3422,7 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
                /* otherwise, set txglomalign */
                value = sdiodev->settings->bus.sdio.sd_sgentry_align;
                /* SDIO ADMA requires at least 32 bit alignment */
-               value = max_t(u32, value, 4);
+               value = max_t(u32, value, ALIGNMENT);
                err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
                                           sizeof(u32));
        }
@@ -3982,21 +3982,26 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
        .get_memdump = brcmf_sdio_bus_get_memdump,
 };
 
-static void brcmf_sdio_firmware_callback(struct device *dev,
+static void brcmf_sdio_firmware_callback(struct device *dev, int err,
                                         const struct firmware *code,
                                         void *nvram, u32 nvram_len)
 {
-       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-       struct brcmf_sdio *bus = sdiodev->bus;
-       int err = 0;
+       struct brcmf_bus *bus_if;
+       struct brcmf_sdio_dev *sdiodev;
+       struct brcmf_sdio *bus;
        u8 saveclk;
 
-       brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev));
+       brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
+       bus_if = dev_get_drvdata(dev);
+       sdiodev = bus_if->bus_priv.sdio;
+       if (err)
+               goto fail;
 
        if (!bus_if->drvr)
                return;
 
+       bus = sdiodev->bus;
+
        /* try to download image and nvram to the dongle */
        bus->alp_only = true;
        err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
@@ -4083,6 +4088,7 @@ release:
 fail:
        brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
        device_release_driver(dev);
+       device_release_driver(&sdiodev->func[2]->dev);
 }
 
 struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
index e4d545f9edeef6f119a0b67f50db679bedfcd91f..0eea48e73331d57297099266b1725df2be35a565 100644 (file)
@@ -1159,17 +1159,18 @@ fail:
        return ret;
 }
 
-static void brcmf_usb_probe_phase2(struct device *dev,
+static void brcmf_usb_probe_phase2(struct device *dev, int ret,
                                   const struct firmware *fw,
                                   void *nvram, u32 nvlen)
 {
        struct brcmf_bus *bus = dev_get_drvdata(dev);
-       struct brcmf_usbdev_info *devinfo;
-       int ret;
+       struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
+
+       if (ret)
+               goto error;
 
        brcmf_dbg(USB, "Start fw downloading\n");
 
-       devinfo = bus->bus_priv.usb->devinfo;
        ret = check_file(fw->data);
        if (ret < 0) {
                brcmf_err("invalid firmware\n");
index 3b3e076571d6d7089ae2df09d2dfbd2008cf81e4..45e2efc70d19e5f44c7a5e2a1cde2cf9a7448f91 100644 (file)
@@ -79,8 +79,8 @@
 /* Lowest firmware API version supported */
 #define IWL7260_UCODE_API_MIN  17
 #define IWL7265_UCODE_API_MIN  17
-#define IWL7265D_UCODE_API_MIN 17
-#define IWL3168_UCODE_API_MIN  20
+#define IWL7265D_UCODE_API_MIN 22
+#define IWL3168_UCODE_API_MIN  22
 
 /* NVM versions */
 #define IWL7260_NVM_VERSION            0x0a1d
index b9718c0cf17480dc4c1ab212fdbfabecb3125775..89137717c1fce778d63a55af99f16f970f3b34d6 100644 (file)
@@ -74,8 +74,8 @@
 #define IWL8265_UCODE_API_MAX  30
 
 /* Lowest firmware API version supported */
-#define IWL8000_UCODE_API_MIN  17
-#define IWL8265_UCODE_API_MIN  20
+#define IWL8000_UCODE_API_MIN  22
+#define IWL8265_UCODE_API_MIN  22
 
 /* NVM versions */
 #define IWL8000_NVM_VERSION            0x0a1d
index 306bc967742ee9a7b5629bab00f20cab77309fa1..77efbb78e867bfac47ae992c2703275e1b5062b2 100644 (file)
 #define MON_DMARB_RD_DATA_ADDR         (0xa03c5c)
 
 #define DBGC_IN_SAMPLE                 (0xa03c00)
+#define DBGC_OUT_CTRL                  (0xa03c0c)
 
 /* enable the ID buf for read */
 #define WFPM_PS_CTL_CLR                        0xA0300C
index 1b7d265ffb0acb476228b5b2a10040c09e41d61c..a10c6aae9ab98de7c752b05b9cc33059337b1410 100644 (file)
@@ -307,6 +307,11 @@ enum {
 /* Bit 1-3: LQ command color. Used to match responses to LQ commands */
 #define LQ_FLAG_COLOR_POS               1
 #define LQ_FLAG_COLOR_MSK               (7 << LQ_FLAG_COLOR_POS)
+#define LQ_FLAG_COLOR_GET(_f)          (((_f) & LQ_FLAG_COLOR_MSK) >>\
+                                        LQ_FLAG_COLOR_POS)
+#define LQ_FLAGS_COLOR_INC(_c)         ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\
+                                        LQ_FLAG_COLOR_MSK)
+#define LQ_FLAG_COLOR_SET(_f, _c)      ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK))
 
 /* Bit 4-5: Tx RTS BW Signalling
  * (0) No RTS BW signalling
index 81b98915b1a42e21a318d293c459015688489c7f..1360ebfdc51bc6475c2c68301781b2296bb03369 100644 (file)
@@ -519,8 +519,11 @@ struct agg_tx_status {
  * bit-7 invalid rate indication
  */
 #define TX_RES_INIT_RATE_INDEX_MSK 0x0f
+#define TX_RES_RATE_TABLE_COLOR_POS 4
 #define TX_RES_RATE_TABLE_COLOR_MSK 0x70
 #define TX_RES_INV_RATE_INDEX_MSK 0x80
+#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\
+                                      TX_RES_RATE_TABLE_COLOR_POS)
 
 #define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)
 #define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
index 7b86a4f1b574c6f507fbde87c1276241fd534a4a..c8712e6eea74187af9c0d8ef3a73622ab7d1d5fd 100644 (file)
@@ -1002,14 +1002,6 @@ int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
        return 0;
 }
 
-static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
-{
-       if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
-               iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
-       else
-               iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
-}
-
 int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
 {
        u8 *ptr;
@@ -1023,10 +1015,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
        /* EARLY START - firmware's configuration is hard coded */
        if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
             !mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
-           conf_id == FW_DBG_START_FROM_ALIVE) {
-               iwl_mvm_restart_early_start(mvm);
+           conf_id == FW_DBG_START_FROM_ALIVE)
                return 0;
-       }
 
        if (!mvm->fw->dbg_conf_tlv[conf_id])
                return -EINVAL;
index 0f1831b419159b606967889ff8ea20c7ef86f0f2..fd2fc46e2fe51d8e8f1930af05e40ee9400c84a6 100644 (file)
@@ -1040,7 +1040,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
                struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6;
                struct iwl_mac_beacon_cmd_v7 beacon_cmd;
        } u = {};
-       struct iwl_mac_beacon_cmd beacon_cmd;
+       struct iwl_mac_beacon_cmd beacon_cmd = {};
        struct ieee80211_tx_info *info;
        u32 beacon_skb_len;
        u32 rate, tx_flags;
index 4e74a6b90e70626d6e0e8bb8092796f078c7d55d..52f8d7a6a7dcec95d32089a11c7c9e37b53748a7 100644 (file)
@@ -1730,8 +1730,11 @@ int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq);
  */
 static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
 {
+       u32 cmd_queue = iwl_mvm_is_dqa_supported(mvm) ? IWL_MVM_DQA_CMD_QUEUE :
+               IWL_MVM_CMD_QUEUE;
+
        return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) &
-               ~BIT(IWL_MVM_CMD_QUEUE));
+               ~BIT(cmd_queue));
 }
 
 static inline
@@ -1753,6 +1756,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
        if (!iwl_mvm_has_new_tx_api(mvm))
                iwl_free_fw_paging(mvm);
        mvm->ucode_loaded = false;
+       mvm->fw_dbg_conf = FW_DBG_INVALID;
        iwl_trans_stop_device(mvm->trans);
 }
 
index 9ffff6ed813386418800cf38906b91989c5b6f52..3da5ec40aaead90731224bce3686071ae9dd9344 100644 (file)
@@ -1149,21 +1149,37 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
 
        mutex_lock(&mvm->mutex);
 
-       /* stop recording */
        if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+               /* stop recording */
                iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
+
+               iwl_mvm_fw_error_dump(mvm);
+
+               /* start recording again if the firmware is not crashed */
+               if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
+                   mvm->fw->dbg_dest_tlv)
+                       iwl_clear_bits_prph(mvm->trans,
+                                           MON_BUFF_SAMPLE_CTL, 0x100);
        } else {
+               u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE);
+               u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL);
+
+               /* stop recording */
                iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
-               /* wait before we collect the data till the DBGC stop */
                udelay(100);
-       }
+               iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0);
+               /* wait before we collect the data till the DBGC stop */
+               udelay(500);
 
-       iwl_mvm_fw_error_dump(mvm);
+               iwl_mvm_fw_error_dump(mvm);
 
-       /* start recording again if the firmware is not crashed */
-       WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) &&
-                    mvm->fw->dbg_dest_tlv &&
-                    iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf));
+               /* start recording again if the firmware is not crashed */
+               if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
+                   mvm->fw->dbg_dest_tlv) {
+                       iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample);
+                       iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl);
+               }
+       }
 
        mutex_unlock(&mvm->mutex);
 
index 7788eefcd2bdd3066c0b40d5f5575e44f2102c0e..aa785cf3cf68399eb724b33d24d9168602f791a1 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2016 Intel Deutschland GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -1083,34 +1083,6 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
                rs_get_lower_rate_in_column(lq_sta, rate);
 }
 
-/* Check if both rates are identical
- * allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B
- * with a rate indicating STBC/BFER and ANT_AB.
- */
-static inline bool rs_rate_equal(struct rs_rate *a,
-                                struct rs_rate *b,
-                                bool allow_ant_mismatch)
-
-{
-       bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) &&
-               (a->bfer == b->bfer);
-
-       if (allow_ant_mismatch) {
-               if (a->stbc || a->bfer) {
-                       WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d",
-                                 a->stbc, a->bfer, a->ant);
-                       ant_match |= (b->ant == ANT_A || b->ant == ANT_B);
-               } else if (b->stbc || b->bfer) {
-                       WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d",
-                                 b->stbc, b->bfer, b->ant);
-                       ant_match |= (a->ant == ANT_A || a->ant == ANT_B);
-               }
-       }
-
-       return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) &&
-               (a->ldpc == b->ldpc) && (a->index == b->index) && ant_match;
-}
-
 /* Check if both rates share the same column */
 static inline bool rs_rate_column_match(struct rs_rate *a,
                                        struct rs_rate *b)
@@ -1182,12 +1154,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        u32 lq_hwrate;
        struct rs_rate lq_rate, tx_resp_rate;
        struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
-       u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0];
+       u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
+       u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
+       u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
        u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
        struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
-       bool allow_ant_mismatch = fw_has_api(&mvm->fw->ucode_capa,
-                                            IWL_UCODE_TLV_API_LQ_SS_PARAMS);
 
        /* Treat uninitialized rate scaling data same as non-existing. */
        if (!lq_sta) {
@@ -1262,10 +1234,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
        rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate);
 
        /* Here we actually compare this rate to the latest LQ command */
-       if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) {
+       if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
                IWL_DEBUG_RATE(mvm,
-                              "initial tx resp rate 0x%x does not match 0x%x\n",
-                              tx_resp_hwrate, lq_hwrate);
+                              "tx resp color 0x%x does not match 0x%x\n",
+                              lq_color, LQ_FLAG_COLOR_GET(table->flags));
 
                /*
                 * Since rates mis-match, the last LQ command may have failed.
@@ -3326,6 +3298,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
        u8 valid_tx_ant = 0;
        struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
        bool toggle_ant = false;
+       u32 color;
 
        memcpy(&rate, initial_rate, sizeof(rate));
 
@@ -3380,6 +3353,9 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
                                 num_rates, num_retries, valid_tx_ant,
                                 toggle_ant);
 
+       /* update the color of the LQ command (as a counter at bits 1-3) */
+       color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags));
+       lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color);
 }
 
 struct rs_bfer_active_iter_data {
index ee207f2c0a90c797e84659473f0bd1a455b00923..3abde1cb03034f9068230420072961371a187262 100644 (file)
@@ -2,6 +2,7 @@
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
@@ -357,6 +358,20 @@ struct iwl_lq_sta {
        } pers;
 };
 
+/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp
+ * Note, it's iwlmvm <-> mac80211 interface.
+ * bits 0-7: reduced tx power
+ * bits 8-10: LQ command's color
+ */
+#define RS_DRV_DATA_TXP_MSK 0xff
+#define RS_DRV_DATA_LQ_COLOR_POS 8
+#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS)
+#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\
+                                     RS_DRV_DATA_LQ_COLOR_POS)
+#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\
+                                 (((uintptr_t)_p) |\
+                                  ((_c) << RS_DRV_DATA_LQ_COLOR_POS)))
+
 /* Initialize station's rate scaling information after adding station */
 void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                          enum nl80211_band band, bool init);
index f5c786ddc52631087b56067807bb4d48e0869664..614d67810d051c539bd093b9452c64dc4e9c8a2f 100644 (file)
@@ -2120,7 +2120,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
        if (!iwl_mvm_is_dqa_supported(mvm))
                return 0;
 
-       if (WARN_ON(vif->type != NL80211_IFTYPE_AP))
+       if (WARN_ON(vif->type != NL80211_IFTYPE_AP &&
+                   vif->type != NL80211_IFTYPE_ADHOC))
                return -ENOTSUPP;
 
        /*
@@ -2155,6 +2156,16 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
                mvmvif->cab_queue = queue;
        } else if (!fw_has_api(&mvm->fw->ucode_capa,
                               IWL_UCODE_TLV_API_STA_TYPE)) {
+               /*
+                * In IBSS, ieee80211_check_queues() sets the cab_queue to be
+                * invalid, so make sure we use the queue we want.
+                * Note that this is done here as we want to avoid making DQA
+                * changes in mac80211 layer.
+                */
+               if (vif->type == NL80211_IFTYPE_ADHOC) {
+                       vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
+                       mvmvif->cab_queue = vif->cab_queue;
+               }
                iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
                                   &cfg, timeout);
        }
@@ -3321,18 +3332,15 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
 
        /* Get the station from the mvm local station table */
        mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
-       if (!mvm_sta) {
-               IWL_ERR(mvm, "Failed to find station\n");
-               return -EINVAL;
-       }
-       sta_id = mvm_sta->sta_id;
+       if (mvm_sta)
+               sta_id = mvm_sta->sta_id;
 
        IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
                      keyconf->keyidx, sta_id);
 
-       if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-           keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-           keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
+       if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
+                       keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
+                       keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256))
                return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
 
        if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
index 2716cb5483bf5ab9851e7dbf1e5af04b887296e7..ad62b67dceb2836cefe354fd69af60aedc856f8e 100644 (file)
@@ -313,6 +313,7 @@ enum iwl_mvm_agg_state {
  *     This is basically (last acked packet++).
  * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
  *     Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA).
+ * @lq_color: the color of the LQ command as it appears in tx response.
  * @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed.
  * @state: state of the BA agreement establishment / tear down.
  * @txq_id: Tx queue used by the BA session / DQA
@@ -331,6 +332,7 @@ struct iwl_mvm_tid_data {
        u16 next_reclaimed;
        /* The rest is Tx AGG related */
        u32 rate_n_flags;
+       u8 lq_color;
        bool amsdu_in_ampdu_allowed;
        enum iwl_mvm_agg_state state;
        u16 txq_id;
index f9cbd197246f7ba6ba9e5e0af816cbec54eb9790..506d58104e1cc007ba9d767a16dd77f9df8f0481 100644 (file)
@@ -790,11 +790,13 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
        struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata);
        int ret;
 
-       if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR))
-               return -EIO;
-
        mutex_lock(&mvm->mutex);
 
+       if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
+               ret = -EIO;
+               goto unlock;
+       }
+
        if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) {
                ret = -EINVAL;
                goto unlock;
index bcaceb64a6e8c230c5127ee5cc4b790b1f4f1d57..f21901cd4a4fdf75dac1b55d7b9525e84f9e65dd 100644 (file)
@@ -1323,6 +1323,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
        struct iwl_mvm_sta *mvmsta;
        struct sk_buff_head skbs;
        u8 skb_freed = 0;
+       u8 lq_color;
        u16 next_reclaimed, seq_ctl;
        bool is_ndp = false;
 
@@ -1405,8 +1406,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                info->status.tx_time =
                        le16_to_cpu(tx_resp->wireless_media_time);
                BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
+               lq_color = TX_RES_RATE_TABLE_COL_GET(tx_resp->tlc_info);
                info->status.status_driver_data[0] =
-                               (void *)(uintptr_t)tx_resp->reduced_tpc;
+                       RS_DRV_DATA_PACK(lq_color, tx_resp->reduced_tpc);
 
                ieee80211_tx_status(mvm->hw, skb);
        }
@@ -1638,6 +1640,9 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
                        le32_to_cpu(tx_resp->initial_rate);
                mvmsta->tid_data[tid].tx_time =
                        le16_to_cpu(tx_resp->wireless_media_time);
+               mvmsta->tid_data[tid].lq_color =
+                       (tx_resp->tlc_info & TX_RES_RATE_TABLE_COLOR_MSK) >>
+                       TX_RES_RATE_TABLE_COLOR_POS;
        }
 
        rcu_read_unlock();
@@ -1707,6 +1712,11 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
        iwl_mvm_check_ratid_empty(mvm, sta, tid);
 
        freed = 0;
+
+       /* pack lq color from tid_data along the reduced txp */
+       ba_info->status.status_driver_data[0] =
+               RS_DRV_DATA_PACK(tid_data->lq_color,
+                                ba_info->status.status_driver_data[0]);
        ba_info->status.status_driver_data[1] = (void *)(uintptr_t)rate;
 
        skb_queue_walk(&reclaimed_skbs, skb) {
index 70acf850a9f19f9750296ae2019d8f4a8c277b67..93cbc7a69bcd55d3560529c88b6a127451606cd7 100644 (file)
@@ -2803,7 +2803,8 @@ static struct iwl_trans_dump_data
 #ifdef CONFIG_PM_SLEEP
 static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
 {
-       if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3)
+       if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 &&
+           (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))
                return iwl_pci_fw_enter_d0i3(trans);
 
        return 0;
@@ -2811,7 +2812,8 @@ static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
 
 static void iwl_trans_pcie_resume(struct iwl_trans *trans)
 {
-       if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3)
+       if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3 &&
+           (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3))
                iwl_pci_fw_exit_d0i3(trans);
 }
 #endif /* CONFIG_PM_SLEEP */
index 9fb46a6f47cf416e55d4416b228be50cdd460e4e..9c9bfbbabdf11ee597dfa7a3614e59d2e49236fe 100644 (file)
@@ -906,7 +906,7 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
 
        if (WARN_ON(iwl_rx_packet_payload_len(hcmd.resp_pkt) != sizeof(*rsp))) {
                ret = -EINVAL;
-               goto error;
+               goto error_free_resp;
        }
 
        rsp = (void *)hcmd.resp_pkt->data;
@@ -915,13 +915,13 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
        if (qid > ARRAY_SIZE(trans_pcie->txq)) {
                WARN_ONCE(1, "queue index %d unsupported", qid);
                ret = -EIO;
-               goto error;
+               goto error_free_resp;
        }
 
        if (test_and_set_bit(qid, trans_pcie->queue_used)) {
                WARN_ONCE(1, "queue %d already used", qid);
                ret = -EIO;
-               goto error;
+               goto error_free_resp;
        }
 
        txq->id = qid;
@@ -934,8 +934,11 @@ int iwl_trans_pcie_dyn_txq_alloc(struct iwl_trans *trans,
                           (txq->write_ptr) | (qid << 16));
        IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d\n", qid);
 
+       iwl_free_resp(&hcmd);
        return qid;
 
+error_free_resp:
+       iwl_free_resp(&hcmd);
 error:
        iwl_pcie_gen2_txq_free_memory(trans, txq);
        return ret;
index 544fc09dcb62435dc7316b2d8463c76d386ed91e..1372b20f931e0cca990a158e0ef8fdfc71fd7f88 100644 (file)
@@ -73,7 +73,7 @@ struct net_device * hostap_add_interface(struct local_info *local,
        dev->mem_end = mdev->mem_end;
 
        hostap_setup_dev(dev, local, type);
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
 
        sprintf(dev->name, "%s%s", prefix, name);
        if (!rtnl_locked)
index 002b25cff5b65e18460a2da08637886274bfdfa5..c854a557998b4266c5d63c55c0463497e8dde715 100644 (file)
@@ -2861,7 +2861,7 @@ static const struct net_device_ops hwsim_netdev_ops = {
 static void hwsim_mon_setup(struct net_device *dev)
 {
        dev->netdev_ops = &hwsim_netdev_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        ether_setup(dev);
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->type = ARPHRD_IEEE80211_RADIOTAP;
index dd87b9ff64c371911a74308be55e93e3a46cdd43..39b6b5e3f6e0e4e9ec6eb81e458250485e94c487 100644 (file)
@@ -1280,7 +1280,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
                              struct net_device *dev)
 {
        dev->netdev_ops = &mwifiex_netdev_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        /* Initialize private structure */
        priv->current_key_index = 0;
        priv->media_connected = false;
index 530586be05b4357dc8ee6439b7a9e225bce012c6..5b1d2e8402d9d5482085018186d947b59cbb35a4 100644 (file)
@@ -199,6 +199,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
        unsigned long   remaining_credit;
        struct timer_list credit_timeout;
        u64 credit_window_start;
+       bool rate_limited;
 
        /* Statistics */
        struct xenvif_stats stats;
index 8397f6c9245158e8b3ff005bc58a419e4250169d..e322a862ddfe70b4e1b2fbdbffd8cd78cbdc4b24 100644 (file)
@@ -106,7 +106,11 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
 
        if (work_done < budget) {
                napi_complete_done(napi, work_done);
-               xenvif_napi_schedule_or_enable_events(queue);
+               /* If the queue is rate-limited, it shall be
+                * rescheduled in the timer callback.
+                */
+               if (likely(!queue->rate_limited))
+                       xenvif_napi_schedule_or_enable_events(queue);
        }
 
        return work_done;
index 602d408fa25e98a4651716b1390d2507bced4605..5042ff8d449af70b2a05ac6e166eb8acbf7ae44c 100644 (file)
@@ -180,6 +180,7 @@ static void tx_add_credit(struct xenvif_queue *queue)
                max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
 
        queue->remaining_credit = min(max_credit, max_burst);
+       queue->rate_limited = false;
 }
 
 void xenvif_tx_credit_callback(unsigned long data)
@@ -686,8 +687,10 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)
                msecs_to_jiffies(queue->credit_usec / 1000);
 
        /* Timer could already be pending in rare cases. */
-       if (timer_pending(&queue->credit_timeout))
+       if (timer_pending(&queue->credit_timeout)) {
+               queue->rate_limited = true;
                return true;
+       }
 
        /* Passed the point where we can replenish credit? */
        if (time_after_eq64(now, next_credit)) {
@@ -702,6 +705,7 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)
                mod_timer(&queue->credit_timeout,
                          next_credit);
                queue->credit_window_start = next_credit;
+               queue->rate_limited = true;
 
                return true;
        }
index 6ffc482550c1d24f9b795f1ab3951101fd901f1c..7b61adb6270c99f8c70f1efa7575b1bb62d96f45 100644 (file)
@@ -1934,8 +1934,7 @@ abort_transaction_no_dev_fatal:
        xennet_disconnect_backend(info);
        xennet_destroy_queues(info);
  out:
-       unregister_netdev(info->netdev);
-       xennet_free_netdev(info->netdev);
+       device_unregister(&dev->dev);
        return err;
 }
 
index c00238491673766e05bc5bd2d2d3bec4aac30484..7b3b6fd63d7d7caa21bbc9c517c4e28910b0548b 100644 (file)
@@ -2878,7 +2878,7 @@ static const struct intel_ntb_reg skx_reg = {
        .link_is_up             = xeon_link_is_up,
        .db_ioread              = skx_db_ioread,
        .db_iowrite             = skx_db_iowrite,
-       .db_size                = sizeof(u64),
+       .db_size                = sizeof(u32),
        .ntb_ctl                = SKX_NTBCNTL_OFFSET,
        .mw_bar                 = {2, 4},
 };
index 02ca45fdd89203f31246f552811b1264059232d6..10e5bf4601398c8723d82b5f3340f9b246d341e5 100644 (file)
@@ -177,14 +177,12 @@ struct ntb_transport_qp {
        u64 rx_err_ver;
        u64 rx_memcpy;
        u64 rx_async;
-       u64 dma_rx_prep_err;
        u64 tx_bytes;
        u64 tx_pkts;
        u64 tx_ring_full;
        u64 tx_err_no_buf;
        u64 tx_memcpy;
        u64 tx_async;
-       u64 dma_tx_prep_err;
 };
 
 struct ntb_transport_mw {
@@ -254,8 +252,6 @@ enum {
 #define QP_TO_MW(nt, qp)       ((qp) % nt->mw_count)
 #define NTB_QP_DEF_NUM_ENTRIES 100
 #define NTB_LINK_DOWN_TIMEOUT  10
-#define DMA_RETRIES            20
-#define DMA_OUT_RESOURCE_TO    msecs_to_jiffies(50)
 
 static void ntb_transport_rxc_db(unsigned long data);
 static const struct ntb_ctx_ops ntb_transport_ops;
@@ -516,12 +512,6 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
        out_offset += snprintf(buf + out_offset, out_count - out_offset,
                               "free tx - \t%u\n",
                               ntb_transport_tx_free_entry(qp));
-       out_offset += snprintf(buf + out_offset, out_count - out_offset,
-                              "DMA tx prep err - \t%llu\n",
-                              qp->dma_tx_prep_err);
-       out_offset += snprintf(buf + out_offset, out_count - out_offset,
-                              "DMA rx prep err - \t%llu\n",
-                              qp->dma_rx_prep_err);
 
        out_offset += snprintf(buf + out_offset, out_count - out_offset,
                               "\n");
@@ -623,7 +613,7 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
        if (!mw->virt_addr)
                return -ENOMEM;
 
-       if (qp_count % mw_count && mw_num + 1 < qp_count / mw_count)
+       if (mw_num < qp_count % mw_count)
                num_qps_mw = qp_count / mw_count + 1;
        else
                num_qps_mw = qp_count / mw_count;
@@ -768,8 +758,6 @@ static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
        qp->tx_err_no_buf = 0;
        qp->tx_memcpy = 0;
        qp->tx_async = 0;
-       qp->dma_tx_prep_err = 0;
-       qp->dma_rx_prep_err = 0;
 }
 
 static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
@@ -1000,7 +988,7 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
        qp->event_handler = NULL;
        ntb_qp_link_down_reset(qp);
 
-       if (qp_count % mw_count && mw_num + 1 < qp_count / mw_count)
+       if (mw_num < qp_count % mw_count)
                num_qps_mw = qp_count / mw_count + 1;
        else
                num_qps_mw = qp_count / mw_count;
@@ -1128,8 +1116,8 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
        qp_count = ilog2(qp_bitmap);
        if (max_num_clients && max_num_clients < qp_count)
                qp_count = max_num_clients;
-       else if (mw_count < qp_count)
-               qp_count = mw_count;
+       else if (nt->mw_count < qp_count)
+               qp_count = nt->mw_count;
 
        qp_bitmap &= BIT_ULL(qp_count) - 1;
 
@@ -1317,7 +1305,6 @@ static int ntb_async_rx_submit(struct ntb_queue_entry *entry, void *offset)
        struct dmaengine_unmap_data *unmap;
        dma_cookie_t cookie;
        void *buf = entry->buf;
-       int retries = 0;
 
        len = entry->len;
        device = chan->device;
@@ -1346,22 +1333,11 @@ static int ntb_async_rx_submit(struct ntb_queue_entry *entry, void *offset)
 
        unmap->from_cnt = 1;
 
-       for (retries = 0; retries < DMA_RETRIES; retries++) {
-               txd = device->device_prep_dma_memcpy(chan,
-                                                    unmap->addr[1],
-                                                    unmap->addr[0], len,
-                                                    DMA_PREP_INTERRUPT);
-               if (txd)
-                       break;
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(DMA_OUT_RESOURCE_TO);
-       }
-
-       if (!txd) {
-               qp->dma_rx_prep_err++;
+       txd = device->device_prep_dma_memcpy(chan, unmap->addr[1],
+                                            unmap->addr[0], len,
+                                            DMA_PREP_INTERRUPT);
+       if (!txd)
                goto err_get_unmap;
-       }
 
        txd->callback_result = ntb_rx_copy_callback;
        txd->callback_param = entry;
@@ -1606,7 +1582,6 @@ static int ntb_async_tx_submit(struct ntb_transport_qp *qp,
        struct dmaengine_unmap_data *unmap;
        dma_addr_t dest;
        dma_cookie_t cookie;
-       int retries = 0;
 
        device = chan->device;
        dest = qp->tx_mw_phys + qp->tx_max_frame * entry->tx_index;
@@ -1628,21 +1603,10 @@ static int ntb_async_tx_submit(struct ntb_transport_qp *qp,
 
        unmap->to_cnt = 1;
 
-       for (retries = 0; retries < DMA_RETRIES; retries++) {
-               txd = device->device_prep_dma_memcpy(chan, dest,
-                                                    unmap->addr[0], len,
-                                                    DMA_PREP_INTERRUPT);
-               if (txd)
-                       break;
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(DMA_OUT_RESOURCE_TO);
-       }
-
-       if (!txd) {
-               qp->dma_tx_prep_err++;
+       txd = device->device_prep_dma_memcpy(chan, dest, unmap->addr[0], len,
+                                            DMA_PREP_INTERRUPT);
+       if (!txd)
                goto err_get_unmap;
-       }
 
        txd->callback_result = ntb_tx_copy_callback;
        txd->callback_param = entry;
index 434e1d474f3340e1d35b48c924a6bebfbfb0fa67..5cab2831ce99ae39dac8fe8a1c8b2bd216a9e901 100644 (file)
@@ -90,11 +90,11 @@ MODULE_PARM_DESC(max_mw_size, "Limit size of large memory windows");
 
 static unsigned int seg_order = 19; /* 512K */
 module_param(seg_order, uint, 0644);
-MODULE_PARM_DESC(seg_order, "size order [n^2] of buffer segment for testing");
+MODULE_PARM_DESC(seg_order, "size order [2^n] of buffer segment for testing");
 
 static unsigned int run_order = 32; /* 4G */
 module_param(run_order, uint, 0644);
-MODULE_PARM_DESC(run_order, "size order [n^2] of total data to transfer");
+MODULE_PARM_DESC(run_order, "size order [2^n] of total data to transfer");
 
 static bool use_dma; /* default to 0 */
 module_param(use_dma, bool, 0644);
index d5e0906262ead5dd9f202385d7ace81444c25a0f..903d5813023a93588c08857ff0db1339bbb99c86 100644 (file)
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(max_retries, "max number of retries a command may have");
 static int nvme_char_major;
 module_param(nvme_char_major, int, 0);
 
-static unsigned long default_ps_max_latency_us = 25000;
+static unsigned long default_ps_max_latency_us = 100000;
 module_param(default_ps_max_latency_us, ulong, 0644);
 MODULE_PARM_DESC(default_ps_max_latency_us,
                 "max power saving latency for new devices; use PM QOS to change per device");
@@ -925,6 +925,29 @@ static int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 }
 
 #ifdef CONFIG_BLK_DEV_INTEGRITY
+static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
+               u16 bs)
+{
+       struct nvme_ns *ns = disk->private_data;
+       u16 old_ms = ns->ms;
+       u8 pi_type = 0;
+
+       ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);
+       ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
+
+       /* PI implementation requires metadata equal t10 pi tuple size */
+       if (ns->ms == sizeof(struct t10_pi_tuple))
+               pi_type = id->dps & NVME_NS_DPS_PI_MASK;
+
+       if (blk_get_integrity(disk) &&
+           (ns->pi_type != pi_type || ns->ms != old_ms ||
+            bs != queue_logical_block_size(disk->queue) ||
+            (ns->ms && ns->ext)))
+               blk_integrity_unregister(disk);
+
+       ns->pi_type = pi_type;
+}
+
 static void nvme_init_integrity(struct nvme_ns *ns)
 {
        struct blk_integrity integrity;
@@ -951,6 +974,10 @@ static void nvme_init_integrity(struct nvme_ns *ns)
        blk_queue_max_integrity_segments(ns->queue, 1);
 }
 #else
+static void nvme_prep_integrity(struct gendisk *disk, struct nvme_id_ns *id,
+               u16 bs)
+{
+}
 static void nvme_init_integrity(struct nvme_ns *ns)
 {
 }
@@ -997,37 +1024,22 @@ static int nvme_revalidate_ns(struct nvme_ns *ns, struct nvme_id_ns **id)
 static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
 {
        struct nvme_ns *ns = disk->private_data;
-       u8 lbaf, pi_type;
-       u16 old_ms;
-       unsigned short bs;
-
-       old_ms = ns->ms;
-       lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
-       ns->lba_shift = id->lbaf[lbaf].ds;
-       ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
-       ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
+       u16 bs;
 
        /*
         * If identify namespace failed, use default 512 byte block size so
         * block layer can use before failing read/write for 0 capacity.
         */
+       ns->lba_shift = id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ds;
        if (ns->lba_shift == 0)
                ns->lba_shift = 9;
        bs = 1 << ns->lba_shift;
-       /* XXX: PI implementation requires metadata equal t10 pi tuple size */
-       pi_type = ns->ms == sizeof(struct t10_pi_tuple) ?
-                                       id->dps & NVME_NS_DPS_PI_MASK : 0;
 
        blk_mq_freeze_queue(disk->queue);
-       if (blk_get_integrity(disk) && (ns->pi_type != pi_type ||
-                               ns->ms != old_ms ||
-                               bs != queue_logical_block_size(disk->queue) ||
-                               (ns->ms && ns->ext)))
-               blk_integrity_unregister(disk);
 
-       ns->pi_type = pi_type;
+       if (ns->ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)
+               nvme_prep_integrity(disk, id, bs);
        blk_queue_logical_block_size(ns->queue, bs);
-
        if (ns->ms && !blk_get_integrity(disk) && !ns->ext)
                nvme_init_integrity(ns);
        if (ns->ms && !(ns->ms == 8 && ns->pi_type) && !blk_get_integrity(disk))
@@ -1330,7 +1342,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
         * transitioning between power states.  Therefore, when running
         * in any given state, we will enter the next lower-power
         * non-operational state after waiting 50 * (enlat + exlat)
-        * microseconds, as long as that state's total latency is under
+        * microseconds, as long as that state's exit latency is under
         * the requested maximum latency.
         *
         * We will not autonomously enter any non-operational state for
@@ -1375,7 +1387,7 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
                 * lowest-power state, not the number of states.
                 */
                for (state = (int)ctrl->npss; state >= 0; state--) {
-                       u64 total_latency_us, transition_ms;
+                       u64 total_latency_us, exit_latency_us, transition_ms;
 
                        if (target)
                                table->entries[state] = target;
@@ -1396,12 +1408,15 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl)
                              NVME_PS_FLAGS_NON_OP_STATE))
                                continue;
 
-                       total_latency_us =
-                               (u64)le32_to_cpu(ctrl->psd[state].entry_lat) +
-                               + le32_to_cpu(ctrl->psd[state].exit_lat);
-                       if (total_latency_us > ctrl->ps_max_latency_us)
+                       exit_latency_us =
+                               (u64)le32_to_cpu(ctrl->psd[state].exit_lat);
+                       if (exit_latency_us > ctrl->ps_max_latency_us)
                                continue;
 
+                       total_latency_us =
+                               exit_latency_us +
+                               le32_to_cpu(ctrl->psd[state].entry_lat);
+
                        /*
                         * This state is good.  Use it as the APST idle
                         * target for higher power states.
@@ -1605,7 +1620,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
        }
        memcpy(ctrl->psd, id->psd, sizeof(ctrl->psd));
 
-       if (ctrl->ops->is_fabrics) {
+       if (ctrl->ops->flags & NVME_F_FABRICS) {
                ctrl->icdoff = le16_to_cpu(id->icdoff);
                ctrl->ioccsz = le32_to_cpu(id->ioccsz);
                ctrl->iorcsz = le32_to_cpu(id->iorcsz);
@@ -2098,7 +2113,6 @@ static void nvme_ns_remove(struct nvme_ns *ns)
                if (ns->ndev)
                        nvme_nvm_unregister_sysfs(ns);
                del_gendisk(ns->disk);
-               blk_mq_abort_requeue_list(ns->queue);
                blk_cleanup_queue(ns->queue);
        }
 
@@ -2427,6 +2441,10 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
        struct nvme_ns *ns;
 
        mutex_lock(&ctrl->namespaces_mutex);
+
+       /* Forcibly start all queues to avoid having stuck requests */
+       blk_mq_start_hw_queues(ctrl->admin_q);
+
        list_for_each_entry(ns, &ctrl->namespaces, list) {
                /*
                 * Revalidating a dead namespace sets capacity to 0. This will
@@ -2436,8 +2454,16 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
                        continue;
                revalidate_disk(ns->disk);
                blk_set_queue_dying(ns->queue);
-               blk_mq_abort_requeue_list(ns->queue);
-               blk_mq_start_stopped_hw_queues(ns->queue, true);
+
+               /*
+                * Forcibly start all queues to avoid having stuck requests.
+                * Note that we must ensure the queues are not stopped
+                * when the final removal happens.
+                */
+               blk_mq_start_hw_queues(ns->queue);
+
+               /* draining requests in requeue list */
+               blk_mq_kick_requeue_list(ns->queue);
        }
        mutex_unlock(&ctrl->namespaces_mutex);
 }
index 70e689bf1cad286869922764ccd52f1872e92524..92964cef0f4be5795bed3e874407c74a3e3cc725 100644 (file)
@@ -45,8 +45,6 @@ enum nvme_fc_queue_flags {
 
 #define NVMEFC_QUEUE_DELAY     3               /* ms units */
 
-#define NVME_FC_MAX_CONNECT_ATTEMPTS   1
-
 struct nvme_fc_queue {
        struct nvme_fc_ctrl     *ctrl;
        struct device           *dev;
@@ -165,8 +163,6 @@ struct nvme_fc_ctrl {
        struct work_struct      delete_work;
        struct work_struct      reset_work;
        struct delayed_work     connect_work;
-       int                     reconnect_delay;
-       int                     connect_attempts;
 
        struct kref             ref;
        u32                     flags;
@@ -1143,6 +1139,7 @@ nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
 /* *********************** NVME Ctrl Routines **************************** */
 
 static void __nvme_fc_final_op_cleanup(struct request *rq);
+static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg);
 
 static int
 nvme_fc_reinit_request(void *data, struct request *rq)
@@ -1269,7 +1266,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
        struct nvme_command *sqe = &op->cmd_iu.sqe;
        __le16 status = cpu_to_le16(NVME_SC_SUCCESS << 1);
        union nvme_result result;
-       bool complete_rq;
+       bool complete_rq, terminate_assoc = true;
 
        /*
         * WARNING:
@@ -1298,6 +1295,14 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
         * fabricate a CQE, the following fields will not be set as they
         * are not referenced:
         *      cqe.sqid,  cqe.sqhd,  cqe.command_id
+        *
+        * Failure or error of an individual i/o, in a transport
+        * detected fashion unrelated to the nvme completion status,
+        * potentially cause the initiator and target sides to get out
+        * of sync on SQ head/tail (aka outstanding io count allowed).
+        * Per FC-NVME spec, failure of an individual command requires
+        * the connection to be terminated, which in turn requires the
+        * association to be terminated.
         */
 
        fc_dma_sync_single_for_cpu(ctrl->lport->dev, op->fcp_req.rspdma,
@@ -1363,6 +1368,8 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                goto done;
        }
 
+       terminate_assoc = false;
+
 done:
        if (op->flags & FCOP_FLAGS_AEN) {
                nvme_complete_async_event(&queue->ctrl->ctrl, status, &result);
@@ -1370,19 +1377,23 @@ done:
                atomic_set(&op->state, FCPOP_STATE_IDLE);
                op->flags = FCOP_FLAGS_AEN;     /* clear other flags */
                nvme_fc_ctrl_put(ctrl);
-               return;
+               goto check_error;
        }
 
        complete_rq = __nvme_fc_fcpop_chk_teardowns(ctrl, op);
        if (!complete_rq) {
                if (unlikely(op->flags & FCOP_FLAGS_TERMIO)) {
-                       status = cpu_to_le16(NVME_SC_ABORT_REQ);
+                       status = cpu_to_le16(NVME_SC_ABORT_REQ << 1);
                        if (blk_queue_dying(rq->q))
-                               status |= cpu_to_le16(NVME_SC_DNR);
+                               status |= cpu_to_le16(NVME_SC_DNR << 1);
                }
                nvme_end_request(rq, status, result);
        } else
                __nvme_fc_final_op_cleanup(rq);
+
+check_error:
+       if (terminate_assoc)
+               nvme_fc_error_recovery(ctrl, "transport detected io error");
 }
 
 static int
@@ -1751,9 +1762,13 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
        dev_warn(ctrl->ctrl.device,
                "NVME-FC{%d}: transport association error detected: %s\n",
                ctrl->cnum, errmsg);
-       dev_info(ctrl->ctrl.device,
+       dev_warn(ctrl->ctrl.device,
                "NVME-FC{%d}: resetting controller\n", ctrl->cnum);
 
+       /* stop the queues on error, cleanup is in reset thread */
+       if (ctrl->queue_count > 1)
+               nvme_stop_queues(&ctrl->ctrl);
+
        if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RECONNECTING)) {
                dev_err(ctrl->ctrl.device,
                        "NVME-FC{%d}: error_recovery: Couldn't change state "
@@ -2191,9 +2206,6 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl)
        if (!opts->nr_io_queues)
                return 0;
 
-       dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n",
-                       opts->nr_io_queues);
-
        nvme_fc_init_io_queues(ctrl);
 
        memset(&ctrl->tag_set, 0, sizeof(ctrl->tag_set));
@@ -2264,9 +2276,6 @@ nvme_fc_reinit_io_queues(struct nvme_fc_ctrl *ctrl)
        if (ctrl->queue_count == 1)
                return 0;
 
-       dev_info(ctrl->ctrl.device, "Recreating %d I/O queues.\n",
-                       opts->nr_io_queues);
-
        nvme_fc_init_io_queues(ctrl);
 
        ret = blk_mq_reinit_tagset(&ctrl->tag_set);
@@ -2302,7 +2311,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        int ret;
        bool changed;
 
-       ctrl->connect_attempts++;
+       ++ctrl->ctrl.opts->nr_reconnects;
 
        /*
         * Create the admin queue
@@ -2399,9 +2408,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
        WARN_ON_ONCE(!changed);
 
-       ctrl->connect_attempts = 0;
-
-       kref_get(&ctrl->ctrl.kref);
+       ctrl->ctrl.opts->nr_reconnects = 0;
 
        if (ctrl->queue_count > 1) {
                nvme_start_queues(&ctrl->ctrl);
@@ -2532,26 +2539,32 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)
 
        /*
         * tear down the controller
-        * This will result in the last reference on the nvme ctrl to
-        * expire, calling the transport nvme_fc_nvme_ctrl_freed() callback.
-        * From there, the transport will tear down it's logical queues and
-        * association.
+        * After the last reference on the nvme ctrl is removed,
+        * the transport nvme_fc_nvme_ctrl_freed() callback will be
+        * invoked. From there, the transport will tear down it's
+        * logical queues and association.
         */
        nvme_uninit_ctrl(&ctrl->ctrl);
 
        nvme_put_ctrl(&ctrl->ctrl);
 }
 
-static int
-__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
+static bool
+__nvme_fc_schedule_delete_work(struct nvme_fc_ctrl *ctrl)
 {
        if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
-               return -EBUSY;
+               return true;
 
        if (!queue_work(nvme_fc_wq, &ctrl->delete_work))
-               return -EBUSY;
+               return true;
 
-       return 0;
+       return false;
+}
+
+static int
+__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
+{
+       return __nvme_fc_schedule_delete_work(ctrl) ? -EBUSY : 0;
 }
 
 /*
@@ -2576,6 +2589,35 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl)
        return ret;
 }
 
+static void
+nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
+{
+       /* If we are resetting/deleting then do nothing */
+       if (ctrl->ctrl.state != NVME_CTRL_RECONNECTING) {
+               WARN_ON_ONCE(ctrl->ctrl.state == NVME_CTRL_NEW ||
+                       ctrl->ctrl.state == NVME_CTRL_LIVE);
+               return;
+       }
+
+       dev_info(ctrl->ctrl.device,
+               "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
+               ctrl->cnum, status);
+
+       if (nvmf_should_reconnect(&ctrl->ctrl)) {
+               dev_info(ctrl->ctrl.device,
+                       "NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
+                       ctrl->cnum, ctrl->ctrl.opts->reconnect_delay);
+               queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
+                               ctrl->ctrl.opts->reconnect_delay * HZ);
+       } else {
+               dev_warn(ctrl->ctrl.device,
+                               "NVME-FC{%d}: Max reconnect attempts (%d) "
+                               "reached. Removing controller\n",
+                               ctrl->cnum, ctrl->ctrl.opts->nr_reconnects);
+               WARN_ON(__nvme_fc_schedule_delete_work(ctrl));
+       }
+}
+
 static void
 nvme_fc_reset_ctrl_work(struct work_struct *work)
 {
@@ -2587,34 +2629,9 @@ nvme_fc_reset_ctrl_work(struct work_struct *work)
        nvme_fc_delete_association(ctrl);
 
        ret = nvme_fc_create_association(ctrl);
-       if (ret) {
-               dev_warn(ctrl->ctrl.device,
-                       "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
-                       ctrl->cnum, ret);
-               if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) {
-                       dev_warn(ctrl->ctrl.device,
-                               "NVME-FC{%d}: Max reconnect attempts (%d) "
-                               "reached. Removing controller\n",
-                               ctrl->cnum, ctrl->connect_attempts);
-
-                       if (!nvme_change_ctrl_state(&ctrl->ctrl,
-                               NVME_CTRL_DELETING)) {
-                               dev_err(ctrl->ctrl.device,
-                                       "NVME-FC{%d}: failed to change state "
-                                       "to DELETING\n", ctrl->cnum);
-                               return;
-                       }
-
-                       WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work));
-                       return;
-               }
-
-               dev_warn(ctrl->ctrl.device,
-                       "NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
-                       ctrl->cnum, ctrl->reconnect_delay);
-               queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
-                               ctrl->reconnect_delay * HZ);
-       } else
+       if (ret)
+               nvme_fc_reconnect_or_delete(ctrl, ret);
+       else
                dev_info(ctrl->ctrl.device,
                        "NVME-FC{%d}: controller reset complete\n", ctrl->cnum);
 }
@@ -2628,7 +2645,7 @@ nvme_fc_reset_nvme_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
 
-       dev_warn(ctrl->ctrl.device,
+       dev_info(ctrl->ctrl.device,
                "NVME-FC{%d}: admin requested controller reset\n", ctrl->cnum);
 
        if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING))
@@ -2645,7 +2662,7 @@ nvme_fc_reset_nvme_ctrl(struct nvme_ctrl *nctrl)
 static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
        .name                   = "fc",
        .module                 = THIS_MODULE,
-       .is_fabrics             = true,
+       .flags                  = NVME_F_FABRICS,
        .reg_read32             = nvmf_reg_read32,
        .reg_read64             = nvmf_reg_read64,
        .reg_write32            = nvmf_reg_write32,
@@ -2667,34 +2684,9 @@ nvme_fc_connect_ctrl_work(struct work_struct *work)
                                struct nvme_fc_ctrl, connect_work);
 
        ret = nvme_fc_create_association(ctrl);
-       if (ret) {
-               dev_warn(ctrl->ctrl.device,
-                       "NVME-FC{%d}: Reconnect attempt failed (%d)\n",
-                       ctrl->cnum, ret);
-               if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) {
-                       dev_warn(ctrl->ctrl.device,
-                               "NVME-FC{%d}: Max reconnect attempts (%d) "
-                               "reached. Removing controller\n",
-                               ctrl->cnum, ctrl->connect_attempts);
-
-                       if (!nvme_change_ctrl_state(&ctrl->ctrl,
-                               NVME_CTRL_DELETING)) {
-                               dev_err(ctrl->ctrl.device,
-                                       "NVME-FC{%d}: failed to change state "
-                                       "to DELETING\n", ctrl->cnum);
-                               return;
-                       }
-
-                       WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work));
-                       return;
-               }
-
-               dev_warn(ctrl->ctrl.device,
-                       "NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
-                       ctrl->cnum, ctrl->reconnect_delay);
-               queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
-                               ctrl->reconnect_delay * HZ);
-       } else
+       if (ret)
+               nvme_fc_reconnect_or_delete(ctrl, ret);
+       else
                dev_info(ctrl->ctrl.device,
                        "NVME-FC{%d}: controller reconnect complete\n",
                        ctrl->cnum);
@@ -2720,6 +2712,12 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        unsigned long flags;
        int ret, idx;
 
+       if (!(rport->remoteport.port_role &
+           (FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET))) {
+               ret = -EBADR;
+               goto out_fail;
+       }
+
        ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
        if (!ctrl) {
                ret = -ENOMEM;
@@ -2745,7 +2743,6 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        INIT_WORK(&ctrl->delete_work, nvme_fc_delete_ctrl_work);
        INIT_WORK(&ctrl->reset_work, nvme_fc_reset_ctrl_work);
        INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
-       ctrl->reconnect_delay = opts->reconnect_delay;
        spin_lock_init(&ctrl->lock);
 
        /* io queue count */
@@ -2825,6 +2822,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
                return ERR_PTR(ret);
        }
 
+       kref_get(&ctrl->ctrl.kref);
+
        dev_info(ctrl->ctrl.device,
                "NVME-FC{%d}: new ctrl: NQN \"%s\"\n",
                ctrl->cnum, ctrl->ctrl.opts->subsysnqn);
@@ -2961,7 +2960,7 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
 static struct nvmf_transport_ops nvme_fc_transport = {
        .name           = "fc",
        .required_opts  = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR,
-       .allowed_opts   = NVMF_OPT_RECONNECT_DELAY,
+       .allowed_opts   = NVMF_OPT_RECONNECT_DELAY | NVMF_OPT_CTRL_LOSS_TMO,
        .create_ctrl    = nvme_fc_create_ctrl,
 };
 
index 29c708ca9621c4622ab3f32d153c02546e9d0ca6..9d6a070d43914dcc5388b2a7a03f477a00b8bd1f 100644 (file)
@@ -208,7 +208,9 @@ struct nvme_ns {
 struct nvme_ctrl_ops {
        const char *name;
        struct module *module;
-       bool is_fabrics;
+       unsigned int flags;
+#define NVME_F_FABRICS                 (1 << 0)
+#define NVME_F_METADATA_SUPPORTED      (1 << 1)
        int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val);
        int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val);
        int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val);
index fed803232edccbdf63139d89028c694efff52409..40c7581caeb00d30a60c7b9152ac67dd99a888d6 100644 (file)
@@ -263,7 +263,7 @@ static void nvme_dbbuf_set(struct nvme_dev *dev)
        c.dbbuf.prp2 = cpu_to_le64(dev->dbbuf_eis_dma_addr);
 
        if (nvme_submit_sync_cmd(dev->ctrl.admin_q, &c, NULL, 0)) {
-               dev_warn(dev->dev, "unable to set dbbuf\n");
+               dev_warn(dev->ctrl.device, "unable to set dbbuf\n");
                /* Free memory and continue on */
                nvme_dbbuf_dma_free(dev);
        }
@@ -1367,7 +1367,7 @@ static bool nvme_should_reset(struct nvme_dev *dev, u32 csts)
        bool nssro = dev->subsystem && (csts & NVME_CSTS_NSSRO);
 
        /* If there is a reset ongoing, we shouldn't reset again. */
-       if (work_busy(&dev->reset_work))
+       if (dev->ctrl.state == NVME_CTRL_RESETTING)
                return false;
 
        /* We shouldn't reset unless the controller is on fatal error state
@@ -1394,11 +1394,11 @@ static void nvme_warn_reset(struct nvme_dev *dev, u32 csts)
        result = pci_read_config_word(to_pci_dev(dev->dev), PCI_STATUS,
                                      &pci_status);
        if (result == PCIBIOS_SUCCESSFUL)
-               dev_warn(dev->dev,
+               dev_warn(dev->ctrl.device,
                         "controller is down; will reset: CSTS=0x%x, PCI_STATUS=0x%hx\n",
                         csts, pci_status);
        else
-               dev_warn(dev->dev,
+               dev_warn(dev->ctrl.device,
                         "controller is down; will reset: CSTS=0x%x, PCI_STATUS read failed (%d)\n",
                         csts, result);
 }
@@ -1506,6 +1506,11 @@ static inline void nvme_release_cmb(struct nvme_dev *dev)
        if (dev->cmb) {
                iounmap(dev->cmb);
                dev->cmb = NULL;
+               if (dev->cmbsz) {
+                       sysfs_remove_file_from_group(&dev->ctrl.device->kobj,
+                                                    &dev_attr_cmb.attr, NULL);
+                       dev->cmbsz = 0;
+               }
        }
 }
 
@@ -1735,8 +1740,8 @@ static int nvme_pci_enable(struct nvme_dev *dev)
         */
        if (pdev->vendor == PCI_VENDOR_ID_APPLE && pdev->device == 0x2001) {
                dev->q_depth = 2;
-               dev_warn(dev->dev, "detected Apple NVMe controller, set "
-                       "queue depth=%u to work around controller resets\n",
+               dev_warn(dev->ctrl.device, "detected Apple NVMe controller, "
+                       "set queue depth=%u to work around controller resets\n",
                        dev->q_depth);
        }
 
@@ -1754,7 +1759,7 @@ static int nvme_pci_enable(struct nvme_dev *dev)
                if (dev->cmbsz) {
                        if (sysfs_add_file_to_group(&dev->ctrl.device->kobj,
                                                    &dev_attr_cmb.attr, NULL))
-                               dev_warn(dev->dev,
+                               dev_warn(dev->ctrl.device,
                                         "failed to add sysfs attribute for CMB\n");
                }
        }
@@ -1779,6 +1784,7 @@ static void nvme_pci_disable(struct nvme_dev *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
+       nvme_release_cmb(dev);
        pci_free_irq_vectors(pdev);
 
        if (pci_is_enabled(pdev)) {
@@ -1799,7 +1805,8 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
        if (pci_is_enabled(pdev)) {
                u32 csts = readl(dev->bar + NVME_REG_CSTS);
 
-               if (dev->ctrl.state == NVME_CTRL_LIVE)
+               if (dev->ctrl.state == NVME_CTRL_LIVE ||
+                   dev->ctrl.state == NVME_CTRL_RESETTING)
                        nvme_start_freeze(&dev->ctrl);
                dead = !!((csts & NVME_CSTS_CFS) || !(csts & NVME_CSTS_RDY) ||
                        pdev->error_state  != pci_channel_io_normal);
@@ -1897,7 +1904,7 @@ static void nvme_reset_work(struct work_struct *work)
        bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
        int result = -ENODEV;
 
-       if (WARN_ON(dev->ctrl.state == NVME_CTRL_RESETTING))
+       if (WARN_ON(dev->ctrl.state != NVME_CTRL_RESETTING))
                goto out;
 
        /*
@@ -1907,9 +1914,6 @@ static void nvme_reset_work(struct work_struct *work)
        if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
                nvme_dev_disable(dev, false);
 
-       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
-               goto out;
-
        result = nvme_pci_enable(dev);
        if (result)
                goto out;
@@ -2003,8 +2007,8 @@ static int nvme_reset(struct nvme_dev *dev)
 {
        if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q))
                return -ENODEV;
-       if (work_busy(&dev->reset_work))
-               return -ENODEV;
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
+               return -EBUSY;
        if (!queue_work(nvme_workq, &dev->reset_work))
                return -EBUSY;
        return 0;
@@ -2041,6 +2045,7 @@ static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl)
 static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
        .name                   = "pcie",
        .module                 = THIS_MODULE,
+       .flags                  = NVME_F_METADATA_SUPPORTED,
        .reg_read32             = nvme_pci_reg_read32,
        .reg_write32            = nvme_pci_reg_write32,
        .reg_read64             = nvme_pci_reg_read64,
@@ -2129,6 +2134,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (result)
                goto release_pools;
 
+       nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING);
        dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
 
        queue_work(nvme_workq, &dev->reset_work);
@@ -2172,6 +2178,7 @@ static void nvme_remove(struct pci_dev *pdev)
 
        nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
 
+       cancel_work_sync(&dev->reset_work);
        pci_set_drvdata(pdev, NULL);
 
        if (!pci_device_is_present(pdev)) {
@@ -2184,7 +2191,6 @@ static void nvme_remove(struct pci_dev *pdev)
        nvme_dev_disable(dev, true);
        nvme_dev_remove_admin(dev);
        nvme_free_queues(dev, 0);
-       nvme_release_cmb(dev);
        nvme_release_prp_pools(dev);
        nvme_dev_unmap(dev);
        nvme_put_ctrl(&dev->ctrl);
@@ -2288,6 +2294,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0x0a54),
                .driver_data = NVME_QUIRK_STRIPE_SIZE |
                                NVME_QUIRK_DEALLOCATE_ZEROES, },
+       { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
+               .driver_data = NVME_QUIRK_NO_DEEPEST_PS },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS, },
        { PCI_DEVICE(0x1c58, 0x0003),   /* HGST adapter */
index dd1c6deef82fcf509b5c04af20d9df1c17746d9b..24397d306d532213cf66e1ca0de9aa43bf12d3d5 100644 (file)
@@ -753,28 +753,26 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
        if (ret)
                goto requeue;
 
-       blk_mq_start_stopped_hw_queues(ctrl->ctrl.admin_q, true);
-
        ret = nvmf_connect_admin_queue(&ctrl->ctrl);
        if (ret)
-               goto stop_admin_q;
+               goto requeue;
 
        set_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[0].flags);
 
        ret = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap);
        if (ret)
-               goto stop_admin_q;
+               goto requeue;
 
        nvme_start_keep_alive(&ctrl->ctrl);
 
        if (ctrl->queue_count > 1) {
                ret = nvme_rdma_init_io_queues(ctrl);
                if (ret)
-                       goto stop_admin_q;
+                       goto requeue;
 
                ret = nvme_rdma_connect_io_queues(ctrl);
                if (ret)
-                       goto stop_admin_q;
+                       goto requeue;
        }
 
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
@@ -782,7 +780,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
        ctrl->ctrl.opts->nr_reconnects = 0;
 
        if (ctrl->queue_count > 1) {
-               nvme_start_queues(&ctrl->ctrl);
                nvme_queue_scan(&ctrl->ctrl);
                nvme_queue_async_events(&ctrl->ctrl);
        }
@@ -791,8 +788,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
 
        return;
 
-stop_admin_q:
-       blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
 requeue:
        dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n",
                        ctrl->ctrl.opts->nr_reconnects);
@@ -823,6 +818,13 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
        blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
                                nvme_cancel_request, &ctrl->ctrl);
 
+       /*
+        * queues are not a live anymore, so restart the queues to fail fast
+        * new IO
+        */
+       blk_mq_start_stopped_hw_queues(ctrl->ctrl.admin_q, true);
+       nvme_start_queues(&ctrl->ctrl);
+
        nvme_rdma_reconnect_or_remove(ctrl);
 }
 
@@ -1038,6 +1040,19 @@ static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
                nvme_rdma_wr_error(cq, wc, "SEND");
 }
 
+static inline int nvme_rdma_queue_sig_limit(struct nvme_rdma_queue *queue)
+{
+       int sig_limit;
+
+       /*
+        * We signal completion every queue depth/2 and also handle the
+        * degenerated case of a  device with queue_depth=1, where we
+        * would need to signal every message.
+        */
+       sig_limit = max(queue->queue_size / 2, 1);
+       return (++queue->sig_count % sig_limit) == 0;
+}
+
 static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
                struct nvme_rdma_qe *qe, struct ib_sge *sge, u32 num_sge,
                struct ib_send_wr *first, bool flush)
@@ -1065,9 +1080,6 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
         * Would have been way to obvious to handle this in hardware or
         * at least the RDMA stack..
         *
-        * This messy and racy code sniplet is copy and pasted from the iSER
-        * initiator, and the magic '32' comes from there as well.
-        *
         * Always signal the flushes. The magic request used for the flush
         * sequencer is not allocated in our driver's tagset and it's
         * triggered to be freed by blk_cleanup_queue(). So we need to
@@ -1075,7 +1087,7 @@ static int nvme_rdma_post_send(struct nvme_rdma_queue *queue,
         * embedded in request's payload, is not freed when __ib_process_cq()
         * calls wr_cqe->done().
         */
-       if ((++queue->sig_count % 32) == 0 || flush)
+       if (nvme_rdma_queue_sig_limit(queue) || flush)
                wr.send_flags |= IB_SEND_SIGNALED;
 
        if (first)
@@ -1423,7 +1435,7 @@ nvme_rdma_timeout(struct request *rq, bool reserved)
 /*
  * We cannot accept any other command until the Connect command has completed.
  */
-static inline bool nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue,
+static inline int nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue,
                struct request *rq)
 {
        if (unlikely(!test_bit(NVME_RDMA_Q_LIVE, &queue->flags))) {
@@ -1431,11 +1443,22 @@ static inline bool nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue,
 
                if (!blk_rq_is_passthrough(rq) ||
                    cmd->common.opcode != nvme_fabrics_command ||
-                   cmd->fabrics.fctype != nvme_fabrics_type_connect)
-                       return false;
+                   cmd->fabrics.fctype != nvme_fabrics_type_connect) {
+                       /*
+                        * reconnecting state means transport disruption, which
+                        * can take a long time and even might fail permanently,
+                        * so we can't let incoming I/O be requeued forever.
+                        * fail it fast to allow upper layers a chance to
+                        * failover.
+                        */
+                       if (queue->ctrl->ctrl.state == NVME_CTRL_RECONNECTING)
+                               return -EIO;
+                       else
+                               return -EAGAIN;
+               }
        }
 
-       return true;
+       return 0;
 }
 
 static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
@@ -1453,8 +1476,9 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
 
        WARN_ON_ONCE(rq->tag < 0);
 
-       if (!nvme_rdma_queue_is_ready(queue, rq))
-               return BLK_MQ_RQ_QUEUE_BUSY;
+       ret = nvme_rdma_queue_is_ready(queue, rq);
+       if (unlikely(ret))
+               goto err;
 
        dev = queue->device->dev;
        ib_dma_sync_single_for_cpu(dev, sqe->dma,
@@ -1782,7 +1806,7 @@ static int nvme_rdma_reset_ctrl(struct nvme_ctrl *nctrl)
 static const struct nvme_ctrl_ops nvme_rdma_ctrl_ops = {
        .name                   = "rdma",
        .module                 = THIS_MODULE,
-       .is_fabrics             = true,
+       .flags                  = NVME_F_FABRICS,
        .reg_read32             = nvmf_reg_read32,
        .reg_read64             = nvmf_reg_read64,
        .reg_write32            = nvmf_reg_write32,
index cf90713043da01ea7180d227feb2895da3653f49..eb9399ac97cff2d5bba89457f6a828238854b98a 100644 (file)
@@ -529,6 +529,12 @@ fail:
 }
 EXPORT_SYMBOL_GPL(nvmet_req_init);
 
+void nvmet_req_uninit(struct nvmet_req *req)
+{
+       percpu_ref_put(&req->sq->ref);
+}
+EXPORT_SYMBOL_GPL(nvmet_req_uninit);
+
 static inline bool nvmet_cc_en(u32 cc)
 {
        return cc & 0x1;
index 62eba29c85fb9b5101d4a974a9392dbb2e71c72d..2006fae61980643d2c42f4d34926aaa11f5f05bc 100644 (file)
@@ -517,9 +517,7 @@ nvmet_fc_queue_to_cpu(struct nvmet_fc_tgtport *tgtport, int qid)
 {
        int cpu, idx, cnt;
 
-       if (!(tgtport->ops->target_features &
-                       NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED) ||
-           tgtport->ops->max_hw_queues == 1)
+       if (tgtport->ops->max_hw_queues == 1)
                return WORK_CPU_UNBOUND;
 
        /* Simple cpu selection based on qid modulo active cpu count */
index 15551ef79c8c4568a6f611b6e9ba9d736127825b..294a6611fb249164e8d321147823e708cfe8a1d1 100644 (file)
@@ -698,7 +698,6 @@ static struct nvmet_fc_target_template tgttemplate = {
        .dma_boundary           = FCLOOP_DMABOUND_4G,
        /* optional features */
        .target_features        = NVMET_FCTGTFEAT_CMD_IN_ISR |
-                                 NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED |
                                  NVMET_FCTGTFEAT_OPDONE_IN_ISR,
        /* sizes of additional private data for data structures */
        .target_priv_sz         = sizeof(struct fcloop_tport),
index feb497134aeea662092424804073be9ed104c464..e503cfff03372fb9cc7605c800743dd4c5891318 100644 (file)
@@ -558,7 +558,7 @@ static int nvme_loop_reset_ctrl(struct nvme_ctrl *nctrl)
 static const struct nvme_ctrl_ops nvme_loop_ctrl_ops = {
        .name                   = "loop",
        .module                 = THIS_MODULE,
-       .is_fabrics             = true,
+       .flags                  = NVME_F_FABRICS,
        .reg_read32             = nvmf_reg_read32,
        .reg_read64             = nvmf_reg_read64,
        .reg_write32            = nvmf_reg_write32,
index 7cb77ba5993b98e0974a66a7712961c434677a7f..cfc5c7fb0ab78411f8d6e96ab7ffaaad241b6244 100644 (file)
@@ -261,6 +261,7 @@ u16 nvmet_parse_fabrics_cmd(struct nvmet_req *req);
 
 bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
                struct nvmet_sq *sq, struct nvmet_fabrics_ops *ops);
+void nvmet_req_uninit(struct nvmet_req *req);
 void nvmet_req_complete(struct nvmet_req *req, u16 status);
 
 void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid,
index 99c69018a35f4419b3dc3a14576c373c044e661a..9e45cde633767be2176770c7ebd71a90b3ca3094 100644 (file)
@@ -567,6 +567,7 @@ static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc)
        rsp->n_rdma = 0;
 
        if (unlikely(wc->status != IB_WC_SUCCESS)) {
+               nvmet_req_uninit(&rsp->req);
                nvmet_rdma_release_rsp(rsp);
                if (wc->status != IB_WC_WR_FLUSH_ERR) {
                        pr_info("RDMA READ for CQE 0x%p failed with status %s (%d).\n",
index 9416d052cb89474e811d8c4e8ca5ca3a81732fbb..28c38c756f92858906ca2aee54a9c922522f9253 100644 (file)
@@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node *np)
                coherent ? " " : " not ");
 
        iommu = of_iommu_configure(dev, np);
-       if (IS_ERR(iommu))
-               return PTR_ERR(iommu);
+       if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
 
        dev_dbg(dev, "device is%sbehind an iommu\n",
                iommu ? " " : " not ");
index 3080d9dd031d14f27553b8596dc4d2dc0248bdfa..43bd69dceabfd36b43368366b8afdc9fa2b30106 100644 (file)
@@ -507,6 +507,9 @@ void *__unflatten_device_tree(const void *blob,
 
        /* Allocate memory for the expanded device tree */
        mem = dt_alloc(size + 4, __alignof__(struct device_node));
+       if (!mem)
+               return NULL;
+
        memset(mem, 0, size);
 
        *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
index 4dec07ea510f5fd67f38fa798727bdffef6c3168..d507c3569a88acac9e796f1f172f412e5386347f 100644 (file)
@@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
        const struct of_device_id *i;
 
        for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) {
-               int const (*initfn)(struct reserved_mem *rmem) = i->data;
+               reservedmem_of_init_fn initfn = i->data;
                const char *compat = i->compatible;
 
                if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
index 71fecc2debfc940affba38afc6c912f3a4aa8b4b..703a42118ffc907571f2da5300639b725c2d529f 100644 (file)
@@ -523,7 +523,7 @@ static int __init of_platform_default_populate_init(void)
 arch_initcall_sync(of_platform_default_populate_init);
 #endif
 
-static int of_platform_device_destroy(struct device *dev, void *data)
+int of_platform_device_destroy(struct device *dev, void *data)
 {
        /* Do not touch devices not populated from the device tree */
        if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
@@ -544,6 +544,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
        of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
        return 0;
 }
+EXPORT_SYMBOL_GPL(of_platform_device_destroy);
 
 /**
  * of_platform_depopulate() - Remove devices populated from device tree
index 74cf5fffb1e1b93fdb1a6d44002d7727544195e7..c80e37a69305c18f2879957c92fa3308bb45b175 100644 (file)
@@ -896,7 +896,7 @@ int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
 {
        if (pci_dev_is_disconnected(dev)) {
                *val = ~0;
-               return -ENODEV;
+               return PCIBIOS_DEVICE_NOT_FOUND;
        }
        return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
 }
@@ -906,7 +906,7 @@ int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
 {
        if (pci_dev_is_disconnected(dev)) {
                *val = ~0;
-               return -ENODEV;
+               return PCIBIOS_DEVICE_NOT_FOUND;
        }
        return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
 }
@@ -917,7 +917,7 @@ int pci_read_config_dword(const struct pci_dev *dev, int where,
 {
        if (pci_dev_is_disconnected(dev)) {
                *val = ~0;
-               return -ENODEV;
+               return PCIBIOS_DEVICE_NOT_FOUND;
        }
        return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
 }
@@ -926,7 +926,7 @@ EXPORT_SYMBOL(pci_read_config_dword);
 int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
 {
        if (pci_dev_is_disconnected(dev))
-               return -ENODEV;
+               return PCIBIOS_DEVICE_NOT_FOUND;
        return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
 }
 EXPORT_SYMBOL(pci_write_config_byte);
@@ -934,7 +934,7 @@ EXPORT_SYMBOL(pci_write_config_byte);
 int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
 {
        if (pci_dev_is_disconnected(dev))
-               return -ENODEV;
+               return PCIBIOS_DEVICE_NOT_FOUND;
        return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
 }
 EXPORT_SYMBOL(pci_write_config_word);
@@ -943,7 +943,7 @@ int pci_write_config_dword(const struct pci_dev *dev, int where,
                                         u32 val)
 {
        if (pci_dev_is_disconnected(dev))
-               return -ENODEV;
+               return PCIBIOS_DEVICE_NOT_FOUND;
        return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
 }
 EXPORT_SYMBOL(pci_write_config_dword);
index a98cba55c7f02e670436787c011a85a8772f5109..19a289b8cc944fefb6e2bb3b627b61a0a2eff3ed 100644 (file)
@@ -252,7 +252,34 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
 static int imx6q_pcie_abort_handler(unsigned long addr,
                unsigned int fsr, struct pt_regs *regs)
 {
-       return 0;
+       unsigned long pc = instruction_pointer(regs);
+       unsigned long instr = *(unsigned long *)pc;
+       int reg = (instr >> 12) & 15;
+
+       /*
+        * If the instruction being executed was a read,
+        * make it look like it read all-ones.
+        */
+       if ((instr & 0x0c100000) == 0x04100000) {
+               unsigned long val;
+
+               if (instr & 0x00400000)
+                       val = 255;
+               else
+                       val = -1;
+
+               regs->uregs[reg] = val;
+               regs->ARM_pc += 4;
+               return 0;
+       }
+
+       if ((instr & 0x0e100090) == 0x00100090) {
+               regs->uregs[reg] = -1;
+               regs->ARM_pc += 4;
+               return 0;
+       }
+
+       return 1;
 }
 
 static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
@@ -819,8 +846,8 @@ static int __init imx6_pcie_init(void)
         * we can install the handler here without risking it
         * accessing some uninitialized driver state.
         */
-       hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
-                       "imprecise external abort");
+       hook_fault_code(8, imx6q_pcie_abort_handler, SIGBUS, 0,
+                       "external abort on non-linefetch");
 
        return platform_driver_register(&imx6_pcie_driver);
 }
index c23f146fb5a668b3a5f5ae27b0bb4f00a8057d7f..c09623ca8c3b14b9b522c471fa9ac118c9522106 100644 (file)
@@ -6,6 +6,7 @@ menu "PCI Endpoint"
 
 config PCI_ENDPOINT
        bool "PCI Endpoint Support"
+       depends on HAS_DMA
        help
           Enable this configuration option to support configurable PCI
           endpoint. This should be enabled if the platform has a PCI
index 175edad42d2f8fe100b762bbbe39bc042dceabe4..2942066607e0e9a6393139bfab65b5c13f6b09c5 100644 (file)
@@ -5,6 +5,7 @@
 config PCI_EPF_TEST
        tristate "PCI Endpoint Test driver"
        depends on PCI_ENDPOINT
+       select CRC32
        help
           Enable this configuration option to enable the test driver
           for PCI Endpoint.
index b01bd5bba8e604709c3b51f14f9fbdb796a2c4fb..563901cd9c06b839f4eea9a74ed78f76309f7f62 100644 (file)
@@ -2144,7 +2144,8 @@ bool pci_dev_keep_suspended(struct pci_dev *pci_dev)
 
        if (!pm_runtime_suspended(dev)
            || pci_target_state(pci_dev) != pci_dev->current_state
-           || platform_pci_need_resume(pci_dev))
+           || platform_pci_need_resume(pci_dev)
+           || (pci_dev->dev_flags & PCI_DEV_FLAGS_NEEDS_RESUME))
                return false;
 
        /*
index cc6e085008fb9c6e72244d9e6a588864c3f2962b..f6a63406c76e0b170e348c882abcf2723f2d401d 100644 (file)
@@ -1291,7 +1291,6 @@ static struct switchtec_dev *stdev_create(struct pci_dev *pdev)
        cdev = &stdev->cdev;
        cdev_init(cdev, &switchtec_fops);
        cdev->owner = THIS_MODULE;
-       cdev->kobj.parent = &dev->kobj;
 
        return stdev;
 
@@ -1442,12 +1441,15 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
        stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
        stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
        stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET;
-       stdev->partition = ioread8(&stdev->mmio_ntb->partition_id);
+       stdev->partition = ioread8(&stdev->mmio_sys_info->partition_id);
        stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count);
        stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET;
        stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition];
        stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET;
 
+       if (stdev->partition_count < 1)
+               stdev->partition_count = 1;
+
        init_pff(stdev);
 
        pci_set_drvdata(pdev, stdev);
@@ -1479,11 +1481,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
                  SWITCHTEC_EVENT_EN_IRQ,
                  &stdev->mmio_part_cfg->mrpc_comp_hdr);
 
-       rc = cdev_add(&stdev->cdev, stdev->dev.devt, 1);
-       if (rc)
-               goto err_put;
-
-       rc = device_add(&stdev->dev);
+       rc = cdev_device_add(&stdev->cdev, &stdev->dev);
        if (rc)
                goto err_devadd;
 
@@ -1492,7 +1490,6 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
        return 0;
 
 err_devadd:
-       cdev_del(&stdev->cdev);
        stdev_kill(stdev);
 err_put:
        ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
@@ -1506,8 +1503,7 @@ static void switchtec_pci_remove(struct pci_dev *pdev)
 
        pci_set_drvdata(pdev, NULL);
 
-       device_del(&stdev->dev);
-       cdev_del(&stdev->cdev);
+       cdev_device_del(&stdev->cdev, &stdev->dev);
        ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
        dev_info(&stdev->dev, "unregistered.\n");
 
index 34c862f213c7e85554830b741cdf051f1fbbd86d..0a9b78705ee810c9e18c6fa1f46551fc27374287 100644 (file)
@@ -29,6 +29,17 @@ static int arm_pmu_acpi_register_irq(int cpu)
                return -EINVAL;
 
        gsi = gicc->performance_interrupt;
+
+       /*
+        * Per the ACPI spec, the MADT cannot describe a PMU that doesn't
+        * have an interrupt. QEMU advertises this by using a GSI of zero,
+        * which is not known to be valid on any hardware despite being
+        * valid per the spec. Take the pragmatic approach and reject a
+        * GSI of zero for now.
+        */
+       if (!gsi)
+               return 0;
+
        if (gicc->flags & ACPI_MADT_PERFORMANCE_IRQ_MODE)
                trigger = ACPI_EDGE_SENSITIVE;
        else
index 727e23be7cac40cfff7ac7103fcf75e6e176c420..78ca62897784abf2704e5f8748155c8e8995515e 100644 (file)
@@ -844,7 +844,7 @@ static int qcom_qmp_phy_vreg_init(struct device *dev)
        int num = qmp->cfg->num_vregs;
        int i;
 
-       qmp->vregs = devm_kcalloc(dev, num, sizeof(qmp->vregs), GFP_KERNEL);
+       qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
        if (!qmp->vregs)
                return -ENOMEM;
 
@@ -983,16 +983,16 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
         * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
         */
        qphy->tx = of_iomap(np, 0);
-       if (IS_ERR(qphy->tx))
-               return PTR_ERR(qphy->tx);
+       if (!qphy->tx)
+               return -ENOMEM;
 
        qphy->rx = of_iomap(np, 1);
-       if (IS_ERR(qphy->rx))
-               return PTR_ERR(qphy->rx);
+       if (!qphy->rx)
+               return -ENOMEM;
 
        qphy->pcs = of_iomap(np, 2);
-       if (IS_ERR(qphy->pcs))
-               return PTR_ERR(qphy->pcs);
+       if (!qphy->pcs)
+               return -ENOMEM;
 
        /*
         * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
index 1653cbda6a8299b33b5cebae92bd4710e41412a4..bd459a93b0e7e9b11c999dd4bf9b95c3500be3e2 100644 (file)
@@ -680,30 +680,16 @@ EXPORT_SYMBOL_GPL(pinctrl_generic_remove_group);
  * pinctrl_generic_free_groups() - removes all pin groups
  * @pctldev: pin controller device
  *
- * Note that the caller must take care of locking.
+ * Note that the caller must take care of locking. The pinctrl groups
+ * are allocated with devm_kzalloc() so no need to free them here.
  */
 static void pinctrl_generic_free_groups(struct pinctrl_dev *pctldev)
 {
        struct radix_tree_iter iter;
-       struct group_desc *group;
-       unsigned long *indices;
        void **slot;
-       int i = 0;
-
-       indices = devm_kzalloc(pctldev->dev, sizeof(*indices) *
-                              pctldev->num_groups, GFP_KERNEL);
-       if (!indices)
-               return;
 
        radix_tree_for_each_slot(slot, &pctldev->pin_group_tree, &iter, 0)
-               indices[i++] = iter.index;
-
-       for (i = 0; i < pctldev->num_groups; i++) {
-               group = radix_tree_lookup(&pctldev->pin_group_tree,
-                                         indices[i]);
-               radix_tree_delete(&pctldev->pin_group_tree, indices[i]);
-               devm_kfree(pctldev->dev, group);
-       }
+               radix_tree_delete(&pctldev->pin_group_tree, iter.index);
 
        pctldev->num_groups = 0;
 }
index 41b5b07d5a2bf51f6b0623597c294862910de78c..6852010a6d708b5010555cbb141bf57ac31de077 100644 (file)
@@ -194,6 +194,16 @@ static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
        return 0;
 }
 
+static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
+{
+       u32 tmp;
+
+       tmp = readl(reg);
+       tmp &= ~(mask << shift);
+       tmp |= value << shift;
+       writel(tmp, reg);
+}
+
 static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
                               unsigned group)
 {
@@ -211,8 +221,7 @@ static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
                reg += bank * 0x20 + pin / 16 * 0x10;
                shift = pin % 16 * 2;
 
-               writel(0x3 << shift, reg + CLR);
-               writel(g->muxsel[i] << shift, reg + SET);
+               mxs_pinctrl_rmwl(g->muxsel[i], 0x3, shift, reg);
        }
 
        return 0;
@@ -279,8 +288,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev,
                        /* mA */
                        if (config & MA_PRESENT) {
                                shift = pin % 8 * 4;
-                               writel(0x3 << shift, reg + CLR);
-                               writel(ma << shift, reg + SET);
+                               mxs_pinctrl_rmwl(ma, 0x3, shift, reg);
                        }
 
                        /* vol */
index 2debba62fac90d956ce37cd09805c518ee4a8da5..20f1b44939944614ff270c757fc7152f901e9f09 100644 (file)
@@ -1539,15 +1539,29 @@ static void chv_gpio_irq_handler(struct irq_desc *desc)
  * is not listed below.
  */
 static const struct dmi_system_id chv_no_valid_mask[] = {
+       /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */
        {
-               /* See https://bugzilla.kernel.org/show_bug.cgi?id=194945 */
-               .ident = "Acer Chromebook (CYAN)",
+               .ident = "Intel_Strago based Chromebooks (All models)",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Edgar"),
-                       DMI_MATCH(DMI_BIOS_DATE, "05/21/2016"),
+                       DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
                },
-       }
+       },
+       {
+               .ident = "Acer Chromebook R11 (Cyan)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
+               },
+       },
+       {
+               .ident = "Samsung Chromebook 3 (Celes)",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
+               },
+       },
+       {}
 };
 
 static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
index 0d6b7f4b82af34a2a85e51c924ca8420bd7a6268..720a19fd38d2c6c24d30e5e1c7dcdf70cae0e590 100644 (file)
@@ -35,7 +35,6 @@ static const struct pin_config_item conf_items[] = {
        PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
                                "input bias pull to pin specific state", NULL, false),
        PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
-       PCONFDUMP(PIN_CONFIG_BIDIRECTIONAL, "bi-directional pin operations", NULL, false),
        PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
        PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
        PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
@@ -161,7 +160,6 @@ static const struct pinconf_generic_params dt_params[] = {
        { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
        { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 },
        { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
-       { "bi-directional", PIN_CONFIG_BIDIRECTIONAL, 1 },
        { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
        { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 },
        { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
@@ -174,7 +172,6 @@ static const struct pinconf_generic_params dt_params[] = {
        { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
        { "low-power-disable", PIN_CONFIG_LOW_POWER_MODE, 0 },
        { "low-power-enable", PIN_CONFIG_LOW_POWER_MODE, 1 },
-       { "output-enable", PIN_CONFIG_OUTPUT, 1, },
        { "output-high", PIN_CONFIG_OUTPUT, 1, },
        { "output-low", PIN_CONFIG_OUTPUT, 0, },
        { "power-source", PIN_CONFIG_POWER_SOURCE, 0 },
index 1482d132fbb879ab39ec62dadcd48e9445feced9..e432ec887479d32b2be5afcc1a26e295909b04cb 100644 (file)
@@ -495,64 +495,54 @@ static struct irq_chip amd_gpio_irqchip = {
        .flags        = IRQCHIP_SKIP_SET_WAKE,
 };
 
-static void amd_gpio_irq_handler(struct irq_desc *desc)
+#define PIN_IRQ_PENDING        (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
+
+static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
 {
-       u32 i;
-       u32 off;
-       u32 reg;
-       u32 pin_reg;
-       u64 reg64;
-       int handled = 0;
-       unsigned int irq;
+       struct amd_gpio *gpio_dev = dev_id;
+       struct gpio_chip *gc = &gpio_dev->gc;
+       irqreturn_t ret = IRQ_NONE;
+       unsigned int i, irqnr;
        unsigned long flags;
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
-       struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+       u32 *regs, regval;
+       u64 status, mask;
 
-       chained_irq_enter(chip, desc);
-       /*enable GPIO interrupt again*/
+       /* Read the wake status */
        raw_spin_lock_irqsave(&gpio_dev->lock, flags);
-       reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
-       reg64 = reg;
-       reg64 = reg64 << 32;
-
-       reg = readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
-       reg64 |= reg;
+       status = readl(gpio_dev->base + WAKE_INT_STATUS_REG1);
+       status <<= 32;
+       status |= readl(gpio_dev->base + WAKE_INT_STATUS_REG0);
        raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
-       /*
-        * first 46 bits indicates interrupt status.
-        * one bit represents four interrupt sources.
-       */
-       for (off = 0; off < 46 ; off++) {
-               if (reg64 & BIT(off)) {
-                       for (i = 0; i < 4; i++) {
-                               pin_reg = readl(gpio_dev->base +
-                                               (off * 4 + i) * 4);
-                               if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
-                                       (pin_reg & BIT(WAKE_STS_OFF))) {
-                                       irq = irq_find_mapping(gc->irqdomain,
-                                                               off * 4 + i);
-                                       generic_handle_irq(irq);
-                                       writel(pin_reg,
-                                               gpio_dev->base
-                                               + (off * 4 + i) * 4);
-                                       handled++;
-                               }
-                       }
+       /* Bit 0-45 contain the relevant status bits */
+       status &= (1ULL << 46) - 1;
+       regs = gpio_dev->base;
+       for (mask = 1, irqnr = 0; status; mask <<= 1, regs += 4, irqnr += 4) {
+               if (!(status & mask))
+                       continue;
+               status &= ~mask;
+
+               /* Each status bit covers four pins */
+               for (i = 0; i < 4; i++) {
+                       regval = readl(regs + i);
+                       if (!(regval & PIN_IRQ_PENDING))
+                               continue;
+                       irq = irq_find_mapping(gc->irqdomain, irqnr + i);
+                       generic_handle_irq(irq);
+                       /* Clear interrupt */
+                       writel(regval, regs + i);
+                       ret = IRQ_HANDLED;
                }
        }
 
-       if (handled == 0)
-               handle_bad_irq(desc);
-
+       /* Signal EOI to the GPIO unit */
        raw_spin_lock_irqsave(&gpio_dev->lock, flags);
-       reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
-       reg |= EOI_MASK;
-       writel(reg, gpio_dev->base + WAKE_INT_MASTER_REG);
+       regval = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+       regval |= EOI_MASK;
+       writel(regval, gpio_dev->base + WAKE_INT_MASTER_REG);
        raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
-       chained_irq_exit(chip, desc);
+       return ret;
 }
 
 static int amd_get_groups_count(struct pinctrl_dev *pctldev)
@@ -821,10 +811,11 @@ static int amd_gpio_probe(struct platform_device *pdev)
                goto out2;
        }
 
-       gpiochip_set_chained_irqchip(&gpio_dev->gc,
-                                &amd_gpio_irqchip,
-                                irq_base,
-                                amd_gpio_irq_handler);
+       ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, 0,
+                              KBUILD_MODNAME, gpio_dev);
+       if (ret)
+               goto out2;
+
        platform_set_drvdata(pdev, gpio_dev);
 
        dev_dbg(&pdev->dev, "amd gpio driver loaded\n");
index f141aa0430b15159111868ad96abd4c658e88ca0..9dd981ddbb178d5516013e34e5b1746bcf483a58 100644 (file)
@@ -143,9 +143,6 @@ struct rockchip_drv {
  * @gpio_chip: gpiolib chip
  * @grange: gpio range
  * @slock: spinlock for the gpio bank
- * @irq_lock: bus lock for irq chip
- * @new_irqs: newly configured irqs which must be muxed as GPIOs in
- *     irq_bus_sync_unlock()
  */
 struct rockchip_pin_bank {
        void __iomem                    *reg_base;
@@ -168,8 +165,6 @@ struct rockchip_pin_bank {
        struct pinctrl_gpio_range       grange;
        raw_spinlock_t                  slock;
        u32                             toggle_edge_mode;
-       struct mutex                    irq_lock;
-       u32                             new_irqs;
 };
 
 #define PIN_BANK(id, pins, label)                      \
@@ -2134,12 +2129,11 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
        int ret;
 
        /* make sure the pin is configured as gpio input */
-       ret = rockchip_verify_mux(bank, d->hwirq, RK_FUNC_GPIO);
+       ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
        if (ret < 0)
                return ret;
 
-       bank->new_irqs |= mask;
-
+       clk_enable(bank->clk);
        raw_spin_lock_irqsave(&bank->slock, flags);
 
        data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
@@ -2197,6 +2191,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
        default:
                irq_gc_unlock(gc);
                raw_spin_unlock_irqrestore(&bank->slock, flags);
+               clk_disable(bank->clk);
                return -EINVAL;
        }
 
@@ -2205,6 +2200,7 @@ static int rockchip_irq_set_type(struct irq_data *d, unsigned int type)
 
        irq_gc_unlock(gc);
        raw_spin_unlock_irqrestore(&bank->slock, flags);
+       clk_disable(bank->clk);
 
        return 0;
 }
@@ -2248,34 +2244,6 @@ static void rockchip_irq_disable(struct irq_data *d)
        clk_disable(bank->clk);
 }
 
-static void rockchip_irq_bus_lock(struct irq_data *d)
-{
-       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       struct rockchip_pin_bank *bank = gc->private;
-
-       clk_enable(bank->clk);
-       mutex_lock(&bank->irq_lock);
-}
-
-static void rockchip_irq_bus_sync_unlock(struct irq_data *d)
-{
-       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       struct rockchip_pin_bank *bank = gc->private;
-
-       while (bank->new_irqs) {
-               unsigned int irq = __ffs(bank->new_irqs);
-               int ret;
-
-               ret = rockchip_set_mux(bank, irq, RK_FUNC_GPIO);
-               WARN_ON(ret < 0);
-
-               bank->new_irqs &= ~BIT(irq);
-       }
-
-       mutex_unlock(&bank->irq_lock);
-       clk_disable(bank->clk);
-}
-
 static int rockchip_interrupts_register(struct platform_device *pdev,
                                                struct rockchip_pinctrl *info)
 {
@@ -2342,9 +2310,6 @@ static int rockchip_interrupts_register(struct platform_device *pdev,
                gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend;
                gc->chip_types[0].chip.irq_resume = rockchip_irq_resume;
                gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type;
-               gc->chip_types[0].chip.irq_bus_lock = rockchip_irq_bus_lock;
-               gc->chip_types[0].chip.irq_bus_sync_unlock =
-                                               rockchip_irq_bus_sync_unlock;
                gc->wake_enabled = IRQ_MSK(bank->nr_pins);
 
                irq_set_chained_handler_and_data(bank->irq,
@@ -2518,7 +2483,6 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
                int bank_pins = 0;
 
                raw_spin_lock_init(&bank->slock);
-               mutex_init(&bank->irq_lock);
                bank->drvdata = d;
                bank->pin_base = ctrl->nr_pins;
                ctrl->nr_pins += bank->nr_pins;
index 9fd6d9087dc508ca7731d7f1e868988e0e320cc2..16b3ae5e4f440c4769db55ebf7c61ebae7e1e5c1 100644 (file)
@@ -826,30 +826,17 @@ EXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
  * pinmux_generic_free_functions() - removes all functions
  * @pctldev: pin controller device
  *
- * Note that the caller must take care of locking.
+ * Note that the caller must take care of locking. The pinctrl
+ * functions are allocated with devm_kzalloc() so no need to free
+ * them here.
  */
 void pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
 {
        struct radix_tree_iter iter;
-       struct function_desc *function;
-       unsigned long *indices;
        void **slot;
-       int i = 0;
-
-       indices = devm_kzalloc(pctldev->dev, sizeof(*indices) *
-                              pctldev->num_functions, GFP_KERNEL);
-       if (!indices)
-               return;
 
        radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
-               indices[i++] = iter.index;
-
-       for (i = 0; i < pctldev->num_functions; i++) {
-               function = radix_tree_lookup(&pctldev->pin_function_tree,
-                                            indices[i]);
-               radix_tree_delete(&pctldev->pin_function_tree, indices[i]);
-               devm_kfree(pctldev->dev, function);
-       }
+               radix_tree_delete(&pctldev->pin_function_tree, iter.index);
 
        pctldev->num_functions = 0;
 }
index d3c5f5dfbbd7974258e4105e3da7114ba7b2324a..222b6685b09f2d72f144daadbf3a3b67a06c1109 100644 (file)
@@ -798,7 +798,7 @@ static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
                break;
        case PIN_CONFIG_OUTPUT:
                __stm32_gpio_set(bank, offset, arg);
-               ret = stm32_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+               ret = stm32_pmx_gpio_set_direction(pctldev, range, pin, false);
                break;
        default:
                ret = -EINVAL;
index 9aec1d2232dd830e2c19a8e1e394e6033e621c21..6624499eae72f5c2ba986c8c54c6f7e583f05f2a 100644 (file)
@@ -394,7 +394,7 @@ static const struct sunxi_desc_pin sun8i_a83t_pins[] = {
        SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 18),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
-                 SUNXI_FUNCTION(0x3, "owa")),          /* DOUT */
+                 SUNXI_FUNCTION(0x3, "spdif")),        /* DOUT */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 19),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out")),
index 2de1e603bd2b1d60afdf4261ce6b8c265c630d01..5f3672153b123b90bdfa4e93fd1fd8f7ec215546 100644 (file)
@@ -704,7 +704,7 @@ static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev)
                /* Reallocate the array */
                u32 new_capacity = 2 * dev->pipes_capacity;
                struct goldfish_pipe **pipes =
-                       kcalloc(new_capacity, sizeof(*pipes), GFP_KERNEL);
+                       kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC);
                if (!pipes)
                        return -ENOMEM;
                memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity);
index ef29f18b195164745bb0a67d9a0852e5b3a676bc..4cc2f4ea0a25043abbfd205465cd3cedeefffa2b 100644 (file)
        } \
 }
 
-#ifdef CONFIG_PM_SLEEP
 static u8 suspend_prep_ok;
 static u32 suspend_shlw_ctr_temp, suspend_deep_ctr_temp;
 static u64 suspend_shlw_res_temp, suspend_deep_res_temp;
-#endif
 
 struct telemetry_susp_stats {
        u32 shlw_swake_ctr;
@@ -807,7 +805,6 @@ static const struct file_operations telem_ioss_trc_verb_ops = {
        .release        = single_release,
 };
 
-#ifdef CONFIG_PM_SLEEP
 static int pm_suspend_prep_cb(void)
 {
        struct telemetry_evtlog evtlog[TELEM_MAX_OS_ALLOCATED_EVENTS];
@@ -937,7 +934,6 @@ static int pm_notification(struct notifier_block *this,
 static struct notifier_block pm_notifier = {
        .notifier_call = pm_notification,
 };
-#endif /* CONFIG_PM_SLEEP */
 
 static int __init telemetry_debugfs_init(void)
 {
@@ -960,14 +956,13 @@ static int __init telemetry_debugfs_init(void)
        if (err < 0)
                return -EINVAL;
 
-
-#ifdef CONFIG_PM_SLEEP
        register_pm_notifier(&pm_notifier);
-#endif /* CONFIG_PM_SLEEP */
 
        debugfs_conf->telemetry_dbg_dir = debugfs_create_dir("telemetry", NULL);
-       if (!debugfs_conf->telemetry_dbg_dir)
-               return -ENOMEM;
+       if (!debugfs_conf->telemetry_dbg_dir) {
+               err = -ENOMEM;
+               goto out_pm;
+       }
 
        f = debugfs_create_file("pss_info", S_IFREG | S_IRUGO,
                                debugfs_conf->telemetry_dbg_dir, NULL,
@@ -1014,6 +1009,8 @@ static int __init telemetry_debugfs_init(void)
 out:
        debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
        debugfs_conf->telemetry_dbg_dir = NULL;
+out_pm:
+       unregister_pm_notifier(&pm_notifier);
 
        return err;
 }
@@ -1022,6 +1019,7 @@ static void __exit telemetry_debugfs_exit(void)
 {
        debugfs_remove_recursive(debugfs_conf->telemetry_dbg_dir);
        debugfs_conf->telemetry_dbg_dir = NULL;
+       unregister_pm_notifier(&pm_notifier);
 }
 
 late_initcall(telemetry_debugfs_init);
index 14bde0db8c245680fd010bf2f0aa39093af5a4c2..5b10b50f8686f953a5fe476f3131b0d8a42307bb 100644 (file)
@@ -538,6 +538,7 @@ struct powercap_zone *powercap_register_zone(
 
        power_zone->id = result;
        idr_init(&power_zone->idr);
+       result = -ENOMEM;
        power_zone->name = kstrdup(name, GFP_KERNEL);
        if (!power_zone->name)
                goto err_name_alloc;
index 35ce53edabf90009efcd228e71a109e410337708..d5e5229308f2291136ebe7c6061346507a733907 100644 (file)
@@ -155,3 +155,5 @@ static int __init hi6220_reset_init(void)
 }
 
 postcore_initcall(hi6220_reset_init);
+
+MODULE_LICENSE("GPL v2");
index b3de973a62607de6812615e81ac1d00bce5c1f1a..9dca53df35845cc64366a5428d9927bff7f28220 100644 (file)
@@ -1088,7 +1088,7 @@ static u32 rtc_handler(void *context)
        }
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       pm_wakeup_event(dev, 0);
+       pm_wakeup_hard_event(dev);
        acpi_clear_event(ACPI_EVENT_RTC);
        acpi_disable_event(ACPI_EVENT_RTC, 0);
        return ACPI_INTERRUPT_HANDLED;
index e443b0d0b23612efec3800a5468e36e58ef7f8d3..34b9ad6b31438fb8864a9068d7f72294722da169 100644 (file)
@@ -35,7 +35,7 @@ static struct bus_type ccwgroup_bus_type;
 static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 {
        int i;
-       char str[8];
+       char str[16];
 
        for (i = 0; i < gdev->count; i++) {
                sprintf(str, "cdev%d", i);
@@ -238,7 +238,7 @@ static void ccwgroup_release(struct device *dev)
 
 static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 {
-       char str[8];
+       char str[16];
        int i, rc;
 
        for (i = 0; i < gdev->count; i++) {
index f33ce85776190ab938548dccbc84fb311d3703fd..1d595d17bf11f6b529eca2caafc494721130b32c 100644 (file)
@@ -11,7 +11,7 @@
 #include "qdio.h"
 
 /* that gives us 15 characters in the text event views */
-#define QDIO_DBF_LEN   16
+#define QDIO_DBF_LEN   32
 
 extern debug_info_t *qdio_dbf_setup;
 extern debug_info_t *qdio_dbf_error;
index e72abbc18ee31afb2e20808364e7830089f94d15..a66a317f3e4fedb6d7caaf2276c3fe3721391a58 100644 (file)
@@ -70,14 +70,14 @@ static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
 {
        return sprintf(buf, "I/O subchannel (Non-QDIO)\n");
 }
-MDEV_TYPE_ATTR_RO(name);
+static MDEV_TYPE_ATTR_RO(name);
 
 static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
                               char *buf)
 {
        return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
 }
-MDEV_TYPE_ATTR_RO(device_api);
+static MDEV_TYPE_ATTR_RO(device_api);
 
 static ssize_t available_instances_show(struct kobject *kobj,
                                        struct device *dev, char *buf)
@@ -86,7 +86,7 @@ static ssize_t available_instances_show(struct kobject *kobj,
 
        return sprintf(buf, "%d\n", atomic_read(&private->avail));
 }
-MDEV_TYPE_ATTR_RO(available_instances);
+static MDEV_TYPE_ATTR_RO(available_instances);
 
 static struct attribute *mdev_types_attrs[] = {
        &mdev_type_attr_name.attr,
@@ -100,7 +100,7 @@ static struct attribute_group mdev_type_group = {
        .attrs = mdev_types_attrs,
 };
 
-struct attribute_group *mdev_type_groups[] = {
+static struct attribute_group *mdev_type_groups[] = {
        &mdev_type_group,
        NULL,
 };
@@ -152,7 +152,7 @@ static int vfio_ccw_mdev_open(struct mdev_device *mdev)
                                      &events, &private->nb);
 }
 
-void vfio_ccw_mdev_release(struct mdev_device *mdev)
+static void vfio_ccw_mdev_release(struct mdev_device *mdev)
 {
        struct vfio_ccw_private *private =
                dev_get_drvdata(mdev_parent_dev(mdev));
@@ -233,7 +233,7 @@ static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info,
        }
 }
 
-int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
+static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info)
 {
        if (info->index != VFIO_CCW_IO_IRQ_INDEX)
                return -EINVAL;
index 9be4596d8a089c7ab8fa35703ebd8c8252608e63..ea099910b4e99466db57f1c2868cc889234e99d3 100644 (file)
@@ -668,10 +668,28 @@ static int ap_device_probe(struct device *dev)
        struct ap_driver *ap_drv = to_ap_drv(dev->driver);
        int rc;
 
+       /* Add queue/card to list of active queues/cards */
+       spin_lock_bh(&ap_list_lock);
+       if (is_card_dev(dev))
+               list_add(&to_ap_card(dev)->list, &ap_card_list);
+       else
+               list_add(&to_ap_queue(dev)->list,
+                        &to_ap_queue(dev)->card->queues);
+       spin_unlock_bh(&ap_list_lock);
+
        ap_dev->drv = ap_drv;
        rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
-       if (rc)
+
+       if (rc) {
+               spin_lock_bh(&ap_list_lock);
+               if (is_card_dev(dev))
+                       list_del_init(&to_ap_card(dev)->list);
+               else
+                       list_del_init(&to_ap_queue(dev)->list);
+               spin_unlock_bh(&ap_list_lock);
                ap_dev->drv = NULL;
+       }
+
        return rc;
 }
 
@@ -680,14 +698,17 @@ static int ap_device_remove(struct device *dev)
        struct ap_device *ap_dev = to_ap_dev(dev);
        struct ap_driver *ap_drv = ap_dev->drv;
 
+       if (ap_drv->remove)
+               ap_drv->remove(ap_dev);
+
+       /* Remove queue/card from list of active queues/cards */
        spin_lock_bh(&ap_list_lock);
        if (is_card_dev(dev))
                list_del_init(&to_ap_card(dev)->list);
        else
                list_del_init(&to_ap_queue(dev)->list);
        spin_unlock_bh(&ap_list_lock);
-       if (ap_drv->remove)
-               ap_drv->remove(ap_dev);
+
        return 0;
 }
 
@@ -1056,10 +1077,6 @@ static void ap_scan_bus(struct work_struct *unused)
                                }
                                /* get it and thus adjust reference counter */
                                get_device(&ac->ap_dev.device);
-                               /* Add card device to card list */
-                               spin_lock_bh(&ap_list_lock);
-                               list_add(&ac->list, &ap_card_list);
-                               spin_unlock_bh(&ap_list_lock);
                        }
                        /* now create the new queue device */
                        aq = ap_queue_create(qid, type);
@@ -1070,10 +1087,6 @@ static void ap_scan_bus(struct work_struct *unused)
                        aq->ap_dev.device.parent = &ac->ap_dev.device;
                        dev_set_name(&aq->ap_dev.device,
                                     "%02x.%04x", id, dom);
-                       /* Add queue device to card queue list */
-                       spin_lock_bh(&ap_list_lock);
-                       list_add(&aq->list, &ac->queues);
-                       spin_unlock_bh(&ap_list_lock);
                        /* Start with a device reset */
                        spin_lock_bh(&aq->lock);
                        ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
@@ -1081,9 +1094,6 @@ static void ap_scan_bus(struct work_struct *unused)
                        /* Register device */
                        rc = device_register(&aq->ap_dev.device);
                        if (rc) {
-                               spin_lock_bh(&ap_list_lock);
-                               list_del_init(&aq->list);
-                               spin_unlock_bh(&ap_list_lock);
                                put_device(&aq->ap_dev.device);
                                continue;
                        }
index cfa161ccc74e92112e48a041cf7f24b99c9204e8..836efac968137aaa297b82476a96a7ee306c1f6a 100644 (file)
@@ -160,7 +160,14 @@ static struct device_type ap_card_type = {
 
 static void ap_card_device_release(struct device *dev)
 {
-       kfree(to_ap_card(dev));
+       struct ap_card *ac = to_ap_card(dev);
+
+       if (!list_empty(&ac->list)) {
+               spin_lock_bh(&ap_list_lock);
+               list_del_init(&ac->list);
+               spin_unlock_bh(&ap_list_lock);
+       }
+       kfree(ac);
 }
 
 struct ap_card *ap_card_create(int id, int queue_depth, int device_type,
index 480c58a637694e3c8c1f885b7eefdeb309e88102..0f1a5d02acb0e151092504754900a3d889514e17 100644 (file)
@@ -584,7 +584,14 @@ static struct device_type ap_queue_type = {
 
 static void ap_queue_device_release(struct device *dev)
 {
-       kfree(to_ap_queue(dev));
+       struct ap_queue *aq = to_ap_queue(dev);
+
+       if (!list_empty(&aq->list)) {
+               spin_lock_bh(&ap_list_lock);
+               list_del_init(&aq->list);
+               spin_unlock_bh(&ap_list_lock);
+       }
+       kfree(aq);
 }
 
 struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type)
index dba94b486f057822ba45d29bea1589adb4026ea5..fa732bd8672961ce89c911f5e60212db1e2da386 100644 (file)
@@ -1954,7 +1954,6 @@ static void netiucv_free_netdevice(struct net_device *dev)
                privptr->conn = NULL; privptr->fsm = NULL;
                /* privptr gets freed by free_netdev() */
        }
-       free_netdev(dev);
 }
 
 /**
@@ -1972,7 +1971,8 @@ static void netiucv_setup_netdevice(struct net_device *dev)
        dev->mtu                 = NETIUCV_MTU_DEFAULT;
        dev->min_mtu             = 576;
        dev->max_mtu             = NETIUCV_MTU_MAX;
-       dev->destructor          = netiucv_free_netdevice;
+       dev->needs_free_netdev   = true;
+       dev->priv_destructor     = netiucv_free_netdevice;
        dev->hard_header_len     = NETIUCV_HDRLEN;
        dev->addr_len            = 0;
        dev->type                = ARPHRD_SLIP;
index f6aa21176d89780e9e745f9045255ff37f1cf788..30bc6105aac3731f2bfad5ffd0d4f14f07f9d291 100644 (file)
@@ -701,6 +701,7 @@ enum qeth_discipline_id {
 };
 
 struct qeth_discipline {
+       const struct device_type *devtype;
        void (*start_poll)(struct ccw_device *, int, unsigned long);
        qdio_handler_t *input_handler;
        qdio_handler_t *output_handler;
@@ -875,6 +876,9 @@ extern struct qeth_discipline qeth_l2_discipline;
 extern struct qeth_discipline qeth_l3_discipline;
 extern const struct attribute_group *qeth_generic_attr_groups[];
 extern const struct attribute_group *qeth_osn_attr_groups[];
+extern const struct attribute_group qeth_device_attr_group;
+extern const struct attribute_group qeth_device_blkt_group;
+extern const struct device_type qeth_generic_devtype;
 extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
index 38114a8d56e00f471360ab400767dcb8ba8a1a7b..fc6d85f2b38d60d4c1b62bd169776d5cfcabcc52 100644 (file)
@@ -5530,10 +5530,12 @@ void qeth_core_free_discipline(struct qeth_card *card)
        card->discipline = NULL;
 }
 
-static const struct device_type qeth_generic_devtype = {
+const struct device_type qeth_generic_devtype = {
        .name = "qeth_generic",
        .groups = qeth_generic_attr_groups,
 };
+EXPORT_SYMBOL_GPL(qeth_generic_devtype);
+
 static const struct device_type qeth_osn_devtype = {
        .name = "qeth_osn",
        .groups = qeth_osn_attr_groups,
@@ -5659,23 +5661,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
                goto err_card;
        }
 
-       if (card->info.type == QETH_CARD_TYPE_OSN)
-               gdev->dev.type = &qeth_osn_devtype;
-       else
-               gdev->dev.type = &qeth_generic_devtype;
-
        switch (card->info.type) {
        case QETH_CARD_TYPE_OSN:
        case QETH_CARD_TYPE_OSM:
                rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
                if (rc)
                        goto err_card;
+
+               gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
+                                       ? card->discipline->devtype
+                                       : &qeth_osn_devtype;
                rc = card->discipline->setup(card->gdev);
                if (rc)
                        goto err_disc;
-       case QETH_CARD_TYPE_OSD:
-       case QETH_CARD_TYPE_OSX:
+               break;
        default:
+               gdev->dev.type = &qeth_generic_devtype;
                break;
        }
 
@@ -5731,8 +5732,10 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
                if (rc)
                        goto err;
                rc = card->discipline->setup(card->gdev);
-               if (rc)
+               if (rc) {
+                       qeth_core_free_discipline(card);
                        goto err;
+               }
        }
        rc = card->discipline->set_online(gdev);
 err:
index 75b29fd2fcf4eab64e82b23b1183fe88211d97ba..db6a285d41e033674706543c2353c0312046e331 100644 (file)
@@ -413,12 +413,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 
        if (card->options.layer2 == newdis)
                goto out;
-       else {
-               card->info.mac_bits  = 0;
-               if (card->discipline) {
-                       card->discipline->remove(card->gdev);
-                       qeth_core_free_discipline(card);
-               }
+       if (card->info.type == QETH_CARD_TYPE_OSM) {
+               /* fixed layer, can't switch */
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       card->info.mac_bits = 0;
+       if (card->discipline) {
+               card->discipline->remove(card->gdev);
+               qeth_core_free_discipline(card);
        }
 
        rc = qeth_core_load_discipline(card, newdis);
@@ -426,6 +430,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
                goto out;
 
        rc = card->discipline->setup(card->gdev);
+       if (rc)
+               qeth_core_free_discipline(card);
 out:
        mutex_unlock(&card->discipline_mutex);
        return rc ? rc : count;
@@ -703,10 +709,11 @@ static struct attribute *qeth_blkt_device_attrs[] = {
        &dev_attr_inter_jumbo.attr,
        NULL,
 };
-static struct attribute_group qeth_device_blkt_group = {
+const struct attribute_group qeth_device_blkt_group = {
        .name = "blkt",
        .attrs = qeth_blkt_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
 
 static struct attribute *qeth_device_attrs[] = {
        &dev_attr_state.attr,
@@ -726,9 +733,10 @@ static struct attribute *qeth_device_attrs[] = {
        &dev_attr_switch_attrs.attr,
        NULL,
 };
-static struct attribute_group qeth_device_attr_group = {
+const struct attribute_group qeth_device_attr_group = {
        .attrs = qeth_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_attr_group);
 
 const struct attribute_group *qeth_generic_attr_groups[] = {
        &qeth_device_attr_group,
index 29d9fb3890ad570826db6d54b1396c149f83fcb5..0d59f9a45ea9e3c52ba4eee9cbc7b37b433dd449 100644 (file)
@@ -8,6 +8,8 @@
 
 #include "qeth_core.h"
 
+extern const struct attribute_group *qeth_l2_attr_groups[];
+
 int qeth_l2_create_device_attributes(struct device *);
 void qeth_l2_remove_device_attributes(struct device *);
 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
index 1b07f382d74c955974d138271bdce2bbbf594f63..bd2df62a5cdf50a85243a878ed98d4d1784b9106 100644 (file)
@@ -880,11 +880,21 @@ static int qeth_l2_stop(struct net_device *dev)
        return 0;
 }
 
+static const struct device_type qeth_l2_devtype = {
+       .name = "qeth_layer2",
+       .groups = qeth_l2_attr_groups,
+};
+
 static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
 
-       qeth_l2_create_device_attributes(&gdev->dev);
+       if (gdev->dev.type == &qeth_generic_devtype) {
+               rc = qeth_l2_create_device_attributes(&gdev->dev);
+               if (rc)
+                       return rc;
+       }
        INIT_LIST_HEAD(&card->vid_list);
        hash_init(card->mac_htable);
        card->options.layer2 = 1;
@@ -896,7 +906,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 {
        struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
 
-       qeth_l2_remove_device_attributes(&cgdev->dev);
+       if (cgdev->dev.type == &qeth_generic_devtype)
+               qeth_l2_remove_device_attributes(&cgdev->dev);
        qeth_set_allowed_threads(card, 0, 1);
        wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
@@ -954,7 +965,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        case QETH_CARD_TYPE_OSN:
                card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
                                         ether_setup);
-               card->dev->flags |= IFF_NOARP;
                break;
        default:
                card->dev = alloc_etherdev(0);
@@ -969,9 +979,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        card->dev->min_mtu = 64;
        card->dev->max_mtu = ETH_MAX_MTU;
        card->dev->netdev_ops = &qeth_l2_netdev_ops;
-       card->dev->ethtool_ops =
-               (card->info.type != QETH_CARD_TYPE_OSN) ?
-               &qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
+       if (card->info.type == QETH_CARD_TYPE_OSN) {
+               card->dev->ethtool_ops = &qeth_l2_osn_ops;
+               card->dev->flags |= IFF_NOARP;
+       } else {
+               card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
+       }
        card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
        if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
                card->dev->hw_features = NETIF_F_SG;
@@ -1269,6 +1282,7 @@ static int qeth_l2_control_event(struct qeth_card *card,
 }
 
 struct qeth_discipline qeth_l2_discipline = {
+       .devtype = &qeth_l2_devtype,
        .start_poll = qeth_qdio_start_poll,
        .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
        .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
index 687972356d6b00f8776cb332e31b1ae0063183a5..9696baa49e2d4409062be4338ea383472a7d4ab0 100644 (file)
@@ -269,3 +269,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
        } else
                qeth_bridgeport_an_set(card, 0);
 }
+
+const struct attribute_group *qeth_l2_attr_groups[] = {
+       &qeth_device_attr_group,
+       &qeth_device_blkt_group,
+       /* l2 specific, see l2_{create,remove}_device_attributes(): */
+       &qeth_l2_bridgeport_attr_group,
+       NULL,
+};
index 6e0354ef4b8629827e4c8ef40b9d569bc11e354b..d8df1e6351636250ea534cf17527c8fb198435f2 100644 (file)
@@ -3039,8 +3039,13 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
 
-       qeth_l3_create_device_attributes(&gdev->dev);
+       rc = qeth_l3_create_device_attributes(&gdev->dev);
+       if (rc)
+               return rc;
+       hash_init(card->ip_htable);
+       hash_init(card->ip_mc_htable);
        card->options.layer2 = 0;
        card->info.hwtrap = 0;
        return 0;
@@ -3306,6 +3311,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
 }
 
 struct qeth_discipline qeth_l3_discipline = {
+       .devtype = &qeth_generic_devtype,
        .start_poll = qeth_qdio_start_poll,
        .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
        .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
index 2a76ea78a0bf1ae9f62508e701cca07a9f690d1f..b18fe2014cf2195a193186c08c956dc8e5cfe7e3 100644 (file)
@@ -87,7 +87,7 @@ struct vq_info_block {
 } __packed;
 
 struct virtio_feature_desc {
-       __u32 features;
+       __le32 features;
        __u8 index;
 } __packed;
 
index 4fc8ed5fe067e1dfb4ca38a934c1f8f21904dba9..1f424e40afdf5c0a608b8a9bd72208c9e2b20e04 100644 (file)
@@ -191,6 +191,7 @@ struct bnx2fc_hba {
        struct bnx2fc_cmd_mgr *cmd_mgr;
        spinlock_t hba_lock;
        struct mutex hba_mutex;
+       struct mutex hba_stats_mutex;
        unsigned long adapter_state;
                #define ADAPTER_STATE_UP                0
                #define ADAPTER_STATE_GOING_DOWN        1
index 93b5a0012417dbc0c6aab8dd8e657e502cbf8681..902722dc4ce3d0d7d1a38d076458a480bc4197ff 100644 (file)
@@ -663,15 +663,17 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
        if (!fw_stats)
                return NULL;
 
+       mutex_lock(&hba->hba_stats_mutex);
+
        bnx2fc_stats = fc_get_host_stats(shost);
 
        init_completion(&hba->stat_req_done);
        if (bnx2fc_send_stat_req(hba))
-               return bnx2fc_stats;
+               goto unlock_stats_mutex;
        rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ));
        if (!rc) {
                BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
-               return bnx2fc_stats;
+               goto unlock_stats_mutex;
        }
        BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt);
        bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt;
@@ -693,6 +695,9 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
 
        memcpy(&hba->prev_stats, hba->stats_buffer,
               sizeof(struct fcoe_statistics_params));
+
+unlock_stats_mutex:
+       mutex_unlock(&hba->hba_stats_mutex);
        return bnx2fc_stats;
 }
 
@@ -1340,6 +1345,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
        }
        spin_lock_init(&hba->hba_lock);
        mutex_init(&hba->hba_mutex);
+       mutex_init(&hba->hba_stats_mutex);
 
        hba->cnic = cnic;
 
index 622bdabc88941430f18ed65b0d70fd9fb0478b9b..dab195f04da78f46921f4eaf044c3f7e953c9a65 100644 (file)
@@ -1769,7 +1769,6 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
                goto bye;
        }
 
-       mempool_free(mbp, hw->mb_mempool);
        if (finicsum != cfcsum) {
                csio_warn(hw,
                      "Config File checksum mismatch: csum=%#x, computed=%#x\n",
@@ -1780,6 +1779,10 @@ csio_hw_use_fwconfig(struct csio_hw *hw, int reset, u32 *fw_cfg_param)
        rv = csio_hw_validate_caps(hw, mbp);
        if (rv != 0)
                goto bye;
+
+       mempool_free(mbp, hw->mb_mempool);
+       mbp = NULL;
+
        /*
         * Note that we're operating with parameters
         * not supplied by the driver, rather than from hard-wired
index 1076c157832291b4794f2d4eaf0ea49489fb1abb..0aae094ab91c8543722fe93e0d8a9c96dd7b72aa 100644 (file)
@@ -1595,7 +1595,6 @@ static void release_offload_resources(struct cxgbi_sock *csk)
                cxgbi_sock_put(csk);
        }
        csk->dst = NULL;
-       csk->cdev = NULL;
 }
 
 static int init_act_open(struct cxgbi_sock *csk)
index bd7d39ecbd2470246a58a8ed3a3fd11367df814f..e4c83b7c96a8180c856627562549c4aae362dcdf 100644 (file)
@@ -867,7 +867,8 @@ static void need_active_close(struct cxgbi_sock *csk)
        log_debug(1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n",
                csk, (csk)->state, (csk)->flags, (csk)->tid);
        spin_lock_bh(&csk->lock);
-       dst_confirm(csk->dst);
+       if (csk->dst)
+               dst_confirm(csk->dst);
        data_lost = skb_queue_len(&csk->receive_queue);
        __skb_queue_purge(&csk->receive_queue);
 
@@ -882,7 +883,8 @@ static void need_active_close(struct cxgbi_sock *csk)
        }
 
        if (close_req) {
-               if (data_lost)
+               if (!cxgbi_sock_flag(csk, CTPF_LOGOUT_RSP_RCVD) ||
+                   data_lost)
                        csk->cdev->csk_send_abort_req(csk);
                else
                        csk->cdev->csk_send_close_req(csk);
@@ -1186,9 +1188,10 @@ static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
                                cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
                skb = next;
        }
-done:
+
        if (likely(skb_queue_len(&csk->write_queue)))
                cdev->csk_push_tx_frames(csk, 1);
+done:
        spin_unlock_bh(&csk->lock);
        return copied;
 
@@ -1568,9 +1571,12 @@ static inline int read_pdu_skb(struct iscsi_conn *conn,
        }
 }
 
-static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
+static int
+skb_read_pdu_bhs(struct cxgbi_sock *csk, struct iscsi_conn *conn,
+                struct sk_buff *skb)
 {
        struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+       int err;
 
        log_debug(1 << CXGBI_DBG_PDU_RX,
                "conn 0x%p, skb 0x%p, len %u, flag 0x%lx.\n",
@@ -1608,7 +1614,16 @@ static int skb_read_pdu_bhs(struct iscsi_conn *conn, struct sk_buff *skb)
                }
        }
 
-       return read_pdu_skb(conn, skb, 0, 0);
+       err = read_pdu_skb(conn, skb, 0, 0);
+       if (likely(err >= 0)) {
+               struct iscsi_hdr *hdr = (struct iscsi_hdr *)skb->data;
+               u8 opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+
+               if (unlikely(opcode == ISCSI_OP_LOGOUT_RSP))
+                       cxgbi_sock_set_flag(csk, CTPF_LOGOUT_RSP_RCVD);
+       }
+
+       return err;
 }
 
 static int skb_read_pdu_data(struct iscsi_conn *conn, struct sk_buff *lskb,
@@ -1713,7 +1728,7 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
                        cxgbi_skcb_rx_pdulen(skb));
 
                if (cxgbi_skcb_test_flag(skb, SKCBF_RX_COALESCED)) {
-                       err = skb_read_pdu_bhs(conn, skb);
+                       err = skb_read_pdu_bhs(csk, conn, skb);
                        if (err < 0) {
                                pr_err("coalesced bhs, csk 0x%p, skb 0x%p,%u, "
                                        "f 0x%lx, plen %u.\n",
@@ -1731,7 +1746,7 @@ void cxgbi_conn_pdu_ready(struct cxgbi_sock *csk)
                                        cxgbi_skcb_flags(skb),
                                        cxgbi_skcb_rx_pdulen(skb));
                } else {
-                       err = skb_read_pdu_bhs(conn, skb);
+                       err = skb_read_pdu_bhs(csk, conn, skb);
                        if (err < 0) {
                                pr_err("bhs, csk 0x%p, skb 0x%p,%u, "
                                        "f 0x%lx, plen %u.\n",
@@ -1873,6 +1888,11 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
        tcp_task->dd_data = tdata;
        task->hdr = NULL;
 
+       if (tdata->skb) {
+               kfree_skb(tdata->skb);
+               tdata->skb = NULL;
+       }
+
        if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
            (opcode == ISCSI_OP_SCSI_DATA_OUT ||
             (opcode == ISCSI_OP_SCSI_CMD &&
@@ -1890,6 +1910,7 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
                return -ENOMEM;
        }
 
+       skb_get(tdata->skb);
        skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
        task->hdr = (struct iscsi_hdr *)tdata->skb->data;
        task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
@@ -2035,9 +2056,9 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
        unsigned int datalen;
        int err;
 
-       if (!skb) {
+       if (!skb || cxgbi_skcb_test_flag(skb, SKCBF_TX_DONE)) {
                log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
-                       "task 0x%p, skb NULL.\n", task);
+                       "task 0x%p, skb 0x%p\n", task, skb);
                return 0;
        }
 
@@ -2050,7 +2071,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
        }
 
        datalen = skb->data_len;
-       tdata->skb = NULL;
 
        /* write ppod first if using ofldq to write ppod */
        if (ttinfo->flags & CXGBI_PPOD_INFO_FLAG_VALID) {
@@ -2078,6 +2098,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
                        pdulen += ISCSI_DIGEST_SIZE;
 
                task->conn->txdata_octets += pdulen;
+               cxgbi_skcb_set_flag(skb, SKCBF_TX_DONE);
                return 0;
        }
 
@@ -2086,7 +2107,6 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
                        "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
                        task, skb, skb->len, skb->data_len, err);
                /* reset skb to send when we are called again */
-               tdata->skb = skb;
                return err;
        }
 
@@ -2094,7 +2114,8 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
                "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
                task->itt, skb, skb->len, skb->data_len, err);
 
-       kfree_skb(skb);
+       __kfree_skb(tdata->skb);
+       tdata->skb = NULL;
 
        iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
        iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
@@ -2113,8 +2134,10 @@ void cxgbi_cleanup_task(struct iscsi_task *task)
 
        tcp_task->dd_data = NULL;
        /*  never reached the xmit task callout */
-       if (tdata->skb)
-               __kfree_skb(tdata->skb);
+       if (tdata->skb) {
+               kfree_skb(tdata->skb);
+               tdata->skb = NULL;
+       }
 
        task_release_itt(task, task->hdr_itt);
        memset(tdata, 0, sizeof(*tdata));
@@ -2714,6 +2737,9 @@ EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible);
 static int __init libcxgbi_init_module(void)
 {
        pr_info("%s", version);
+
+       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+                    sizeof(struct cxgbi_skb_cb));
        return 0;
 }
 
index 18e0ea83d36172cf2fcc55ecfe8f3b133913f1d5..37f07aaab1e463bc78a46e3f363365ed814ac491 100644 (file)
@@ -187,6 +187,7 @@ enum cxgbi_sock_flags {
        CTPF_HAS_ATID,          /* reserved atid */
        CTPF_HAS_TID,           /* reserved hw tid */
        CTPF_OFFLOAD_DOWN,      /* offload function off */
+       CTPF_LOGOUT_RSP_RCVD,   /* received logout response */
 };
 
 struct cxgbi_skb_rx_cb {
@@ -195,7 +196,8 @@ struct cxgbi_skb_rx_cb {
 };
 
 struct cxgbi_skb_tx_cb {
-       void *l2t;
+       void *handle;
+       void *arp_err_handler;
        struct sk_buff *wr_next;
 };
 
@@ -203,6 +205,7 @@ enum cxgbi_skcb_flags {
        SKCBF_TX_NEED_HDR,      /* packet needs a header */
        SKCBF_TX_MEM_WRITE,     /* memory write */
        SKCBF_TX_FLAG_COMPL,    /* wr completion flag */
+       SKCBF_TX_DONE,          /* skb tx done */
        SKCBF_RX_COALESCED,     /* received whole pdu */
        SKCBF_RX_HDR,           /* received pdu header */
        SKCBF_RX_DATA,          /* received pdu payload */
@@ -215,13 +218,13 @@ enum cxgbi_skcb_flags {
 };
 
 struct cxgbi_skb_cb {
-       unsigned char ulp_mode;
-       unsigned long flags;
-       unsigned int seq;
        union {
                struct cxgbi_skb_rx_cb rx;
                struct cxgbi_skb_tx_cb tx;
        };
+       unsigned char ulp_mode;
+       unsigned long flags;
+       unsigned int seq;
 };
 
 #define CXGBI_SKB_CB(skb)      ((struct cxgbi_skb_cb *)&((skb)->cb[0]))
@@ -374,11 +377,9 @@ static inline void cxgbi_sock_enqueue_wr(struct cxgbi_sock *csk,
        cxgbi_skcb_tx_wr_next(skb) = NULL;
        /*
         * We want to take an extra reference since both us and the driver
-        * need to free the packet before it's really freed. We know there's
-        * just one user currently so we use atomic_set rather than skb_get
-        * to avoid the atomic op.
+        * need to free the packet before it's really freed.
         */
-       atomic_set(&skb->users, 2);
+       skb_get(skb);
 
        if (!csk->wr_pending_head)
                csk->wr_pending_head = skb;
index c052104e523ee4f7212ce3c70be08509f8f7df5b..a011c5dbf214055315c6bbdd73c814fd752c2bbe 100644 (file)
@@ -5,6 +5,7 @@
 config CXLFLASH
        tristate "Support for IBM CAPI Flash"
        depends on PCI && SCSI && CXL && EEH
+       select IRQ_POLL
        default m
        help
          Allows CAPI Accelerated IO to Flash
index 3cbab8710e58133ead0cb173cb60ea7a4cafc8e2..2ceff585f1896d9762fd288a93f4bcfde0bf2623 100644 (file)
@@ -265,18 +265,16 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr,
                                      struct list_head *list,
                                      unsigned char *cdb)
 {
-       struct scsi_device *sdev = ctlr->ms_sdev;
-       struct rdac_dh_data *h = sdev->handler_data;
        struct rdac_mode_common *common;
        unsigned data_size;
        struct rdac_queue_data *qdata;
        u8 *lun_table;
 
-       if (h->ctlr->use_ms10) {
+       if (ctlr->use_ms10) {
                struct rdac_pg_expanded *rdac_pg;
 
                data_size = sizeof(struct rdac_pg_expanded);
-               rdac_pg = &h->ctlr->mode_select.expanded;
+               rdac_pg = &ctlr->mode_select.expanded;
                memset(rdac_pg, 0, data_size);
                common = &rdac_pg->common;
                rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
@@ -288,7 +286,7 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr,
                struct rdac_pg_legacy *rdac_pg;
 
                data_size = sizeof(struct rdac_pg_legacy);
-               rdac_pg = &h->ctlr->mode_select.legacy;
+               rdac_pg = &ctlr->mode_select.legacy;
                memset(rdac_pg, 0, data_size);
                common = &rdac_pg->common;
                rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
@@ -304,7 +302,7 @@ static unsigned int rdac_failover_get(struct rdac_controller *ctlr,
        }
 
        /* Prepare the command. */
-       if (h->ctlr->use_ms10) {
+       if (ctlr->use_ms10) {
                cdb[0] = MODE_SELECT_10;
                cdb[7] = data_size >> 8;
                cdb[8] = data_size & 0xff;
index d390325c99ecf9487c9b4441fd0e25aec05378c7..abf6026645dd2308fba55179ca750b0e786da5fa 100644 (file)
@@ -1170,6 +1170,8 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
                cmd = list_first_entry_or_null(&vscsi->free_cmd,
                                               struct ibmvscsis_cmd, list);
                if (cmd) {
+                       if (cmd->abort_cmd)
+                               cmd->abort_cmd = NULL;
                        cmd->flags &= ~(DELAY_SEND);
                        list_del(&cmd->list);
                        cmd->iue = iue;
@@ -1774,6 +1776,7 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
                                if (cmd->abort_cmd) {
                                        retry = true;
                                        cmd->abort_cmd->flags &= ~(DELAY_SEND);
+                                       cmd->abort_cmd = NULL;
                                }
 
                                /*
@@ -1788,6 +1791,25 @@ static void ibmvscsis_send_messages(struct scsi_info *vscsi)
                                        list_del(&cmd->list);
                                        ibmvscsis_free_cmd_resources(vscsi,
                                                                     cmd);
+                                       /*
+                                        * With a successfully aborted op
+                                        * through LIO we want to increment the
+                                        * the vscsi credit so that when we dont
+                                        * send a rsp to the original scsi abort
+                                        * op (h_send_crq), but the tm rsp to
+                                        * the abort is sent, the credit is
+                                        * correctly sent with the abort tm rsp.
+                                        * We would need 1 for the abort tm rsp
+                                        * and 1 credit for the aborted scsi op.
+                                        * Thus we need to increment here.
+                                        * Also we want to increment the credit
+                                        * here because we want to make sure
+                                        * cmd is actually released first
+                                        * otherwise the client will think it
+                                        * it can send a new cmd, and we could
+                                        * find ourselves short of cmd elements.
+                                        */
+                                       vscsi->credit += 1;
                                } else {
                                        iue = cmd->iue;
 
@@ -2962,10 +2984,7 @@ static long srp_build_response(struct scsi_info *vscsi,
 
        rsp->opcode = SRP_RSP;
 
-       if (vscsi->credit > 0 && vscsi->state == SRP_PROCESSING)
-               rsp->req_lim_delta = cpu_to_be32(vscsi->credit);
-       else
-               rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
+       rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
        rsp->tag = cmd->rsp.tag;
        rsp->flags = 0;
 
index a808e8ef1d08d433ba4b703353d486a4f5ef3564..234352da5c3cebeff0d523bbe3842d297ddd8272 100644 (file)
@@ -407,11 +407,12 @@ unlock:
  * can_queue. Eventually we will hit the point where we run
  * on all reserved structs.
  */
-static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
+static bool fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
 {
        struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
        unsigned long flags;
        int can_queue;
+       bool changed = false;
 
        spin_lock_irqsave(lport->host->host_lock, flags);
 
@@ -427,9 +428,11 @@ static void fc_fcp_can_queue_ramp_down(struct fc_lport *lport)
        if (!can_queue)
                can_queue = 1;
        lport->host->can_queue = can_queue;
+       changed = true;
 
 unlock:
        spin_unlock_irqrestore(lport->host->host_lock, flags);
+       return changed;
 }
 
 /*
@@ -1896,11 +1899,11 @@ int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
 
        if (!fc_fcp_lport_queue_ready(lport)) {
                if (lport->qfull) {
-                       fc_fcp_can_queue_ramp_down(lport);
-                       shost_printk(KERN_ERR, lport->host,
-                                    "libfc: queue full, "
-                                    "reducing can_queue to %d.\n",
-                                    lport->host->can_queue);
+                       if (fc_fcp_can_queue_ramp_down(lport))
+                               shost_printk(KERN_ERR, lport->host,
+                                            "libfc: queue full, "
+                                            "reducing can_queue to %d.\n",
+                                            lport->host->can_queue);
                }
                rc = SCSI_MLQUEUE_HOST_BUSY;
                goto out;
index b44c3136eb5181311f12f982fa1ab77b5e95a5f5..520325867e2b4c05528bd89a7eeaccea2f5c6f94 100644 (file)
@@ -1422,7 +1422,7 @@ static void fc_rport_recv_rtv_req(struct fc_rport_priv *rdata,
        fp = fc_frame_alloc(lport, sizeof(*rtv));
        if (!fp) {
                rjt_data.reason = ELS_RJT_UNAB;
-               rjt_data.reason = ELS_EXPL_INSUF_RES;
+               rjt_data.explan = ELS_EXPL_INSUF_RES;
                fc_seq_els_rsp_send(in_fp, ELS_LS_RJT, &rjt_data);
                goto drop;
        }
index 6d7840b096e6f0899823e99d98e12153683e4f07..f2c0ba6ced78bad65694cde021611d9e0e9f9f25 100644 (file)
@@ -141,6 +141,13 @@ struct lpfc_dmabuf {
        uint32_t   buffer_tag;  /* used for tagged queue ring */
 };
 
+struct lpfc_nvmet_ctxbuf {
+       struct list_head list;
+       struct lpfc_nvmet_rcv_ctx *context;
+       struct lpfc_iocbq *iocbq;
+       struct lpfc_sglq *sglq;
+};
+
 struct lpfc_dma_pool {
        struct lpfc_dmabuf   *elements;
        uint32_t    max_count;
@@ -163,9 +170,7 @@ struct rqb_dmabuf {
        struct lpfc_dmabuf dbuf;
        uint16_t total_size;
        uint16_t bytes_recv;
-       void *context;
-       struct lpfc_iocbq *iocbq;
-       struct lpfc_sglq *sglq;
+       uint16_t idx;
        struct lpfc_queue *hrq;   /* ptr to associated Header RQ */
        struct lpfc_queue *drq;   /* ptr to associated Data RQ */
 };
@@ -670,6 +675,8 @@ struct lpfc_hba {
                                        /* INIT_LINK mailbox command */
 #define LS_NPIV_FAB_SUPPORTED 0x2      /* Fabric supports NPIV */
 #define LS_IGNORE_ERATT       0x4      /* intr handler should ignore ERATT */
+#define LS_MDS_LINK_DOWN      0x8      /* MDS Diagnostics Link Down */
+#define LS_MDS_LOOPBACK      0x16      /* MDS Diagnostics Link Up (Loopback) */
 
        uint32_t hba_flag;      /* hba generic flags */
 #define HBA_ERATT_HANDLED      0x1 /* This flag is set when eratt handled */
@@ -777,7 +784,6 @@ struct lpfc_hba {
        uint32_t cfg_nvme_oas;
        uint32_t cfg_nvme_io_channel;
        uint32_t cfg_nvmet_mrq;
-       uint32_t cfg_nvmet_mrq_post;
        uint32_t cfg_enable_nvmet;
        uint32_t cfg_nvme_enable_fb;
        uint32_t cfg_nvmet_fb_size;
@@ -943,6 +949,7 @@ struct lpfc_hba {
        struct pci_pool *lpfc_mbuf_pool;
        struct pci_pool *lpfc_hrb_pool; /* header receive buffer pool */
        struct pci_pool *lpfc_drb_pool; /* data receive buffer pool */
+       struct pci_pool *lpfc_nvmet_drb_pool; /* data receive buffer pool */
        struct pci_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */
        struct pci_pool *txrdy_payload_pool;
        struct lpfc_dma_pool lpfc_mbuf_safety_pool;
@@ -1228,7 +1235,11 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
 static inline struct lpfc_sli_ring *
 lpfc_phba_elsring(struct lpfc_hba *phba)
 {
-       if (phba->sli_rev == LPFC_SLI_REV4)
-               return phba->sli4_hba.els_wq->pring;
+       if (phba->sli_rev == LPFC_SLI_REV4) {
+               if (phba->sli4_hba.els_wq)
+                       return phba->sli4_hba.els_wq->pring;
+               else
+                       return NULL;
+       }
        return &phba->sli.sli3_ring[LPFC_ELS_RING];
 }
index 4830370bfab14247f567de976787aecc9d6b6d28..bb2d9e238225a43315fa846ddcab4052b4de1caa 100644 (file)
@@ -60,9 +60,9 @@
 #define LPFC_MIN_DEVLOSS_TMO   1
 #define LPFC_MAX_DEVLOSS_TMO   255
 
-#define LPFC_DEF_MRQ_POST      256
-#define LPFC_MIN_MRQ_POST      32
-#define LPFC_MAX_MRQ_POST      512
+#define LPFC_DEF_MRQ_POST      512
+#define LPFC_MIN_MRQ_POST      512
+#define LPFC_MAX_MRQ_POST      2048
 
 /*
  * Write key size should be multiple of 4. If write key is changed
@@ -205,8 +205,9 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                                atomic_read(&tgtp->xmt_ls_rsp_error));
 
                len += snprintf(buf+len, PAGE_SIZE-len,
-                               "FCP: Rcv %08x Drop %08x\n",
+                               "FCP: Rcv %08x Release %08x Drop %08x\n",
                                atomic_read(&tgtp->rcv_fcp_cmd_in),
+                               atomic_read(&tgtp->xmt_fcp_release),
                                atomic_read(&tgtp->rcv_fcp_cmd_drop));
 
                if (atomic_read(&tgtp->rcv_fcp_cmd_in) !=
@@ -218,15 +219,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                }
 
                len += snprintf(buf+len, PAGE_SIZE-len,
-                               "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x\n",
+                               "FCP Rsp: RD %08x rsp %08x WR %08x rsp %08x "
+                               "drop %08x\n",
                                atomic_read(&tgtp->xmt_fcp_read),
                                atomic_read(&tgtp->xmt_fcp_read_rsp),
                                atomic_read(&tgtp->xmt_fcp_write),
-                               atomic_read(&tgtp->xmt_fcp_rsp));
-
-               len += snprintf(buf+len, PAGE_SIZE-len,
-                               "FCP Rsp: abort %08x drop %08x\n",
-                               atomic_read(&tgtp->xmt_fcp_abort),
+                               atomic_read(&tgtp->xmt_fcp_rsp),
                                atomic_read(&tgtp->xmt_fcp_drop));
 
                len += snprintf(buf+len, PAGE_SIZE-len,
@@ -236,10 +234,22 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                                atomic_read(&tgtp->xmt_fcp_rsp_drop));
 
                len += snprintf(buf+len, PAGE_SIZE-len,
-                               "ABORT: Xmt %08x Err %08x Cmpl %08x",
+                               "ABORT: Xmt %08x Cmpl %08x\n",
+                               atomic_read(&tgtp->xmt_fcp_abort),
+                               atomic_read(&tgtp->xmt_fcp_abort_cmpl));
+
+               len += snprintf(buf + len, PAGE_SIZE - len,
+                               "ABORT: Sol %08x  Usol %08x Err %08x Cmpl %08x",
+                               atomic_read(&tgtp->xmt_abort_sol),
+                               atomic_read(&tgtp->xmt_abort_unsol),
                                atomic_read(&tgtp->xmt_abort_rsp),
-                               atomic_read(&tgtp->xmt_abort_rsp_error),
-                               atomic_read(&tgtp->xmt_abort_cmpl));
+                               atomic_read(&tgtp->xmt_abort_rsp_error));
+
+               len += snprintf(buf + len, PAGE_SIZE - len,
+                               "IO_CTX: %08x outstanding %08x total %x",
+                               phba->sli4_hba.nvmet_ctx_cnt,
+                               phba->sli4_hba.nvmet_io_wait_cnt,
+                               phba->sli4_hba.nvmet_io_wait_total);
 
                len +=  snprintf(buf+len, PAGE_SIZE-len, "\n");
                return len;
@@ -3311,14 +3321,6 @@ LPFC_ATTR_R(nvmet_mrq,
            1, 1, 16,
            "Specify number of RQ pairs for processing NVMET cmds");
 
-/*
- * lpfc_nvmet_mrq_post: Specify number buffers to post on every MRQ
- *
- */
-LPFC_ATTR_R(nvmet_mrq_post, LPFC_DEF_MRQ_POST,
-           LPFC_MIN_MRQ_POST, LPFC_MAX_MRQ_POST,
-           "Specify number of buffers to post on every MRQ");
-
 /*
  * lpfc_enable_fc4_type: Defines what FC4 types are supported.
  * Supported Values:  1 - register just FCP
@@ -5154,7 +5156,6 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_suppress_rsp,
        &dev_attr_lpfc_nvme_io_channel,
        &dev_attr_lpfc_nvmet_mrq,
-       &dev_attr_lpfc_nvmet_mrq_post,
        &dev_attr_lpfc_nvme_enable_fb,
        &dev_attr_lpfc_nvmet_fb_size,
        &dev_attr_lpfc_enable_bg,
@@ -6194,7 +6195,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
 
        lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type);
        lpfc_nvmet_mrq_init(phba, lpfc_nvmet_mrq);
-       lpfc_nvmet_mrq_post_init(phba, lpfc_nvmet_mrq_post);
 
        /* Initialize first burst. Target vs Initiator are different. */
        lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
@@ -6291,7 +6291,6 @@ lpfc_nvme_mod_param_dep(struct lpfc_hba *phba)
                /* Not NVME Target mode.  Turn off Target parameters. */
                phba->nvmet_support = 0;
                phba->cfg_nvmet_mrq = 0;
-               phba->cfg_nvmet_mrq_post = 0;
                phba->cfg_nvmet_fb_size = 0;
        }
 
index 944b32ca493144f3fc66d625cc2f960ad484373d..da669dce12feb09c6df8564d16f3b0a3fc14c150 100644 (file)
@@ -75,6 +75,10 @@ void lpfc_init_vpi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_cancel_all_vport_retry_delay_timer(struct lpfc_hba *);
 void lpfc_retry_pport_discovery(struct lpfc_hba *);
 void lpfc_release_rpi(struct lpfc_hba *, struct lpfc_vport *, uint16_t);
+int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
+void lpfc_free_iocb_list(struct lpfc_hba *phba);
+int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
+                       struct lpfc_queue *drq, int count, int idx);
 
 void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -123,7 +127,7 @@ int lpfc_disc_state_machine(struct lpfc_vport *, struct lpfc_nodelist *, void *,
 void lpfc_do_scr_ns_plogi(struct lpfc_hba *, struct lpfc_vport *);
 int lpfc_check_sparm(struct lpfc_vport *, struct lpfc_nodelist *,
                     struct serv_parm *, uint32_t, int);
-int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
+void lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist *);
 void lpfc_more_plogi(struct lpfc_vport *);
 void lpfc_more_adisc(struct lpfc_vport *);
 void lpfc_end_rscn(struct lpfc_vport *);
@@ -246,16 +250,14 @@ struct hbq_dmabuf *lpfc_sli4_rb_alloc(struct lpfc_hba *);
 void lpfc_sli4_rb_free(struct lpfc_hba *, struct hbq_dmabuf *);
 struct rqb_dmabuf *lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba);
 void lpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab);
-void lpfc_nvmet_rq_post(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp,
-                       struct lpfc_dmabuf *mp);
+void lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba,
+                           struct lpfc_nvmet_ctxbuf *ctxp);
 int lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
                               struct fc_frame_header *fc_hdr);
 void lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *, struct fcf_record *,
                        uint16_t);
 int lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
                     struct lpfc_rqe *hrqe, struct lpfc_rqe *drqe);
-int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hq,
-                       struct lpfc_queue *dq, int count);
 int lpfc_free_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hq);
 void lpfc_unregister_fcf(struct lpfc_hba *);
 void lpfc_unregister_fcf_rescan(struct lpfc_hba *);
@@ -271,6 +273,7 @@ int lpfc_sli4_fcf_rr_next_proc(struct lpfc_vport *, uint16_t);
 void lpfc_sli4_clear_fcf_rr_bmask(struct lpfc_hba *);
 
 int lpfc_mem_alloc(struct lpfc_hba *, int align);
+int lpfc_nvmet_mem_alloc(struct lpfc_hba *phba);
 int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *);
 void lpfc_mem_free(struct lpfc_hba *);
 void lpfc_mem_free_all(struct lpfc_hba *);
@@ -294,6 +297,7 @@ int lpfc_selective_reset(struct lpfc_hba *);
 void lpfc_reset_barrier(struct lpfc_hba *);
 int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
 int lpfc_sli_brdkill(struct lpfc_hba *);
+int lpfc_sli_chipset_init(struct lpfc_hba *phba);
 int lpfc_sli_brdreset(struct lpfc_hba *);
 int lpfc_sli_brdrestart(struct lpfc_hba *);
 int lpfc_sli_hba_setup(struct lpfc_hba *);
index 1487406aea778411476b1d95f6c454c790c559bb..24ce96dcc94d4ce0fffd8109e89a80193b71bb16 100644 (file)
@@ -630,7 +630,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type,
                                                NLP_EVT_DEVICE_RECOVERY);
                        spin_lock_irq(shost->host_lock);
                        ndlp->nlp_flag &= ~NLP_NVMET_RECOV;
-                       spin_lock_irq(shost->host_lock);
+                       spin_unlock_irq(shost->host_lock);
                }
        }
 
@@ -978,9 +978,10 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                         ndlp, did, ndlp->nlp_fc4_type,
                                         FC_TYPE_FCP, FC_TYPE_NVME);
                        ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
+
+                       lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
+                       lpfc_issue_els_prli(vport, ndlp, 0);
                }
-               lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
-               lpfc_issue_els_prli(vport, ndlp, 0);
        } else
                lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
                                 "3065 GFT_ID failed x%08x\n", irsp->ulpStatus);
@@ -2092,6 +2093,7 @@ lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
 
        ae->un.AttrTypes[3] = 0x02; /* Type 1 - ELS */
        ae->un.AttrTypes[2] = 0x01; /* Type 8 - FCP */
+       ae->un.AttrTypes[6] = 0x01; /* Type 40 - NVME */
        ae->un.AttrTypes[7] = 0x01; /* Type 32 - CT */
        size = FOURBYTES + 32;
        ad->AttrLen = cpu_to_be16(size);
index fce549a91911c197d8e616bce9e0c13cb17de535..4bcb92c844ca5f5061c8a4a5cdfb3d7835594162 100644 (file)
@@ -797,11 +797,6 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
                                atomic_read(&tgtp->xmt_fcp_write),
                                atomic_read(&tgtp->xmt_fcp_rsp));
 
-               len += snprintf(buf + len, size - len,
-                               "FCP Rsp: abort %08x drop %08x\n",
-                               atomic_read(&tgtp->xmt_fcp_abort),
-                               atomic_read(&tgtp->xmt_fcp_drop));
-
                len += snprintf(buf + len, size - len,
                                "FCP Rsp Cmpl: %08x err %08x drop %08x\n",
                                atomic_read(&tgtp->xmt_fcp_rsp_cmpl),
@@ -809,10 +804,16 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
                                atomic_read(&tgtp->xmt_fcp_rsp_drop));
 
                len += snprintf(buf + len, size - len,
-                               "ABORT: Xmt %08x Err %08x Cmpl %08x",
+                               "ABORT: Xmt %08x Cmpl %08x\n",
+                               atomic_read(&tgtp->xmt_fcp_abort),
+                               atomic_read(&tgtp->xmt_fcp_abort_cmpl));
+
+               len += snprintf(buf + len, size - len,
+                               "ABORT: Sol %08x  Usol %08x Err %08x Cmpl %08x",
+                               atomic_read(&tgtp->xmt_abort_sol),
+                               atomic_read(&tgtp->xmt_abort_unsol),
                                atomic_read(&tgtp->xmt_abort_rsp),
-                               atomic_read(&tgtp->xmt_abort_rsp_error),
-                               atomic_read(&tgtp->xmt_abort_cmpl));
+                               atomic_read(&tgtp->xmt_abort_rsp_error));
 
                len +=  snprintf(buf + len, size - len, "\n");
 
@@ -841,6 +842,12 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
                        }
                        spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
                }
+
+               len += snprintf(buf + len, size - len,
+                               "IO_CTX: %08x  outstanding %08x total %08x\n",
+                               phba->sli4_hba.nvmet_ctx_cnt,
+                               phba->sli4_hba.nvmet_io_wait_cnt,
+                               phba->sli4_hba.nvmet_io_wait_total);
        } else {
                if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
                        return len;
@@ -1959,6 +1966,7 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
                atomic_set(&tgtp->rcv_ls_req_out, 0);
                atomic_set(&tgtp->rcv_ls_req_drop, 0);
                atomic_set(&tgtp->xmt_ls_abort, 0);
+               atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
                atomic_set(&tgtp->xmt_ls_rsp, 0);
                atomic_set(&tgtp->xmt_ls_drop, 0);
                atomic_set(&tgtp->xmt_ls_rsp_error, 0);
@@ -1967,19 +1975,22 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf,
                atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
                atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
                atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
-               atomic_set(&tgtp->xmt_fcp_abort, 0);
                atomic_set(&tgtp->xmt_fcp_drop, 0);
                atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
                atomic_set(&tgtp->xmt_fcp_read, 0);
                atomic_set(&tgtp->xmt_fcp_write, 0);
                atomic_set(&tgtp->xmt_fcp_rsp, 0);
+               atomic_set(&tgtp->xmt_fcp_release, 0);
                atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
                atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
                atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
 
+               atomic_set(&tgtp->xmt_fcp_abort, 0);
+               atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
+               atomic_set(&tgtp->xmt_abort_sol, 0);
+               atomic_set(&tgtp->xmt_abort_unsol, 0);
                atomic_set(&tgtp->xmt_abort_rsp, 0);
                atomic_set(&tgtp->xmt_abort_rsp_error, 0);
-               atomic_set(&tgtp->xmt_abort_cmpl, 0);
        }
        return nbytes;
 }
@@ -3070,11 +3081,11 @@ __lpfc_idiag_print_wq(struct lpfc_queue *qp, char *wqtype,
                        qp->assoc_qid, qp->q_cnt_1,
                        (unsigned long long)qp->q_cnt_4);
        len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
-                       "\t\tWQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
-                       "HOST-IDX[%04d], PORT-IDX[%04d]",
+                       "\t\tWQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+                       "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]",
                        qp->queue_id, qp->entry_count,
                        qp->entry_size, qp->host_index,
-                       qp->hba_index);
+                       qp->hba_index, qp->entry_repost);
        len +=  snprintf(pbuffer + len,
                        LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
        return len;
@@ -3121,11 +3132,11 @@ __lpfc_idiag_print_cq(struct lpfc_queue *qp, char *cqtype,
                        qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
                        qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
        len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
-                       "\tCQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
-                       "HOST-IDX[%04d], PORT-IDX[%04d]",
+                       "\tCQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+                       "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]",
                        qp->queue_id, qp->entry_count,
                        qp->entry_size, qp->host_index,
-                       qp->hba_index);
+                       qp->hba_index, qp->entry_repost);
 
        len +=  snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
 
@@ -3143,20 +3154,20 @@ __lpfc_idiag_print_rqpair(struct lpfc_queue *qp, struct lpfc_queue *datqp,
                        "\t\t%s RQ info: ", rqtype);
        len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
                        "AssocCQID[%02d]: RQ-STAT[nopost:x%x nobuf:x%x "
-                       "trunc:x%x rcv:x%llx]\n",
+                       "posted:x%x rcv:x%llx]\n",
                        qp->assoc_qid, qp->q_cnt_1, qp->q_cnt_2,
                        qp->q_cnt_3, (unsigned long long)qp->q_cnt_4);
        len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
-                       "\t\tHQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
-                       "HOST-IDX[%04d], PORT-IDX[%04d]\n",
+                       "\t\tHQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+                       "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]\n",
                        qp->queue_id, qp->entry_count, qp->entry_size,
-                       qp->host_index, qp->hba_index);
+                       qp->host_index, qp->hba_index, qp->entry_repost);
        len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
-                       "\t\tDQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
-                       "HOST-IDX[%04d], PORT-IDX[%04d]\n",
+                       "\t\tDQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+                       "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]\n",
                        datqp->queue_id, datqp->entry_count,
                        datqp->entry_size, datqp->host_index,
-                       datqp->hba_index);
+                       datqp->hba_index, datqp->entry_repost);
        return len;
 }
 
@@ -3242,10 +3253,10 @@ __lpfc_idiag_print_eq(struct lpfc_queue *qp, char *eqtype,
                        eqtype, qp->q_cnt_1, qp->q_cnt_2, qp->q_cnt_3,
                        (unsigned long long)qp->q_cnt_4);
        len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
-                       "EQID[%02d], QE-CNT[%04d], QE-SIZE[%04d], "
-                       "HOST-IDX[%04d], PORT-IDX[%04d]",
+                       "EQID[%02d], QE-CNT[%04d], QE-SZ[%04d], "
+                       "HST-IDX[%04d], PRT-IDX[%04d], PST[%03d]",
                        qp->queue_id, qp->entry_count, qp->entry_size,
-                       qp->host_index, qp->hba_index);
+                       qp->host_index, qp->hba_index, qp->entry_repost);
        len +=  snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len, "\n");
 
        return len;
@@ -5855,8 +5866,10 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
                        atomic_dec(&lpfc_debugfs_hba_count);
                }
 
-               debugfs_remove(lpfc_debugfs_root); /* lpfc */
-               lpfc_debugfs_root = NULL;
+               if (atomic_read(&lpfc_debugfs_hba_count) == 0) {
+                       debugfs_remove(lpfc_debugfs_root); /* lpfc */
+                       lpfc_debugfs_root = NULL;
+               }
        }
 #endif
        return;
index 9d5a379f4b15734a484c643fc9cc81b0ba8b33e9..094c97b9e5f741faba5e0ef904f97faa3cc7a734 100644 (file)
@@ -90,6 +90,7 @@ struct lpfc_nodelist {
 #define NLP_FCP_INITIATOR  0x10                        /* entry is an FCP Initiator */
 #define NLP_NVME_TARGET    0x20                        /* entry is a NVME Target */
 #define NLP_NVME_INITIATOR 0x40                        /* entry is a NVME Initiator */
+#define NLP_NVME_DISCOVERY 0x80                 /* entry has NVME disc srvc */
 
        uint16_t        nlp_fc4_type;           /* FC types node supports. */
                                                /* Assigned from GID_FF, only
index 67827e397431abe8b55955d9cc6497cbf680c054..8e532b39ae93af5c35a1199084f606b627e37ff0 100644 (file)
@@ -1047,6 +1047,13 @@ stop_rr_fcf_flogi:
                                 irsp->ulpStatus, irsp->un.ulpWord[4],
                                 irsp->ulpTimeout);
 
+
+               /* If this is not a loop open failure, bail out */
+               if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+                     ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
+                                       IOERR_LOOP_OPEN_FAILURE)))
+                       goto flogifail;
+
                /* FLOGI failed, so there is no fabric */
                spin_lock_irq(shost->host_lock);
                vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
@@ -2077,16 +2084,19 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
        if (irsp->ulpStatus) {
                /* Check for retry */
+               ndlp->fc4_prli_sent--;
                if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
                        /* ELS command is being retried */
-                       ndlp->fc4_prli_sent--;
                        goto out;
                }
+
                /* PRLI failed */
                lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-                                "2754 PRLI failure DID:%06X Status:x%x/x%x\n",
+                                "2754 PRLI failure DID:%06X Status:x%x/x%x, "
+                                "data: x%x\n",
                                 ndlp->nlp_DID, irsp->ulpStatus,
-                                irsp->un.ulpWord[4]);
+                                irsp->un.ulpWord[4], ndlp->fc4_prli_sent);
+
                /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
                if (lpfc_error_lost_link(irsp))
                        goto out;
@@ -7441,6 +7451,13 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
         */
        spin_lock_irq(&phba->hbalock);
        pring = lpfc_phba_elsring(phba);
+
+       /* Bail out if we've no ELS wq, like in PCI error recovery case. */
+       if (unlikely(!pring)) {
+               spin_unlock_irq(&phba->hbalock);
+               return;
+       }
+
        if (phba->sli_rev == LPFC_SLI_REV4)
                spin_lock(&pring->ring_lock);
 
@@ -8667,7 +8684,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                lpfc_do_scr_ns_plogi(phba, vport);
        goto out;
 fdisc_failed:
-       if (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS)
+       if (vport->fc_vport &&
+           (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS))
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
        /* Cancel discovery timer */
        lpfc_can_disctmo(vport);
index 0482c558033104d3a44f75290750e1acdc3ee0d9..3ffcd9215ca892eb7ef3e5972df50a427ef17369 100644 (file)
@@ -693,15 +693,16 @@ lpfc_work_done(struct lpfc_hba *phba)
        pring = lpfc_phba_elsring(phba);
        status = (ha_copy & (HA_RXMASK  << (4*LPFC_ELS_RING)));
        status >>= (4*LPFC_ELS_RING);
-       if ((status & HA_RXMASK) ||
-           (pring->flag & LPFC_DEFERRED_RING_EVENT) ||
-           (phba->hba_flag & HBA_SP_QUEUE_EVT)) {
+       if (pring && (status & HA_RXMASK ||
+                     pring->flag & LPFC_DEFERRED_RING_EVENT ||
+                     phba->hba_flag & HBA_SP_QUEUE_EVT)) {
                if (pring->flag & LPFC_STOP_IOCB_EVENT) {
                        pring->flag |= LPFC_DEFERRED_RING_EVENT;
                        /* Set the lpfc data pending flag */
                        set_bit(LPFC_DATA_READY, &phba->data_flags);
                } else {
-                       if (phba->link_state >= LPFC_LINK_UP) {
+                       if (phba->link_state >= LPFC_LINK_UP ||
+                           phba->link_flag & LS_MDS_LOOPBACK) {
                                pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
                                lpfc_sli_handle_slow_ring_event(phba, pring,
                                                                (status &
index 1d12f2be36bcccd336f8892aa0a20d3109d7150c..e0a5fce416aeea7604ab9a46464d8514e82fb0cb 100644 (file)
@@ -1356,6 +1356,7 @@ struct lpfc_mbx_wq_destroy {
 
 #define LPFC_HDR_BUF_SIZE 128
 #define LPFC_DATA_BUF_SIZE 2048
+#define LPFC_NVMET_DATA_BUF_SIZE 128
 struct rq_context {
        uint32_t word0;
 #define lpfc_rq_context_rqe_count_SHIFT        16      /* Version 0 Only */
@@ -4420,6 +4421,19 @@ struct fcp_treceive64_wqe {
 };
 #define TXRDY_PAYLOAD_LEN      12
 
+#define CMD_SEND_FRAME 0xE1
+
+struct send_frame_wqe {
+       struct ulp_bde64 bde;          /* words 0-2 */
+       uint32_t frame_len;            /* word 3 */
+       uint32_t fc_hdr_wd0;           /* word 4 */
+       uint32_t fc_hdr_wd1;           /* word 5 */
+       struct wqe_common wqe_com;     /* words 6-11 */
+       uint32_t fc_hdr_wd2;           /* word 12 */
+       uint32_t fc_hdr_wd3;           /* word 13 */
+       uint32_t fc_hdr_wd4;           /* word 14 */
+       uint32_t fc_hdr_wd5;           /* word 15 */
+};
 
 union lpfc_wqe {
        uint32_t words[16];
@@ -4438,7 +4452,7 @@ union lpfc_wqe {
        struct fcp_trsp64_wqe fcp_trsp;
        struct fcp_tsend64_wqe fcp_tsend;
        struct fcp_treceive64_wqe fcp_treceive;
-
+       struct send_frame_wqe send_frame;
 };
 
 union lpfc_wqe128 {
index 90ae354a9c458c9151b03f6bdff444a248d0da0e..9add9473cae52a1f2bf5d1b78a8854a57c9f6192 100644 (file)
@@ -1099,7 +1099,7 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
 
                list_for_each_entry_safe(ctxp, ctxp_next, &nvmet_aborts, list) {
                        ctxp->flag &= ~(LPFC_NVMET_XBUSY | LPFC_NVMET_ABORT_OP);
-                       lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
+                       lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
                }
        }
 
@@ -3381,7 +3381,7 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba)
 {
        struct lpfc_sglq *sglq_entry = NULL, *sglq_entry_next = NULL;
        uint16_t i, lxri, xri_cnt, els_xri_cnt;
-       uint16_t nvmet_xri_cnt, tot_cnt;
+       uint16_t nvmet_xri_cnt;
        LIST_HEAD(nvmet_sgl_list);
        int rc;
 
@@ -3389,15 +3389,9 @@ lpfc_sli4_nvmet_sgl_update(struct lpfc_hba *phba)
         * update on pci function's nvmet xri-sgl list
         */
        els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
-       nvmet_xri_cnt = phba->cfg_nvmet_mrq * phba->cfg_nvmet_mrq_post;
-       tot_cnt = phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt;
-       if (nvmet_xri_cnt > tot_cnt) {
-               phba->cfg_nvmet_mrq_post = tot_cnt / phba->cfg_nvmet_mrq;
-               nvmet_xri_cnt = phba->cfg_nvmet_mrq * phba->cfg_nvmet_mrq_post;
-               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                               "6301 NVMET post-sgl count changed to %d\n",
-                               phba->cfg_nvmet_mrq_post);
-       }
+
+       /* For NVMET, ALL remaining XRIs are dedicated for IO processing */
+       nvmet_xri_cnt = phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt;
 
        if (nvmet_xri_cnt > phba->sli4_hba.nvmet_xri_cnt) {
                /* els xri-sgl expanded */
@@ -3602,6 +3596,13 @@ lpfc_get_wwpn(struct lpfc_hba *phba)
        LPFC_MBOXQ_t *mboxq;
        MAILBOX_t *mb;
 
+       if (phba->sli_rev < LPFC_SLI_REV4) {
+               /* Reset the port first */
+               lpfc_sli_brdrestart(phba);
+               rc = lpfc_sli_chipset_init(phba);
+               if (rc)
+                       return (uint64_t)-1;
+       }
 
        mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
                                                GFP_KERNEL);
@@ -4539,6 +4540,19 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
        pmb->vport = phba->pport;
 
        if (phba->sli4_hba.link_state.status != LPFC_FC_LA_TYPE_LINK_UP) {
+               phba->link_flag &= ~(LS_MDS_LINK_DOWN | LS_MDS_LOOPBACK);
+
+               switch (phba->sli4_hba.link_state.status) {
+               case LPFC_FC_LA_TYPE_MDS_LINK_DOWN:
+                       phba->link_flag |= LS_MDS_LINK_DOWN;
+                       break;
+               case LPFC_FC_LA_TYPE_MDS_LOOPBACK:
+                       phba->link_flag |= LS_MDS_LOOPBACK;
+                       break;
+               default:
+                       break;
+               }
+
                /* Parse and translate status field */
                mb = &pmb->u.mb;
                mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
@@ -5823,6 +5837,9 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                spin_lock_init(&phba->sli4_hba.abts_nvme_buf_list_lock);
                INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_nvme_buf_list);
                INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_nvmet_ctx_list);
+               INIT_LIST_HEAD(&phba->sli4_hba.lpfc_nvmet_ctx_list);
+               INIT_LIST_HEAD(&phba->sli4_hba.lpfc_nvmet_io_wait_list);
+
                /* Fast-path XRI aborted CQ Event work queue list */
                INIT_LIST_HEAD(&phba->sli4_hba.sp_nvme_xri_aborted_work_queue);
        }
@@ -5830,6 +5847,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        /* This abort list used by worker thread */
        spin_lock_init(&phba->sli4_hba.sgl_list_lock);
        spin_lock_init(&phba->sli4_hba.nvmet_io_lock);
+       spin_lock_init(&phba->sli4_hba.nvmet_io_wait_lock);
 
        /*
         * Initialize driver internal slow-path work queues
@@ -5944,16 +5962,21 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                for (i = 0; i < lpfc_enable_nvmet_cnt; i++) {
                        if (wwn == lpfc_enable_nvmet[i]) {
 #if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
+                               if (lpfc_nvmet_mem_alloc(phba))
+                                       break;
+
+                               phba->nvmet_support = 1; /* a match */
+
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                                "6017 NVME Target %016llx\n",
                                                wwn);
-                               phba->nvmet_support = 1; /* a match */
 #else
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                                "6021 Can't enable NVME Target."
                                                " NVME_TARGET_FC infrastructure"
                                                " is not in kernel\n");
 #endif
+                               break;
                        }
                }
        }
@@ -6262,7 +6285,7 @@ lpfc_unset_driver_resource_phase2(struct lpfc_hba *phba)
  *
  * This routine is invoked to free the driver's IOCB list and memory.
  **/
-static void
+void
 lpfc_free_iocb_list(struct lpfc_hba *phba)
 {
        struct lpfc_iocbq *iocbq_entry = NULL, *iocbq_next = NULL;
@@ -6290,7 +6313,7 @@ lpfc_free_iocb_list(struct lpfc_hba *phba)
  *     0 - successful
  *     other values - error
  **/
-static int
+int
 lpfc_init_iocb_list(struct lpfc_hba *phba, int iocb_count)
 {
        struct lpfc_iocbq *iocbq_entry = NULL;
@@ -6518,7 +6541,6 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
        uint16_t rpi_limit, curr_rpi_range;
        struct lpfc_dmabuf *dmabuf;
        struct lpfc_rpi_hdr *rpi_hdr;
-       uint32_t rpi_count;
 
        /*
         * If the SLI4 port supports extents, posting the rpi header isn't
@@ -6531,8 +6553,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
                return NULL;
 
        /* The limit on the logical index is just the max_rpi count. */
-       rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base +
-       phba->sli4_hba.max_cfg_param.max_rpi - 1;
+       rpi_limit = phba->sli4_hba.max_cfg_param.max_rpi;
 
        spin_lock_irq(&phba->hbalock);
        /*
@@ -6543,18 +6564,10 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
        curr_rpi_range = phba->sli4_hba.next_rpi;
        spin_unlock_irq(&phba->hbalock);
 
-       /*
-        * The port has a limited number of rpis. The increment here
-        * is LPFC_RPI_HDR_COUNT - 1 to account for the starting value
-        * and to allow the full max_rpi range per port.
-        */
-       if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit)
-               rpi_count = rpi_limit - curr_rpi_range;
-       else
-               rpi_count = LPFC_RPI_HDR_COUNT;
-
-       if (!rpi_count)
+       /* Reached full RPI range */
+       if (curr_rpi_range == rpi_limit)
                return NULL;
+
        /*
         * First allocate the protocol header region for the port.  The
         * port expects a 4KB DMA-mapped memory region that is 4K aligned.
@@ -6588,13 +6601,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
 
        /* The rpi_hdr stores the logical index only. */
        rpi_hdr->start_rpi = curr_rpi_range;
+       rpi_hdr->next_rpi = phba->sli4_hba.next_rpi + LPFC_RPI_HDR_COUNT;
        list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list);
 
-       /*
-        * The next_rpi stores the next logical module-64 rpi value used
-        * to post physical rpis in subsequent rpi postings.
-        */
-       phba->sli4_hba.next_rpi += rpi_count;
        spin_unlock_irq(&phba->hbalock);
        return rpi_hdr;
 
@@ -8165,7 +8174,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                        /* Create NVMET Receive Queue for header */
                        qdesc = lpfc_sli4_queue_alloc(phba,
                                                      phba->sli4_hba.rq_esize,
-                                                     phba->sli4_hba.rq_ecount);
+                                                     LPFC_NVMET_RQE_DEF_COUNT);
                        if (!qdesc) {
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                                "3146 Failed allocate "
@@ -8187,7 +8196,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                        /* Create NVMET Receive Queue for data */
                        qdesc = lpfc_sli4_queue_alloc(phba,
                                                      phba->sli4_hba.rq_esize,
-                                                     phba->sli4_hba.rq_ecount);
+                                                     LPFC_NVMET_RQE_DEF_COUNT);
                        if (!qdesc) {
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                                "3156 Failed allocate "
@@ -8318,46 +8327,6 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
        INIT_LIST_HEAD(&phba->sli4_hba.lpfc_wq_list);
 }
 
-int
-lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
-                   struct lpfc_queue *drq, int count)
-{
-       int rc, i;
-       struct lpfc_rqe hrqe;
-       struct lpfc_rqe drqe;
-       struct lpfc_rqb *rqbp;
-       struct rqb_dmabuf *rqb_buffer;
-       LIST_HEAD(rqb_buf_list);
-
-       rqbp = hrq->rqbp;
-       for (i = 0; i < count; i++) {
-               rqb_buffer = (rqbp->rqb_alloc_buffer)(phba);
-               if (!rqb_buffer)
-                       break;
-               rqb_buffer->hrq = hrq;
-               rqb_buffer->drq = drq;
-               list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list);
-       }
-       while (!list_empty(&rqb_buf_list)) {
-               list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf,
-                                hbuf.list);
-
-               hrqe.address_lo = putPaddrLow(rqb_buffer->hbuf.phys);
-               hrqe.address_hi = putPaddrHigh(rqb_buffer->hbuf.phys);
-               drqe.address_lo = putPaddrLow(rqb_buffer->dbuf.phys);
-               drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys);
-               rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe);
-               if (rc < 0) {
-                       (rqbp->rqb_free_buffer)(phba, rqb_buffer);
-               } else {
-                       list_add_tail(&rqb_buffer->hbuf.list,
-                                     &rqbp->rqb_buffer_list);
-                       rqbp->buffer_count++;
-               }
-       }
-       return 1;
-}
-
 int
 lpfc_free_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *rq)
 {
@@ -8777,9 +8746,6 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                goto out_destroy;
        }
 
-       lpfc_rq_adjust_repost(phba, phba->sli4_hba.hdr_rq, LPFC_ELS_HBQ);
-       lpfc_rq_adjust_repost(phba, phba->sli4_hba.dat_rq, LPFC_ELS_HBQ);
-
        rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
                            phba->sli4_hba.els_cq, LPFC_USOL);
        if (rc) {
@@ -8847,7 +8813,7 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
                lpfc_wq_destroy(phba, phba->sli4_hba.nvmels_wq);
 
        /* Unset ELS work queue */
-       if (phba->sli4_hba.els_cq)
+       if (phba->sli4_hba.els_wq)
                lpfc_wq_destroy(phba, phba->sli4_hba.els_wq);
 
        /* Unset unsolicited receive queue */
@@ -11103,7 +11069,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
        struct Scsi_Host  *shost = NULL;
-       int error, cnt;
+       int error;
        uint32_t cfg_mode, intr_mode;
 
        /* Allocate memory for HBA structure */
@@ -11137,22 +11103,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_unset_pci_mem_s4;
        }
 
-       cnt = phba->cfg_iocb_cnt * 1024;
-       if (phba->nvmet_support)
-               cnt += phba->cfg_nvmet_mrq_post * phba->cfg_nvmet_mrq;
-
-       /* Initialize and populate the iocb list per host */
-       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                       "2821 initialize iocb list %d total %d\n",
-                       phba->cfg_iocb_cnt, cnt);
-       error = lpfc_init_iocb_list(phba, cnt);
-
-       if (error) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "1413 Failed to initialize iocb list.\n");
-               goto out_unset_driver_resource_s4;
-       }
-
        INIT_LIST_HEAD(&phba->active_rrq_list);
        INIT_LIST_HEAD(&phba->fcf.fcf_pri_list);
 
@@ -11161,7 +11111,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        if (error) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "1414 Failed to set up driver resource.\n");
-               goto out_free_iocb_list;
+               goto out_unset_driver_resource_s4;
        }
 
        /* Get the default values for Model Name and Description */
@@ -11261,8 +11211,6 @@ out_destroy_shost:
        lpfc_destroy_shost(phba);
 out_unset_driver_resource:
        lpfc_unset_driver_resource_phase2(phba);
-out_free_iocb_list:
-       lpfc_free_iocb_list(phba);
 out_unset_driver_resource_s4:
        lpfc_sli4_driver_resource_unset(phba);
 out_unset_pci_mem_s4:
index 5986c7957199df6ef97343a3c0402931cbdeb7ad..fcc05a1517c21d5134282e6cc9337ade5ee1a5c9 100644 (file)
@@ -214,6 +214,21 @@ fail_free_drb_pool:
        return -ENOMEM;
 }
 
+int
+lpfc_nvmet_mem_alloc(struct lpfc_hba *phba)
+{
+       phba->lpfc_nvmet_drb_pool =
+               pci_pool_create("lpfc_nvmet_drb_pool",
+                               phba->pcidev, LPFC_NVMET_DATA_BUF_SIZE,
+                               SGL_ALIGN_SZ, 0);
+       if (!phba->lpfc_nvmet_drb_pool) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "6024 Can't enable NVME Target - no memory\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
 /**
  * lpfc_mem_free - Frees memory allocated by lpfc_mem_alloc
  * @phba: HBA to free memory for
@@ -232,6 +247,9 @@ lpfc_mem_free(struct lpfc_hba *phba)
 
        /* Free HBQ pools */
        lpfc_sli_hbqbuf_free_all(phba);
+       if (phba->lpfc_nvmet_drb_pool)
+               pci_pool_destroy(phba->lpfc_nvmet_drb_pool);
+       phba->lpfc_nvmet_drb_pool = NULL;
        if (phba->lpfc_drb_pool)
                pci_pool_destroy(phba->lpfc_drb_pool);
        phba->lpfc_drb_pool = NULL;
@@ -611,8 +629,6 @@ struct rqb_dmabuf *
 lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
 {
        struct rqb_dmabuf *dma_buf;
-       struct lpfc_iocbq *nvmewqe;
-       union lpfc_wqe128 *wqe;
 
        dma_buf = kzalloc(sizeof(struct rqb_dmabuf), GFP_KERNEL);
        if (!dma_buf)
@@ -624,69 +640,15 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
                kfree(dma_buf);
                return NULL;
        }
-       dma_buf->dbuf.virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
-                                           &dma_buf->dbuf.phys);
+       dma_buf->dbuf.virt = pci_pool_alloc(phba->lpfc_nvmet_drb_pool,
+                                           GFP_KERNEL, &dma_buf->dbuf.phys);
        if (!dma_buf->dbuf.virt) {
                pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
                              dma_buf->hbuf.phys);
                kfree(dma_buf);
                return NULL;
        }
-       dma_buf->total_size = LPFC_DATA_BUF_SIZE;
-
-       dma_buf->context = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx),
-                                  GFP_KERNEL);
-       if (!dma_buf->context) {
-               pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
-                             dma_buf->dbuf.phys);
-               pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
-                             dma_buf->hbuf.phys);
-               kfree(dma_buf);
-               return NULL;
-       }
-
-       dma_buf->iocbq = lpfc_sli_get_iocbq(phba);
-       if (!dma_buf->iocbq) {
-               kfree(dma_buf->context);
-               pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
-                             dma_buf->dbuf.phys);
-               pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
-                             dma_buf->hbuf.phys);
-               kfree(dma_buf);
-               lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
-                               "2621 Ran out of nvmet iocb/WQEs\n");
-               return NULL;
-       }
-       dma_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
-       nvmewqe = dma_buf->iocbq;
-       wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
-       /* Initialize WQE */
-       memset(wqe, 0, sizeof(union lpfc_wqe));
-       /* Word 7 */
-       bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI);
-       bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
-       bf_set(wqe_pu, &wqe->generic.wqe_com, 1);
-       /* Word 10 */
-       bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
-       bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
-       bf_set(wqe_qosd, &wqe->generic.wqe_com, 0);
-
-       dma_buf->iocbq->context1 = NULL;
-       spin_lock(&phba->sli4_hba.sgl_list_lock);
-       dma_buf->sglq = __lpfc_sli_get_nvmet_sglq(phba, dma_buf->iocbq);
-       spin_unlock(&phba->sli4_hba.sgl_list_lock);
-       if (!dma_buf->sglq) {
-               lpfc_sli_release_iocbq(phba, dma_buf->iocbq);
-               kfree(dma_buf->context);
-               pci_pool_free(phba->lpfc_drb_pool, dma_buf->dbuf.virt,
-                             dma_buf->dbuf.phys);
-               pci_pool_free(phba->lpfc_hrb_pool, dma_buf->hbuf.virt,
-                             dma_buf->hbuf.phys);
-               kfree(dma_buf);
-               lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
-                               "6132 Ran out of nvmet XRIs\n");
-               return NULL;
-       }
+       dma_buf->total_size = LPFC_NVMET_DATA_BUF_SIZE;
        return dma_buf;
 }
 
@@ -705,20 +667,9 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba)
 void
 lpfc_sli4_nvmet_free(struct lpfc_hba *phba, struct rqb_dmabuf *dmab)
 {
-       unsigned long flags;
-
-       __lpfc_clear_active_sglq(phba, dmab->sglq->sli4_lxritag);
-       dmab->sglq->state = SGL_FREED;
-       dmab->sglq->ndlp = NULL;
-
-       spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, flags);
-       list_add_tail(&dmab->sglq->list, &phba->sli4_hba.lpfc_nvmet_sgl_list);
-       spin_unlock_irqrestore(&phba->sli4_hba.sgl_list_lock, flags);
-
-       lpfc_sli_release_iocbq(phba, dmab->iocbq);
-       kfree(dmab->context);
        pci_pool_free(phba->lpfc_hrb_pool, dmab->hbuf.virt, dmab->hbuf.phys);
-       pci_pool_free(phba->lpfc_drb_pool, dmab->dbuf.virt, dmab->dbuf.phys);
+       pci_pool_free(phba->lpfc_nvmet_drb_pool,
+                     dmab->dbuf.virt, dmab->dbuf.phys);
        kfree(dmab);
 }
 
@@ -803,6 +754,11 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp)
        rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe);
        if (rc < 0) {
                (rqbp->rqb_free_buffer)(phba, rqb_entry);
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "6409 Cannot post to RQ %d: %x %x\n",
+                               rqb_entry->hrq->queue_id,
+                               rqb_entry->hrq->host_index,
+                               rqb_entry->hrq->hba_index);
        } else {
                list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list);
                rqbp->buffer_count++;
index 8777c2d5f50d35ecae18223da67245157811b4be..f74cb0142fd4edac4e1378db1e85d14ec21c71a8 100644 (file)
@@ -206,7 +206,7 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
  * associated with a LPFC_NODELIST entry. This
  * routine effectively results in a "software abort".
  */
-int
+void
 lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
        LIST_HEAD(abort_list);
@@ -215,6 +215,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 
        pring = lpfc_phba_elsring(phba);
 
+       /* In case of error recovery path, we might have a NULL pring here */
+       if (!pring)
+               return;
+
        /* Abort outstanding I/O on NPort <nlp_DID> */
        lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
                         "2819 Abort outstanding I/O on NPort x%x "
@@ -273,7 +277,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
                              IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);
 
        lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
-       return 0;
 }
 
 static int
@@ -1944,7 +1947,13 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
                /* Target driver cannot solicit NVME FB. */
                if (bf_get_be32(prli_tgt, nvpr)) {
+                       /* Complete the nvme target roles.  The transport
+                        * needs to know if the rport is capable of
+                        * discovery in addition to its role.
+                        */
                        ndlp->nlp_type |= NLP_NVME_TARGET;
+                       if (bf_get_be32(prli_disc, nvpr))
+                               ndlp->nlp_type |= NLP_NVME_DISCOVERY;
                        if ((bf_get_be32(prli_fba, nvpr) == 1) &&
                            (bf_get_be32(prli_fb_sz, nvpr) > 0) &&
                            (phba->cfg_nvme_enable_fb) &&
index 94434e621c335e678ad2aa1c3301b967cb15a210..518b15e6f22236c7289a174388ad6ae5916db725 100644 (file)
@@ -142,7 +142,7 @@ out:
 }
 
 /**
- * lpfc_nvmet_rq_post - Repost a NVMET RQ DMA buffer and clean up context
+ * lpfc_nvmet_ctxbuf_post - Repost a NVMET RQ DMA buffer and clean up context
  * @phba: HBA buffer is associated with
  * @ctxp: context to clean up
  * @mp: Buffer to free
@@ -155,24 +155,113 @@ out:
  * Returns: None
  **/
 void
-lpfc_nvmet_rq_post(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp,
-                  struct lpfc_dmabuf *mp)
+lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
 {
-       if (ctxp) {
-               if (ctxp->flag)
-                       lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
-                               "6314 rq_post ctx xri x%x flag x%x\n",
-                               ctxp->oxid, ctxp->flag);
-
-               if (ctxp->txrdy) {
-                       pci_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
-                                     ctxp->txrdy_phys);
-                       ctxp->txrdy = NULL;
-                       ctxp->txrdy_phys = 0;
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
+       struct lpfc_nvmet_rcv_ctx *ctxp = ctx_buf->context;
+       struct lpfc_nvmet_tgtport *tgtp;
+       struct fc_frame_header *fc_hdr;
+       struct rqb_dmabuf *nvmebuf;
+       struct lpfc_dmabuf *hbufp;
+       uint32_t *payload;
+       uint32_t size, oxid, sid, rc;
+       unsigned long iflag;
+
+       if (ctxp->txrdy) {
+               pci_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
+                             ctxp->txrdy_phys);
+               ctxp->txrdy = NULL;
+               ctxp->txrdy_phys = 0;
+       }
+       ctxp->state = LPFC_NVMET_STE_FREE;
+
+       spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
+       if (phba->sli4_hba.nvmet_io_wait_cnt) {
+               hbufp = &nvmebuf->hbuf;
+               list_remove_head(&phba->sli4_hba.lpfc_nvmet_io_wait_list,
+                                nvmebuf, struct rqb_dmabuf,
+                                hbuf.list);
+               phba->sli4_hba.nvmet_io_wait_cnt--;
+               spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
+                                      iflag);
+
+               fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
+               oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+               tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+               payload = (uint32_t *)(nvmebuf->dbuf.virt);
+               size = nvmebuf->bytes_recv;
+               sid = sli4_sid_from_fc_hdr(fc_hdr);
+
+               ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
+               memset(ctxp, 0, sizeof(ctxp->ctx));
+               ctxp->wqeq = NULL;
+               ctxp->txrdy = NULL;
+               ctxp->offset = 0;
+               ctxp->phba = phba;
+               ctxp->size = size;
+               ctxp->oxid = oxid;
+               ctxp->sid = sid;
+               ctxp->state = LPFC_NVMET_STE_RCV;
+               ctxp->entry_cnt = 1;
+               ctxp->flag = 0;
+               ctxp->ctxbuf = ctx_buf;
+               spin_lock_init(&ctxp->ctxlock);
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+               if (phba->ktime_on) {
+                       ctxp->ts_cmd_nvme = ktime_get_ns();
+                       ctxp->ts_isr_cmd = ctxp->ts_cmd_nvme;
+                       ctxp->ts_nvme_data = 0;
+                       ctxp->ts_data_wqput = 0;
+                       ctxp->ts_isr_data = 0;
+                       ctxp->ts_data_nvme = 0;
+                       ctxp->ts_nvme_status = 0;
+                       ctxp->ts_status_wqput = 0;
+                       ctxp->ts_isr_status = 0;
+                       ctxp->ts_status_nvme = 0;
                }
-               ctxp->state = LPFC_NVMET_STE_FREE;
+#endif
+               atomic_inc(&tgtp->rcv_fcp_cmd_in);
+               /*
+                * The calling sequence should be:
+                * nvmet_fc_rcv_fcp_req->lpfc_nvmet_xmt_fcp_op/cmp- req->done
+                * lpfc_nvmet_xmt_fcp_op_cmp should free the allocated ctxp.
+                * When we return from nvmet_fc_rcv_fcp_req, all relevant info
+                * the NVME command / FC header is stored.
+                * A buffer has already been reposted for this IO, so just free
+                * the nvmebuf.
+                */
+               rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
+                                         payload, size);
+
+               /* Process FCP command */
+               if (rc == 0) {
+                       atomic_inc(&tgtp->rcv_fcp_cmd_out);
+                       nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
+                       return;
+               }
+
+               atomic_inc(&tgtp->rcv_fcp_cmd_drop);
+               lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+                               "2582 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
+                               ctxp->oxid, rc,
+                               atomic_read(&tgtp->rcv_fcp_cmd_in),
+                               atomic_read(&tgtp->rcv_fcp_cmd_out),
+                               atomic_read(&tgtp->xmt_fcp_release));
+
+               lpfc_nvmet_defer_release(phba, ctxp);
+               lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, sid, oxid);
+               nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
+               return;
        }
-       lpfc_rq_buf_free(phba, mp);
+       spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
+
+       spin_lock_irqsave(&phba->sli4_hba.nvmet_io_lock, iflag);
+       list_add_tail(&ctx_buf->list,
+                     &phba->sli4_hba.lpfc_nvmet_ctx_list);
+       phba->sli4_hba.nvmet_ctx_cnt++;
+       spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_lock, iflag);
+#endif
 }
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -502,6 +591,7 @@ lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
                                "6150 LS Drop IO x%x: Prep\n",
                                ctxp->oxid);
                lpfc_in_buf_free(phba, &nvmebuf->dbuf);
+               atomic_inc(&nvmep->xmt_ls_abort);
                lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp,
                                                ctxp->sid, ctxp->oxid);
                return -ENOMEM;
@@ -545,6 +635,7 @@ lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
        lpfc_nlp_put(nvmewqeq->context1);
 
        lpfc_in_buf_free(phba, &nvmebuf->dbuf);
+       atomic_inc(&nvmep->xmt_ls_abort);
        lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, ctxp->sid, ctxp->oxid);
        return -ENXIO;
 }
@@ -612,9 +703,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
        lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n",
                         ctxp->oxid, rsp->op, rsp->rsplen);
 
+       ctxp->flag |= LPFC_NVMET_IO_INP;
        rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, nvmewqeq);
        if (rc == WQE_SUCCESS) {
-               ctxp->flag |= LPFC_NVMET_IO_INP;
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
                if (!phba->ktime_on)
                        return 0;
@@ -692,6 +783,7 @@ static void
 lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
                           struct nvmefc_tgt_fcp_req *rsp)
 {
+       struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
        struct lpfc_nvmet_rcv_ctx *ctxp =
                container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
        struct lpfc_hba *phba = ctxp->phba;
@@ -707,13 +799,15 @@ lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
        }
        spin_unlock_irqrestore(&ctxp->ctxlock, flags);
 
-       lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d\n", ctxp->oxid,
-                        ctxp->state, 0);
+       lpfc_nvmeio_data(phba, "NVMET FCP FREE: xri x%x ste %d abt %d\n", ctxp->oxid,
+                        ctxp->state, aborting);
+
+       atomic_inc(&lpfc_nvmep->xmt_fcp_release);
 
        if (aborting)
                return;
 
-       lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
+       lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
 }
 
 static struct nvmet_fc_target_template lpfc_tgttemplate = {
@@ -734,17 +828,128 @@ static struct nvmet_fc_target_template lpfc_tgttemplate = {
        .target_priv_sz = sizeof(struct lpfc_nvmet_tgtport),
 };
 
+void
+lpfc_nvmet_cleanup_io_context(struct lpfc_hba *phba)
+{
+       struct lpfc_nvmet_ctxbuf *ctx_buf, *next_ctx_buf;
+       unsigned long flags;
+
+       list_for_each_entry_safe(
+               ctx_buf, next_ctx_buf,
+               &phba->sli4_hba.lpfc_nvmet_ctx_list, list) {
+               spin_lock_irqsave(
+                       &phba->sli4_hba.abts_nvme_buf_list_lock, flags);
+               list_del_init(&ctx_buf->list);
+               spin_unlock_irqrestore(
+                       &phba->sli4_hba.abts_nvme_buf_list_lock, flags);
+               __lpfc_clear_active_sglq(phba,
+                                        ctx_buf->sglq->sli4_lxritag);
+               ctx_buf->sglq->state = SGL_FREED;
+               ctx_buf->sglq->ndlp = NULL;
+
+               spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, flags);
+               list_add_tail(&ctx_buf->sglq->list,
+                             &phba->sli4_hba.lpfc_nvmet_sgl_list);
+               spin_unlock_irqrestore(&phba->sli4_hba.sgl_list_lock,
+                                      flags);
+
+               lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
+               kfree(ctx_buf->context);
+       }
+}
+
+int
+lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
+{
+       struct lpfc_nvmet_ctxbuf *ctx_buf;
+       struct lpfc_iocbq *nvmewqe;
+       union lpfc_wqe128 *wqe;
+       int i;
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_NVME,
+                       "6403 Allocate NVMET resources for %d XRIs\n",
+                       phba->sli4_hba.nvmet_xri_cnt);
+
+       /* For all nvmet xris, allocate resources needed to process a
+        * received command on a per xri basis.
+        */
+       for (i = 0; i < phba->sli4_hba.nvmet_xri_cnt; i++) {
+               ctx_buf = kzalloc(sizeof(*ctx_buf), GFP_KERNEL);
+               if (!ctx_buf) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+                                       "6404 Ran out of memory for NVMET\n");
+                       return -ENOMEM;
+               }
+
+               ctx_buf->context = kzalloc(sizeof(*ctx_buf->context),
+                                          GFP_KERNEL);
+               if (!ctx_buf->context) {
+                       kfree(ctx_buf);
+                       lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+                                       "6405 Ran out of NVMET "
+                                       "context memory\n");
+                       return -ENOMEM;
+               }
+               ctx_buf->context->ctxbuf = ctx_buf;
+
+               ctx_buf->iocbq = lpfc_sli_get_iocbq(phba);
+               if (!ctx_buf->iocbq) {
+                       kfree(ctx_buf->context);
+                       kfree(ctx_buf);
+                       lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+                                       "6406 Ran out of NVMET iocb/WQEs\n");
+                       return -ENOMEM;
+               }
+               ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
+               nvmewqe = ctx_buf->iocbq;
+               wqe = (union lpfc_wqe128 *)&nvmewqe->wqe;
+               /* Initialize WQE */
+               memset(wqe, 0, sizeof(union lpfc_wqe));
+               /* Word 7 */
+               bf_set(wqe_ct, &wqe->generic.wqe_com, SLI4_CT_RPI);
+               bf_set(wqe_class, &wqe->generic.wqe_com, CLASS3);
+               bf_set(wqe_pu, &wqe->generic.wqe_com, 1);
+               /* Word 10 */
+               bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1);
+               bf_set(wqe_ebde_cnt, &wqe->generic.wqe_com, 0);
+               bf_set(wqe_qosd, &wqe->generic.wqe_com, 0);
+
+               ctx_buf->iocbq->context1 = NULL;
+               spin_lock(&phba->sli4_hba.sgl_list_lock);
+               ctx_buf->sglq = __lpfc_sli_get_nvmet_sglq(phba, ctx_buf->iocbq);
+               spin_unlock(&phba->sli4_hba.sgl_list_lock);
+               if (!ctx_buf->sglq) {
+                       lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
+                       kfree(ctx_buf->context);
+                       kfree(ctx_buf);
+                       lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+                                       "6407 Ran out of NVMET XRIs\n");
+                       return -ENOMEM;
+               }
+               spin_lock(&phba->sli4_hba.nvmet_io_lock);
+               list_add_tail(&ctx_buf->list,
+                             &phba->sli4_hba.lpfc_nvmet_ctx_list);
+               spin_unlock(&phba->sli4_hba.nvmet_io_lock);
+       }
+       phba->sli4_hba.nvmet_ctx_cnt = phba->sli4_hba.nvmet_xri_cnt;
+       return 0;
+}
+
 int
 lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
 {
        struct lpfc_vport  *vport = phba->pport;
        struct lpfc_nvmet_tgtport *tgtp;
        struct nvmet_fc_port_info pinfo;
-       int error = 0;
+       int error;
 
        if (phba->targetport)
                return 0;
 
+       error = lpfc_nvmet_setup_io_context(phba);
+       if (error)
+               return error;
+
        memset(&pinfo, 0, sizeof(struct nvmet_fc_port_info));
        pinfo.node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
        pinfo.port_name = wwn_to_u64(vport->fc_portname.u.wwn);
@@ -764,7 +969,6 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
        lpfc_tgttemplate.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
        lpfc_tgttemplate.max_hw_queues = phba->cfg_nvme_io_channel;
        lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP |
-                                          NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED |
                                           NVMET_FCTGTFEAT_CMD_IN_ISR |
                                           NVMET_FCTGTFEAT_OPDONE_IN_ISR;
 
@@ -773,13 +977,16 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
                                             &phba->pcidev->dev,
                                             &phba->targetport);
 #else
-       error = -ENOMEM;
+       error = -ENOENT;
 #endif
        if (error) {
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
                                "6025 Cannot register NVME targetport "
                                "x%x\n", error);
                phba->targetport = NULL;
+
+               lpfc_nvmet_cleanup_io_context(phba);
+
        } else {
                tgtp = (struct lpfc_nvmet_tgtport *)
                        phba->targetport->private;
@@ -796,6 +1003,7 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
                atomic_set(&tgtp->rcv_ls_req_out, 0);
                atomic_set(&tgtp->rcv_ls_req_drop, 0);
                atomic_set(&tgtp->xmt_ls_abort, 0);
+               atomic_set(&tgtp->xmt_ls_abort_cmpl, 0);
                atomic_set(&tgtp->xmt_ls_rsp, 0);
                atomic_set(&tgtp->xmt_ls_drop, 0);
                atomic_set(&tgtp->xmt_ls_rsp_error, 0);
@@ -803,18 +1011,21 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
                atomic_set(&tgtp->rcv_fcp_cmd_in, 0);
                atomic_set(&tgtp->rcv_fcp_cmd_out, 0);
                atomic_set(&tgtp->rcv_fcp_cmd_drop, 0);
-               atomic_set(&tgtp->xmt_fcp_abort, 0);
                atomic_set(&tgtp->xmt_fcp_drop, 0);
                atomic_set(&tgtp->xmt_fcp_read_rsp, 0);
                atomic_set(&tgtp->xmt_fcp_read, 0);
                atomic_set(&tgtp->xmt_fcp_write, 0);
                atomic_set(&tgtp->xmt_fcp_rsp, 0);
+               atomic_set(&tgtp->xmt_fcp_release, 0);
                atomic_set(&tgtp->xmt_fcp_rsp_cmpl, 0);
                atomic_set(&tgtp->xmt_fcp_rsp_error, 0);
                atomic_set(&tgtp->xmt_fcp_rsp_drop, 0);
+               atomic_set(&tgtp->xmt_fcp_abort, 0);
+               atomic_set(&tgtp->xmt_fcp_abort_cmpl, 0);
+               atomic_set(&tgtp->xmt_abort_unsol, 0);
+               atomic_set(&tgtp->xmt_abort_sol, 0);
                atomic_set(&tgtp->xmt_abort_rsp, 0);
                atomic_set(&tgtp->xmt_abort_rsp_error, 0);
-               atomic_set(&tgtp->xmt_abort_cmpl, 0);
        }
        return error;
 }
@@ -865,7 +1076,7 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
        list_for_each_entry_safe(ctxp, next_ctxp,
                                 &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
                                 list) {
-               if (ctxp->rqb_buffer->sglq->sli4_xritag != xri)
+               if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
                        continue;
 
                /* Check if we already received a free context call
@@ -886,7 +1097,7 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
                    (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE ||
                     ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
                        lpfc_set_rrq_active(phba, ndlp,
-                               ctxp->rqb_buffer->sglq->sli4_lxritag,
+                               ctxp->ctxbuf->sglq->sli4_lxritag,
                                rxid, 1);
                        lpfc_sli4_abts_err_handler(phba, ndlp, axri);
                }
@@ -895,8 +1106,8 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
                                "6318 XB aborted %x flg x%x (%x)\n",
                                ctxp->oxid, ctxp->flag, released);
                if (released)
-                       lpfc_nvmet_rq_post(phba, ctxp,
-                                          &ctxp->rqb_buffer->hbuf);
+                       lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
+
                if (rrq_empty)
                        lpfc_worker_wake_up(phba);
                return;
@@ -924,7 +1135,7 @@ lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
        list_for_each_entry_safe(ctxp, next_ctxp,
                                 &phba->sli4_hba.lpfc_abts_nvmet_ctx_list,
                                 list) {
-               if (ctxp->rqb_buffer->sglq->sli4_xritag != xri)
+               if (ctxp->ctxbuf->sglq->sli4_xritag != xri)
                        continue;
 
                spin_unlock(&phba->sli4_hba.abts_nvme_buf_list_lock);
@@ -976,6 +1187,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
                init_completion(&tgtp->tport_unreg_done);
                nvmet_fc_unregister_targetport(phba->targetport);
                wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
+               lpfc_nvmet_cleanup_io_context(phba);
        }
        phba->targetport = NULL;
 #endif
@@ -1011,6 +1223,7 @@ lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                oxid = 0;
                size = 0;
                sid = 0;
+               ctxp = NULL;
                goto dropit;
        }
 
@@ -1105,39 +1318,71 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
        struct lpfc_nvmet_rcv_ctx *ctxp;
        struct lpfc_nvmet_tgtport *tgtp;
        struct fc_frame_header *fc_hdr;
+       struct lpfc_nvmet_ctxbuf *ctx_buf;
        uint32_t *payload;
-       uint32_t size, oxid, sid, rc;
+       uint32_t size, oxid, sid, rc, qno;
+       unsigned long iflag;
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        uint32_t id;
 #endif
 
+       ctx_buf = NULL;
        if (!nvmebuf || !phba->targetport) {
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
-                               "6157 FCP Drop IO\n");
+                               "6157 NVMET FCP Drop IO\n");
                oxid = 0;
                size = 0;
                sid = 0;
+               ctxp = NULL;
                goto dropit;
        }
 
+       spin_lock_irqsave(&phba->sli4_hba.nvmet_io_lock, iflag);
+       if (phba->sli4_hba.nvmet_ctx_cnt) {
+               list_remove_head(&phba->sli4_hba.lpfc_nvmet_ctx_list,
+                                ctx_buf, struct lpfc_nvmet_ctxbuf, list);
+               phba->sli4_hba.nvmet_ctx_cnt--;
+       }
+       spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_lock, iflag);
 
-       tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-       payload = (uint32_t *)(nvmebuf->dbuf.virt);
        fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
-       size = nvmebuf->bytes_recv;
        oxid = be16_to_cpu(fc_hdr->fh_ox_id);
-       sid = sli4_sid_from_fc_hdr(fc_hdr);
+       size = nvmebuf->bytes_recv;
 
-       ctxp = (struct lpfc_nvmet_rcv_ctx *)nvmebuf->context;
-       if (ctxp == NULL) {
-               atomic_inc(&tgtp->rcv_fcp_cmd_drop);
-               lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
-                               "6158 FCP Drop IO x%x: Alloc\n",
-                               oxid);
-               lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
-               /* Cannot send ABTS without context */
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+       if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) {
+               id = smp_processor_id();
+               if (id < LPFC_CHECK_CPU_CNT)
+                       phba->cpucheck_rcv_io[id]++;
+       }
+#endif
+
+       lpfc_nvmeio_data(phba, "NVMET FCP  RCV: xri x%x sz %d CPU %02x\n",
+                        oxid, size, smp_processor_id());
+
+       if (!ctx_buf) {
+               /* Queue this NVME IO to process later */
+               spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
+               list_add_tail(&nvmebuf->hbuf.list,
+                             &phba->sli4_hba.lpfc_nvmet_io_wait_list);
+               phba->sli4_hba.nvmet_io_wait_cnt++;
+               phba->sli4_hba.nvmet_io_wait_total++;
+               spin_unlock_irqrestore(&phba->sli4_hba.nvmet_io_wait_lock,
+                                      iflag);
+
+               /* Post a brand new DMA buffer to RQ */
+               qno = nvmebuf->idx;
+               lpfc_post_rq_buffer(
+                       phba, phba->sli4_hba.nvmet_mrq_hdr[qno],
+                       phba->sli4_hba.nvmet_mrq_data[qno], 1, qno);
                return;
        }
+
+       tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+       payload = (uint32_t *)(nvmebuf->dbuf.virt);
+       sid = sli4_sid_from_fc_hdr(fc_hdr);
+
+       ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
        memset(ctxp, 0, sizeof(ctxp->ctx));
        ctxp->wqeq = NULL;
        ctxp->txrdy = NULL;
@@ -1147,9 +1392,9 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
        ctxp->oxid = oxid;
        ctxp->sid = sid;
        ctxp->state = LPFC_NVMET_STE_RCV;
-       ctxp->rqb_buffer = nvmebuf;
        ctxp->entry_cnt = 1;
        ctxp->flag = 0;
+       ctxp->ctxbuf = ctx_buf;
        spin_lock_init(&ctxp->ctxlock);
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -1165,22 +1410,16 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
                ctxp->ts_isr_status = 0;
                ctxp->ts_status_nvme = 0;
        }
-
-       if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) {
-               id = smp_processor_id();
-               if (id < LPFC_CHECK_CPU_CNT)
-                       phba->cpucheck_rcv_io[id]++;
-       }
 #endif
 
-       lpfc_nvmeio_data(phba, "NVMET FCP  RCV: xri x%x sz %d CPU %02x\n",
-                        oxid, size, smp_processor_id());
-
        atomic_inc(&tgtp->rcv_fcp_cmd_in);
        /*
         * The calling sequence should be:
         * nvmet_fc_rcv_fcp_req -> lpfc_nvmet_xmt_fcp_op/cmp -> req->done
         * lpfc_nvmet_xmt_fcp_op_cmp should free the allocated ctxp.
+        * When we return from nvmet_fc_rcv_fcp_req, all relevant info in
+        * the NVME command / FC header is stored, so we are free to repost
+        * the buffer.
         */
        rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
                                  payload, size);
@@ -1188,26 +1427,32 @@ lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
        /* Process FCP command */
        if (rc == 0) {
                atomic_inc(&tgtp->rcv_fcp_cmd_out);
+               lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
                return;
        }
 
        atomic_inc(&tgtp->rcv_fcp_cmd_drop);
        lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
-                       "6159 FCP Drop IO x%x: err x%x\n",
-                       ctxp->oxid, rc);
+                       "6159 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
+                       ctxp->oxid, rc,
+                       atomic_read(&tgtp->rcv_fcp_cmd_in),
+                       atomic_read(&tgtp->rcv_fcp_cmd_out),
+                       atomic_read(&tgtp->xmt_fcp_release));
 dropit:
        lpfc_nvmeio_data(phba, "NVMET FCP DROP: xri x%x sz %d from %06x\n",
                         oxid, size, sid);
        if (oxid) {
+               lpfc_nvmet_defer_release(phba, ctxp);
                lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, sid, oxid);
+               lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
                return;
        }
 
-       if (nvmebuf) {
-               nvmebuf->iocbq->hba_wqidx = 0;
-               /* We assume a rcv'ed cmd ALWAYs fits into 1 buffer */
-               lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
-       }
+       if (ctx_buf)
+               lpfc_nvmet_ctxbuf_post(phba, ctx_buf);
+
+       if (nvmebuf)
+               lpfc_rq_buf_free(phba, &nvmebuf->hbuf); /* repost */
 #endif
 }
 
@@ -1259,7 +1504,7 @@ lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba,
                           uint64_t isr_timestamp)
 {
        if (phba->nvmet_support == 0) {
-               lpfc_nvmet_rq_post(phba, NULL, &nvmebuf->hbuf);
+               lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
                return;
        }
        lpfc_nvmet_unsol_fcp_buffer(phba, pring, nvmebuf,
@@ -1460,7 +1705,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
        nvmewqe = ctxp->wqeq;
        if (nvmewqe == NULL) {
                /* Allocate buffer for  command wqe */
-               nvmewqe = ctxp->rqb_buffer->iocbq;
+               nvmewqe = ctxp->ctxbuf->iocbq;
                if (nvmewqe == NULL) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
                                        "6110 lpfc_nvmet_prep_fcp_wqe: No "
@@ -1487,7 +1732,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
                return NULL;
        }
 
-       sgl  = (struct sli4_sge *)ctxp->rqb_buffer->sglq->sgl;
+       sgl  = (struct sli4_sge *)ctxp->ctxbuf->sglq->sgl;
        switch (rsp->op) {
        case NVMET_FCOP_READDATA:
        case NVMET_FCOP_READDATA_RSP:
@@ -1812,7 +2057,8 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
        result = wcqe->parameter;
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-       atomic_inc(&tgtp->xmt_abort_cmpl);
+       if (ctxp->flag & LPFC_NVMET_ABORT_OP)
+               atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
 
        ctxp->state = LPFC_NVMET_STE_DONE;
 
@@ -1827,6 +2073,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
        }
        ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
        spin_unlock_irqrestore(&ctxp->ctxlock, flags);
+       atomic_inc(&tgtp->xmt_abort_rsp);
 
        lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
                        "6165 ABORT cmpl: xri x%x flg x%x (%d) "
@@ -1835,15 +2082,16 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
                        wcqe->word0, wcqe->total_data_placed,
                        result, wcqe->word3);
 
+       cmdwqe->context2 = NULL;
+       cmdwqe->context3 = NULL;
        /*
         * if transport has released ctx, then can reuse it. Otherwise,
         * will be recycled by transport release call.
         */
        if (released)
-               lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
+               lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
 
-       cmdwqe->context2 = NULL;
-       cmdwqe->context3 = NULL;
+       /* This is the iocbq for the abort, not the command */
        lpfc_sli_release_iocbq(phba, cmdwqe);
 
        /* Since iaab/iaar are NOT set, there is no work left.
@@ -1877,7 +2125,8 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
        result = wcqe->parameter;
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-       atomic_inc(&tgtp->xmt_abort_cmpl);
+       if (ctxp->flag & LPFC_NVMET_ABORT_OP)
+               atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
 
        if (!ctxp) {
                /* if context is clear, related io alrady complete */
@@ -1907,6 +2156,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
        }
        ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
        spin_unlock_irqrestore(&ctxp->ctxlock, flags);
+       atomic_inc(&tgtp->xmt_abort_rsp);
 
        lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
                        "6316 ABTS cmpl xri x%x flg x%x (%x) "
@@ -1914,15 +2164,15 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
                        ctxp->oxid, ctxp->flag, released,
                        wcqe->word0, wcqe->total_data_placed,
                        result, wcqe->word3);
+
+       cmdwqe->context2 = NULL;
+       cmdwqe->context3 = NULL;
        /*
         * if transport has released ctx, then can reuse it. Otherwise,
         * will be recycled by transport release call.
         */
        if (released)
-               lpfc_nvmet_rq_post(phba, ctxp, &ctxp->rqb_buffer->hbuf);
-
-       cmdwqe->context2 = NULL;
-       cmdwqe->context3 = NULL;
+               lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
 
        /* Since iaab/iaar are NOT set, there is no work left.
         * For LPFC_NVMET_XBUSY, lpfc_sli4_nvmet_xri_aborted
@@ -1953,7 +2203,7 @@ lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
        result = wcqe->parameter;
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-       atomic_inc(&tgtp->xmt_abort_cmpl);
+       atomic_inc(&tgtp->xmt_ls_abort_cmpl);
 
        lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
                        "6083 Abort cmpl: ctx %p WCQE: %08x %08x %08x %08x\n",
@@ -1984,10 +2234,6 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
                        sid, xri, ctxp->wqeq->sli4_xritag);
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-       if (!ctxp->wqeq) {
-               ctxp->wqeq = ctxp->rqb_buffer->iocbq;
-               ctxp->wqeq->hba_wqidx = 0;
-       }
 
        ndlp = lpfc_findnode_did(phba->pport, sid);
        if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
@@ -2083,7 +2329,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
        if (!ctxp->wqeq) {
-               ctxp->wqeq = ctxp->rqb_buffer->iocbq;
+               ctxp->wqeq = ctxp->ctxbuf->iocbq;
                ctxp->wqeq->hba_wqidx = 0;
        }
 
@@ -2104,6 +2350,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
        /* Issue ABTS for this WQE based on iotag */
        ctxp->abort_wqeq = lpfc_sli_get_iocbq(phba);
        if (!ctxp->abort_wqeq) {
+               atomic_inc(&tgtp->xmt_abort_rsp_error);
                lpfc_printf_log(phba, KERN_WARNING, LOG_NVME_ABTS,
                                "6161 ABORT failed: No wqeqs: "
                                "xri: x%x\n", ctxp->oxid);
@@ -2128,6 +2375,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
        /* driver queued commands are in process of being flushed */
        if (phba->hba_flag & HBA_NVME_IOQ_FLUSH) {
                spin_unlock_irqrestore(&phba->hbalock, flags);
+               atomic_inc(&tgtp->xmt_abort_rsp_error);
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
                                "6163 Driver in reset cleanup - flushing "
                                "NVME Req now. hba_flag x%x oxid x%x\n",
@@ -2140,6 +2388,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
        /* Outstanding abort is in progress */
        if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) {
                spin_unlock_irqrestore(&phba->hbalock, flags);
+               atomic_inc(&tgtp->xmt_abort_rsp_error);
                lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
                                "6164 Outstanding NVME I/O Abort Request "
                                "still pending on oxid x%x\n",
@@ -2190,9 +2439,12 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
        abts_wqeq->context2 = ctxp;
        rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, abts_wqeq);
        spin_unlock_irqrestore(&phba->hbalock, flags);
-       if (rc == WQE_SUCCESS)
+       if (rc == WQE_SUCCESS) {
+               atomic_inc(&tgtp->xmt_abort_sol);
                return 0;
+       }
 
+       atomic_inc(&tgtp->xmt_abort_rsp_error);
        ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
        lpfc_sli_release_iocbq(phba, abts_wqeq);
        lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
@@ -2215,7 +2467,7 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
 
        tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
        if (!ctxp->wqeq) {
-               ctxp->wqeq = ctxp->rqb_buffer->iocbq;
+               ctxp->wqeq = ctxp->ctxbuf->iocbq;
                ctxp->wqeq->hba_wqidx = 0;
        }
 
@@ -2231,11 +2483,11 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
        rc = lpfc_sli4_issue_wqe(phba, LPFC_FCP_RING, abts_wqeq);
        spin_unlock_irqrestore(&phba->hbalock, flags);
        if (rc == WQE_SUCCESS) {
-               atomic_inc(&tgtp->xmt_abort_rsp);
                return 0;
        }
 
 aerr:
+       atomic_inc(&tgtp->xmt_abort_rsp_error);
        ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
        atomic_inc(&tgtp->xmt_abort_rsp_error);
        lpfc_printf_log(phba, KERN_WARNING, LOG_NVME_ABTS,
@@ -2270,6 +2522,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
        }
        abts_wqeq = ctxp->wqeq;
        wqe_abts = &abts_wqeq->wqe;
+
        lpfc_nvmet_unsol_issue_abort(phba, ctxp, sid, xri);
 
        spin_lock_irqsave(&phba->hbalock, flags);
@@ -2279,7 +2532,7 @@ lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
        rc = lpfc_sli4_issue_wqe(phba, LPFC_ELS_RING, abts_wqeq);
        spin_unlock_irqrestore(&phba->hbalock, flags);
        if (rc == WQE_SUCCESS) {
-               atomic_inc(&tgtp->xmt_abort_rsp);
+               atomic_inc(&tgtp->xmt_abort_unsol);
                return 0;
        }
 
index 128759fe665058dba133febdaa7140f29469f733..6eb2f5d8d4eda40f931097752c72f175354f14da 100644 (file)
@@ -22,6 +22,7 @@
  ********************************************************************/
 
 #define LPFC_NVMET_DEFAULT_SEGS                (64 + 1)        /* 256K IOs */
+#define LPFC_NVMET_RQE_DEF_COUNT       512
 #define LPFC_NVMET_SUCCESS_LEN 12
 
 /* Used for NVME Target */
@@ -34,6 +35,7 @@ struct lpfc_nvmet_tgtport {
        atomic_t rcv_ls_req_out;
        atomic_t rcv_ls_req_drop;
        atomic_t xmt_ls_abort;
+       atomic_t xmt_ls_abort_cmpl;
 
        /* Stats counters - lpfc_nvmet_xmt_ls_rsp */
        atomic_t xmt_ls_rsp;
@@ -47,9 +49,9 @@ struct lpfc_nvmet_tgtport {
        atomic_t rcv_fcp_cmd_in;
        atomic_t rcv_fcp_cmd_out;
        atomic_t rcv_fcp_cmd_drop;
+       atomic_t xmt_fcp_release;
 
        /* Stats counters - lpfc_nvmet_xmt_fcp_op */
-       atomic_t xmt_fcp_abort;
        atomic_t xmt_fcp_drop;
        atomic_t xmt_fcp_read_rsp;
        atomic_t xmt_fcp_read;
@@ -62,12 +64,13 @@ struct lpfc_nvmet_tgtport {
        atomic_t xmt_fcp_rsp_drop;
 
 
-       /* Stats counters - lpfc_nvmet_unsol_issue_abort */
+       /* Stats counters - lpfc_nvmet_xmt_fcp_abort */
+       atomic_t xmt_fcp_abort;
+       atomic_t xmt_fcp_abort_cmpl;
+       atomic_t xmt_abort_sol;
+       atomic_t xmt_abort_unsol;
        atomic_t xmt_abort_rsp;
        atomic_t xmt_abort_rsp_error;
-
-       /* Stats counters - lpfc_nvmet_xmt_abort_cmp */
-       atomic_t xmt_abort_cmpl;
 };
 
 struct lpfc_nvmet_rcv_ctx {
@@ -103,6 +106,7 @@ struct lpfc_nvmet_rcv_ctx {
 #define LPFC_NVMET_CTX_RLS             0x8  /* ctx free requested */
 #define LPFC_NVMET_ABTS_RCV            0x10  /* ABTS received on exchange */
        struct rqb_dmabuf *rqb_buffer;
+       struct lpfc_nvmet_ctxbuf *ctxbuf;
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
        uint64_t ts_isr_cmd;
index cf19f4976f5fb6338509d85a6e9c4624b9b882b5..d6b184839bc2ff951233ee8fbcf477d6b133206f 100644 (file)
@@ -74,6 +74,8 @@ static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *,
                                                         struct lpfc_iocbq *);
 static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
                                      struct hbq_dmabuf *);
+static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+                                         struct hbq_dmabuf *dmabuf);
 static int lpfc_sli4_fp_handle_cqe(struct lpfc_hba *, struct lpfc_queue *,
                                    struct lpfc_cqe *);
 static int lpfc_sli4_post_sgl_list(struct lpfc_hba *, struct list_head *,
@@ -479,22 +481,23 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
        if (unlikely(!hq) || unlikely(!dq))
                return -ENOMEM;
        put_index = hq->host_index;
-       temp_hrqe = hq->qe[hq->host_index].rqe;
+       temp_hrqe = hq->qe[put_index].rqe;
        temp_drqe = dq->qe[dq->host_index].rqe;
 
        if (hq->type != LPFC_HRQ || dq->type != LPFC_DRQ)
                return -EINVAL;
-       if (hq->host_index != dq->host_index)
+       if (put_index != dq->host_index)
                return -EINVAL;
        /* If the host has not yet processed the next entry then we are done */
-       if (((hq->host_index + 1) % hq->entry_count) == hq->hba_index)
+       if (((put_index + 1) % hq->entry_count) == hq->hba_index)
                return -EBUSY;
        lpfc_sli_pcimem_bcopy(hrqe, temp_hrqe, hq->entry_size);
        lpfc_sli_pcimem_bcopy(drqe, temp_drqe, dq->entry_size);
 
        /* Update the host index to point to the next slot */
-       hq->host_index = ((hq->host_index + 1) % hq->entry_count);
+       hq->host_index = ((put_index + 1) % hq->entry_count);
        dq->host_index = ((dq->host_index + 1) % dq->entry_count);
+       hq->RQ_buf_posted++;
 
        /* Ring The Header Receive Queue Doorbell */
        if (!(hq->host_index % hq->entry_repost)) {
@@ -4204,13 +4207,16 @@ lpfc_sli_brdreset(struct lpfc_hba *phba)
        /* Reset HBA */
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                        "0325 Reset HBA Data: x%x x%x\n",
-                       phba->pport->port_state, psli->sli_flag);
+                       (phba->pport) ? phba->pport->port_state : 0,
+                       psli->sli_flag);
 
        /* perform board reset */
        phba->fc_eventTag = 0;
        phba->link_events = 0;
-       phba->pport->fc_myDID = 0;
-       phba->pport->fc_prevDID = 0;
+       if (phba->pport) {
+               phba->pport->fc_myDID = 0;
+               phba->pport->fc_prevDID = 0;
+       }
 
        /* Turn off parity checking and serr during the physical reset */
        pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
@@ -4336,7 +4342,8 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba)
        /* Restart HBA */
        lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                        "0337 Restart HBA Data: x%x x%x\n",
-                       phba->pport->port_state, psli->sli_flag);
+                       (phba->pport) ? phba->pport->port_state : 0,
+                       psli->sli_flag);
 
        word0 = 0;
        mb = (MAILBOX_t *) &word0;
@@ -4350,7 +4357,7 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba)
        readl(to_slim); /* flush */
 
        /* Only skip post after fc_ffinit is completed */
-       if (phba->pport->port_state)
+       if (phba->pport && phba->pport->port_state)
                word0 = 1;      /* This is really setting up word1 */
        else
                word0 = 0;      /* This is really setting up word1 */
@@ -4359,7 +4366,8 @@ lpfc_sli_brdrestart_s3(struct lpfc_hba *phba)
        readl(to_slim); /* flush */
 
        lpfc_sli_brdreset(phba);
-       phba->pport->stopped = 0;
+       if (phba->pport)
+               phba->pport->stopped = 0;
        phba->link_state = LPFC_INIT_START;
        phba->hba_flag = 0;
        spin_unlock_irq(&phba->hbalock);
@@ -4446,7 +4454,7 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
  * iteration, the function will restart the HBA again. The function returns
  * zero if HBA successfully restarted else returns negative error code.
  **/
-static int
+int
 lpfc_sli_chipset_init(struct lpfc_hba *phba)
 {
        uint32_t status, i = 0;
@@ -5901,7 +5909,7 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
                bf_set(lpfc_mbx_set_feature_mds,
                       &mbox->u.mqe.un.set_feature, 1);
                bf_set(lpfc_mbx_set_feature_mds_deep_loopbk,
-                      &mbox->u.mqe.un.set_feature, 0);
+                      &mbox->u.mqe.un.set_feature, 1);
                mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
                mbox->u.mqe.un.set_feature.param_len = 8;
                break;
@@ -6507,6 +6515,50 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
                 (phba->hba_flag & HBA_FCOE_MODE) ? "FCoE" : "FC");
 }
 
+int
+lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
+                   struct lpfc_queue *drq, int count, int idx)
+{
+       int rc, i;
+       struct lpfc_rqe hrqe;
+       struct lpfc_rqe drqe;
+       struct lpfc_rqb *rqbp;
+       struct rqb_dmabuf *rqb_buffer;
+       LIST_HEAD(rqb_buf_list);
+
+       rqbp = hrq->rqbp;
+       for (i = 0; i < count; i++) {
+               /* IF RQ is already full, don't bother */
+               if (rqbp->buffer_count + i >= rqbp->entry_count - 1)
+                       break;
+               rqb_buffer = rqbp->rqb_alloc_buffer(phba);
+               if (!rqb_buffer)
+                       break;
+               rqb_buffer->hrq = hrq;
+               rqb_buffer->drq = drq;
+               rqb_buffer->idx = idx;
+               list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list);
+       }
+       while (!list_empty(&rqb_buf_list)) {
+               list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf,
+                                hbuf.list);
+
+               hrqe.address_lo = putPaddrLow(rqb_buffer->hbuf.phys);
+               hrqe.address_hi = putPaddrHigh(rqb_buffer->hbuf.phys);
+               drqe.address_lo = putPaddrLow(rqb_buffer->dbuf.phys);
+               drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys);
+               rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe);
+               if (rc < 0) {
+                       rqbp->rqb_free_buffer(phba, rqb_buffer);
+               } else {
+                       list_add_tail(&rqb_buffer->hbuf.list,
+                                     &rqbp->rqb_buffer_list);
+                       rqbp->buffer_count++;
+               }
+       }
+       return 1;
+}
+
 /**
  * lpfc_sli4_hba_setup - SLI4 device initialization PCI function
  * @phba: Pointer to HBA context object.
@@ -6519,7 +6571,7 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
 int
 lpfc_sli4_hba_setup(struct lpfc_hba *phba)
 {
-       int rc, i;
+       int rc, i, cnt;
        LPFC_MBOXQ_t *mboxq;
        struct lpfc_mqe *mqe;
        uint8_t *vpd;
@@ -6870,6 +6922,21 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                        goto out_destroy_queue;
                }
                phba->sli4_hba.nvmet_xri_cnt = rc;
+
+               cnt = phba->cfg_iocb_cnt * 1024;
+               /* We need 1 iocbq for every SGL, for IO processing */
+               cnt += phba->sli4_hba.nvmet_xri_cnt;
+               /* Initialize and populate the iocb list per host */
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "2821 initialize iocb list %d total %d\n",
+                               phba->cfg_iocb_cnt, cnt);
+               rc = lpfc_init_iocb_list(phba, cnt);
+               if (rc) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "1413 Failed to init iocb list.\n");
+                       goto out_destroy_queue;
+               }
+
                lpfc_nvmet_create_targetport(phba);
        } else {
                /* update host scsi xri-sgl sizes and mappings */
@@ -6889,28 +6956,34 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                                        "and mapping: %d\n", rc);
                        goto out_destroy_queue;
                }
+
+               cnt = phba->cfg_iocb_cnt * 1024;
+               /* Initialize and populate the iocb list per host */
+               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "2820 initialize iocb list %d total %d\n",
+                               phba->cfg_iocb_cnt, cnt);
+               rc = lpfc_init_iocb_list(phba, cnt);
+               if (rc) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "6301 Failed to init iocb list.\n");
+                       goto out_destroy_queue;
+               }
        }
 
        if (phba->nvmet_support && phba->cfg_nvmet_mrq) {
-
                /* Post initial buffers to all RQs created */
                for (i = 0; i < phba->cfg_nvmet_mrq; i++) {
                        rqbp = phba->sli4_hba.nvmet_mrq_hdr[i]->rqbp;
                        INIT_LIST_HEAD(&rqbp->rqb_buffer_list);
                        rqbp->rqb_alloc_buffer = lpfc_sli4_nvmet_alloc;
                        rqbp->rqb_free_buffer = lpfc_sli4_nvmet_free;
-                       rqbp->entry_count = 256;
+                       rqbp->entry_count = LPFC_NVMET_RQE_DEF_COUNT;
                        rqbp->buffer_count = 0;
 
-                       /* Divide by 4 and round down to multiple of 16 */
-                       rc = (phba->cfg_nvmet_mrq_post >> 2) & 0xfff8;
-                       phba->sli4_hba.nvmet_mrq_hdr[i]->entry_repost = rc;
-                       phba->sli4_hba.nvmet_mrq_data[i]->entry_repost = rc;
-
                        lpfc_post_rq_buffer(
                                phba, phba->sli4_hba.nvmet_mrq_hdr[i],
                                phba->sli4_hba.nvmet_mrq_data[i],
-                               phba->cfg_nvmet_mrq_post);
+                               LPFC_NVMET_RQE_DEF_COUNT, i);
                }
        }
 
@@ -7077,6 +7150,7 @@ out_unset_queue:
        /* Unset all the queues set up in this routine when error out */
        lpfc_sli4_queue_unset(phba);
 out_destroy_queue:
+       lpfc_free_iocb_list(phba);
        lpfc_sli4_queue_destroy(phba);
 out_stop_timers:
        lpfc_stop_hba_timers(phba);
@@ -8616,8 +8690,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                memset(wqe, 0, sizeof(union lpfc_wqe128));
        /* Some of the fields are in the right position already */
        memcpy(wqe, &iocbq->iocb, sizeof(union lpfc_wqe));
-       wqe->generic.wqe_com.word7 = 0; /* The ct field has moved so reset */
-       wqe->generic.wqe_com.word10 = 0;
+       if (iocbq->iocb.ulpCommand != CMD_SEND_FRAME) {
+               /* The ct field has moved so reset */
+               wqe->generic.wqe_com.word7 = 0;
+               wqe->generic.wqe_com.word10 = 0;
+       }
 
        abort_tag = (uint32_t) iocbq->iotag;
        xritag = iocbq->sli4_xritag;
@@ -9111,6 +9188,10 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                }
 
                break;
+       case CMD_SEND_FRAME:
+               bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
+               bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
+               return 0;
        case CMD_XRI_ABORTED_CX:
        case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
        case CMD_IOCB_FCP_IBIDIR64_CR: /* bidirectional xfer */
@@ -12783,6 +12864,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        struct fc_frame_header *fc_hdr;
        struct lpfc_queue *hrq = phba->sli4_hba.hdr_rq;
        struct lpfc_queue *drq = phba->sli4_hba.dat_rq;
+       struct lpfc_nvmet_tgtport *tgtp;
        struct hbq_dmabuf *dma_buf;
        uint32_t status, rq_id;
        unsigned long iflags;
@@ -12803,7 +12885,6 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "2537 Receive Frame Truncated!!\n");
-               hrq->RQ_buf_trunc++;
        case FC_STATUS_RQ_SUCCESS:
                lpfc_sli4_rq_release(hrq, drq);
                spin_lock_irqsave(&phba->hbalock, iflags);
@@ -12814,6 +12895,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
                        goto out;
                }
                hrq->RQ_rcv_buf++;
+               hrq->RQ_buf_posted--;
                memcpy(&dma_buf->cq_event.cqe.rcqe_cmpl, rcqe, sizeof(*rcqe));
 
                /* If a NVME LS event (type 0x28), treat it as Fast path */
@@ -12827,8 +12909,21 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
                spin_unlock_irqrestore(&phba->hbalock, iflags);
                workposted = true;
                break;
-       case FC_STATUS_INSUFF_BUF_NEED_BUF:
        case FC_STATUS_INSUFF_BUF_FRM_DISC:
+               if (phba->nvmet_support) {
+                       tgtp = phba->targetport->private;
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME,
+                                       "6402 RQE Error x%x, posted %d err_cnt "
+                                       "%d: %x %x %x\n",
+                                       status, hrq->RQ_buf_posted,
+                                       hrq->RQ_no_posted_buf,
+                                       atomic_read(&tgtp->rcv_fcp_cmd_in),
+                                       atomic_read(&tgtp->rcv_fcp_cmd_out),
+                                       atomic_read(&tgtp->xmt_fcp_release));
+               }
+               /* fallthrough */
+
+       case FC_STATUS_INSUFF_BUF_NEED_BUF:
                hrq->RQ_no_posted_buf++;
                /* Post more buffers if possible */
                spin_lock_irqsave(&phba->hbalock, iflags);
@@ -12946,7 +13041,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
                while ((cqe = lpfc_sli4_cq_get(cq))) {
                        workposted |= lpfc_sli4_sp_handle_mcqe(phba, cqe);
                        if (!(++ecount % cq->entry_repost))
-                               lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+                               break;
                        cq->CQ_mbox++;
                }
                break;
@@ -12960,7 +13055,7 @@ lpfc_sli4_sp_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe,
                                workposted |= lpfc_sli4_sp_handle_cqe(phba, cq,
                                                                      cqe);
                        if (!(++ecount % cq->entry_repost))
-                               lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+                               break;
                }
 
                /* Track the max number of CQEs processed in 1 EQ */
@@ -13130,6 +13225,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        struct lpfc_queue *drq;
        struct rqb_dmabuf *dma_buf;
        struct fc_frame_header *fc_hdr;
+       struct lpfc_nvmet_tgtport *tgtp;
        uint32_t status, rq_id;
        unsigned long iflags;
        uint32_t fctl, idx;
@@ -13160,8 +13256,6 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "6126 Receive Frame Truncated!!\n");
-               hrq->RQ_buf_trunc++;
-               break;
        case FC_STATUS_RQ_SUCCESS:
                lpfc_sli4_rq_release(hrq, drq);
                spin_lock_irqsave(&phba->hbalock, iflags);
@@ -13173,6 +13267,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                }
                spin_unlock_irqrestore(&phba->hbalock, iflags);
                hrq->RQ_rcv_buf++;
+               hrq->RQ_buf_posted--;
                fc_hdr = (struct fc_frame_header *)dma_buf->hbuf.virt;
 
                /* Just some basic sanity checks on FCP Command frame */
@@ -13195,14 +13290,23 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
 drop:
                lpfc_in_buf_free(phba, &dma_buf->dbuf);
                break;
-       case FC_STATUS_INSUFF_BUF_NEED_BUF:
        case FC_STATUS_INSUFF_BUF_FRM_DISC:
+               if (phba->nvmet_support) {
+                       tgtp = phba->targetport->private;
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME,
+                                       "6401 RQE Error x%x, posted %d err_cnt "
+                                       "%d: %x %x %x\n",
+                                       status, hrq->RQ_buf_posted,
+                                       hrq->RQ_no_posted_buf,
+                                       atomic_read(&tgtp->rcv_fcp_cmd_in),
+                                       atomic_read(&tgtp->rcv_fcp_cmd_out),
+                                       atomic_read(&tgtp->xmt_fcp_release));
+               }
+               /* fallthrough */
+
+       case FC_STATUS_INSUFF_BUF_NEED_BUF:
                hrq->RQ_no_posted_buf++;
                /* Post more buffers if possible */
-               spin_lock_irqsave(&phba->hbalock, iflags);
-               phba->hba_flag |= HBA_POST_RECEIVE_BUFFER;
-               spin_unlock_irqrestore(&phba->hbalock, iflags);
-               workposted = true;
                break;
        }
 out:
@@ -13356,7 +13460,7 @@ process_cq:
        while ((cqe = lpfc_sli4_cq_get(cq))) {
                workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
                if (!(++ecount % cq->entry_repost))
-                       lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+                       break;
        }
 
        /* Track the max number of CQEs processed in 1 EQ */
@@ -13447,7 +13551,7 @@ lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
        while ((cqe = lpfc_sli4_cq_get(cq))) {
                workposted |= lpfc_sli4_fp_handle_cqe(phba, cq, cqe);
                if (!(++ecount % cq->entry_repost))
-                       lpfc_sli4_cq_release(cq, LPFC_QUEUE_NOARM);
+                       break;
        }
 
        /* Track the max number of CQEs processed in 1 EQ */
@@ -13529,7 +13633,7 @@ lpfc_sli4_fof_intr_handler(int irq, void *dev_id)
        while ((eqe = lpfc_sli4_eq_get(eq))) {
                lpfc_sli4_fof_handle_eqe(phba, eqe);
                if (!(++ecount % eq->entry_repost))
-                       lpfc_sli4_eq_release(eq, LPFC_QUEUE_NOARM);
+                       break;
                eq->EQ_processed++;
        }
 
@@ -13646,7 +13750,7 @@ lpfc_sli4_hba_intr_handler(int irq, void *dev_id)
 
                lpfc_sli4_hba_handle_eqe(phba, eqe, hba_eqidx);
                if (!(++ecount % fpeq->entry_repost))
-                       lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_NOARM);
+                       break;
                fpeq->EQ_processed++;
        }
 
@@ -13827,17 +13931,10 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t entry_size,
        }
        queue->entry_size = entry_size;
        queue->entry_count = entry_count;
-
-       /*
-        * entry_repost is calculated based on the number of entries in the
-        * queue. This works out except for RQs. If buffers are NOT initially
-        * posted for every RQE, entry_repost should be adjusted accordingly.
-        */
-       queue->entry_repost = (entry_count >> 3);
-       if (queue->entry_repost < LPFC_QUEUE_MIN_REPOST)
-               queue->entry_repost = LPFC_QUEUE_MIN_REPOST;
        queue->phba = phba;
 
+       /* entry_repost will be set during q creation */
+
        return queue;
 out_fail:
        lpfc_sli4_queue_free(queue);
@@ -14068,6 +14165,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
                status = -ENXIO;
        eq->host_index = 0;
        eq->hba_index = 0;
+       eq->entry_repost = LPFC_EQ_REPOST;
 
        mempool_free(mbox, phba->mbox_mem_pool);
        return status;
@@ -14141,9 +14239,9 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0361 Unsupported CQ count: "
-                               "entry cnt %d sz %d pg cnt %d repost %d\n",
+                               "entry cnt %d sz %d pg cnt %d\n",
                                cq->entry_count, cq->entry_size,
-                               cq->page_count, cq->entry_repost);
+                               cq->page_count);
                if (cq->entry_count < 256) {
                        status = -EINVAL;
                        goto out;
@@ -14196,6 +14294,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
        cq->assoc_qid = eq->queue_id;
        cq->host_index = 0;
        cq->hba_index = 0;
+       cq->entry_repost = LPFC_CQ_REPOST;
 
 out:
        mempool_free(mbox, phba->mbox_mem_pool);
@@ -14387,6 +14486,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                cq->assoc_qid = eq->queue_id;
                cq->host_index = 0;
                cq->hba_index = 0;
+               cq->entry_repost = LPFC_CQ_REPOST;
 
                rc = 0;
                list_for_each_entry(dmabuf, &cq->page_list, list) {
@@ -14635,6 +14735,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
        mq->subtype = subtype;
        mq->host_index = 0;
        mq->hba_index = 0;
+       mq->entry_repost = LPFC_MQ_REPOST;
 
        /* link the mq onto the parent cq child list */
        list_add_tail(&mq->list, &cq->child_list);
@@ -14859,34 +14960,6 @@ out:
        return status;
 }
 
-/**
- * lpfc_rq_adjust_repost - Adjust entry_repost for an RQ
- * @phba: HBA structure that indicates port to create a queue on.
- * @rq:   The queue structure to use for the receive queue.
- * @qno:  The associated HBQ number
- *
- *
- * For SLI4 we need to adjust the RQ repost value based on
- * the number of buffers that are initially posted to the RQ.
- */
-void
-lpfc_rq_adjust_repost(struct lpfc_hba *phba, struct lpfc_queue *rq, int qno)
-{
-       uint32_t cnt;
-
-       /* sanity check on queue memory */
-       if (!rq)
-               return;
-       cnt = lpfc_hbq_defs[qno]->entry_count;
-
-       /* Recalc repost for RQs based on buffers initially posted */
-       cnt = (cnt >> 3);
-       if (cnt < LPFC_QUEUE_MIN_REPOST)
-               cnt = LPFC_QUEUE_MIN_REPOST;
-
-       rq->entry_repost = cnt;
-}
-
 /**
  * lpfc_rq_create - Create a Receive Queue on the HBA
  * @phba: HBA structure that indicates port to create a queue on.
@@ -15072,6 +15145,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
        hrq->subtype = subtype;
        hrq->host_index = 0;
        hrq->hba_index = 0;
+       hrq->entry_repost = LPFC_RQ_REPOST;
 
        /* now create the data queue */
        lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
@@ -15082,7 +15156,12 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
        if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
                bf_set(lpfc_rq_context_rqe_count_1,
                       &rq_create->u.request.context, hrq->entry_count);
-               rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE;
+               if (subtype == LPFC_NVMET)
+                       rq_create->u.request.context.buffer_size =
+                               LPFC_NVMET_DATA_BUF_SIZE;
+               else
+                       rq_create->u.request.context.buffer_size =
+                               LPFC_DATA_BUF_SIZE;
                bf_set(lpfc_rq_context_rqe_size, &rq_create->u.request.context,
                       LPFC_RQE_SIZE_8);
                bf_set(lpfc_rq_context_page_size, &rq_create->u.request.context,
@@ -15119,8 +15198,14 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                               LPFC_RQ_RING_SIZE_4096);
                        break;
                }
-               bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
-                      LPFC_DATA_BUF_SIZE);
+               if (subtype == LPFC_NVMET)
+                       bf_set(lpfc_rq_context_buf_size,
+                              &rq_create->u.request.context,
+                              LPFC_NVMET_DATA_BUF_SIZE);
+               else
+                       bf_set(lpfc_rq_context_buf_size,
+                              &rq_create->u.request.context,
+                              LPFC_DATA_BUF_SIZE);
        }
        bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
               cq->queue_id);
@@ -15153,6 +15238,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
        drq->subtype = subtype;
        drq->host_index = 0;
        drq->hba_index = 0;
+       drq->entry_repost = LPFC_RQ_REPOST;
 
        /* link the header and data RQs onto the parent cq child list */
        list_add_tail(&hrq->list, &cq->child_list);
@@ -15265,7 +15351,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
                               cq->queue_id);
                        bf_set(lpfc_rq_context_data_size,
                               &rq_create->u.request.context,
-                              LPFC_DATA_BUF_SIZE);
+                              LPFC_NVMET_DATA_BUF_SIZE);
                        bf_set(lpfc_rq_context_hdr_size,
                               &rq_create->u.request.context,
                               LPFC_HDR_BUF_SIZE);
@@ -15310,6 +15396,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
                hrq->subtype = subtype;
                hrq->host_index = 0;
                hrq->hba_index = 0;
+               hrq->entry_repost = LPFC_RQ_REPOST;
 
                drq->db_format = LPFC_DB_RING_FORMAT;
                drq->db_regaddr = phba->sli4_hba.RQDBregaddr;
@@ -15318,6 +15405,7 @@ lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
                drq->subtype = subtype;
                drq->host_index = 0;
                drq->hba_index = 0;
+               drq->entry_repost = LPFC_RQ_REPOST;
 
                list_add_tail(&hrq->list, &cq->child_list);
                list_add_tail(&drq->list, &cq->child_list);
@@ -16058,6 +16146,8 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
        struct fc_vft_header *fc_vft_hdr;
        uint32_t *header = (uint32_t *) fc_hdr;
 
+#define FC_RCTL_MDS_DIAGS      0xF4
+
        switch (fc_hdr->fh_r_ctl) {
        case FC_RCTL_DD_UNCAT:          /* uncategorized information */
        case FC_RCTL_DD_SOL_DATA:       /* solicited data */
@@ -16085,6 +16175,7 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
        case FC_RCTL_F_BSY:     /* fabric busy to data frame */
        case FC_RCTL_F_BSYL:    /* fabric busy to link control frame */
        case FC_RCTL_LCR:       /* link credit reset */
+       case FC_RCTL_MDS_DIAGS: /* MDS Diagnostics */
        case FC_RCTL_END:       /* end */
                break;
        case FC_RCTL_VFTH:      /* Virtual Fabric tagging Header */
@@ -16094,12 +16185,16 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
        default:
                goto drop;
        }
+
+#define FC_TYPE_VENDOR_UNIQUE  0xFF
+
        switch (fc_hdr->fh_type) {
        case FC_TYPE_BLS:
        case FC_TYPE_ELS:
        case FC_TYPE_FCP:
        case FC_TYPE_CT:
        case FC_TYPE_NVME:
+       case FC_TYPE_VENDOR_UNIQUE:
                break;
        case FC_TYPE_IP:
        case FC_TYPE_ILS:
@@ -16110,12 +16205,14 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr)
        lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
                        "2538 Received frame rctl:%s (x%x), type:%s (x%x), "
                        "frame Data:%08x %08x %08x %08x %08x %08x %08x\n",
+                       (fc_hdr->fh_r_ctl == FC_RCTL_MDS_DIAGS) ? "MDS Diags" :
                        lpfc_rctl_names[fc_hdr->fh_r_ctl], fc_hdr->fh_r_ctl,
-                       lpfc_type_names[fc_hdr->fh_type], fc_hdr->fh_type,
-                       be32_to_cpu(header[0]), be32_to_cpu(header[1]),
-                       be32_to_cpu(header[2]), be32_to_cpu(header[3]),
-                       be32_to_cpu(header[4]), be32_to_cpu(header[5]),
-                       be32_to_cpu(header[6]));
+                       (fc_hdr->fh_type == FC_TYPE_VENDOR_UNIQUE) ?
+                       "Vendor Unique" : lpfc_type_names[fc_hdr->fh_type],
+                       fc_hdr->fh_type, be32_to_cpu(header[0]),
+                       be32_to_cpu(header[1]), be32_to_cpu(header[2]),
+                       be32_to_cpu(header[3]), be32_to_cpu(header[4]),
+                       be32_to_cpu(header[5]), be32_to_cpu(header[6]));
        return 0;
 drop:
        lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -16921,6 +17018,96 @@ lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *vport,
        lpfc_sli_release_iocbq(phba, iocbq);
 }
 
+static void
+lpfc_sli4_mds_loopback_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+                           struct lpfc_iocbq *rspiocb)
+{
+       struct lpfc_dmabuf *pcmd = cmdiocb->context2;
+
+       if (pcmd && pcmd->virt)
+               pci_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
+       kfree(pcmd);
+       lpfc_sli_release_iocbq(phba, cmdiocb);
+}
+
+static void
+lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+                             struct hbq_dmabuf *dmabuf)
+{
+       struct fc_frame_header *fc_hdr;
+       struct lpfc_hba *phba = vport->phba;
+       struct lpfc_iocbq *iocbq = NULL;
+       union  lpfc_wqe *wqe;
+       struct lpfc_dmabuf *pcmd = NULL;
+       uint32_t frame_len;
+       int rc;
+
+       fc_hdr = (struct fc_frame_header *)dmabuf->hbuf.virt;
+       frame_len = bf_get(lpfc_rcqe_length, &dmabuf->cq_event.cqe.rcqe_cmpl);
+
+       /* Send the received frame back */
+       iocbq = lpfc_sli_get_iocbq(phba);
+       if (!iocbq)
+               goto exit;
+
+       /* Allocate buffer for command payload */
+       pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+       if (pcmd)
+               pcmd->virt = pci_pool_alloc(phba->lpfc_drb_pool, GFP_KERNEL,
+                                           &pcmd->phys);
+       if (!pcmd || !pcmd->virt)
+               goto exit;
+
+       INIT_LIST_HEAD(&pcmd->list);
+
+       /* copyin the payload */
+       memcpy(pcmd->virt, dmabuf->dbuf.virt, frame_len);
+
+       /* fill in BDE's for command */
+       iocbq->iocb.un.xseq64.bdl.addrHigh = putPaddrHigh(pcmd->phys);
+       iocbq->iocb.un.xseq64.bdl.addrLow = putPaddrLow(pcmd->phys);
+       iocbq->iocb.un.xseq64.bdl.bdeFlags = BUFF_TYPE_BDE_64;
+       iocbq->iocb.un.xseq64.bdl.bdeSize = frame_len;
+
+       iocbq->context2 = pcmd;
+       iocbq->vport = vport;
+       iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK;
+       iocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
+
+       /*
+        * Setup rest of the iocb as though it were a WQE
+        * Build the SEND_FRAME WQE
+        */
+       wqe = (union lpfc_wqe *)&iocbq->iocb;
+
+       wqe->send_frame.frame_len = frame_len;
+       wqe->send_frame.fc_hdr_wd0 = be32_to_cpu(*((uint32_t *)fc_hdr));
+       wqe->send_frame.fc_hdr_wd1 = be32_to_cpu(*((uint32_t *)fc_hdr + 1));
+       wqe->send_frame.fc_hdr_wd2 = be32_to_cpu(*((uint32_t *)fc_hdr + 2));
+       wqe->send_frame.fc_hdr_wd3 = be32_to_cpu(*((uint32_t *)fc_hdr + 3));
+       wqe->send_frame.fc_hdr_wd4 = be32_to_cpu(*((uint32_t *)fc_hdr + 4));
+       wqe->send_frame.fc_hdr_wd5 = be32_to_cpu(*((uint32_t *)fc_hdr + 5));
+
+       iocbq->iocb.ulpCommand = CMD_SEND_FRAME;
+       iocbq->iocb.ulpLe = 1;
+       iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl;
+       rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0);
+       if (rc == IOCB_ERROR)
+               goto exit;
+
+       lpfc_in_buf_free(phba, &dmabuf->dbuf);
+       return;
+
+exit:
+       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                       "2023 Unable to process MDS loopback frame\n");
+       if (pcmd && pcmd->virt)
+               pci_pool_free(phba->lpfc_drb_pool, pcmd->virt, pcmd->phys);
+       kfree(pcmd);
+       lpfc_sli_release_iocbq(phba, iocbq);
+       lpfc_in_buf_free(phba, &dmabuf->dbuf);
+}
+
 /**
  * lpfc_sli4_handle_received_buffer - Handle received buffers from firmware
  * @phba: Pointer to HBA context object.
@@ -16959,6 +17146,13 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba,
                fcfi = bf_get(lpfc_rcqe_fcf_id,
                              &dmabuf->cq_event.cqe.rcqe_cmpl);
 
+       if (fc_hdr->fh_r_ctl == 0xF4 && fc_hdr->fh_type == 0xFF) {
+               vport = phba->pport;
+               /* Handle MDS Loopback frames */
+               lpfc_sli4_handle_mds_loopback(vport, dmabuf);
+               return;
+       }
+
        /* d_id this frame is directed to */
        did = sli4_did_from_fc_hdr(fc_hdr);
 
@@ -17132,6 +17326,14 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
                                "status x%x add_status x%x, mbx status x%x\n",
                                shdr_status, shdr_add_status, rc);
                rc = -ENXIO;
+       } else {
+               /*
+                * The next_rpi stores the next logical module-64 rpi value used
+                * to post physical rpis in subsequent rpi postings.
+                */
+               spin_lock_irq(&phba->hbalock);
+               phba->sli4_hba.next_rpi = rpi_page->next_rpi;
+               spin_unlock_irq(&phba->hbalock);
        }
        return rc;
 }
@@ -18712,7 +18914,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, uint32_t ring_number,
 
                spin_lock_irqsave(&pring->ring_lock, iflags);
                ctxp = pwqe->context2;
-               sglq = ctxp->rqb_buffer->sglq;
+               sglq = ctxp->ctxbuf->sglq;
                if (pwqe->sli4_xritag ==  NO_XRI) {
                        pwqe->sli4_lxritag = sglq->sli4_lxritag;
                        pwqe->sli4_xritag = sglq->sli4_xritag;
index da46471337c8a7e3b6c38164bc4afe1a4f0087c2..cf863db27700a2400463bcc65777ec15f9806da4 100644 (file)
@@ -24,7 +24,6 @@
 #define LPFC_XRI_EXCH_BUSY_WAIT_TMO            10000
 #define LPFC_XRI_EXCH_BUSY_WAIT_T1             10
 #define LPFC_XRI_EXCH_BUSY_WAIT_T2              30000
-#define LPFC_RELEASE_NOTIFICATION_INTERVAL     32
 #define LPFC_RPI_LOW_WATER_MARK                        10
 
 #define LPFC_UNREG_FCF                          1
@@ -155,7 +154,11 @@ struct lpfc_queue {
        uint32_t entry_count;   /* Number of entries to support on the queue */
        uint32_t entry_size;    /* Size of each queue entry. */
        uint32_t entry_repost;  /* Count of entries before doorbell is rung */
-#define LPFC_QUEUE_MIN_REPOST  8
+#define LPFC_EQ_REPOST         8
+#define LPFC_MQ_REPOST         8
+#define LPFC_CQ_REPOST         64
+#define LPFC_RQ_REPOST         64
+#define LPFC_RELEASE_NOTIFICATION_INTERVAL     32  /* For WQs */
        uint32_t queue_id;      /* Queue ID assigned by the hardware */
        uint32_t assoc_qid;     /* Queue ID associated with, for CQ/WQ/MQ */
        uint32_t page_count;    /* Number of pages allocated for this queue */
@@ -195,7 +198,7 @@ struct lpfc_queue {
 /* defines for RQ stats */
 #define        RQ_no_posted_buf        q_cnt_1
 #define        RQ_no_buf_found         q_cnt_2
-#define        RQ_buf_trunc            q_cnt_3
+#define        RQ_buf_posted           q_cnt_3
 #define        RQ_rcv_buf              q_cnt_4
 
        uint64_t isr_timestamp;
@@ -617,12 +620,17 @@ struct lpfc_sli4_hba {
        uint16_t scsi_xri_start;
        uint16_t els_xri_cnt;
        uint16_t nvmet_xri_cnt;
+       uint16_t nvmet_ctx_cnt;
+       uint16_t nvmet_io_wait_cnt;
+       uint16_t nvmet_io_wait_total;
        struct list_head lpfc_els_sgl_list;
        struct list_head lpfc_abts_els_sgl_list;
        struct list_head lpfc_nvmet_sgl_list;
        struct list_head lpfc_abts_nvmet_ctx_list;
        struct list_head lpfc_abts_scsi_buf_list;
        struct list_head lpfc_abts_nvme_buf_list;
+       struct list_head lpfc_nvmet_ctx_list;
+       struct list_head lpfc_nvmet_io_wait_list;
        struct lpfc_sglq **lpfc_sglq_active_list;
        struct list_head lpfc_rpi_hdr_list;
        unsigned long *rpi_bmask;
@@ -654,6 +662,7 @@ struct lpfc_sli4_hba {
        spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */
        spinlock_t sgl_list_lock; /* list of aborted els IOs */
        spinlock_t nvmet_io_lock;
+       spinlock_t nvmet_io_wait_lock; /* IOs waiting for ctx resources */
        uint32_t physical_port;
 
        /* CPU to vector mapping information */
@@ -661,8 +670,6 @@ struct lpfc_sli4_hba {
        uint16_t num_online_cpu;
        uint16_t num_present_cpu;
        uint16_t curr_disp_cpu;
-
-       uint16_t nvmet_mrq_post_idx;
 };
 
 enum lpfc_sge_type {
@@ -698,6 +705,7 @@ struct lpfc_rpi_hdr {
        struct lpfc_dmabuf *dmabuf;
        uint32_t page_count;
        uint32_t start_rpi;
+       uint16_t next_rpi;
 };
 
 struct lpfc_rsrc_blks {
@@ -762,7 +770,6 @@ int lpfc_rq_create(struct lpfc_hba *, struct lpfc_queue *,
 int lpfc_mrq_create(struct lpfc_hba *phba, struct lpfc_queue **hrqp,
                        struct lpfc_queue **drqp, struct lpfc_queue **cqp,
                        uint32_t subtype);
-void lpfc_rq_adjust_repost(struct lpfc_hba *, struct lpfc_queue *, int);
 int lpfc_eq_destroy(struct lpfc_hba *, struct lpfc_queue *);
 int lpfc_cq_destroy(struct lpfc_hba *, struct lpfc_queue *);
 int lpfc_mq_destroy(struct lpfc_hba *, struct lpfc_queue *);
index 1c26dc67151b65e050b729e63a0871cb6846564f..c2653244221cb1b2cb987d962686daeed43094c3 100644 (file)
@@ -20,7 +20,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "11.2.0.12"
+#define LPFC_DRIVER_VERSION "11.2.0.14"
 #define LPFC_DRIVER_NAME               "lpfc"
 
 /* Used for SLI 2/3 */
index a4aadf5f4dc61e9d80a5f1382fd63f11d169dd0d..1cc814f1505a3c149133a0c8c5c2f5f556c056d4 100644 (file)
@@ -3770,9 +3770,6 @@ static long pmcraid_ioctl_passthrough(
                        pmcraid_err("couldn't build passthrough ioadls\n");
                        goto out_free_cmd;
                }
-       } else if (request_size < 0) {
-               rc = -EINVAL;
-               goto out_free_cmd;
        }
 
        /* If data is being written into the device, copy the data from user
index 40aeb6bb96a2afd11c3264b7ea0004110033e2d1..07ee88200e91cfc072eed5506c6eca0974dda67f 100644 (file)
@@ -259,7 +259,7 @@ struct qedf_io_log {
        uint16_t task_id;
        uint32_t port_id; /* Remote port fabric ID */
        int lun;
-       char op; /* SCSI CDB */
+       unsigned char op; /* SCSI CDB */
        uint8_t lba[4];
        unsigned int bufflen; /* SCSI buffer length */
        unsigned int sg_count; /* Number of SG elements */
index c505d41f6dc843825fb52fabaaca33e5dd25d1ce..90627033bde600c551af700004858a18ddadaa6c 100644 (file)
@@ -109,7 +109,7 @@ retry_els:
        did = fcport->rdata->ids.port_id;
        sid = fcport->sid;
 
-       __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, sid, did,
+       __fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
                           FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
                           FC_FC_SEQ_INIT, 0);
 
index cceddd995a4bf46605ae94143cfcff9df693fb83..a5c97342fd5d2bc5f9826d34974e8d7b7c285dd3 100644 (file)
@@ -2895,7 +2895,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
        slowpath_params.drv_minor = QEDF_DRIVER_MINOR_VER;
        slowpath_params.drv_rev = QEDF_DRIVER_REV_VER;
        slowpath_params.drv_eng = QEDF_DRIVER_ENG_VER;
-       memcpy(slowpath_params.name, "qedf", QED_DRV_VER_STR_SIZE);
+       strncpy(slowpath_params.name, "qedf", QED_DRV_VER_STR_SIZE);
        rc = qed_ops->common->slowpath_start(qedf->cdev, &slowpath_params);
        if (rc) {
                QEDF_ERR(&(qedf->dbg_ctx), "Cannot start slowpath.\n");
index 5ca3e8c28a3f6af3b4faf1d82ec1ab6f37480127..32632c9b22766d59e223a256c430810a4fa33bec 100644 (file)
@@ -38,7 +38,7 @@ struct qedi_endpoint;
 #define QEDI_MAX_ISCSI_TASK            4096
 #define QEDI_MAX_TASK_NUM              0x0FFF
 #define QEDI_MAX_ISCSI_CONNS_PER_HBA   1024
-#define QEDI_ISCSI_MAX_BDS_PER_CMD     256     /* Firmware max BDs is 256 */
+#define QEDI_ISCSI_MAX_BDS_PER_CMD     255     /* Firmware max BDs is 255 */
 #define MAX_OUSTANDING_TASKS_PER_CON   1024
 
 #define QEDI_MAX_BD_LEN                0xffff
@@ -63,6 +63,7 @@ struct qedi_endpoint;
 #define QEDI_PAGE_MASK         (~((QEDI_PAGE_SIZE) - 1))
 
 #define QEDI_PAGE_SIZE         4096
+#define QEDI_HW_DMA_BOUNDARY   0xfff
 #define QEDI_PATH_HANDLE       0xFE0000000UL
 
 struct qedi_uio_ctrl {
index d6978cbc56f0586aa8a075191433184c50c93b01..507512cc478b1dd2632e033ac7d9a2dc99b8ab5d 100644 (file)
@@ -870,7 +870,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi,
                QEDI_ERR(&qedi->dbg_ctx,
                         "Delayed or untracked cleanup response, itt=0x%x, tid=0x%x, cid=0x%x, task=%p\n",
                         protoitt, cqe->itid, qedi_conn->iscsi_conn_id, task);
-               WARN_ON(1);
        }
 }
 
@@ -1494,6 +1493,8 @@ static int qedi_send_iscsi_tmf(struct qedi_conn *qedi_conn,
        tmf_hdr = (struct iscsi_tm *)mtask->hdr;
        qedi_cmd = (struct qedi_cmd *)mtask->dd_data;
        ep = qedi_conn->ep;
+       if (!ep)
+               return -ENODEV;
 
        tid = qedi_get_task_idx(qedi);
        if (tid == -1)
index 3548d46f9b275825a9f76765966cf8c943762e88..87f0af358b33ae4563ba2ee83a1aaa4ce9ca7945 100644 (file)
@@ -59,6 +59,7 @@ struct scsi_host_template qedi_host_template = {
        .this_id = -1,
        .sg_tablesize = QEDI_ISCSI_MAX_BDS_PER_CMD,
        .max_sectors = 0xffff,
+       .dma_boundary = QEDI_HW_DMA_BOUNDARY,
        .cmd_per_lun = 128,
        .use_clustering = ENABLE_CLUSTERING,
        .shost_attrs = qedi_shost_attrs,
@@ -1223,8 +1224,12 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
 
        iscsi_cid = (u32)path_data->handle;
        qedi_ep = qedi->ep_tbl[iscsi_cid];
-       QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_CONN,
+       QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
                  "iscsi_cid=0x%x, qedi_ep=%p\n", iscsi_cid, qedi_ep);
+       if (!qedi_ep) {
+               ret = -EINVAL;
+               goto set_path_exit;
+       }
 
        if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
                QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
index 92775a8b74b1cdc068b8d8808b7bd9ccd5b212eb..879d3b7462f94f38bba4618aecf51dde947aa458 100644 (file)
@@ -151,6 +151,11 @@ static int qedi_uio_close(struct uio_info *uinfo, struct inode *inode)
 
 static void __qedi_free_uio_rings(struct qedi_uio_dev *udev)
 {
+       if (udev->uctrl) {
+               free_page((unsigned long)udev->uctrl);
+               udev->uctrl = NULL;
+       }
+
        if (udev->ll2_ring) {
                free_page((unsigned long)udev->ll2_ring);
                udev->ll2_ring = NULL;
@@ -169,7 +174,6 @@ static void __qedi_free_uio(struct qedi_uio_dev *udev)
        __qedi_free_uio_rings(udev);
 
        pci_dev_put(udev->pdev);
-       kfree(udev->uctrl);
        kfree(udev);
 }
 
@@ -208,6 +212,11 @@ static int __qedi_alloc_uio_rings(struct qedi_uio_dev *udev)
        if (udev->ll2_ring || udev->ll2_buf)
                return rc;
 
+       /* Memory for control area.  */
+       udev->uctrl = (void *)get_zeroed_page(GFP_KERNEL);
+       if (!udev->uctrl)
+               return -ENOMEM;
+
        /* Allocating memory for LL2 ring  */
        udev->ll2_ring_size = QEDI_PAGE_SIZE;
        udev->ll2_ring = (void *)get_zeroed_page(GFP_KERNEL | __GFP_COMP);
@@ -237,7 +246,6 @@ exit_alloc_ring:
 static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
 {
        struct qedi_uio_dev *udev = NULL;
-       struct qedi_uio_ctrl *uctrl = NULL;
        int rc = 0;
 
        list_for_each_entry(udev, &qedi_udev_list, list) {
@@ -258,21 +266,14 @@ static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
                goto err_udev;
        }
 
-       uctrl = kzalloc(sizeof(*uctrl), GFP_KERNEL);
-       if (!uctrl) {
-               rc = -ENOMEM;
-               goto err_uctrl;
-       }
-
        udev->uio_dev = -1;
 
        udev->qedi = qedi;
        udev->pdev = qedi->pdev;
-       udev->uctrl = uctrl;
 
        rc = __qedi_alloc_uio_rings(udev);
        if (rc)
-               goto err_uio_rings;
+               goto err_uctrl;
 
        list_add(&udev->list, &qedi_udev_list);
 
@@ -283,8 +284,6 @@ static int qedi_alloc_uio_rings(struct qedi_ctx *qedi)
        udev->rx_pkt = udev->ll2_buf + LL2_SINGLE_BUF_SIZE;
        return 0;
 
- err_uio_rings:
-       kfree(uctrl);
  err_uctrl:
        kfree(udev);
  err_udev:
@@ -828,6 +827,8 @@ static int qedi_set_iscsi_pf_param(struct qedi_ctx *qedi)
        qedi->pf_params.iscsi_pf_params.num_uhq_pages_in_ring = num_sq_pages;
        qedi->pf_params.iscsi_pf_params.num_queues = qedi->num_queues;
        qedi->pf_params.iscsi_pf_params.debug_mode = qedi_fw_debug;
+       qedi->pf_params.iscsi_pf_params.two_msl_timer = 4000;
+       qedi->pf_params.iscsi_pf_params.max_fin_rt = 2;
 
        for (log_page_size = 0 ; log_page_size < 32 ; log_page_size++) {
                if ((1 << log_page_size) == PAGE_SIZE)
@@ -1498,11 +1499,9 @@ err_idx:
 
 void qedi_clear_task_idx(struct qedi_ctx *qedi, int idx)
 {
-       if (!test_and_clear_bit(idx, qedi->task_idx_map)) {
+       if (!test_and_clear_bit(idx, qedi->task_idx_map))
                QEDI_ERR(&qedi->dbg_ctx,
                         "FW task context, already cleared, tid=0x%x\n", idx);
-               WARN_ON(1);
-       }
 }
 
 void qedi_update_itt_map(struct qedi_ctx *qedi, u32 tid, u32 proto_itt,
index 16d1cd50feed5eee4744ff168709d589672a132b..ca3420de5a013f4e39760fb6da1edbb5358d26b1 100644 (file)
@@ -730,6 +730,8 @@ qla2x00_process_loopback(struct bsg_job *bsg_job)
                return -EIO;
        }
 
+       memset(&elreq, 0, sizeof(elreq));
+
        elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
                bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
                DMA_TO_DEVICE);
@@ -795,10 +797,9 @@ qla2x00_process_loopback(struct bsg_job *bsg_job)
 
        if (atomic_read(&vha->loop_state) == LOOP_READY &&
            (ha->current_topology == ISP_CFG_F ||
-           ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
-           le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
-           && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
-               elreq.options == EXTERNAL_LOOPBACK) {
+           (le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE &&
+            req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
+           elreq.options == EXTERNAL_LOOPBACK) {
                type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
                ql_dbg(ql_dbg_user, vha, 0x701e,
                    "BSG request type: %s.\n", type);
index 51b4179469d1851be96872ee39b24739fc34135e..88748a6ab73f6fc59f4a2b9fb202fa9efe24c7de 100644 (file)
@@ -1131,7 +1131,7 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
 
        /* Mailbox registers. */
        mbx_reg = &reg->mailbox0;
-       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++)
+       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
                fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
 
        /* Transfer sequence registers. */
@@ -2090,7 +2090,7 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
 
        /* Mailbox registers. */
        mbx_reg = &reg->mailbox0;
-       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++)
+       for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
                fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
 
        /* Transfer sequence registers. */
index ae119018dfaae9fe65c5cfe1869cdc655b27a3ea..eddbc1218a39ba511700d3d4f446771eb06524f8 100644 (file)
@@ -3425,6 +3425,7 @@ struct qla_hw_data {
        uint8_t         max_req_queues;
        uint8_t         max_rsp_queues;
        uint8_t         max_qpairs;
+       uint8_t         num_qpairs;
        struct qla_qpair *base_qpair;
        struct qla_npiv_entry *npiv_info;
        uint16_t        nvram_npiv_size;
index 034743309adaa93f7093cf79d9548fe05fb4bb3b..0391fc3170035e10bd5a34423cd58601eca0850e 100644 (file)
@@ -7543,12 +7543,13 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, int v
                /* Assign available que pair id */
                mutex_lock(&ha->mq_lock);
                qpair_id = find_first_zero_bit(ha->qpair_qid_map, ha->max_qpairs);
-               if (qpair_id >= ha->max_qpairs) {
+               if (ha->num_qpairs >= ha->max_qpairs) {
                        mutex_unlock(&ha->mq_lock);
                        ql_log(ql_log_warn, vha, 0x0183,
                            "No resources to create additional q pair.\n");
                        goto fail_qid_map;
                }
+               ha->num_qpairs++;
                set_bit(qpair_id, ha->qpair_qid_map);
                ha->queue_pair_map[qpair_id] = qpair;
                qpair->id = qpair_id;
@@ -7635,6 +7636,7 @@ fail_rsp:
 fail_msix:
        ha->queue_pair_map[qpair_id] = NULL;
        clear_bit(qpair_id, ha->qpair_qid_map);
+       ha->num_qpairs--;
        mutex_unlock(&ha->mq_lock);
 fail_qid_map:
        kfree(qpair);
@@ -7660,6 +7662,7 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
        mutex_lock(&ha->mq_lock);
        ha->queue_pair_map[qpair->id] = NULL;
        clear_bit(qpair->id, ha->qpair_qid_map);
+       ha->num_qpairs--;
        list_del(&qpair->qp_list_elem);
        if (list_empty(&vha->qp_list))
                vha->flags.qpairs_available = 0;
index 66df6cec59da4059f064410536c48995635c80ee..c61a6a871c8e0d5bee96b566639abf84d4fe544f 100644 (file)
@@ -129,28 +129,16 @@ qla2x00_clear_loop_id(fc_port_t *fcport) {
 }
 
 static inline void
-qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp,
-       struct qla_tgt_cmd *tc)
+qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx)
 {
-       struct dsd_dma *dsd_ptr, *tdsd_ptr;
-       struct crc_context *ctx;
-
-       if (sp)
-               ctx = (struct crc_context *)GET_CMD_CTX_SP(sp);
-       else if (tc)
-               ctx = (struct crc_context *)tc->ctx;
-       else {
-               BUG();
-               return;
-       }
+       struct dsd_dma *dsd, *tdsd;
 
        /* clean up allocated prev pool */
-       list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
-           &ctx->dsd_list, list) {
-               dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
-                   dsd_ptr->dsd_list_dma);
-               list_del(&dsd_ptr->list);
-               kfree(dsd_ptr);
+       list_for_each_entry_safe(dsd, tdsd, &ctx->dsd_list, list) {
+               dma_pool_free(ha->dl_dma_pool, dsd->dsd_addr,
+                   dsd->dsd_list_dma);
+               list_del(&dsd->list);
+               kfree(dsd);
        }
        INIT_LIST_HEAD(&ctx->dsd_list);
 }
index aac03504d9a359c9d48a88bf12ff2b3c51eba308..2572121b765b488b4ee5dbec726e9240e0df25a9 100644 (file)
@@ -3282,7 +3282,7 @@ msix_register_fail:
        }
 
        /* Enable MSI-X vector for response queue update for queue 0 */
-       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+       if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
                if (ha->msixbase && ha->mqiobase &&
                    (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
                     ql2xmqsupport))
index a113ab3592a7f86eb16ce8f76d82337557cab029..cba1fc5e8be9d58fce789694b508734790689a83 100644 (file)
@@ -3676,15 +3676,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                                qlt_update_host_map(vha, id);
                        }
 
-                       fc_host_port_name(vha->host) =
-                           wwn_to_u64(vha->port_name);
-
-                       if (qla_ini_mode_enabled(vha))
-                               ql_dbg(ql_dbg_mbx, vha, 0x1018,
-                                   "FA-WWN portname %016llx (%x)\n",
-                                   fc_host_port_name(vha->host),
-                                   rptid_entry->vp_status);
-
                        set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
                        set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
                } else {
@@ -4821,9 +4812,9 @@ qla2x00_echo_test(scsi_qla_host_t *vha, struct msg_echo_lb *mreq,
 
        memset(mcp->mb, 0 , sizeof(mcp->mb));
        mcp->mb[0] = MBC_DIAGNOSTIC_ECHO;
-       mcp->mb[1] = mreq->options | BIT_6;     /* BIT_6 specifies 64bit address */
+       /* BIT_6 specifies 64bit address */
+       mcp->mb[1] = mreq->options | BIT_15 | BIT_6;
        if (IS_CNA_CAPABLE(ha)) {
-               mcp->mb[1] |= BIT_15;
                mcp->mb[2] = vha->fcoe_fcf_idx;
        }
        mcp->mb[16] = LSW(mreq->rcv_dma);
index 1c79579032835af29aefa337448f50548f7fb37d..79f050256c55c735c612c4553124ccf9e80fda0c 100644 (file)
@@ -630,29 +630,34 @@ qla2x00_sp_free_dma(void *ptr)
                sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
        }
 
+       if (!ctx)
+               goto end;
+
        if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
                /* List assured to be having elements */
-               qla2x00_clean_dsd_pool(ha, sp, NULL);
+               qla2x00_clean_dsd_pool(ha, ctx);
                sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
        }
 
        if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
-               dma_pool_free(ha->dl_dma_pool, ctx,
-                   ((struct crc_context *)ctx)->crc_ctx_dma);
+               struct crc_context *ctx0 = ctx;
+
+               dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma);
                sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
        }
 
        if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
-               struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx;
+               struct ct6_dsd *ctx1 = ctx;
 
                dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
-                       ctx1->fcp_cmnd_dma);
+                   ctx1->fcp_cmnd_dma);
                list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
                ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
                ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
                mempool_free(ctx1, ha->ctx_mempool);
        }
 
+end:
        CMD_SP(cmd) = NULL;
        qla2x00_rel_sp(sp);
 }
@@ -699,21 +704,24 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
                sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
        }
 
+       if (!ctx)
+               goto end;
+
        if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
                /* List assured to be having elements */
-               qla2x00_clean_dsd_pool(ha, sp, NULL);
+               qla2x00_clean_dsd_pool(ha, ctx);
                sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
        }
 
        if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
-               dma_pool_free(ha->dl_dma_pool, ctx,
-                   ((struct crc_context *)ctx)->crc_ctx_dma);
+               struct crc_context *ctx0 = ctx;
+
+               dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma);
                sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
        }
 
        if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
-               struct ct6_dsd *ctx1 = (struct ct6_dsd *)ctx;
-
+               struct ct6_dsd *ctx1 = ctx;
                dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
                    ctx1->fcp_cmnd_dma);
                list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
@@ -721,7 +729,7 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
                ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
                mempool_free(ctx1, ha->ctx_mempool);
        }
-
+end:
        CMD_SP(cmd) = NULL;
        qla2xxx_rel_qpair_sp(sp->qpair, sp);
 }
@@ -1632,7 +1640,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
 void
 qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
 {
-       int que, cnt;
+       int que, cnt, status;
        unsigned long flags;
        srb_t *sp;
        struct qla_hw_data *ha = vha->hw;
@@ -1662,8 +1670,12 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
                                         */
                                        sp_get(sp);
                                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
-                                       qla2xxx_eh_abort(GET_CMD_SP(sp));
+                                       status = qla2xxx_eh_abort(GET_CMD_SP(sp));
                                        spin_lock_irqsave(&ha->hardware_lock, flags);
+                                       /* Get rid of extra reference if immediate exit
+                                        * from ql2xxx_eh_abort */
+                                       if (status == FAILED && (qla2x00_isp_reg_stat(ha)))
+                                               atomic_dec(&sp->ref_count);
                                }
                                req->outstanding_cmds[cnt] = NULL;
                                sp->done(sp, res);
@@ -2623,10 +2635,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        if (mem_only) {
                if (pci_enable_device_mem(pdev))
-                       goto probe_out;
+                       return ret;
        } else {
                if (pci_enable_device(pdev))
-                       goto probe_out;
+                       return ret;
        }
 
        /* This may fail but that's ok */
@@ -2636,7 +2648,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!ha) {
                ql_log_pci(ql_log_fatal, pdev, 0x0009,
                    "Unable to allocate memory for ha.\n");
-               goto probe_out;
+               goto disable_device;
        }
        ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
            "Memory allocated for ha=%p.\n", ha);
@@ -3254,7 +3266,7 @@ iospace_config_failed:
        pci_release_selected_regions(ha->pdev, ha->bars);
        kfree(ha);
 
-probe_out:
+disable_device:
        pci_disable_device(pdev);
        return ret;
 }
index 0e03ca2ab3e52358c817cdd2cdc667ba2bfb1ba3..e766d8412384fd63ec598354cf6f75aa7a8decfe 100644 (file)
@@ -2245,11 +2245,13 @@ static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
                pci_unmap_sg(ha->pdev, cmd->prot_sg, cmd->prot_sg_cnt,
                        cmd->dma_data_direction);
 
+       if (!cmd->ctx)
+               return;
+
        if (cmd->ctx_dsd_alloced)
-               qla2x00_clean_dsd_pool(ha, NULL, cmd);
+               qla2x00_clean_dsd_pool(ha, cmd->ctx);
 
-       if (cmd->ctx)
-               dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma);
+       dma_pool_free(ha->dl_dma_pool, cmd->ctx, cmd->ctx->crc_ctx_dma);
 }
 
 static int qlt_check_reserve_free_req(struct scsi_qla_host *vha,
index 8a58ef3adab4425ba69a992dd2f51bd9357f44c9..c197972a3e2d465e1c64509c6c34839390ec1db7 100644 (file)
@@ -371,7 +371,7 @@ qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha,
                goto done;
        }
 
-       if (end <= start || start == 0 || end == 0) {
+       if (end < start || start == 0 || end == 0) {
                ql_dbg(ql_dbg_misc, vha, 0xd023,
                    "%s: unusable range (start=%x end=%x)\n", __func__,
                    ent->t262.end_addr, ent->t262.start_addr);
index 7bfbcfa7af40b7df8bff2a0f38728621ee9f13e0..61cdd99ae41ec7e45a0cf0de604be4e169172368 100644 (file)
@@ -763,6 +763,8 @@ struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost,
        struct scsi_device *sdev;
 
        list_for_each_entry(sdev, &shost->__devices, siblings) {
+               if (sdev->sdev_state == SDEV_DEL)
+                       continue;
                if (sdev->channel == channel && sdev->id == id &&
                                sdev->lun ==lun)
                        return sdev;
index 17249c3650fef2c414a009013efa4582d7ab9b8d..dc095a292c61b4ad64f63fcd9685d9e047acf7b6 100644 (file)
@@ -1404,7 +1404,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
        arr[4] = SDEBUG_LONG_INQ_SZ - 5;
        arr[5] = (int)have_dif_prot;    /* PROTECT bit */
        if (sdebug_vpd_use_hostno == 0)
-               arr[5] = 0x10; /* claim: implicit TGPS */
+               arr[5] |= 0x10; /* claim: implicit TPGS */
        arr[6] = 0x10; /* claim: MultiP */
        /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
        arr[7] = 0xa; /* claim: LINKED + CMDQUE */
index 814a4bd8405dca1a4897edd7f4cb66a163cb2545..99e16ac479e365d343840f44c9f7b0c50b4042cc 100644 (file)
@@ -30,6 +30,7 @@
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h> /* __scsi_init_queue() */
 #include <scsi/scsi_dh.h>
 
 #include <trace/events/scsi.h>
@@ -1850,7 +1851,7 @@ static int scsi_mq_prep_fn(struct request *req)
 
        /* zero out the cmd, except for the embedded scsi_request */
        memset((char *)cmd + sizeof(cmd->req), 0,
-               sizeof(*cmd) - sizeof(cmd->req));
+               sizeof(*cmd) - sizeof(cmd->req) + shost->hostt->cmd_size);
 
        req->special = cmd;
 
index f9d1432d7cc589360354c9d3fdbe4c0967e23ee6..b6bb4e0ce0e3288f321ef1319621063f02d6c868 100644 (file)
@@ -827,21 +827,32 @@ static int sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
        struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
        u64 sector = blk_rq_pos(rq) >> (ilog2(sdp->sector_size) - 9);
        u32 nr_sectors = blk_rq_sectors(rq) >> (ilog2(sdp->sector_size) - 9);
+       int ret;
 
        if (!(rq->cmd_flags & REQ_NOUNMAP)) {
                switch (sdkp->zeroing_mode) {
                case SD_ZERO_WS16_UNMAP:
-                       return sd_setup_write_same16_cmnd(cmd, true);
+                       ret = sd_setup_write_same16_cmnd(cmd, true);
+                       goto out;
                case SD_ZERO_WS10_UNMAP:
-                       return sd_setup_write_same10_cmnd(cmd, true);
+                       ret = sd_setup_write_same10_cmnd(cmd, true);
+                       goto out;
                }
        }
 
        if (sdp->no_write_same)
                return BLKPREP_INVALID;
+
        if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff)
-               return sd_setup_write_same16_cmnd(cmd, false);
-       return sd_setup_write_same10_cmnd(cmd, false);
+               ret = sd_setup_write_same16_cmnd(cmd, false);
+       else
+               ret = sd_setup_write_same10_cmnd(cmd, false);
+
+out:
+       if (sd_is_zoned(sdkp) && ret == BLKPREP_OK)
+               return sd_zbc_write_lock_zone(cmd);
+
+       return ret;
 }
 
 static void sd_config_write_same(struct scsi_disk *sdkp)
@@ -948,6 +959,10 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
        rq->__data_len = sdp->sector_size;
        ret = scsi_init_io(cmd);
        rq->__data_len = nr_bytes;
+
+       if (sd_is_zoned(sdkp) && ret != BLKPREP_OK)
+               sd_zbc_write_unlock_zone(cmd);
+
        return ret;
 }
 
@@ -1567,17 +1582,21 @@ out:
        return retval;
 }
 
-static int sd_sync_cache(struct scsi_disk *sdkp)
+static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
 {
        int retries, res;
        struct scsi_device *sdp = sdkp->device;
        const int timeout = sdp->request_queue->rq_timeout
                * SD_FLUSH_TIMEOUT_MULTIPLIER;
-       struct scsi_sense_hdr sshdr;
+       struct scsi_sense_hdr my_sshdr;
 
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
+       /* caller might not be interested in sense, but we need it */
+       if (!sshdr)
+               sshdr = &my_sshdr;
+
        for (retries = 3; retries > 0; --retries) {
                unsigned char cmd[10] = { 0 };
 
@@ -1586,7 +1605,7 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
                 * Leave the rest of the command zero to indicate
                 * flush everything.
                 */
-               res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
+               res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, sshdr,
                                timeout, SD_MAX_RETRIES, 0, RQF_PM, NULL);
                if (res == 0)
                        break;
@@ -1596,11 +1615,12 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
                sd_print_result(sdkp, "Synchronize Cache(10) failed", res);
 
                if (driver_byte(res) & DRIVER_SENSE)
-                       sd_print_sense_hdr(sdkp, &sshdr);
+                       sd_print_sense_hdr(sdkp, sshdr);
+
                /* we need to evaluate the error return  */
-               if (scsi_sense_valid(&sshdr) &&
-                       (sshdr.asc == 0x3a ||   /* medium not present */
-                        sshdr.asc == 0x20))    /* invalid command */
+               if (scsi_sense_valid(sshdr) &&
+                       (sshdr->asc == 0x3a ||  /* medium not present */
+                        sshdr->asc == 0x20))   /* invalid command */
                                /* this is no error here */
                                return 0;
 
@@ -3444,7 +3464,7 @@ static void sd_shutdown(struct device *dev)
 
        if (sdkp->WCE && sdkp->media_present) {
                sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
-               sd_sync_cache(sdkp);
+               sd_sync_cache(sdkp, NULL);
        }
 
        if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
@@ -3456,6 +3476,7 @@ static void sd_shutdown(struct device *dev)
 static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
 {
        struct scsi_disk *sdkp = dev_get_drvdata(dev);
+       struct scsi_sense_hdr sshdr;
        int ret = 0;
 
        if (!sdkp)      /* E.g.: runtime suspend following sd_remove() */
@@ -3463,12 +3484,23 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
 
        if (sdkp->WCE && sdkp->media_present) {
                sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
-               ret = sd_sync_cache(sdkp);
+               ret = sd_sync_cache(sdkp, &sshdr);
+
                if (ret) {
                        /* ignore OFFLINE device */
                        if (ret == -ENODEV)
-                               ret = 0;
-                       goto done;
+                               return 0;
+
+                       if (!scsi_sense_valid(&sshdr) ||
+                           sshdr.sense_key != ILLEGAL_REQUEST)
+                               return ret;
+
+                       /*
+                        * sshdr.sense_key == ILLEGAL_REQUEST means this drive
+                        * doesn't support sync. There's not much to do and
+                        * suspend shouldn't fail.
+                        */
+                        ret = 0;
                }
        }
 
@@ -3480,7 +3512,6 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
                        ret = 0;
        }
 
-done:
        return ret;
 }
 
index 0a38ba01b7b4aac2151faf88421c8f2645dbd86a..82c33a6edbeaa7a00e6f7840ef4b5d8cdb8a084f 100644 (file)
@@ -2074,11 +2074,12 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
                if ((1 == resp->done) && (!resp->sg_io_owned) &&
                    ((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
                        resp->done = 2; /* guard against other readers */
-                       break;
+                       write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+                       return resp;
                }
        }
        write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
-       return resp;
+       return NULL;
 }
 
 /* always adds to end of list */
index abc7e87937cc3087617ca404dc73b01b39ff7822..ffe8d86088181c7da9c30ad58986418842f7016d 100644 (file)
@@ -7698,6 +7698,12 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba)
        ufshcd_add_spm_lvl_sysfs_nodes(hba);
 }
 
+static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba)
+{
+       device_remove_file(hba->dev, &hba->rpm_lvl_attr);
+       device_remove_file(hba->dev, &hba->spm_lvl_attr);
+}
+
 /**
  * ufshcd_shutdown - shutdown routine
  * @hba: per adapter instance
@@ -7735,6 +7741,7 @@ EXPORT_SYMBOL(ufshcd_shutdown);
  */
 void ufshcd_remove(struct ufs_hba *hba)
 {
+       ufshcd_remove_sysfs_nodes(hba);
        scsi_remove_host(hba->host);
        /* disable interrupts */
        ufshcd_disable_intr(hba, hba->intr_mask);
index b6195fdf0d0033c7ec24afb9cff100cd5dcf0978..22e98a90468c8e35d50e0a1f0da0f73c177084f5 100644 (file)
@@ -49,7 +49,7 @@ static const struct of_device_id sun_top_ctrl_match[] = {
        { .compatible = "brcm,bcm7420-sun-top-ctrl", },
        { .compatible = "brcm,bcm7425-sun-top-ctrl", },
        { .compatible = "brcm,bcm7429-sun-top-ctrl", },
-       { .compatible = "brcm,bcm7425-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7435-sun-top-ctrl", },
        { .compatible = "brcm,brcmstb-sun-top-ctrl", },
        { }
 };
index 357a5d8f8da004d611058b24baa698fc3fbf159c..a5b86a28f343bb9c90c575310848b94855fcc3b4 100644 (file)
@@ -2,8 +2,9 @@ menu "i.MX SoC drivers"
 
 config IMX7_PM_DOMAINS
        bool "i.MX7 PM domains"
-       select PM_GENERIC_DOMAINS
        depends on SOC_IMX7D || (COMPILE_TEST && OF)
+       depends on PM
+       select PM_GENERIC_DOMAINS
        default y if SOC_IMX7D
 
 endmenu
index ecebe2eecc3aac5058de888817b719f42934d526..026182d3b27c1405a9b875d529795a2e8295a0aa 100644 (file)
@@ -413,7 +413,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name,
  * @name:      slave channel name
  * @config:    dma configuration parameters
  *
- * Returns pointer to appropriate DMA channel on success or NULL.
+ * Returns pointer to appropriate DMA channel on success or error.
  */
 void *knav_dma_open_channel(struct device *dev, const char *name,
                                        struct knav_dma_cfg *config)
index 1eb83c9613d59cb0a3ab709aea61516e59226c4a..78c885d80c961fe050ce2b6c05ccad713efd8502 100644 (file)
@@ -269,6 +269,7 @@ struct atmel_spi_caps {
        bool    is_spi2;
        bool    has_wdrbt;
        bool    has_dma_support;
+       bool    has_pdc_support;
 };
 
 /*
@@ -1426,7 +1427,28 @@ static void atmel_get_caps(struct atmel_spi *as)
 
        as->caps.is_spi2 = version > 0x121;
        as->caps.has_wdrbt = version >= 0x210;
+#ifdef CONFIG_SOC_SAM_V4_V5
+       /*
+        * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf()
+        * since this later function tries to map buffers with dma_map_sg()
+        * even if they have not been allocated inside DMA-safe areas.
+        * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for
+        * those ARM cores, the data cache follows the PIPT model.
+        * Also the L2 cache controller of SAMA5D2 uses the PIPT model too.
+        * In case of PIPT caches, there cannot be cache aliases.
+        * However on ARM9 cores, the data cache follows the VIVT model, hence
+        * the cache aliases issue can occur when buffers are allocated from
+        * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is
+        * not taken into account or at least not handled completely (cache
+        * lines of aliases are not invalidated).
+        * This is not a theorical issue: it was reproduced when trying to mount
+        * a UBI file-system on a at91sam9g35ek board.
+        */
+       as->caps.has_dma_support = false;
+#else
        as->caps.has_dma_support = version >= 0x212;
+#endif
+       as->caps.has_pdc_support = version < 0x212;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1567,7 +1589,7 @@ static int atmel_spi_probe(struct platform_device *pdev)
                } else if (ret == -EPROBE_DEFER) {
                        return ret;
                }
-       } else {
+       } else if (as->caps.has_pdc_support) {
                as->use_pdc = true;
        }
 
index 5514cd02e93a565d49b4429d6f4e35eb39b15991..4da2d4a524ca48075d7220737303274d559f064b 100644 (file)
@@ -484,6 +484,7 @@ static const struct of_device_id bcm63xx_hsspi_of_match[] = {
        { .compatible = "brcm,bcm6328-hsspi", },
        { },
 };
+MODULE_DEVICE_TABLE(of, bcm63xx_hsspi_of_match);
 
 static struct platform_driver bcm63xx_hsspi_driver = {
        .driver = {
index 15201645bdc4ffed5f8d88e19c3a4be7bef37d00..d89127f4a46dfd567e2c7cfb290833d038c930ed 100644 (file)
@@ -1032,7 +1032,8 @@ static int dspi_probe(struct platform_device *pdev)
                goto out_master_put;
 
        if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) {
-               if (dspi_request_dma(dspi, res->start)) {
+               ret = dspi_request_dma(dspi, res->start);
+               if (ret < 0) {
                        dev_err(&pdev->dev, "can't get dma channels\n");
                        goto out_clk_put;
                }
index 89254a55eb2e78c44e2a2c27bc693d9af623662b..7bb733d91519bc246027934814afab842df59757 100644 (file)
@@ -2021,7 +2021,7 @@ static void devm_spi_unregister(struct device *dev, void *res)
 }
 
 /**
- * dev_spi_register_master - register managed SPI master controller
+ * devm_spi_register_master - register managed SPI master controller
  * @dev:    device managing SPI master
  * @master: initialized master, originally from spi_alloc_master()
  * Context: can sleep
diff --git a/drivers/staging/android/ion/devicetree.txt b/drivers/staging/android/ion/devicetree.txt
deleted file mode 100644 (file)
index 1687152..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-Ion Memory Manager
-
-Ion is a memory manager that allows for sharing of buffers via dma-buf.
-Ion allows for different types of allocation via an abstraction called
-a 'heap'. A heap represents a specific type of memory. Each heap has
-a different type. There can be multiple instances of the same heap
-type.
-
-Specific heap instances are tied to heap IDs. Heap IDs are not to be specified
-in the devicetree.
-
-Required properties for Ion
-
-- compatible: "linux,ion" PLUS a compatible property for the device
-
-All child nodes of a linux,ion node are interpreted as heaps
-
-required properties for heaps
-
-- compatible: compatible string for a heap type PLUS a compatible property
-for the specific instance of the heap. Current heap types
--- linux,ion-heap-system
--- linux,ion-heap-system-contig
--- linux,ion-heap-carveout
--- linux,ion-heap-chunk
--- linux,ion-heap-dma
--- linux,ion-heap-custom
-
-Optional properties
-- memory-region: A phandle to a memory region. Required for DMA heap type
-(see reserved-memory.txt for details on the reservation)
-
-Example:
-
-       ion {
-               compatbile = "hisilicon,ion", "linux,ion";
-
-               ion-system-heap {
-                       compatbile = "hisilicon,system-heap", "linux,ion-heap-system"
-               };
-
-               ion-camera-region {
-                       compatible = "hisilicon,camera-heap", "linux,ion-heap-dma"
-                       memory-region = <&camera_region>;
-               };
-
-               ion-fb-region {
-                       compatbile = "hisilicon,fb-heap", "linux,ion-heap-dma"
-                       memory-region = <&fb_region>;
-               };
-       }
index ae627049c499aaaa716f80864a77f4dd796a6eaa..4be87f503e3be8f611fcd893edd53255032c93cd 100644 (file)
@@ -1,6 +1,6 @@
 config CRYPTO_DEV_CCREE
        tristate "Support for ARM TrustZone CryptoCell C7XX family of Crypto accelerators"
-       depends on CRYPTO_HW && OF && HAS_DMA
+       depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA
        default n
        select CRYPTO_HASH
        select CRYPTO_BLKCIPHER
index 038e2ff5e545f4b10e7c6ef34a30926aaffc5496..6471d3d2d3752ff52ff6f7ba064858b81bfed9a4 100644 (file)
@@ -216,7 +216,8 @@ void ssi_buffer_mgr_copy_scatterlist_portion(
        uint32_t nents, lbytes;
 
        nents = ssi_buffer_mgr_get_sgl_nents(sg, end, &lbytes, NULL);
-       sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip), 0, (direct == SSI_SG_TO_BUF));
+       sg_copy_buffer(sg, nents, (void *)dest, (end - to_skip + 1), to_skip,
+                      (direct == SSI_SG_TO_BUF));
 }
 
 static inline int ssi_buffer_mgr_render_buff_to_mlli(
index 522bd62c102eafe592349006206f2916ad67b15b..8611adf3bb2e9e8f42d5b210db9a0d20670085c2 100644 (file)
@@ -376,7 +376,6 @@ int send_request(
        rc = ssi_power_mgr_runtime_get(&drvdata->plat_dev->dev);
        if (rc != 0) {
                SSI_LOG_ERR("ssi_power_mgr_runtime_get returned %x\n",rc);
-               spin_unlock_bh(&req_mgr_h->hw_lock);
                return rc;
        }
 #endif
index 2e325cb747ae97bace5497964e27c76b49fe1f80..730fd6d4db33e9bb9fc607b0a6d1cbc26f7079b2 100644 (file)
@@ -12,6 +12,7 @@ config FSL_DPAA2
 config FSL_DPAA2_ETH
        tristate "Freescale DPAA2 Ethernet"
        depends on FSL_DPAA2 && FSL_MC_DPIO
+       depends on NETDEVICES && ETHERNET
        ---help---
          Ethernet driver for Freescale DPAA2 SoCs, using the
          Freescale MC bus driver
index dc6ecd8243659012629e5a2c1206861eec647eb3..ff10d1f0a7e452fb1f526395794caf0bd1ef26c4 100644 (file)
@@ -231,16 +231,12 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val)
        if (i >= ARRAY_SIZE(ad7152_filter_rate_table))
                i = ARRAY_SIZE(ad7152_filter_rate_table) - 1;
 
-       mutex_lock(&chip->state_lock);
        ret = i2c_smbus_write_byte_data(chip->client,
                                        AD7152_REG_CFG2, AD7152_CFG2_OSR(i));
-       if (ret < 0) {
-               mutex_unlock(&chip->state_lock);
+       if (ret < 0)
                return ret;
-       }
 
        chip->filter_rate_setup = i;
-       mutex_unlock(&chip->state_lock);
 
        return ret;
 }
index 2e1bd47337fd84954f37965b379f86d1d363b9d4..e6727cefde05bb536cb29f600edb7ab8312861ac 100644 (file)
@@ -293,18 +293,10 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm,
        size_t lmmk_size;
        size_t lum_size;
        int rc;
-       mm_segment_t seg;
 
        if (!lsm)
                return -ENODATA;
 
-       /*
-        * "Switch to kernel segment" to allow copying from kernel space by
-        * copy_{to,from}_user().
-        */
-       seg = get_fs();
-       set_fs(KERNEL_DS);
-
        if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) {
                CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n",
                       lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3);
@@ -406,6 +398,5 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm,
 out_free:
        kvfree(lmmk);
 out:
-       set_fs(seg);
        return rc;
 }
index 8ea01904c0eae72b9273919c0214510072e89813..466517c7c8e618112dcdea3716631be9f277d400 100644 (file)
@@ -19,5 +19,3 @@ obj-$(CONFIG_VIDEO_AP1302)     += ap1302.o
 
 obj-$(CONFIG_VIDEO_LM3554) += lm3554.o
 
-ccflags-y += -Werror
-
index 1d7f7ab94cac3b7ebf454b16a890dab9dc255314..6b13a3a66e49e3ee064887fa324685ddf05d1a0c 100644 (file)
@@ -4,5 +4,3 @@ imx1x5-objs := imx.o drv201.o ad5816g.o dw9714.o dw9719.o dw9718.o vcm.o otp.o o
 
 ov8858_driver-objs := ../ov8858.o dw9718.o vcm.o
 obj-$(CONFIG_VIDEO_OV8858)     += ov8858_driver.o
-
-ccflags-y += -Werror
index fceb9e9b881bac608e81ae76ed50dad139e2432e..c9c0e1245858470147768987c12de5727e68ad22 100644 (file)
@@ -1,3 +1 @@
 obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
-
-ccflags-y += -Werror
index 3fa7c1c1479f330367b7ab01bf41d8c502a69349..f126a89a08e93ff6511b603960285bfbe3a3c4f7 100644 (file)
@@ -351,5 +351,5 @@ DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -D__HOST__
 DEFINES += -DATOMISP_POSTFIX=\"css2400b0_v21\" -DISP2400B0
 DEFINES += -DSYSTEM_hive_isp_css_2400_system -DISP2400
 
-ccflags-y += $(INCLUDES) $(DEFINES) -fno-common -Werror
+ccflags-y += $(INCLUDES) $(DEFINES) -fno-common
 
index cfe37eb026d6d4418664b767c7b61473d79b1020..859d0d6051cdf6748d298a8f547aff141e5c55c6 100644 (file)
@@ -152,7 +152,7 @@ static const struct net_device_ops mon_netdev_ops = {
 static void mon_setup(struct net_device *dev)
 {
        dev->netdev_ops = &mon_netdev_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        ether_setup(dev);
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->type = ARPHRD_IEEE80211;
index 4723a0bd5067595fdbc38850887cdc69a947c59e..1c6ed5b2a6f96d1d227fb72d9b84f37776c4ece3 100644 (file)
@@ -97,8 +97,9 @@ void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
 
        switch (variable) {
        case HW_VAR_BSSID:
-               rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]);
-               rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
+               /* BSSIDR 2 byte alignment */
+               rtl92e_writew(dev, BSSIDR, *(u16 *)val);
+               rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(val + 2));
                break;
 
        case HW_VAR_MEDIA_STATUS:
@@ -624,7 +625,7 @@ void rtl92e_get_eeprom_size(struct net_device *dev)
        struct r8192_priv *priv = rtllib_priv(dev);
 
        RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
-       curCR = rtl92e_readl(dev, EPROM_CMD);
+       curCR = rtl92e_readw(dev, EPROM_CMD);
        RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
                 curCR);
        priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
@@ -961,8 +962,8 @@ static void _rtl92e_net_update(struct net_device *dev)
        rtl92e_config_rate(dev, &rate_config);
        priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
         priv->basic_rate = rate_config &= 0x15f;
-       rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]);
-       rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+       rtl92e_writew(dev, BSSIDR, *(u16 *)net->bssid);
+       rtl92e_writel(dev, BSSIDR + 2, *(u32 *)(net->bssid + 2));
 
        if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
                rtl92e_writew(dev, ATIMWND, 2);
@@ -1182,8 +1183,7 @@ void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
                          struct cb_desc *cb_desc, struct sk_buff *skb)
 {
        struct r8192_priv *priv = rtllib_priv(dev);
-       dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
-                        PCI_DMA_TODEVICE);
+       dma_addr_t mapping;
        struct tx_fwinfo_8190pci *pTxFwInfo;
 
        pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
@@ -1194,8 +1194,6 @@ void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
        pTxFwInfo->Short = _rtl92e_query_is_short(pTxFwInfo->TxHT,
                                                  pTxFwInfo->TxRate, cb_desc);
 
-       if (pci_dma_mapping_error(priv->pdev, mapping))
-               netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
        if (cb_desc->bAMPDUEnable) {
                pTxFwInfo->AllowAggregation = 1;
                pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1230,6 +1228,14 @@ void  rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
        }
 
        memset((u8 *)pdesc, 0, 12);
+
+       mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+                                PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(priv->pdev, mapping)) {
+               netdev_err(dev, "%s(): DMA Mapping error\n", __func__);
+               return;
+       }
+
        pdesc->LINIP = 0;
        pdesc->CmdInit = 1;
        pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
index 48bbd9e8a52f3444ff345a934a0721faf556ccc7..dcc4eb691889245e65927172a6e97a206d05fa6c 100644 (file)
@@ -306,11 +306,6 @@ static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
        pTsCommonInfo->TClasNum = TCLAS_Num;
 }
 
-static bool IsACValid(unsigned int tid)
-{
-       return tid < 7;
-}
-
 bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
           u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
 {
@@ -328,12 +323,6 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
        if (ieee->current_network.qos_data.supported == 0) {
                UP = 0;
        } else {
-               if (!IsACValid(TID)) {
-                       netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
-                                   __func__, TID);
-                       return false;
-               }
-
                switch (TID) {
                case 0:
                case 3:
@@ -351,6 +340,10 @@ bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
                case 7:
                        UP = 7;
                        break;
+               default:
+                       netdev_warn(ieee->dev, "%s(): TID(%d) is not valid\n",
+                                   __func__, TID);
+                       return false;
                }
        }
 
index 5e7a61f24f8dc38daea774986696ec6cc1d9ce9d..bd4352fe2de315a8b1f636a73d09974f0bcd6628 100644 (file)
@@ -2667,7 +2667,8 @@ static int rtw_cfg80211_add_monitor_if (struct adapter *padapter, char *name, st
        mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
        strncpy(mon_ndev->name, name, IFNAMSIZ);
        mon_ndev->name[IFNAMSIZ - 1] = 0;
-       mon_ndev->destructor = rtw_ndev_destructor;
+       mon_ndev->needs_free_netdev = true;
+       mon_ndev->priv_destructor = rtw_ndev_destructor;
 
        mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
 
@@ -3531,7 +3532,6 @@ int rtw_wdev_alloc(struct adapter *padapter, struct device *dev)
                pwdev_priv->power_mgmt = true;
        else
                pwdev_priv->power_mgmt = false;
-       kfree((u8 *)wdev);
 
        return ret;
 
index f83cfc76505c441392f8384bca9cfda850d1b273..021589913681075bbcaeb50cf97add2bf4228629 100644 (file)
@@ -1207,8 +1207,6 @@ void rtw_ndev_destructor(struct net_device *ndev)
 
        if (ndev->ieee80211_ptr)
                kfree((u8 *)ndev->ieee80211_ptr);
-
-       free_netdev(ndev);
 }
 
 void rtw_dev_unload(struct adapter *padapter)
index 02db59e8b593309e6e4b161d977178947cd24c57..aa16d1ab955b43ae57c1a317beb365b2cfd2d476 100644 (file)
@@ -160,7 +160,7 @@ static int isFileReadable(char *path)
                oldfs = get_fs(); set_fs(get_ds());
 
                if (1!=readFile(fp, &buf, 1))
-                       ret = PTR_ERR(fp);
+                       ret = -EINVAL;
 
                set_fs(oldfs);
                filp_close(fp, NULL);
index 2cee9a952c9b8d164fc3f94140ea6cb63e982d7a..4a356e509fe450b4260ac3b49ec001d4fa9aea7a 100644 (file)
@@ -264,22 +264,36 @@ static void fusb302_debugfs_exit(const struct fusb302_chip *chip) { }
 
 #define FUSB302_RESUME_RETRY 10
 #define FUSB302_RESUME_RETRY_SLEEP 50
-static int fusb302_i2c_write(struct fusb302_chip *chip,
-                            u8 address, u8 data)
+
+static bool fusb302_is_suspended(struct fusb302_chip *chip)
 {
        int retry_cnt;
-       int ret = 0;
 
-       atomic_set(&chip->i2c_busy, 1);
        for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
                if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
+                       dev_err(chip->dev, "i2c: pm suspend, retry %d/%d\n",
+                               retry_cnt + 1, FUSB302_RESUME_RETRY);
                        msleep(FUSB302_RESUME_RETRY_SLEEP);
                } else {
-                       break;
+                       return false;
                }
        }
+
+       return true;
+}
+
+static int fusb302_i2c_write(struct fusb302_chip *chip,
+                            u8 address, u8 data)
+{
+       int ret = 0;
+
+       atomic_set(&chip->i2c_busy, 1);
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
+       }
+
        ret = i2c_smbus_write_byte_data(chip->i2c_client, address, data);
        if (ret < 0)
                fusb302_log(chip, "cannot write 0x%02x to 0x%02x, ret=%d",
@@ -292,21 +306,17 @@ static int fusb302_i2c_write(struct fusb302_chip *chip,
 static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
                                   u8 length, const u8 *data)
 {
-       int retry_cnt;
        int ret = 0;
 
        if (length <= 0)
                return ret;
        atomic_set(&chip->i2c_busy, 1);
-       for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
-               if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
-                       msleep(FUSB302_RESUME_RETRY_SLEEP);
-               } else {
-                       break;
-               }
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
        }
+
        ret = i2c_smbus_write_i2c_block_data(chip->i2c_client, address,
                                             length, data);
        if (ret < 0)
@@ -320,19 +330,15 @@ static int fusb302_i2c_block_write(struct fusb302_chip *chip, u8 address,
 static int fusb302_i2c_read(struct fusb302_chip *chip,
                            u8 address, u8 *data)
 {
-       int retry_cnt;
        int ret = 0;
 
        atomic_set(&chip->i2c_busy, 1);
-       for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
-               if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
-                       msleep(FUSB302_RESUME_RETRY_SLEEP);
-               } else {
-                       break;
-               }
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
        }
+
        ret = i2c_smbus_read_byte_data(chip->i2c_client, address);
        *data = (u8)ret;
        if (ret < 0)
@@ -345,33 +351,31 @@ static int fusb302_i2c_read(struct fusb302_chip *chip,
 static int fusb302_i2c_block_read(struct fusb302_chip *chip, u8 address,
                                  u8 length, u8 *data)
 {
-       int retry_cnt;
        int ret = 0;
 
        if (length <= 0)
                return ret;
        atomic_set(&chip->i2c_busy, 1);
-       for (retry_cnt = 0; retry_cnt < FUSB302_RESUME_RETRY; retry_cnt++) {
-               if (atomic_read(&chip->pm_suspend)) {
-                       pr_err("fusb302_i2c: pm suspend, retry %d/%d\n",
-                              retry_cnt + 1, FUSB302_RESUME_RETRY);
-                       msleep(FUSB302_RESUME_RETRY_SLEEP);
-               } else {
-                       break;
-               }
+
+       if (fusb302_is_suspended(chip)) {
+               atomic_set(&chip->i2c_busy, 0);
+               return -ETIMEDOUT;
        }
+
        ret = i2c_smbus_read_i2c_block_data(chip->i2c_client, address,
                                            length, data);
        if (ret < 0) {
                fusb302_log(chip, "cannot block read 0x%02x, len=%d, ret=%d",
                            address, length, ret);
-               return ret;
+               goto done;
        }
        if (ret != length) {
                fusb302_log(chip, "only read %d/%d bytes from 0x%02x",
                            ret, length, address);
-               return -EIO;
+               ret = -EIO;
        }
+
+done:
        atomic_set(&chip->i2c_busy, 0);
 
        return ret;
@@ -489,7 +493,7 @@ static int tcpm_init(struct tcpc_dev *dev)
        ret = fusb302_i2c_read(chip, FUSB_REG_STATUS0, &data);
        if (ret < 0)
                return ret;
-       chip->vbus_present = !!(FUSB_REG_STATUS0 & FUSB_REG_STATUS0_VBUSOK);
+       chip->vbus_present = !!(data & FUSB_REG_STATUS0_VBUSOK);
        ret = fusb302_i2c_read(chip, FUSB_REG_DEVICE_ID, &data);
        if (ret < 0)
                return ret;
@@ -1025,7 +1029,7 @@ static int fusb302_pd_send_message(struct fusb302_chip *chip,
        buf[pos++] = FUSB302_TKN_SYNC1;
        buf[pos++] = FUSB302_TKN_SYNC2;
 
-       len = pd_header_cnt(msg->header) * 4;
+       len = pd_header_cnt_le(msg->header) * 4;
        /* plug 2 for header */
        len += 2;
        if (len > 0x1F) {
@@ -1481,7 +1485,7 @@ static int fusb302_pd_read_message(struct fusb302_chip *chip,
                                     (u8 *)&msg->header);
        if (ret < 0)
                return ret;
-       len = pd_header_cnt(msg->header) * 4;
+       len = pd_header_cnt_le(msg->header) * 4;
        /* add 4 to length to include the CRC */
        if (len > PD_MAX_PAYLOAD * 4) {
                fusb302_log(chip, "PD message too long %d", len);
@@ -1663,14 +1667,12 @@ static int init_gpio(struct fusb302_chip *chip)
        if (ret < 0) {
                fusb302_log(chip,
                            "cannot set GPIO Int_N to input, ret=%d", ret);
-               gpio_free(chip->gpio_int_n);
                return ret;
        }
        ret = gpio_to_irq(chip->gpio_int_n);
        if (ret < 0) {
                fusb302_log(chip,
                            "cannot request IRQ for GPIO Int_N, ret=%d", ret);
-               gpio_free(chip->gpio_int_n);
                return ret;
        }
        chip->gpio_int_n_irq = ret;
@@ -1787,11 +1789,13 @@ static const struct of_device_id fusb302_dt_match[] = {
        {.compatible = "fcs,fusb302"},
        {},
 };
+MODULE_DEVICE_TABLE(of, fusb302_dt_match);
 
 static const struct i2c_device_id fusb302_i2c_device_id[] = {
        {"typec_fusb302", 0},
        {},
 };
+MODULE_DEVICE_TABLE(i2c, fusb302_i2c_device_id);
 
 static const struct dev_pm_ops fusb302_pm_ops = {
        .suspend = fusb302_pm_suspend,
index 8d97bdb95f2385c7450cf093b8d7042d17520c15..510ef7279900617d5057f559b414239f99a36e03 100644 (file)
@@ -92,6 +92,16 @@ static inline unsigned int pd_header_type_le(__le16 header)
        return pd_header_type(le16_to_cpu(header));
 }
 
+static inline unsigned int pd_header_msgid(u16 header)
+{
+       return (header >> PD_HEADER_ID_SHIFT) & PD_HEADER_ID_MASK;
+}
+
+static inline unsigned int pd_header_msgid_le(__le16 header)
+{
+       return pd_header_msgid(le16_to_cpu(header));
+}
+
 #define PD_MAX_PAYLOAD         7
 
 struct pd_message {
index dba172e0e0d1faf52c9e9c287ef6c7e5be2e11da..d92259f8de0a835ad2a634d079e6d08ab327f654 100644 (file)
@@ -22,6 +22,9 @@
  * VDM object is minimum of VDM header + 6 additional data objects.
  */
 
+#define VDO_MAX_OBJECTS                6
+#define VDO_MAX_SIZE           (VDO_MAX_OBJECTS + 1)
+
 /*
  * VDM header
  * ----------
@@ -34,7 +37,6 @@
  * <5>      :: reserved (SVDM), command type (UVDM)
  * <4:0>    :: command
  */
-#define VDO_MAX_SIZE 7
 #define VDO(vid, type, custom)                         \
        (((vid) << 16) |                                \
         ((type) << 15) |                               \
index 5e5be74c7850032e4bd40705e1628e5cb14bb344..df72d8b01e730d5b2a9de183dbf9d64f662226f6 100644 (file)
@@ -425,7 +425,7 @@ static const struct regmap_config tcpci_regmap_config = {
        .max_register = 0x7F, /* 0x80 .. 0xFF are vendor defined */
 };
 
-const struct tcpc_config tcpci_tcpc_config = {
+static const struct tcpc_config tcpci_tcpc_config = {
        .type = TYPEC_PORT_DFP,
        .default_role = TYPEC_SINK,
 };
index abba655ba00a3469537c61070a747d276aa06cfa..20eb4ebcf8c3dba29f03fa58fa09169c281bf27c 100644 (file)
@@ -238,6 +238,7 @@ struct tcpm_port {
        unsigned int hard_reset_count;
        bool pd_capable;
        bool explicit_contract;
+       unsigned int rx_msgid;
 
        /* Partner capabilities/requests */
        u32 sink_request;
@@ -251,6 +252,8 @@ struct tcpm_port {
        unsigned int nr_src_pdo;
        u32 snk_pdo[PDO_MAX_OBJECTS];
        unsigned int nr_snk_pdo;
+       u32 snk_vdo[VDO_MAX_OBJECTS];
+       unsigned int nr_snk_vdo;
 
        unsigned int max_snk_mv;
        unsigned int max_snk_ma;
@@ -997,6 +1000,7 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
        struct pd_mode_data *modep;
        int rlen = 0;
        u16 svid;
+       int i;
 
        tcpm_log(port, "Rx VDM cmd 0x%x type %d cmd %d len %d",
                 p0, cmd_type, cmd, cnt);
@@ -1007,6 +1011,14 @@ static int tcpm_pd_svdm(struct tcpm_port *port, const __le32 *payload, int cnt,
        case CMDT_INIT:
                switch (cmd) {
                case CMD_DISCOVER_IDENT:
+                       /* 6.4.4.3.1: Only respond as UFP (device) */
+                       if (port->data_role == TYPEC_DEVICE &&
+                           port->nr_snk_vdo) {
+                               for (i = 0; i <  port->nr_snk_vdo; i++)
+                                       response[i + 1]
+                                               = cpu_to_le32(port->snk_vdo[i]);
+                               rlen = port->nr_snk_vdo + 1;
+                       }
                        break;
                case CMD_DISCOVER_SVID:
                        break;
@@ -1415,6 +1427,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                        break;
                case SOFT_RESET_SEND:
                        port->message_id = 0;
+                       port->rx_msgid = -1;
                        if (port->pwr_role == TYPEC_SOURCE)
                                next_state = SRC_SEND_CAPABILITIES;
                        else
@@ -1503,6 +1516,22 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
                 port->attached);
 
        if (port->attached) {
+               enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
+               unsigned int msgid = pd_header_msgid_le(msg->header);
+
+               /*
+                * USB PD standard, 6.6.1.2:
+                * "... if MessageID value in a received Message is the
+                * same as the stored value, the receiver shall return a
+                * GoodCRC Message with that MessageID value and drop
+                * the Message (this is a retry of an already received
+                * Message). Note: this shall not apply to the Soft_Reset
+                * Message which always has a MessageID value of zero."
+                */
+               if (msgid == port->rx_msgid && type != PD_CTRL_SOFT_RESET)
+                       goto done;
+               port->rx_msgid = msgid;
+
                /*
                 * If both ends believe to be DFP/host, we have a data role
                 * mismatch.
@@ -1520,6 +1549,7 @@ static void tcpm_pd_rx_handler(struct work_struct *work)
                }
        }
 
+done:
        mutex_unlock(&port->lock);
        kfree(event);
 }
@@ -1719,8 +1749,7 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo)
        }
        ma = min(ma, port->max_snk_ma);
 
-       /* XXX: Any other flags need to be set? */
-       flags = 0;
+       flags = RDO_USB_COMM | RDO_NO_SUSPEND;
 
        /* Set mismatch bit if offered power is less than operating power */
        mw = ma * mv / 1000;
@@ -1957,6 +1986,12 @@ static void tcpm_reset_port(struct tcpm_port *port)
        port->attached = false;
        port->pd_capable = false;
 
+       /*
+        * First Rx ID should be 0; set this to a sentinel of -1 so that
+        * we can check tcpm_pd_rx_handler() if we had seen it before.
+        */
+       port->rx_msgid = -1;
+
        port->tcpc->set_pd_rx(port->tcpc, false);
        tcpm_init_vbus(port);   /* also disables charging */
        tcpm_init_vconn(port);
@@ -2170,6 +2205,7 @@ static void run_state_machine(struct tcpm_port *port)
                port->pwr_opmode = TYPEC_PWR_MODE_USB;
                port->caps_count = 0;
                port->message_id = 0;
+               port->rx_msgid = -1;
                port->explicit_contract = false;
                tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
                break;
@@ -2329,6 +2365,7 @@ static void run_state_machine(struct tcpm_port *port)
                typec_set_pwr_opmode(port->typec_port, TYPEC_PWR_MODE_USB);
                port->pwr_opmode = TYPEC_PWR_MODE_USB;
                port->message_id = 0;
+               port->rx_msgid = -1;
                port->explicit_contract = false;
                tcpm_set_state(port, SNK_DISCOVERY, 0);
                break;
@@ -2496,6 +2533,7 @@ static void run_state_machine(struct tcpm_port *port)
        /* Soft_Reset states */
        case SOFT_RESET:
                port->message_id = 0;
+               port->rx_msgid = -1;
                tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
                if (port->pwr_role == TYPEC_SOURCE)
                        tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
@@ -2504,6 +2542,7 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case SOFT_RESET_SEND:
                port->message_id = 0;
+               port->rx_msgid = -1;
                if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
                        tcpm_set_state_cond(port, hard_reset_state(port), 0);
                else
@@ -2568,6 +2607,14 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case PR_SWAP_SRC_SNK_SOURCE_OFF:
                tcpm_set_cc(port, TYPEC_CC_RD);
+               /*
+                * USB-PD standard, 6.2.1.4, Port Power Role:
+                * "During the Power Role Swap Sequence, for the initial Source
+                * Port, the Port Power Role field shall be set to Sink in the
+                * PS_RDY Message indicating that the initial Source’s power
+                * supply is turned off"
+                */
+               tcpm_set_pwr_role(port, TYPEC_SINK);
                if (tcpm_pd_send_control(port, PD_CTRL_PS_RDY)) {
                        tcpm_set_state(port, ERROR_RECOVERY, 0);
                        break;
@@ -2575,7 +2622,6 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_state_cond(port, SNK_UNATTACHED, PD_T_PS_SOURCE_ON);
                break;
        case PR_SWAP_SRC_SNK_SINK_ON:
-               tcpm_set_pwr_role(port, TYPEC_SINK);
                tcpm_swap_complete(port, 0);
                tcpm_set_state(port, SNK_STARTUP, 0);
                break;
@@ -2587,8 +2633,15 @@ static void run_state_machine(struct tcpm_port *port)
        case PR_SWAP_SNK_SRC_SOURCE_ON:
                tcpm_set_cc(port, tcpm_rp_cc(port));
                tcpm_set_vbus(port, true);
-               tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
+               /*
+                * USB PD standard, 6.2.1.4:
+                * "Subsequent Messages initiated by the Policy Engine,
+                * such as the PS_RDY Message sent to indicate that Vbus
+                * is ready, will have the Port Power Role field set to
+                * Source."
+                */
                tcpm_set_pwr_role(port, TYPEC_SOURCE);
+               tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
                tcpm_swap_complete(port, 0);
                tcpm_set_state(port, SRC_STARTUP, 0);
                break;
@@ -3292,6 +3345,20 @@ static int tcpm_copy_pdos(u32 *dest_pdo, const u32 *src_pdo,
        return nr_pdo;
 }
 
+static int tcpm_copy_vdos(u32 *dest_vdo, const u32 *src_vdo,
+                         unsigned int nr_vdo)
+{
+       unsigned int i;
+
+       if (nr_vdo > VDO_MAX_OBJECTS)
+               nr_vdo = VDO_MAX_OBJECTS;
+
+       for (i = 0; i < nr_vdo; i++)
+               dest_vdo[i] = src_vdo[i];
+
+       return nr_vdo;
+}
+
 void tcpm_update_source_capabilities(struct tcpm_port *port, const u32 *pdo,
                                     unsigned int nr_pdo)
 {
@@ -3382,6 +3449,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
                                          tcpc->config->nr_src_pdo);
        port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo,
                                          tcpc->config->nr_snk_pdo);
+       port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo,
+                                         tcpc->config->nr_snk_vdo);
 
        port->max_snk_mv = tcpc->config->max_snk_mv;
        port->max_snk_ma = tcpc->config->max_snk_ma;
index 969b365e65497775f4481478641ab9f07cbbe2c4..19c307d31a5a39267abe546451c89f953ccc0945 100644 (file)
@@ -60,6 +60,9 @@ struct tcpc_config {
        const u32 *snk_pdo;
        unsigned int nr_snk_pdo;
 
+       const u32 *snk_vdo;
+       unsigned int nr_snk_vdo;
+
        unsigned int max_snk_mv;
        unsigned int max_snk_ma;
        unsigned int max_snk_mw;
index 988ee61fb4a7be9d4248c97c89f99ab947465fb0..d04db3f555192d58a9e1f0d9357b0b25578f1a91 100644 (file)
@@ -502,8 +502,15 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
         */
        sg_init_table(scatterlist, num_pages);
        /* Now set the pages for each scatterlist */
-       for (i = 0; i < num_pages; i++)
-               sg_set_page(scatterlist + i, pages[i], PAGE_SIZE, 0);
+       for (i = 0; i < num_pages; i++) {
+               unsigned int len = PAGE_SIZE - offset;
+
+               if (len > count)
+                       len = count;
+               sg_set_page(scatterlist + i, pages[i], len, offset);
+               offset = 0;
+               count -= len;
+       }
 
        dma_buffers = dma_map_sg(g_dev,
                                 scatterlist,
@@ -524,20 +531,20 @@ create_pagelist(char __user *buf, size_t count, unsigned short type,
                u32 addr = sg_dma_address(sg);
 
                /* Note: addrs is the address + page_count - 1
-                * The firmware expects the block to be page
+                * The firmware expects blocks after the first to be page-
                 * aligned and a multiple of the page size
                 */
                WARN_ON(len == 0);
-               WARN_ON(len & ~PAGE_MASK);
-               WARN_ON(addr & ~PAGE_MASK);
+               WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
+               WARN_ON(i && (addr & ~PAGE_MASK));
                if (k > 0 &&
-                   ((addrs[k - 1] & PAGE_MASK) |
-                       ((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT)
-                   == addr) {
-                       addrs[k - 1] += (len >> PAGE_SHIFT);
-               } else {
-                       addrs[k++] = addr | ((len >> PAGE_SHIFT) - 1);
-               }
+                   ((addrs[k - 1] & PAGE_MASK) +
+                    (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT))
+                   == (addr & PAGE_MASK))
+                       addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
+               else
+                       addrs[k++] = (addr & PAGE_MASK) |
+                               (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
        }
 
        /* Partial cache lines (fragments) require special measures */
index 26a9bcd5ee6a40c391195ef13e205d8d936c8a54..3fdca2cdd8da954b5a9c9d906c8b2d2b5e14f040 100644 (file)
@@ -1279,6 +1279,18 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
         */
        if (dump_payload)
                goto after_immediate_data;
+       /*
+        * Check for underflow case where both EDTL and immediate data payload
+        * exceeds what is presented by CDB's TRANSFER LENGTH, and what has
+        * already been set in target_cmd_size_check() as se_cmd->data_length.
+        *
+        * For this special case, fail the command and dump the immediate data
+        * payload.
+        */
+       if (cmd->first_burst_len > cmd->se_cmd.data_length) {
+               cmd->sense_reason = TCM_INVALID_CDB_FIELD;
+               goto after_immediate_data;
+       }
 
        immed_ret = iscsit_handle_immediate_data(cmd, hdr,
                                        cmd->first_burst_len);
@@ -3790,6 +3802,8 @@ int iscsi_target_tx_thread(void *arg)
 {
        int ret = 0;
        struct iscsi_conn *conn = arg;
+       bool conn_freed = false;
+
        /*
         * Allow ourselves to be interrupted by SIGINT so that a
         * connection recovery / failure event can be triggered externally.
@@ -3815,12 +3829,14 @@ get_immediate:
                        goto transport_err;
 
                ret = iscsit_handle_response_queue(conn);
-               if (ret == 1)
+               if (ret == 1) {
                        goto get_immediate;
-               else if (ret == -ECONNRESET)
+               } else if (ret == -ECONNRESET) {
+                       conn_freed = true;
                        goto out;
-               else if (ret < 0)
+               } else if (ret < 0) {
                        goto transport_err;
+               }
        }
 
 transport_err:
@@ -3830,8 +3846,13 @@ transport_err:
         * responsible for cleaning up the early connection failure.
         */
        if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
-               iscsit_take_action_for_connection_exit(conn);
+               iscsit_take_action_for_connection_exit(conn, &conn_freed);
 out:
+       if (!conn_freed) {
+               while (!kthread_should_stop()) {
+                       msleep(100);
+               }
+       }
        return 0;
 }
 
@@ -4004,6 +4025,7 @@ int iscsi_target_rx_thread(void *arg)
 {
        int rc;
        struct iscsi_conn *conn = arg;
+       bool conn_freed = false;
 
        /*
         * Allow ourselves to be interrupted by SIGINT so that a
@@ -4016,7 +4038,7 @@ int iscsi_target_rx_thread(void *arg)
         */
        rc = wait_for_completion_interruptible(&conn->rx_login_comp);
        if (rc < 0 || iscsi_target_check_conn_state(conn))
-               return 0;
+               goto out;
 
        if (!conn->conn_transport->iscsit_get_rx_pdu)
                return 0;
@@ -4025,7 +4047,15 @@ int iscsi_target_rx_thread(void *arg)
 
        if (!signal_pending(current))
                atomic_set(&conn->transport_failed, 1);
-       iscsit_take_action_for_connection_exit(conn);
+       iscsit_take_action_for_connection_exit(conn, &conn_freed);
+
+out:
+       if (!conn_freed) {
+               while (!kthread_should_stop()) {
+                       msleep(100);
+               }
+       }
+
        return 0;
 }
 
@@ -4405,8 +4435,11 @@ static void iscsit_logout_post_handler_closesession(
         * always sleep waiting for RX/TX thread shutdown to complete
         * within iscsit_close_connection().
         */
-       if (!conn->conn_transport->rdma_shutdown)
+       if (!conn->conn_transport->rdma_shutdown) {
                sleep = cmpxchg(&conn->tx_thread_active, true, false);
+               if (!sleep)
+                       return;
+       }
 
        atomic_set(&conn->conn_logout_remove, 0);
        complete(&conn->conn_logout_comp);
@@ -4422,8 +4455,11 @@ static void iscsit_logout_post_handler_samecid(
 {
        int sleep = 1;
 
-       if (!conn->conn_transport->rdma_shutdown)
+       if (!conn->conn_transport->rdma_shutdown) {
                sleep = cmpxchg(&conn->tx_thread_active, true, false);
+               if (!sleep)
+                       return;
+       }
 
        atomic_set(&conn->conn_logout_remove, 0);
        complete(&conn->conn_logout_comp);
index 9a96e17bf7cd5f7448c880ffafcaa123730ebe71..7fe2aa73cff69e04f8df8d79e3af1c634fb5ca04 100644 (file)
@@ -930,8 +930,10 @@ static void iscsit_handle_connection_cleanup(struct iscsi_conn *conn)
        }
 }
 
-void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
+void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn, bool *conn_freed)
 {
+       *conn_freed = false;
+
        spin_lock_bh(&conn->state_lock);
        if (atomic_read(&conn->connection_exit)) {
                spin_unlock_bh(&conn->state_lock);
@@ -942,6 +944,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
        if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
                spin_unlock_bh(&conn->state_lock);
                iscsit_close_connection(conn);
+               *conn_freed = true;
                return;
        }
 
@@ -955,4 +958,5 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
        spin_unlock_bh(&conn->state_lock);
 
        iscsit_handle_connection_cleanup(conn);
+       *conn_freed = true;
 }
index 60e69e2af6eda981efb74e4ac313fb0d031093bd..3822d9cd12302071467af03d4920fda601fdd351 100644 (file)
@@ -15,6 +15,6 @@ extern int iscsit_stop_time2retain_timer(struct iscsi_session *);
 extern void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *);
 extern void iscsit_cause_connection_reinstatement(struct iscsi_conn *, int);
 extern void iscsit_fall_back_to_erl0(struct iscsi_session *);
-extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *);
+extern void iscsit_take_action_for_connection_exit(struct iscsi_conn *, bool *);
 
 #endif   /*** ISCSI_TARGET_ERL0_H ***/
index 66238477137bc46d35cade3167451e19f2d401ce..92b96b51d5068e77c45d85a5a4d16efc9ffa5a93 100644 (file)
@@ -1464,5 +1464,9 @@ int iscsi_target_login_thread(void *arg)
                        break;
        }
 
+       while (!kthread_should_stop()) {
+               msleep(100);
+       }
+
        return 0;
 }
index 7ccc9c1cbfd1a664fb4c37a5dd71f305e735f4bb..6f88b31242b0562b297e60fdf61552719ed7a97c 100644 (file)
@@ -493,14 +493,60 @@ static void iscsi_target_restore_sock_callbacks(struct iscsi_conn *conn)
 
 static int iscsi_target_do_login(struct iscsi_conn *, struct iscsi_login *);
 
-static bool iscsi_target_sk_state_check(struct sock *sk)
+static bool __iscsi_target_sk_check_close(struct sock *sk)
 {
        if (sk->sk_state == TCP_CLOSE_WAIT || sk->sk_state == TCP_CLOSE) {
-               pr_debug("iscsi_target_sk_state_check: TCP_CLOSE_WAIT|TCP_CLOSE,"
+               pr_debug("__iscsi_target_sk_check_close: TCP_CLOSE_WAIT|TCP_CLOSE,"
                        "returning FALSE\n");
-               return false;
+               return true;
        }
-       return true;
+       return false;
+}
+
+static bool iscsi_target_sk_check_close(struct iscsi_conn *conn)
+{
+       bool state = false;
+
+       if (conn->sock) {
+               struct sock *sk = conn->sock->sk;
+
+               read_lock_bh(&sk->sk_callback_lock);
+               state = (__iscsi_target_sk_check_close(sk) ||
+                        test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags));
+               read_unlock_bh(&sk->sk_callback_lock);
+       }
+       return state;
+}
+
+static bool iscsi_target_sk_check_flag(struct iscsi_conn *conn, unsigned int flag)
+{
+       bool state = false;
+
+       if (conn->sock) {
+               struct sock *sk = conn->sock->sk;
+
+               read_lock_bh(&sk->sk_callback_lock);
+               state = test_bit(flag, &conn->login_flags);
+               read_unlock_bh(&sk->sk_callback_lock);
+       }
+       return state;
+}
+
+static bool iscsi_target_sk_check_and_clear(struct iscsi_conn *conn, unsigned int flag)
+{
+       bool state = false;
+
+       if (conn->sock) {
+               struct sock *sk = conn->sock->sk;
+
+               write_lock_bh(&sk->sk_callback_lock);
+               state = (__iscsi_target_sk_check_close(sk) ||
+                        test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags));
+               if (!state)
+                       clear_bit(flag, &conn->login_flags);
+               write_unlock_bh(&sk->sk_callback_lock);
+       }
+       return state;
 }
 
 static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login)
@@ -540,6 +586,20 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
 
        pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n",
                        conn, current->comm, current->pid);
+       /*
+        * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready()
+        * before initial PDU processing in iscsi_target_start_negotiation()
+        * has completed, go ahead and retry until it's cleared.
+        *
+        * Otherwise if the TCP connection drops while this is occuring,
+        * iscsi_target_start_negotiation() will detect the failure, call
+        * cancel_delayed_work_sync(&conn->login_work), and cleanup the
+        * remaining iscsi connection resources from iscsi_np process context.
+        */
+       if (iscsi_target_sk_check_flag(conn, LOGIN_FLAGS_INITIAL_PDU)) {
+               schedule_delayed_work(&conn->login_work, msecs_to_jiffies(10));
+               return;
+       }
 
        spin_lock(&tpg->tpg_state_lock);
        state = (tpg->tpg_state == TPG_STATE_ACTIVE);
@@ -547,26 +607,12 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
 
        if (!state) {
                pr_debug("iscsi_target_do_login_rx: tpg_state != TPG_STATE_ACTIVE\n");
-               iscsi_target_restore_sock_callbacks(conn);
-               iscsi_target_login_drop(conn, login);
-               iscsit_deaccess_np(np, tpg, tpg_np);
-               return;
+               goto err;
        }
 
-       if (conn->sock) {
-               struct sock *sk = conn->sock->sk;
-
-               read_lock_bh(&sk->sk_callback_lock);
-               state = iscsi_target_sk_state_check(sk);
-               read_unlock_bh(&sk->sk_callback_lock);
-
-               if (!state) {
-                       pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n");
-                       iscsi_target_restore_sock_callbacks(conn);
-                       iscsi_target_login_drop(conn, login);
-                       iscsit_deaccess_np(np, tpg, tpg_np);
-                       return;
-               }
+       if (iscsi_target_sk_check_close(conn)) {
+               pr_debug("iscsi_target_do_login_rx, TCP state CLOSE\n");
+               goto err;
        }
 
        conn->login_kworker = current;
@@ -584,34 +630,29 @@ static void iscsi_target_do_login_rx(struct work_struct *work)
        flush_signals(current);
        conn->login_kworker = NULL;
 
-       if (rc < 0) {
-               iscsi_target_restore_sock_callbacks(conn);
-               iscsi_target_login_drop(conn, login);
-               iscsit_deaccess_np(np, tpg, tpg_np);
-               return;
-       }
+       if (rc < 0)
+               goto err;
 
        pr_debug("iscsi_target_do_login_rx after rx_login_io, %p, %s:%d\n",
                        conn, current->comm, current->pid);
 
        rc = iscsi_target_do_login(conn, login);
        if (rc < 0) {
-               iscsi_target_restore_sock_callbacks(conn);
-               iscsi_target_login_drop(conn, login);
-               iscsit_deaccess_np(np, tpg, tpg_np);
+               goto err;
        } else if (!rc) {
-               if (conn->sock) {
-                       struct sock *sk = conn->sock->sk;
-
-                       write_lock_bh(&sk->sk_callback_lock);
-                       clear_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags);
-                       write_unlock_bh(&sk->sk_callback_lock);
-               }
+               if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_READ_ACTIVE))
+                       goto err;
        } else if (rc == 1) {
                iscsi_target_nego_release(conn);
                iscsi_post_login_handler(np, conn, zero_tsih);
                iscsit_deaccess_np(np, tpg, tpg_np);
        }
+       return;
+
+err:
+       iscsi_target_restore_sock_callbacks(conn);
+       iscsi_target_login_drop(conn, login);
+       iscsit_deaccess_np(np, tpg, tpg_np);
 }
 
 static void iscsi_target_do_cleanup(struct work_struct *work)
@@ -659,31 +700,54 @@ static void iscsi_target_sk_state_change(struct sock *sk)
                orig_state_change(sk);
                return;
        }
+       state = __iscsi_target_sk_check_close(sk);
+       pr_debug("__iscsi_target_sk_close_change: state: %d\n", state);
+
        if (test_bit(LOGIN_FLAGS_READ_ACTIVE, &conn->login_flags)) {
                pr_debug("Got LOGIN_FLAGS_READ_ACTIVE=1 sk_state_change"
                         " conn: %p\n", conn);
+               if (state)
+                       set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags);
                write_unlock_bh(&sk->sk_callback_lock);
                orig_state_change(sk);
                return;
        }
-       if (test_and_set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
+       if (test_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags)) {
                pr_debug("Got LOGIN_FLAGS_CLOSED=1 sk_state_change conn: %p\n",
                         conn);
                write_unlock_bh(&sk->sk_callback_lock);
                orig_state_change(sk);
                return;
        }
+       /*
+        * If the TCP connection has dropped, go ahead and set LOGIN_FLAGS_CLOSED,
+        * but only queue conn->login_work -> iscsi_target_do_login_rx()
+        * processing if LOGIN_FLAGS_INITIAL_PDU has already been cleared.
+        *
+        * When iscsi_target_do_login_rx() runs, iscsi_target_sk_check_close()
+        * will detect the dropped TCP connection from delayed workqueue context.
+        *
+        * If LOGIN_FLAGS_INITIAL_PDU is still set, which means the initial
+        * iscsi_target_start_negotiation() is running, iscsi_target_do_login()
+        * via iscsi_target_sk_check_close() or iscsi_target_start_negotiation()
+        * via iscsi_target_sk_check_and_clear() is responsible for detecting the
+        * dropped TCP connection in iscsi_np process context, and cleaning up
+        * the remaining iscsi connection resources.
+        */
+       if (state) {
+               pr_debug("iscsi_target_sk_state_change got failed state\n");
+               set_bit(LOGIN_FLAGS_CLOSED, &conn->login_flags);
+               state = test_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags);
+               write_unlock_bh(&sk->sk_callback_lock);
 
-       state = iscsi_target_sk_state_check(sk);
-       write_unlock_bh(&sk->sk_callback_lock);
-
-       pr_debug("iscsi_target_sk_state_change: state: %d\n", state);
+               orig_state_change(sk);
 
-       if (!state) {
-               pr_debug("iscsi_target_sk_state_change got failed state\n");
-               schedule_delayed_work(&conn->login_cleanup_work, 0);
+               if (!state)
+                       schedule_delayed_work(&conn->login_work, 0);
                return;
        }
+       write_unlock_bh(&sk->sk_callback_lock);
+
        orig_state_change(sk);
 }
 
@@ -946,6 +1010,15 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
                        if (iscsi_target_handle_csg_one(conn, login) < 0)
                                return -1;
                        if (login_rsp->flags & ISCSI_FLAG_LOGIN_TRANSIT) {
+                               /*
+                                * Check to make sure the TCP connection has not
+                                * dropped asynchronously while session reinstatement
+                                * was occuring in this kthread context, before
+                                * transitioning to full feature phase operation.
+                                */
+                               if (iscsi_target_sk_check_close(conn))
+                                       return -1;
+
                                login->tsih = conn->sess->tsih;
                                login->login_complete = 1;
                                iscsi_target_restore_sock_callbacks(conn);
@@ -972,21 +1045,6 @@ static int iscsi_target_do_login(struct iscsi_conn *conn, struct iscsi_login *lo
                break;
        }
 
-       if (conn->sock) {
-               struct sock *sk = conn->sock->sk;
-               bool state;
-
-               read_lock_bh(&sk->sk_callback_lock);
-               state = iscsi_target_sk_state_check(sk);
-               read_unlock_bh(&sk->sk_callback_lock);
-
-               if (!state) {
-                       pr_debug("iscsi_target_do_login() failed state for"
-                                " conn: %p\n", conn);
-                       return -1;
-               }
-       }
-
        return 0;
 }
 
@@ -1255,10 +1313,22 @@ int iscsi_target_start_negotiation(
 
                write_lock_bh(&sk->sk_callback_lock);
                set_bit(LOGIN_FLAGS_READY, &conn->login_flags);
+               set_bit(LOGIN_FLAGS_INITIAL_PDU, &conn->login_flags);
                write_unlock_bh(&sk->sk_callback_lock);
        }
-
+       /*
+        * If iscsi_target_do_login returns zero to signal more PDU
+        * exchanges are required to complete the login, go ahead and
+        * clear LOGIN_FLAGS_INITIAL_PDU but only if the TCP connection
+        * is still active.
+        *
+        * Otherwise if TCP connection dropped asynchronously, go ahead
+        * and perform connection cleanup now.
+        */
        ret = iscsi_target_do_login(conn, login);
+       if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU))
+               ret = -1;
+
        if (ret < 0) {
                cancel_delayed_work_sync(&conn->login_work);
                cancel_delayed_work_sync(&conn->login_cleanup_work);
index 9ab7090f7c839c6900cb30ddf7db1b8be4bc78cf..0912de7c0cf8f3ade048de694b4e75f77fe27acd 100644 (file)
@@ -136,7 +136,7 @@ int init_se_kmem_caches(void);
 void   release_se_kmem_caches(void);
 u32    scsi_get_new_index(scsi_index_t);
 void   transport_subsystem_check_init(void);
-void   transport_cmd_finish_abort(struct se_cmd *, int);
+int    transport_cmd_finish_abort(struct se_cmd *, int);
 unsigned char *transport_dump_cmd_direction(struct se_cmd *);
 void   transport_dump_dev_state(struct se_device *, char *, int *);
 void   transport_dump_dev_info(struct se_device *, struct se_lun *,
index dce1e1b47316173329292f90276843d26d32407b..13f47bf4d16b1d790ab470b92127254835e76078 100644 (file)
@@ -75,7 +75,7 @@ void core_tmr_release_req(struct se_tmr_req *tmr)
        kfree(tmr);
 }
 
-static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
+static int core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
 {
        unsigned long flags;
        bool remove = true, send_tas;
@@ -91,7 +91,7 @@ static void core_tmr_handle_tas_abort(struct se_cmd *cmd, int tas)
                transport_send_task_abort(cmd);
        }
 
-       transport_cmd_finish_abort(cmd, remove);
+       return transport_cmd_finish_abort(cmd, remove);
 }
 
 static int target_check_cdb_and_preempt(struct list_head *list,
@@ -184,8 +184,8 @@ void core_tmr_abort_task(
                cancel_work_sync(&se_cmd->work);
                transport_wait_for_tasks(se_cmd);
 
-               transport_cmd_finish_abort(se_cmd, true);
-               target_put_sess_cmd(se_cmd);
+               if (!transport_cmd_finish_abort(se_cmd, true))
+                       target_put_sess_cmd(se_cmd);
 
                printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
                                " ref_tag: %llu\n", ref_tag);
@@ -281,8 +281,8 @@ static void core_tmr_drain_tmr_list(
                cancel_work_sync(&cmd->work);
                transport_wait_for_tasks(cmd);
 
-               transport_cmd_finish_abort(cmd, 1);
-               target_put_sess_cmd(cmd);
+               if (!transport_cmd_finish_abort(cmd, 1))
+                       target_put_sess_cmd(cmd);
        }
 }
 
@@ -380,8 +380,8 @@ static void core_tmr_drain_state_list(
                cancel_work_sync(&cmd->work);
                transport_wait_for_tasks(cmd);
 
-               core_tmr_handle_tas_abort(cmd, tas);
-               target_put_sess_cmd(cmd);
+               if (!core_tmr_handle_tas_abort(cmd, tas))
+                       target_put_sess_cmd(cmd);
        }
 }
 
index 37f57357d4a0827f5669cb89d1619c4651192547..f1b3a46bdcaffaf8a301569ef7e328ad2c47087f 100644 (file)
@@ -651,9 +651,10 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
                percpu_ref_put(&lun->lun_ref);
 }
 
-void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
+int transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 {
        bool ack_kref = (cmd->se_cmd_flags & SCF_ACK_KREF);
+       int ret = 0;
 
        if (cmd->se_cmd_flags & SCF_SE_LUN_CMD)
                transport_lun_remove_cmd(cmd);
@@ -665,9 +666,11 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
                cmd->se_tfo->aborted_task(cmd);
 
        if (transport_cmd_check_stop_to_fabric(cmd))
-               return;
+               return 1;
        if (remove && ack_kref)
-               transport_put_cmd(cmd);
+               ret = transport_put_cmd(cmd);
+
+       return ret;
 }
 
 static void target_complete_failure_work(struct work_struct *work)
@@ -1160,15 +1163,28 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
        if (cmd->unknown_data_length) {
                cmd->data_length = size;
        } else if (size != cmd->data_length) {
-               pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
+               pr_warn_ratelimited("TARGET_CORE[%s]: Expected Transfer Length:"
                        " %u does not match SCSI CDB Length: %u for SAM Opcode:"
                        " 0x%02x\n", cmd->se_tfo->get_fabric_name(),
                                cmd->data_length, size, cmd->t_task_cdb[0]);
 
-               if (cmd->data_direction == DMA_TO_DEVICE &&
-                   cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
-                       pr_err("Rejecting underflow/overflow WRITE data\n");
-                       return TCM_INVALID_CDB_FIELD;
+               if (cmd->data_direction == DMA_TO_DEVICE) {
+                       if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
+                               pr_err_ratelimited("Rejecting underflow/overflow"
+                                                  " for WRITE data CDB\n");
+                               return TCM_INVALID_CDB_FIELD;
+                       }
+                       /*
+                        * Some fabric drivers like iscsi-target still expect to
+                        * always reject overflow writes.  Reject this case until
+                        * full fabric driver level support for overflow writes
+                        * is introduced tree-wide.
+                        */
+                       if (size > cmd->data_length) {
+                               pr_err_ratelimited("Rejecting overflow for"
+                                                  " WRITE control CDB\n");
+                               return TCM_INVALID_CDB_FIELD;
+                       }
                }
                /*
                 * Reject READ_* or WRITE_* with overflow/underflow for
index 9045837f748bd3b602256cfa9e83058ae92b8b33..beb5f098f32d6f7bb5851deb810065ab37e4ac4a 100644 (file)
@@ -97,7 +97,7 @@ struct tcmu_hba {
 
 struct tcmu_dev {
        struct list_head node;
-
+       struct kref kref;
        struct se_device se_dev;
 
        char *name;
@@ -969,6 +969,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
        udev = kzalloc(sizeof(struct tcmu_dev), GFP_KERNEL);
        if (!udev)
                return NULL;
+       kref_init(&udev->kref);
 
        udev->name = kstrdup(name, GFP_KERNEL);
        if (!udev->name) {
@@ -1145,6 +1146,24 @@ static int tcmu_open(struct uio_info *info, struct inode *inode)
        return 0;
 }
 
+static void tcmu_dev_call_rcu(struct rcu_head *p)
+{
+       struct se_device *dev = container_of(p, struct se_device, rcu_head);
+       struct tcmu_dev *udev = TCMU_DEV(dev);
+
+       kfree(udev->uio_info.name);
+       kfree(udev->name);
+       kfree(udev);
+}
+
+static void tcmu_dev_kref_release(struct kref *kref)
+{
+       struct tcmu_dev *udev = container_of(kref, struct tcmu_dev, kref);
+       struct se_device *dev = &udev->se_dev;
+
+       call_rcu(&dev->rcu_head, tcmu_dev_call_rcu);
+}
+
 static int tcmu_release(struct uio_info *info, struct inode *inode)
 {
        struct tcmu_dev *udev = container_of(info, struct tcmu_dev, uio_info);
@@ -1152,7 +1171,8 @@ static int tcmu_release(struct uio_info *info, struct inode *inode)
        clear_bit(TCMU_DEV_BIT_OPEN, &udev->flags);
 
        pr_debug("close\n");
-
+       /* release ref from configure */
+       kref_put(&udev->kref, tcmu_dev_kref_release);
        return 0;
 }
 
@@ -1272,6 +1292,12 @@ static int tcmu_configure_device(struct se_device *dev)
                dev->dev_attrib.hw_max_sectors = 128;
        dev->dev_attrib.hw_queue_depth = 128;
 
+       /*
+        * Get a ref incase userspace does a close on the uio device before
+        * LIO has initiated tcmu_free_device.
+        */
+       kref_get(&udev->kref);
+
        ret = tcmu_netlink_event(TCMU_CMD_ADDED_DEVICE, udev->uio_info.name,
                                 udev->uio_info.uio_dev->minor);
        if (ret)
@@ -1284,11 +1310,13 @@ static int tcmu_configure_device(struct se_device *dev)
        return 0;
 
 err_netlink:
+       kref_put(&udev->kref, tcmu_dev_kref_release);
        uio_unregister_device(&udev->uio_info);
 err_register:
        vfree(udev->mb_addr);
 err_vzalloc:
        kfree(info->name);
+       info->name = NULL;
 
        return ret;
 }
@@ -1302,14 +1330,6 @@ static int tcmu_check_and_free_pending_cmd(struct tcmu_cmd *cmd)
        return -EINVAL;
 }
 
-static void tcmu_dev_call_rcu(struct rcu_head *p)
-{
-       struct se_device *dev = container_of(p, struct se_device, rcu_head);
-       struct tcmu_dev *udev = TCMU_DEV(dev);
-
-       kfree(udev);
-}
-
 static bool tcmu_dev_configured(struct tcmu_dev *udev)
 {
        return udev->uio_info.uio_dev ? true : false;
@@ -1364,10 +1384,10 @@ static void tcmu_free_device(struct se_device *dev)
                                   udev->uio_info.uio_dev->minor);
 
                uio_unregister_device(&udev->uio_info);
-               kfree(udev->uio_info.name);
-               kfree(udev->name);
        }
-       call_rcu(&dev->rcu_head, tcmu_dev_call_rcu);
+
+       /* release ref from init */
+       kref_put(&udev->kref, tcmu_dev_kref_release);
 }
 
 enum {
index 2330a4eb4e8b71ff30103ba57de63fc868c34726..a6df12d88f90cd097ab88df8d151970243aea26b 100644 (file)
@@ -1,6 +1,7 @@
 # Generic Trusted Execution Environment Configuration
 config TEE
        tristate "Trusted Execution Environment support"
+       depends on HAVE_ARM_SMCCC || COMPILE_TEST
        select DMA_SHARED_BUFFER
        select GENERIC_ALLOCATOR
        help
index ab08af4654ef18c05d1ab9725dd96fb44f9264bf..42c098e86f849393eeb580e85fef1f93a14bdac7 100644 (file)
@@ -9,8 +9,9 @@ config BCM2835_THERMAL
 config BCM_NS_THERMAL
        tristate "Northstar thermal driver"
        depends on ARCH_BCM_IPROC || COMPILE_TEST
+       default y if ARCH_BCM_IPROC
        help
-         Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
-         BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
-         with a thermal sensor that allows checking CPU temperature. This
-         driver provides support for it.
+         Support for the Northstar and Northstar Plus family of SoCs (e.g.
+         BCM4708, BCM4709, BCM5301x, BCM95852X, etc). It contains DMU (Device
+         Management Unit) block with a thermal sensor that allows checking CPU
+         temperature.
index 644ba526d9ea09d2b1d0525cbf298cf10893cad0..4362a69ac88dcff8573e88e16fd6f3653432dd68 100644 (file)
@@ -195,7 +195,6 @@ static struct thermal_zone_of_device_ops tmu_tz_ops = {
 static int qoriq_tmu_probe(struct platform_device *pdev)
 {
        int ret;
-       const struct thermal_trip *trip;
        struct qoriq_tmu_data *data;
        struct device_node *np = pdev->dev.of_node;
        u32 site = 0;
@@ -243,8 +242,6 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
                goto err_tmu;
        }
 
-       trip = of_thermal_get_trip_points(data->tz);
-
        /* Enable monitoring */
        site |= 0x1 << (15 - data->sensor_id);
        tmu_write(data, site | TMR_ME | TMR_ALPF, &data->regs->tmr);
index b21b9cc2c8d6412897193a4ce53e295966737e9c..5a51c740e37238b31b9883d689aa67ffaea15704 100644 (file)
@@ -359,7 +359,7 @@ static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,
  * This may be called from any critical situation to trigger a system shutdown
  * after a known period of time. By default this is not scheduled.
  */
-void thermal_emergency_poweroff(void)
+static void thermal_emergency_poweroff(void)
 {
        int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
        /*
index ba9c302454fb398490046be46831c0a0f821788c..696ab3046b87d98cff65182f60499c98578175bd 100644 (file)
@@ -1010,7 +1010,7 @@ ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
 }
 
 /**
- * ti_bandgap_set_continous_mode() - One time enabling of continuous mode
+ * ti_bandgap_set_continuous_mode() - One time enabling of continuous mode
  * @bgp: pointer to struct ti_bandgap
  *
  * Call this function only if HAS(MODE_CONFIG) is set. As this driver may
@@ -1214,22 +1214,18 @@ static struct ti_bandgap *ti_bandgap_build(struct platform_device *pdev)
        }
 
        bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
-       if (!bgp) {
-               dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+       if (!bgp)
                return ERR_PTR(-ENOMEM);
-       }
 
        of_id = of_match_device(of_ti_bandgap_match, &pdev->dev);
        if (of_id)
                bgp->conf = of_id->data;
 
        /* register shadow for context save and restore */
-       bgp->regval = devm_kzalloc(&pdev->dev, sizeof(*bgp->regval) *
-                                  bgp->conf->sensor_count, GFP_KERNEL);
-       if (!bgp->regval) {
-               dev_err(&pdev->dev, "Unable to allocate mem for driver ref\n");
+       bgp->regval = devm_kcalloc(&pdev->dev, bgp->conf->sensor_count,
+                                  sizeof(*bgp->regval), GFP_KERNEL);
+       if (!bgp->regval)
                return ERR_PTR(-ENOMEM);
-       }
 
        i = 0;
        do {
index 7ac9bcdf1e61a551bb8286a48c0afc492e4a95ee..61fe8d6fd24e1bb0cf2cdfd2a4de67ceb05123bf 100644 (file)
@@ -764,7 +764,7 @@ static int __init ehv_bc_init(void)
        ehv_bc_driver = alloc_tty_driver(count);
        if (!ehv_bc_driver) {
                ret = -ENOMEM;
-               goto error;
+               goto err_free_bcs;
        }
 
        ehv_bc_driver->driver_name = "ehv-bc";
@@ -778,24 +778,23 @@ static int __init ehv_bc_init(void)
        ret = tty_register_driver(ehv_bc_driver);
        if (ret) {
                pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
-               goto error;
+               goto err_put_tty_driver;
        }
 
        ret = platform_driver_register(&ehv_bc_tty_driver);
        if (ret) {
                pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
                       ret);
-               goto error;
+               goto err_deregister_tty_driver;
        }
 
        return 0;
 
-error:
-       if (ehv_bc_driver) {
-               tty_unregister_driver(ehv_bc_driver);
-               put_tty_driver(ehv_bc_driver);
-       }
-
+err_deregister_tty_driver:
+       tty_unregister_driver(ehv_bc_driver);
+err_put_tty_driver:
+       put_tty_driver(ehv_bc_driver);
+err_free_bcs:
        kfree(bcs);
 
        return ret;
index 433de5ea9b02f53386b9367e64ad880ac6795e07..f71b47334149ace03ff276e41d8ecfd2a7038c6e 100644 (file)
@@ -122,6 +122,18 @@ void serdev_device_write_wakeup(struct serdev_device *serdev)
 }
 EXPORT_SYMBOL_GPL(serdev_device_write_wakeup);
 
+int serdev_device_write_buf(struct serdev_device *serdev,
+                           const unsigned char *buf, size_t count)
+{
+       struct serdev_controller *ctrl = serdev->ctrl;
+
+       if (!ctrl || !ctrl->ops->write_buf)
+               return -EINVAL;
+
+       return ctrl->ops->write_buf(ctrl, buf, count);
+}
+EXPORT_SYMBOL_GPL(serdev_device_write_buf);
+
 int serdev_device_write(struct serdev_device *serdev,
                        const unsigned char *buf, size_t count,
                        unsigned long timeout)
index 487c88f6aa0e36b5f986f5c02477e65f0f55143c..d0a021c93986252ceae888d7c26bde3eba295e9e 100644 (file)
@@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
                return PTR_ERR(tty);
        serport->tty = tty;
 
-       serport->port->client_ops = &client_ops;
-       serport->port->client_data = ctrl;
-
        if (tty->ops->open)
                tty->ops->open(serport->tty, NULL);
        else
@@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
                                        struct device *parent,
                                        struct tty_driver *drv, int idx)
 {
+       const struct tty_port_client_operations *old_ops;
        struct serdev_controller *ctrl;
        struct serport *serport;
        int ret;
@@ -233,28 +231,37 @@ struct device *serdev_tty_port_register(struct tty_port *port,
 
        ctrl->ops = &ctrl_ops;
 
+       old_ops = port->client_ops;
+       port->client_ops = &client_ops;
+       port->client_data = ctrl;
+
        ret = serdev_controller_add(ctrl);
        if (ret)
-               goto err_controller_put;
+               goto err_reset_data;
 
        dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
        return &ctrl->dev;
 
-err_controller_put:
+err_reset_data:
+       port->client_data = NULL;
+       port->client_ops = old_ops;
        serdev_controller_put(ctrl);
+
        return ERR_PTR(ret);
 }
 
-void serdev_tty_port_unregister(struct tty_port *port)
+int serdev_tty_port_unregister(struct tty_port *port)
 {
        struct serdev_controller *ctrl = port->client_data;
        struct serport *serport = serdev_controller_get_drvdata(ctrl);
 
        if (!serport)
-               return;
+               return -ENODEV;
 
        serdev_controller_remove(ctrl);
        port->client_ops = NULL;
        port->client_data = NULL;
        serdev_controller_put(ctrl);
+
+       return 0;
 }
index 09a65a3ec7f7df0bb3f7355fd7758d797169f960..68fd045a7025047726860547ecd661b95d61ac80 100644 (file)
@@ -47,6 +47,7 @@
 /*
  * These are definitions for the Exar XR17V35X and XR17(C|D)15X
  */
+#define UART_EXAR_INT0         0x80
 #define UART_EXAR_SLEEP                0x8b    /* Sleep mode */
 #define UART_EXAR_DVID         0x8d    /* Device identification */
 
@@ -1337,7 +1338,7 @@ out_lock:
        /*
         * Check if the device is a Fintek F81216A
         */
-       if (port->type == PORT_16550A)
+       if (port->type == PORT_16550A && port->iotype == UPIO_PORT)
                fintek_8250_probe(up);
 
        if (up->capabilities != old_capabilities) {
@@ -1869,17 +1870,13 @@ static int serial8250_default_handle_irq(struct uart_port *port)
 static int exar_handle_irq(struct uart_port *port)
 {
        unsigned int iir = serial_port_in(port, UART_IIR);
-       int ret;
+       int ret = 0;
 
-       ret = serial8250_handle_irq(port, iir);
+       if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) &&
+           serial_port_in(port, UART_EXAR_INT0) != 0)
+               ret = 1;
 
-       if ((port->type == PORT_XR17V35X) ||
-          (port->type == PORT_XR17D15X)) {
-               serial_port_in(port, 0x80);
-               serial_port_in(port, 0x81);
-               serial_port_in(port, 0x82);
-               serial_port_in(port, 0x83);
-       }
+       ret |= serial8250_handle_irq(port, iir);
 
        return ret;
 }
@@ -2177,6 +2174,8 @@ int serial8250_do_startup(struct uart_port *port)
        serial_port_in(port, UART_RX);
        serial_port_in(port, UART_IIR);
        serial_port_in(port, UART_MSR);
+       if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
+               serial_port_in(port, UART_EXAR_INT0);
 
        /*
         * At this point, there's no way the LSR could still be 0xff;
@@ -2335,6 +2334,8 @@ dont_test_tx_en:
        serial_port_in(port, UART_RX);
        serial_port_in(port, UART_IIR);
        serial_port_in(port, UART_MSR);
+       if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
+               serial_port_in(port, UART_EXAR_INT0);
        up->lsr_saved_flags = 0;
        up->msr_saved_flags = 0;
 
index 18e3f8342b8554ae4e7d414dd39653fb3a33b26f..0475f5d261cef6ee60f7bcd2e9cde6572a520c46 100644 (file)
@@ -478,6 +478,7 @@ static int altera_jtaguart_remove(struct platform_device *pdev)
 
        port = &altera_jtaguart_ports[i].port;
        uart_remove_one_port(&altera_jtaguart_driver, port);
+       iounmap(port->membase);
 
        return 0;
 }
index 46d3438a0d27014ce97115e7a17b0eb024f12035..3e4b717670d7432e32d4b66568900773f6e239ce 100644 (file)
@@ -615,6 +615,7 @@ static int altera_uart_remove(struct platform_device *pdev)
        if (port) {
                uart_remove_one_port(&altera_uart_driver, port);
                port->mapbase = 0;
+               iounmap(port->membase);
        }
 
        return 0;
index ebd8569f9ad5da126b2ff15985943e630135925a..9fff25be87f9db91273aa96e5b015705e7fd9118 100644 (file)
@@ -27,6 +27,7 @@
 #define UARTn_FRAME            0x04
 #define UARTn_FRAME_DATABITS__MASK     0x000f
 #define UARTn_FRAME_DATABITS(n)                ((n) - 3)
+#define UARTn_FRAME_PARITY__MASK       0x0300
 #define UARTn_FRAME_PARITY_NONE                0x0000
 #define UARTn_FRAME_PARITY_EVEN                0x0200
 #define UARTn_FRAME_PARITY_ODD         0x0300
@@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port,
                        16 * (4 + (clkdiv >> 6)));
 
        frame = efm32_uart_read32(efm_port, UARTn_FRAME);
-       if (frame & UARTn_FRAME_PARITY_ODD)
+       switch (frame & UARTn_FRAME_PARITY__MASK) {
+       case UARTn_FRAME_PARITY_ODD:
                *parity = 'o';
-       else if (frame & UARTn_FRAME_PARITY_EVEN)
+               break;
+       case UARTn_FRAME_PARITY_EVEN:
                *parity = 'e';
-       else
+               break;
+       default:
                *parity = 'n';
+       }
 
        *bits = (frame & UARTn_FRAME_DATABITS__MASK) -
                        UARTn_FRAME_DATABITS(4) + 4;
index 157883653256da9ebeae89d7dabead3285656c82..f190a84a02465668d64f3b6a57d6462588d781ad 100644 (file)
@@ -1382,9 +1382,9 @@ static struct spi_driver ifx_spi_driver = {
 static void __exit ifx_spi_exit(void)
 {
        /* unregister */
+       spi_unregister_driver(&ifx_spi_driver);
        tty_unregister_driver(tty_drv);
        put_tty_driver(tty_drv);
-       spi_unregister_driver(&ifx_spi_driver);
        unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
 }
 
index 33509b4beaec237715de1e8febd63e861fbb9c15..bbefddd92bfeae77b637033af8028ac481642931 100644 (file)
@@ -2184,7 +2184,9 @@ static int serial_imx_probe(struct platform_device *pdev)
                 * and DCD (when they are outputs) or enables the respective
                 * irqs. So set this bit early, i.e. before requesting irqs.
                 */
-               writel(UFCR_DCEDTE, sport->port.membase + UFCR);
+               reg = readl(sport->port.membase + UFCR);
+               if (!(reg & UFCR_DCEDTE))
+                       writel(reg | UFCR_DCEDTE, sport->port.membase + UFCR);
 
                /*
                 * Disable UCR3_RI and UCR3_DCD irqs. They are also not
@@ -2195,7 +2197,15 @@ static int serial_imx_probe(struct platform_device *pdev)
                       sport->port.membase + UCR3);
 
        } else {
-               writel(0, sport->port.membase + UFCR);
+               unsigned long ucr3 = UCR3_DSR;
+
+               reg = readl(sport->port.membase + UFCR);
+               if (reg & UFCR_DCEDTE)
+                       writel(reg & ~UFCR_DCEDTE, sport->port.membase + UFCR);
+
+               if (!is_imx1_uart(sport))
+                       ucr3 |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP;
+               writel(ucr3, sport->port.membase + UCR3);
        }
 
        clk_disable_unprepare(sport->clk_ipg);
index 0f45b7884a2c58a299668591e87bead1f6628f98..13bfd5dcffce5c0bfaee47879277e32aedf308a9 100644 (file)
@@ -2083,7 +2083,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
        mutex_lock(&port->mutex);
 
        tty_dev = device_find_child(uport->dev, &match, serial_match_port);
-       if (device_may_wakeup(tty_dev)) {
+       if (tty_dev && device_may_wakeup(tty_dev)) {
                if (!enable_irq_wake(uport->irq))
                        uport->irq_wake = 1;
                put_device(tty_dev);
@@ -2782,7 +2782,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
         * Register the port whether it's detected or not.  This allows
         * setserial to be used to alter this port's parameters.
         */
-       tty_dev = tty_port_register_device_attr(port, drv->tty_driver,
+       tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver,
                        uport->line, uport->dev, port, uport->tty_groups);
        if (likely(!IS_ERR(tty_dev))) {
                device_set_wakeup_capable(tty_dev, 1);
@@ -2845,7 +2845,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
        /*
         * Remove the devices from the tty layer
         */
-       tty_unregister_device(drv->tty_driver, uport->line);
+       tty_port_unregister_device(port, drv->tty_driver, uport->line);
 
        tty = tty_port_tty_get(port);
        if (tty) {
index 1d21a9c1d33e6e3c5ef007a25e4b4550fb62a51c..6b137194069fee47bc45b1866865ee27adfd33c5 100644 (file)
@@ -128,20 +128,86 @@ struct device *tty_port_register_device_attr(struct tty_port *port,
                struct tty_driver *driver, unsigned index,
                struct device *device, void *drvdata,
                const struct attribute_group **attr_grp)
+{
+       tty_port_link_device(port, driver, index);
+       return tty_register_device_attr(driver, index, device, drvdata,
+                       attr_grp);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+
+/**
+ * tty_port_register_device_attr_serdev - register tty or serdev device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ * @drvdata: driver data for the device
+ * @attr_grp: attribute group for the device
+ *
+ * Register a serdev or tty device depending on if the parent device has any
+ * defined serdev clients or not.
+ */
+struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
+               struct tty_driver *driver, unsigned index,
+               struct device *device, void *drvdata,
+               const struct attribute_group **attr_grp)
 {
        struct device *dev;
 
        tty_port_link_device(port, driver, index);
 
        dev = serdev_tty_port_register(port, device, driver, index);
-       if (PTR_ERR(dev) != -ENODEV)
+       if (PTR_ERR(dev) != -ENODEV) {
                /* Skip creating cdev if we registered a serdev device */
                return dev;
+       }
 
        return tty_register_device_attr(driver, index, device, drvdata,
                        attr_grp);
 }
-EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
+EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
+
+/**
+ * tty_port_register_device_serdev - register tty or serdev device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ * @device: parent if exists, otherwise NULL
+ *
+ * Register a serdev or tty device depending on if the parent device has any
+ * defined serdev clients or not.
+ */
+struct device *tty_port_register_device_serdev(struct tty_port *port,
+               struct tty_driver *driver, unsigned index,
+               struct device *device)
+{
+       return tty_port_register_device_attr_serdev(port, driver, index,
+                       device, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
+
+/**
+ * tty_port_unregister_device - deregister a tty or serdev device
+ * @port: tty_port of the device
+ * @driver: tty_driver for this device
+ * @index: index of the tty
+ *
+ * If a tty or serdev device is registered with a call to
+ * tty_port_register_device_serdev() then this function must be called when
+ * the device is gone.
+ */
+void tty_port_unregister_device(struct tty_port *port,
+               struct tty_driver *driver, unsigned index)
+{
+       int ret;
+
+       ret = serdev_tty_port_unregister(port);
+       if (ret == 0)
+               return;
+
+       tty_unregister_device(driver, index);
+}
+EXPORT_SYMBOL_GPL(tty_port_unregister_device);
 
 int tty_port_alloc_xmit_buf(struct tty_port *port)
 {
@@ -189,9 +255,6 @@ static void tty_port_destructor(struct kref *kref)
        /* check if last port ref was dropped before tty release */
        if (WARN_ON(port->itty))
                return;
-
-       serdev_tty_port_unregister(port);
-
        if (port->xmit_buf)
                free_page((unsigned long)port->xmit_buf);
        tty_port_destroy(port);
index 1c196f87e9d967886c88b1ae7fe05cc5f01ed4ee..ff04b7f8549f06f5730afb1cf6334785afab9d05 100644 (file)
@@ -279,7 +279,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
                map = kzalloc(sizeof(*map), GFP_KERNEL);
                if (!map) {
                        ret = -ENOMEM;
-                       goto err_map_kobj;
+                       goto err_map;
                }
                kobject_init(&map->kobj, &map_attr_type);
                map->mem = mem;
@@ -289,7 +289,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
                        goto err_map_kobj;
                ret = kobject_uevent(&map->kobj, KOBJ_ADD);
                if (ret)
-                       goto err_map;
+                       goto err_map_kobj;
        }
 
        for (pi = 0; pi < MAX_UIO_PORT_REGIONS; pi++) {
@@ -308,7 +308,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
                portio = kzalloc(sizeof(*portio), GFP_KERNEL);
                if (!portio) {
                        ret = -ENOMEM;
-                       goto err_portio_kobj;
+                       goto err_portio;
                }
                kobject_init(&portio->kobj, &portio_attr_type);
                portio->port = port;
@@ -319,7 +319,7 @@ static int uio_dev_add_attributes(struct uio_device *idev)
                        goto err_portio_kobj;
                ret = kobject_uevent(&portio->kobj, KOBJ_ADD);
                if (ret)
-                       goto err_portio;
+                       goto err_portio_kobj;
        }
 
        return 0;
index 9e217b1361ea76af9b9a5bb999b81559643e8e25..fe4fe24407296d52ba28a0408e39ba131b4e3737 100644 (file)
@@ -843,7 +843,10 @@ static ssize_t ci_role_show(struct device *dev, struct device_attribute *attr,
 {
        struct ci_hdrc *ci = dev_get_drvdata(dev);
 
-       return sprintf(buf, "%s\n", ci_role(ci)->name);
+       if (ci->role != CI_ROLE_END)
+               return sprintf(buf, "%s\n", ci_role(ci)->name);
+
+       return 0;
 }
 
 static ssize_t ci_role_store(struct device *dev,
index 6d23eede4d8cda5014b041f965f3e060d201be74..1c31e8a088101ff70d3aa37553d1e9b2d906b324 100644 (file)
@@ -294,7 +294,8 @@ static int ci_role_show(struct seq_file *s, void *data)
 {
        struct ci_hdrc *ci = s->private;
 
-       seq_printf(s, "%s\n", ci_role(ci)->name);
+       if (ci->role != CI_ROLE_END)
+               seq_printf(s, "%s\n", ci_role(ci)->name);
 
        return 0;
 }
index 56d2d32130765dfc655ecbb6e105f8d411070d1d..d68b125796f987d7133fef50fc8486363a5ef305 100644 (file)
@@ -1993,6 +1993,7 @@ static void udc_id_switch_for_host(struct ci_hdrc *ci)
 int ci_hdrc_gadget_init(struct ci_hdrc *ci)
 {
        struct ci_role_driver *rdrv;
+       int ret;
 
        if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DC))
                return -ENXIO;
@@ -2005,7 +2006,10 @@ int ci_hdrc_gadget_init(struct ci_hdrc *ci)
        rdrv->stop      = udc_id_switch_for_host;
        rdrv->irq       = udc_irq;
        rdrv->name      = "gadget";
-       ci->roles[CI_ROLE_GADGET] = rdrv;
 
-       return udc_start(ci);
+       ret = udc_start(ci);
+       if (!ret)
+               ci->roles[CI_ROLE_GADGET] = rdrv;
+
+       return ret;
 }
index e77a4ed4f021da17f5c1f366e22b8447c366474a..9f4a0185dd609c09f6873f85b849c9553821dca1 100644 (file)
@@ -108,6 +108,8 @@ struct imx_usbmisc {
        const struct usbmisc_ops *ops;
 };
 
+static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data);
+
 static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
 {
        struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
@@ -242,10 +244,15 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
                        val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
                                | MX53_USB_UHx_CTRL_ULPI_INT_EN;
                        writel(val, reg);
-                       /* Disable internal 60Mhz clock */
-                       reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
-                       val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
-                       writel(val, reg);
+                       if (is_imx53_usbmisc(data)) {
+                               /* Disable internal 60Mhz clock */
+                               reg = usbmisc->base +
+                                       MX53_USB_CLKONOFF_CTRL_OFFSET;
+                               val = readl(reg) |
+                                       MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
+                               writel(val, reg);
+                       }
+
                }
                if (data->disable_oc) {
                        reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
@@ -267,10 +274,15 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
                        val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
                                | MX53_USB_UHx_CTRL_ULPI_INT_EN;
                        writel(val, reg);
-                       /* Disable internal 60Mhz clock */
-                       reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
-                       val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
-                       writel(val, reg);
+
+                       if (is_imx53_usbmisc(data)) {
+                               /* Disable internal 60Mhz clock */
+                               reg = usbmisc->base +
+                                       MX53_USB_CLKONOFF_CTRL_OFFSET;
+                               val = readl(reg) |
+                                       MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
+                               writel(val, reg);
+                       }
                }
                if (data->disable_oc) {
                        reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
@@ -456,6 +468,10 @@ static const struct usbmisc_ops imx27_usbmisc_ops = {
        .init = usbmisc_imx27_init,
 };
 
+static const struct usbmisc_ops imx51_usbmisc_ops = {
+       .init = usbmisc_imx53_init,
+};
+
 static const struct usbmisc_ops imx53_usbmisc_ops = {
        .init = usbmisc_imx53_init,
 };
@@ -479,6 +495,13 @@ static const struct usbmisc_ops imx7d_usbmisc_ops = {
        .set_wakeup = usbmisc_imx7d_set_wakeup,
 };
 
+static inline bool is_imx53_usbmisc(struct imx_usbmisc_data *data)
+{
+       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+
+       return usbmisc->ops == &imx53_usbmisc_ops;
+}
+
 int imx_usbmisc_init(struct imx_usbmisc_data *data)
 {
        struct imx_usbmisc *usbmisc;
@@ -536,7 +559,7 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
        },
        {
                .compatible = "fsl,imx51-usbmisc",
-               .data = &imx53_usbmisc_ops,
+               .data = &imx51_usbmisc_ops,
        },
        {
                .compatible = "fsl,imx53-usbmisc",
index cfc3cff6e8d5901be03e89d1423c6f66aa6a7d06..8e6ef671be9b60f948e521d4c273228f161cdbb6 100644 (file)
@@ -475,11 +475,11 @@ static void snoop_urb(struct usb_device *udev,
 
        if (userurb) {          /* Async */
                if (when == SUBMIT)
-                       dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
+                       dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
                                        "length %u\n",
                                        userurb, ep, t, d, length);
                else
-                       dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
+                       dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
                                        "actual_length %u status %d\n",
                                        userurb, ep, t, d, length,
                                        timeout_or_status);
@@ -1895,7 +1895,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
        if (as) {
                int retval;
 
-               snoop(&ps->dev->dev, "reap %p\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
@@ -1912,7 +1912,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg)
 
        as = async_getcompleted(ps);
        if (as) {
-               snoop(&ps->dev->dev, "reap %p\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@ -2043,7 +2043,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
        if (as) {
                int retval;
 
-               snoop(&ps->dev->dev, "reap %p\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
@@ -2060,7 +2060,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar
 
        as = async_getcompleted(ps);
        if (as) {
-               snoop(&ps->dev->dev, "reap %p\n", as->userurb);
+               snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@ -2489,7 +2489,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
 #endif
 
        case USBDEVFS_DISCARDURB:
-               snoop(&dev->dev, "%s: DISCARDURB %p\n", __func__, p);
+               snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p);
                ret = proc_unlinkurb(ps, p);
                break;
 
index 49550790a3cba255df329dd73ca6e08e17a13af7..5dea98358c05c46b09f913fee8b7c48d9f2c4f85 100644 (file)
@@ -1723,7 +1723,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status)
                if (retval == 0)
                        retval = -EINPROGRESS;
                else if (retval != -EIDRM && retval != -EBUSY)
-                       dev_dbg(&udev->dev, "hcd_unlink_urb %p fail %d\n",
+                       dev_dbg(&udev->dev, "hcd_unlink_urb %pK fail %d\n",
                                        urb, retval);
                usb_put_dev(udev);
        }
@@ -1890,7 +1890,7 @@ rescan:
                /* kick hcd */
                unlink1(hcd, urb, -ESHUTDOWN);
                dev_dbg (hcd->self.controller,
-                       "shutdown urb %p ep%d%s%s\n",
+                       "shutdown urb %pK ep%d%s%s\n",
                        urb, usb_endpoint_num(&ep->desc),
                        is_in ? "in" : "out",
                        ({      char *s;
@@ -2520,6 +2520,7 @@ struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
                hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
                                GFP_KERNEL);
                if (!hcd->bandwidth_mutex) {
+                       kfree(hcd->address0_mutex);
                        kfree(hcd);
                        dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
                        return NULL;
index 9dca59ef18b3454437da9affb5e6d93619e88ba3..b8bb20d7acdb9f1480009605f10e2f5ae4045ec9 100644 (file)
@@ -362,7 +362,8 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
 }
 
 /* USB 2.0 spec Section 11.24.4.5 */
-static int get_hub_descriptor(struct usb_device *hdev, void *data)
+static int get_hub_descriptor(struct usb_device *hdev,
+               struct usb_hub_descriptor *desc)
 {
        int i, ret, size;
        unsigned dtype;
@@ -378,10 +379,18 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data)
        for (i = 0; i < 3; i++) {
                ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
-                       dtype << 8, 0, data, size,
+                       dtype << 8, 0, desc, size,
                        USB_CTRL_GET_TIMEOUT);
-               if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
+               if (hub_is_superspeed(hdev)) {
+                       if (ret == size)
+                               return ret;
+               } else if (ret >= USB_DT_HUB_NONVAR_SIZE + 2) {
+                       /* Make sure we have the DeviceRemovable field. */
+                       size = USB_DT_HUB_NONVAR_SIZE + desc->bNbrPorts / 8 + 1;
+                       if (ret < size)
+                               return -EMSGSIZE;
                        return ret;
+               }
        }
        return -EINVAL;
 }
@@ -1313,7 +1322,7 @@ static int hub_configure(struct usb_hub *hub,
        }
        mutex_init(&hub->status_mutex);
 
-       hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+       hub->descriptor = kzalloc(sizeof(*hub->descriptor), GFP_KERNEL);
        if (!hub->descriptor) {
                ret = -ENOMEM;
                goto fail;
@@ -1321,13 +1330,19 @@ static int hub_configure(struct usb_hub *hub,
 
        /* Request the entire hub descriptor.
         * hub->descriptor can handle USB_MAXCHILDREN ports,
-        * but the hub can/will return fewer bytes here.
+        * but a (non-SS) hub can/will return fewer bytes here.
         */
        ret = get_hub_descriptor(hdev, hub->descriptor);
        if (ret < 0) {
                message = "can't read hub descriptor";
                goto fail;
-       } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
+       }
+
+       maxchild = USB_MAXCHILDREN;
+       if (hub_is_superspeed(hdev))
+               maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS);
+
+       if (hub->descriptor->bNbrPorts > maxchild) {
                message = "hub has too many ports!";
                ret = -ENODEV;
                goto fail;
index d787f195a9a682c99e6289166d364d9aed110b2b..d563cbcf76cfbfb197aa1e45be1dc5f700102770 100644 (file)
@@ -53,6 +53,9 @@ EXPORT_SYMBOL_GPL(usb_of_get_child_node);
  *
  * Find the companion device from platform bus.
  *
+ * Takes a reference to the returned struct device which needs to be dropped
+ * after use.
+ *
  * Return: On success, a pointer to the companion device, %NULL on failure.
  */
 struct device *usb_of_get_companion_dev(struct device *dev)
index d75cb8c0f7df76ca1c78d1c39de9db17f9039af0..47903d510955b03967da9a125092b6965118c0be 100644 (file)
@@ -338,7 +338,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
        if (!urb || !urb->complete)
                return -EINVAL;
        if (urb->hcpriv) {
-               WARN_ONCE(1, "URB %p submitted while active\n", urb);
+               WARN_ONCE(1, "URB %pK submitted while active\n", urb);
                return -EBUSY;
        }
 
index 9cd8722f24f65994d83cdb0378387c021e773e5f..a3ffe97170ffd7ccdaf42cc892963ec22793d380 100644 (file)
@@ -144,6 +144,8 @@ const struct of_device_id dwc2_of_match_table[] = {
        { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params },
        { .compatible = "snps,dwc2" },
        { .compatible = "samsung,s3c6400-hsotg" },
+       { .compatible = "amlogic,meson8-usb",
+         .data = dwc2_set_amlogic_params },
        { .compatible = "amlogic,meson8b-usb",
          .data = dwc2_set_amlogic_params },
        { .compatible = "amlogic,meson-gxbb-usb",
index 72664700b8a25c7d9bcee89c16c68fa6b5792565..12ee23f53cdde17ea924344ff7e84d88cf9881cb 100644 (file)
@@ -107,6 +107,10 @@ static int kdwc3_probe(struct platform_device *pdev)
                return PTR_ERR(kdwc->usbss);
 
        kdwc->clk = devm_clk_get(kdwc->dev, "usb");
+       if (IS_ERR(kdwc->clk)) {
+               dev_err(kdwc->dev, "unable to get usb clock\n");
+               return PTR_ERR(kdwc->clk);
+       }
 
        error = clk_prepare_enable(kdwc->clk);
        if (error < 0) {
index a15ec71d04233a3ac9e93fe5d9063edb0a4d89af..84a2cebfc712023182dbb4622cbc355b3545310d 100644 (file)
@@ -39,6 +39,8 @@
 #define PCI_DEVICE_ID_INTEL_APL                        0x5aaa
 #define PCI_DEVICE_ID_INTEL_KBP                        0xa2b0
 #define PCI_DEVICE_ID_INTEL_GLK                        0x31aa
+#define PCI_DEVICE_ID_INTEL_CNPLP              0x9dee
+#define PCI_DEVICE_ID_INTEL_CNPH               0xa36e
 
 #define PCI_INTEL_BXT_DSM_UUID         "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
 #define PCI_INTEL_BXT_FUNC_PMU_PWR     4
@@ -270,6 +272,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPLP), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CNPH), },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
        {  }    /* Terminating Entry */
 };
index 6f6f0b3be3ad7a3491d244ff5648a3ef852479c4..aea9a5b948b4beda91988152b80ff666e8890b26 100644 (file)
@@ -1261,14 +1261,24 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                                __dwc3_gadget_start_isoc(dwc, dep, cur_uf);
                                dep->flags &= ~DWC3_EP_PENDING_REQUEST;
                        }
+                       return 0;
                }
-               return 0;
+
+               if ((dep->flags & DWC3_EP_BUSY) &&
+                   !(dep->flags & DWC3_EP_MISSED_ISOC)) {
+                       WARN_ON_ONCE(!dep->resource_index);
+                       ret = __dwc3_gadget_kick_transfer(dep,
+                                                         dep->resource_index);
+               }
+
+               goto out;
        }
 
        if (!dwc3_calc_trbs_left(dep))
                return 0;
 
        ret = __dwc3_gadget_kick_transfer(dep, 0);
+out:
        if (ret == -EBUSY)
                ret = 0;
 
@@ -3026,6 +3036,15 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
                return IRQ_HANDLED;
        }
 
+       /*
+        * With PCIe legacy interrupt, test shows that top-half irq handler can
+        * be called again after HW interrupt deassertion. Check if bottom-half
+        * irq event handler completes before caching new event to prevent
+        * losing events.
+        */
+       if (evt->flags & DWC3_EVENT_PENDING)
+               return IRQ_HANDLED;
+
        count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
        count &= DWC3_GEVNTCOUNT_MASK;
        if (!count)
index 49d685ad0da90d1a1282dd9d25f31ad64db22087..45b554032332e882e9bc99cb5489044053bd663c 100644 (file)
@@ -315,6 +315,9 @@ void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
        list_del(&f->list);
        if (f->unbind)
                f->unbind(c, f);
+
+       if (f->bind_deactivated)
+               usb_function_activate(f);
 }
 EXPORT_SYMBOL_GPL(usb_remove_function);
 
@@ -956,12 +959,8 @@ static void remove_config(struct usb_composite_dev *cdev,
 
                f = list_first_entry(&config->functions,
                                struct usb_function, list);
-               list_del(&f->list);
-               if (f->unbind) {
-                       DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
-                       f->unbind(config, f);
-                       /* may free memory for "f" */
-               }
+
+               usb_remove_function(config, f);
        }
        list_del(&config->list);
        if (config->unbind) {
index 71dd27c0d7f27daf9d2db08b6a0b72901844ba3f..47dda3450abd9391de37cf19115abfa0b927a402 100644 (file)
@@ -1858,12 +1858,12 @@ static int ffs_func_eps_enable(struct ffs_function *func)
                ep->ep->driver_data = ep;
                ep->ep->desc = ds;
 
-               comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
-                               USB_DT_ENDPOINT_SIZE);
-               ep->ep->maxburst = comp_desc->bMaxBurst + 1;
-
-               if (needs_comp_desc)
+               if (needs_comp_desc) {
+                       comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
+                                       USB_DT_ENDPOINT_SIZE);
+                       ep->ep->maxburst = comp_desc->bMaxBurst + 1;
                        ep->ep->comp_desc = comp_desc;
+               }
 
                ret = usb_ep_enable(ep->ep);
                if (likely(!ret)) {
index 4c8aacc232c07b300b5efffebe25999f8d9d244c..74d57d6994da1602ad72798aabc922ecbea9a0b1 100644 (file)
@@ -396,7 +396,11 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep)
 /* Caller must hold fsg->lock */
 static void wakeup_thread(struct fsg_common *common)
 {
-       smp_wmb();      /* ensure the write of bh->state is complete */
+       /*
+        * Ensure the reading of thread_wakeup_needed
+        * and the writing of bh->state are completed
+        */
+       smp_mb();
        /* Tell the main thread that something has happened */
        common->thread_wakeup_needed = 1;
        if (common->thread_task)
@@ -627,7 +631,12 @@ static int sleep_thread(struct fsg_common *common, bool can_freeze)
        }
        __set_current_state(TASK_RUNNING);
        common->thread_wakeup_needed = 0;
-       smp_rmb();      /* ensure the latest bh->state is visible */
+
+       /*
+        * Ensure the writing of thread_wakeup_needed
+        * and the reading of bh->state are completed
+        */
+       smp_mb();
        return rc;
 }
 
index b4058f0000e4878efae4a475f834d06f16679fdd..6a1ce6a551587f232207612404df80807af215cd 100644 (file)
@@ -281,7 +281,7 @@ static void pn_net_setup(struct net_device *dev)
        dev->tx_queue_len       = 1;
 
        dev->netdev_ops         = &pn_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->header_ops         = &phonet_header_ops;
 }
 
index 000677c991b0264ee079f46e79be1ab271001c9b..9b0805f55ad79b3a6b12069508ddc583d2765053 100644 (file)
@@ -1256,7 +1256,7 @@ static void gserial_console_exit(void)
        struct gscons_info *info = &gscons_info;
 
        unregister_console(&gserial_cons);
-       if (info->console_thread != NULL)
+       if (!IS_ERR_OR_NULL(info->console_thread))
                kthread_stop(info->console_thread);
        gs_buf_free(&info->con_buf);
 }
index b9ca0a26cbd93e540a2df8f78544adb81e298805..684900fcfe24c3c5ab206568f24da857434a654f 100644 (file)
@@ -1183,8 +1183,10 @@ dev_release (struct inode *inode, struct file *fd)
 
        /* closing ep0 === shutdown all */
 
-       if (dev->gadget_registered)
+       if (dev->gadget_registered) {
                usb_gadget_unregister_driver (&gadgetfs_driver);
+               dev->gadget_registered = false;
+       }
 
        /* at this point "good" hardware has disconnected the
         * device from USB; the host won't see it any more.
@@ -1677,9 +1679,10 @@ static void
 gadgetfs_suspend (struct usb_gadget *gadget)
 {
        struct dev_data         *dev = get_gadget_data (gadget);
+       unsigned long           flags;
 
        INFO (dev, "suspended from state %d\n", dev->state);
-       spin_lock (&dev->lock);
+       spin_lock_irqsave(&dev->lock, flags);
        switch (dev->state) {
        case STATE_DEV_SETUP:           // VERY odd... host died??
        case STATE_DEV_CONNECTED:
@@ -1690,7 +1693,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
        default:
                break;
        }
-       spin_unlock (&dev->lock);
+       spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 static struct usb_gadget_driver gadgetfs_driver = {
index c79081952ea068c770887298ed1c5483f0e61dac..7635fd7cc328caa371751d7a6ac15a5bb9ebdbae 100644 (file)
@@ -442,23 +442,16 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
                /* Report reset and disconnect events to the driver */
                if (dum->driver && (disconnect || reset)) {
                        stop_activity(dum);
-                       spin_unlock(&dum->lock);
                        if (reset)
                                usb_gadget_udc_reset(&dum->gadget, dum->driver);
                        else
                                dum->driver->disconnect(&dum->gadget);
-                       spin_lock(&dum->lock);
                }
        } else if (dum_hcd->active != dum_hcd->old_active) {
-               if (dum_hcd->old_active && dum->driver->suspend) {
-                       spin_unlock(&dum->lock);
+               if (dum_hcd->old_active && dum->driver->suspend)
                        dum->driver->suspend(&dum->gadget);
-                       spin_lock(&dum->lock);
-               } else if (!dum_hcd->old_active &&  dum->driver->resume) {
-                       spin_unlock(&dum->lock);
+               else if (!dum_hcd->old_active &&  dum->driver->resume)
                        dum->driver->resume(&dum->gadget);
-                       spin_lock(&dum->lock);
-               }
        }
 
        dum_hcd->old_status = dum_hcd->port_status;
@@ -983,7 +976,9 @@ static int dummy_udc_stop(struct usb_gadget *g)
        struct dummy_hcd        *dum_hcd = gadget_to_dummy_hcd(g);
        struct dummy            *dum = dum_hcd->dum;
 
+       spin_lock_irq(&dum->lock);
        dum->driver = NULL;
+       spin_unlock_irq(&dum->lock);
 
        return 0;
 }
@@ -2008,7 +2003,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc)
                        HUB_CHAR_COMMON_OCPM);
        desc->bNbrPorts = 1;
        desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
-       desc->u.ss.DeviceRemovable = 0xffff;
+       desc->u.ss.DeviceRemovable = 0;
 }
 
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
@@ -2020,8 +2015,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
                        HUB_CHAR_INDV_PORT_LPSM |
                        HUB_CHAR_COMMON_OCPM);
        desc->bNbrPorts = 1;
-       desc->u.hs.DeviceRemovable[0] = 0xff;
-       desc->u.hs.DeviceRemovable[1] = 0xff;
+       desc->u.hs.DeviceRemovable[0] = 0;
+       desc->u.hs.DeviceRemovable[1] = 0xff;   /* PortPwrCtrlMask */
 }
 
 static int dummy_hub_control(
index 6cf07857eacaa19b873b18c299079fd07507a5cf..f2cbd7f8005e149e028a11409aaa6aedc0716c36 100644 (file)
@@ -2470,11 +2470,8 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
                nuke(&dev->ep[i]);
 
        /* report disconnect; the driver is already quiesced */
-       if (driver) {
-               spin_unlock(&dev->lock);
+       if (driver)
                driver->disconnect(&dev->gadget);
-               spin_lock(&dev->lock);
-       }
 
        usb_reinit(dev);
 }
@@ -3348,8 +3345,6 @@ next_endpoints:
                BIT(PCI_RETRY_ABORT_INTERRUPT))
 
 static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
-__releases(dev->lock)
-__acquires(dev->lock)
 {
        struct net2280_ep       *ep;
        u32                     tmp, num, mask, scratch;
@@ -3390,14 +3385,12 @@ __acquires(dev->lock)
                        if (disconnect || reset) {
                                stop_activity(dev, dev->driver);
                                ep0_start(dev);
-                               spin_unlock(&dev->lock);
                                if (reset)
                                        usb_gadget_udc_reset
                                                (&dev->gadget, dev->driver);
                                else
                                        (dev->driver->disconnect)
                                                (&dev->gadget);
-                               spin_lock(&dev->lock);
                                return;
                        }
                }
index 5a2d845fb1a68708a3ea27b3822ae8de7afb85df..cd4c885297213bd3e1a5b024d0f2fdde3e6232d6 100644 (file)
@@ -623,7 +623,6 @@ static void renesas_usb3_stop_controller(struct renesas_usb3 *usb3)
 {
        usb3_disconnect(usb3);
        usb3_write(usb3, 0, USB3_P0_INT_ENA);
-       usb3_write(usb3, 0, USB3_PN_INT_ENA);
        usb3_write(usb3, 0, USB3_USB_OTG_INT_ENA);
        usb3_write(usb3, 0, USB3_USB_INT_ENA_1);
        usb3_write(usb3, 0, USB3_USB_INT_ENA_2);
@@ -1475,7 +1474,13 @@ static void usb3_request_done_pipen(struct renesas_usb3 *usb3,
                                    struct renesas_usb3_request *usb3_req,
                                    int status)
 {
-       usb3_pn_stop(usb3);
+       unsigned long flags;
+
+       spin_lock_irqsave(&usb3->lock, flags);
+       if (usb3_pn_change(usb3, usb3_ep->num))
+               usb3_pn_stop(usb3);
+       spin_unlock_irqrestore(&usb3->lock, flags);
+
        usb3_disable_pipe_irq(usb3, usb3_ep->num);
        usb3_request_done(usb3_ep, usb3_req, status);
 
@@ -1504,30 +1509,46 @@ static void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num)
 {
        struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
        struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
+       bool done = false;
 
        if (!usb3_req)
                return;
 
+       spin_lock(&usb3->lock);
+       if (usb3_pn_change(usb3, num))
+               goto out;
+
        if (usb3_ep->dir_in) {
                /* Do not stop the IN pipe here to detect LSTTR interrupt */
                if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE))
                        usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA);
        } else {
                if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ))
-                       usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
+                       done = true;
        }
+
+out:
+       /* need to unlock because usb3_request_done_pipen() locks it */
+       spin_unlock(&usb3->lock);
+
+       if (done)
+               usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
 }
 
 static void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num)
 {
        u32 pn_int_sta;
 
-       if (usb3_pn_change(usb3, num) < 0)
+       spin_lock(&usb3->lock);
+       if (usb3_pn_change(usb3, num) < 0) {
+               spin_unlock(&usb3->lock);
                return;
+       }
 
        pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA);
        pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA);
        usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA);
+       spin_unlock(&usb3->lock);
        if (pn_int_sta & PN_INT_LSTTR)
                usb3_irq_epc_pipen_lsttr(usb3, num);
        if (pn_int_sta & PN_INT_BFRDY)
@@ -1660,6 +1681,7 @@ static int usb3_disable_pipe_n(struct renesas_usb3_ep *usb3_ep)
 
        spin_lock_irqsave(&usb3->lock, flags);
        if (!usb3_pn_change(usb3, usb3_ep->num)) {
+               usb3_write(usb3, 0, USB3_PN_INT_ENA);
                usb3_write(usb3, 0, USB3_PN_RAMMAP);
                usb3_clear_bit(usb3, PN_CON_EN, USB3_PN_CON);
        }
@@ -1799,6 +1821,9 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
        /* hook up the driver */
        usb3->driver = driver;
 
+       pm_runtime_enable(usb3_to_dev(usb3));
+       pm_runtime_get_sync(usb3_to_dev(usb3));
+
        renesas_usb3_init_controller(usb3);
 
        return 0;
@@ -1807,14 +1832,14 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
 static int renesas_usb3_stop(struct usb_gadget *gadget)
 {
        struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
-       unsigned long flags;
 
-       spin_lock_irqsave(&usb3->lock, flags);
        usb3->softconnect = false;
        usb3->gadget.speed = USB_SPEED_UNKNOWN;
        usb3->driver = NULL;
        renesas_usb3_stop_controller(usb3);
-       spin_unlock_irqrestore(&usb3->lock, flags);
+
+       pm_runtime_put(usb3_to_dev(usb3));
+       pm_runtime_disable(usb3_to_dev(usb3));
 
        return 0;
 }
@@ -1891,9 +1916,6 @@ static int renesas_usb3_remove(struct platform_device *pdev)
 
        device_remove_file(&pdev->dev, &dev_attr_role);
 
-       pm_runtime_put(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
-
        usb_del_gadget_udc(&usb3->gadget);
 
        __renesas_usb3_ep_free_request(usb3->ep0_req);
@@ -2099,9 +2121,6 @@ static int renesas_usb3_probe(struct platform_device *pdev)
 
        usb3->workaround_for_vbus = priv->workaround_for_vbus;
 
-       pm_runtime_enable(&pdev->dev);
-       pm_runtime_get_sync(&pdev->dev);
-
        dev_info(&pdev->dev, "probed\n");
 
        return 0;
index bc7b9be12f540cb22dc3a5e9ab93aa49f4c722ef..f1908ea9fbd863f9d693d6a852e154e72087770c 100644 (file)
@@ -384,8 +384,10 @@ static int ehci_platform_resume(struct device *dev)
        }
 
        companion_dev = usb_of_get_companion_dev(hcd->self.controller);
-       if (companion_dev)
+       if (companion_dev) {
                device_pm_wait_for_dev(hcd->self.controller, companion_dev);
+               put_device(companion_dev);
+       }
 
        ehci_resume(hcd, priv->reset_on_resume);
        return 0;
index bfa7fa3d2eea0143b89298b3c722f9627af98fce..7bf78be1fd32503571df68999197008c85b64879 100644 (file)
@@ -1269,7 +1269,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
                        time = 30;
                        break;
                default:
-                       time = 300;
+                       time = 50;
                        break;
                }
 
@@ -1785,6 +1785,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597)
                pipe = td->pipe;
                pipe_stop(r8a66597, pipe);
 
+               /* Select a different address or endpoint */
                new_td = td;
                do {
                        list_move_tail(&new_td->queue,
@@ -1794,7 +1795,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597)
                                new_td = td;
                                break;
                        }
-               } while (td != new_td && td->address == new_td->address);
+               } while (td != new_td && td->address == new_td->address &&
+                       td->pipe->info.epnum == new_td->pipe->info.epnum);
 
                start_transfer(r8a66597, new_td);
 
index 5e3e9d4c6956bab71a815a86ef8e658cce12b48e..0dde49c35dd23d858feb2d537840b568fd1c4643 100644 (file)
@@ -419,7 +419,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend)
        wait_for_completion(cmd->completion);
 
        if (cmd->status == COMP_COMMAND_ABORTED ||
-                       cmd->status == COMP_STOPPED) {
+           cmd->status == COMP_COMMAND_RING_STOPPED) {
                xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
                ret = -ETIME;
        }
index bbe22bcc550a7f2641c8be1f379510c2ba0d9162..fddf2731f798ea3a05a5b18bae7749c064eb4af7 100644 (file)
@@ -56,7 +56,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
        }
 
        if (max_packet) {
-               seg->bounce_buf = kzalloc(max_packet, flags | GFP_DMA);
+               seg->bounce_buf = kzalloc(max_packet, flags);
                if (!seg->bounce_buf) {
                        dma_pool_free(xhci->segment_pool, seg->trbs, dma);
                        kfree(seg);
@@ -1724,7 +1724,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
        xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
        for (i = 0; i < num_sp; i++) {
                dma_addr_t dma;
-               void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma,
+               void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma,
                                flags);
                if (!buf)
                        goto fail_sp4;
@@ -2119,11 +2119,12 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 {
        u32 temp, port_offset, port_count;
        int i;
-       u8 major_revision;
+       u8 major_revision, minor_revision;
        struct xhci_hub *rhub;
 
        temp = readl(addr);
        major_revision = XHCI_EXT_PORT_MAJOR(temp);
+       minor_revision = XHCI_EXT_PORT_MINOR(temp);
 
        if (major_revision == 0x03) {
                rhub = &xhci->usb3_rhub;
@@ -2137,7 +2138,9 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                return;
        }
        rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
-       rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
+
+       if (rhub->min_rev < minor_revision)
+               rhub->min_rev = minor_revision;
 
        /* Port offset and count in the third dword, see section 7.2 */
        temp = readl(addr + 2);
@@ -2307,10 +2310,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
        /* Place limits on the number of roothub ports so that the hub
         * descriptors aren't longer than the USB core will allocate.
         */
-       if (xhci->num_usb3_ports > 15) {
+       if (xhci->num_usb3_ports > USB_SS_MAXPORTS) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-                               "Limiting USB 3.0 roothub ports to 15.");
-               xhci->num_usb3_ports = 15;
+                               "Limiting USB 3.0 roothub ports to %u.",
+                               USB_SS_MAXPORTS);
+               xhci->num_usb3_ports = USB_SS_MAXPORTS;
        }
        if (xhci->num_usb2_ports > USB_MAXCHILDREN) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_init,
index 7b86508ac8cf522e1143561a6e9a7d8f40f5a964..1bcf971141c09a69f3cd1674cca282bcc6ec8d46 100644 (file)
@@ -52,6 +52,7 @@
 #define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI             0x0aa8
 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI             0x1aa8
 #define PCI_DEVICE_ID_INTEL_APL_XHCI                   0x5aa8
+#define PCI_DEVICE_ID_INTEL_DNV_XHCI                   0x19d0
 
 static const char hcd_name[] = "xhci_hcd";
 
@@ -166,7 +167,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI ||
-                pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) {
+                pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) {
                xhci->quirks |= XHCI_PME_STUCK_QUIRK;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
@@ -175,7 +177,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
            (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
-            pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
+            pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
+            pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
                xhci->quirks |= XHCI_MISSING_CAS;
 
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
@@ -198,6 +201,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
                        pdev->device == 0x1042)
                xhci->quirks |= XHCI_BROKEN_STREAMS;
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+                       pdev->device == 0x1142)
+               xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
        if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
                xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
index 7c2a9e7c8e0f2aa4d5cc7f5e413f23ccc75c116d..c04144b25a673a2f2438854ea4183dd7cc0b0fab 100644 (file)
@@ -177,7 +177,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
-               return -ENODEV;
+               return irq;
 
        /*
         * sysdev must point to a device that is known to the system firmware
index 74bf5c60a26075fff92cf74f6d3b2a2d4af4f0d4..03f63f50afb6213d58b498f559021db28f8a4d5a 100644 (file)
@@ -323,7 +323,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
                if (i_cmd->status != COMP_COMMAND_ABORTED)
                        continue;
 
-               i_cmd->status = COMP_STOPPED;
+               i_cmd->status = COMP_COMMAND_RING_STOPPED;
 
                xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
                         i_cmd->command_trb);
@@ -641,8 +641,8 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
        xhci_urb_free_priv(urb_priv);
        usb_hcd_unlink_urb_from_ep(hcd, urb);
        spin_unlock(&xhci->lock);
-       usb_hcd_giveback_urb(hcd, urb, status);
        trace_xhci_urb_giveback(urb);
+       usb_hcd_giveback_urb(hcd, urb, status);
        spin_lock(&xhci->lock);
 }
 
@@ -1380,7 +1380,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
        cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
 
        /* If CMD ring stopped we own the trbs between enqueue and dequeue */
-       if (cmd_comp_code == COMP_STOPPED) {
+       if (cmd_comp_code == COMP_COMMAND_RING_STOPPED) {
                complete_all(&xhci->cmd_ring_stop_completion);
                return;
        }
@@ -1436,8 +1436,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
                break;
        case TRB_CMD_NOOP:
                /* Is this an aborted command turned to NO-OP? */
-               if (cmd->status == COMP_STOPPED)
-                       cmd_comp_code = COMP_STOPPED;
+               if (cmd->status == COMP_COMMAND_RING_STOPPED)
+                       cmd_comp_code = COMP_COMMAND_RING_STOPPED;
                break;
        case TRB_RESET_EP:
                WARN_ON(slot_id != TRB_TO_SLOT_ID(
@@ -2677,11 +2677,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        union xhci_trb *event_ring_deq;
        irqreturn_t ret = IRQ_NONE;
+       unsigned long flags;
        dma_addr_t deq;
        u64 temp_64;
        u32 status;
 
-       spin_lock(&xhci->lock);
+       spin_lock_irqsave(&xhci->lock, flags);
        /* Check if the xHC generated the interrupt, or the irq is shared */
        status = readl(&xhci->op_regs->status);
        if (status == ~(u32)0) {
@@ -2707,12 +2708,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
         */
        status |= STS_EINT;
        writel(status, &xhci->op_regs->status);
-       /* FIXME when MSI-X is supported and there are multiple vectors */
-       /* Clear the MSI-X event interrupt status */
 
-       if (hcd->irq) {
+       if (!hcd->msi_enabled) {
                u32 irq_pending;
-               /* Acknowledge the PCI interrupt */
                irq_pending = readl(&xhci->ir_set->irq_pending);
                irq_pending |= IMAN_IP;
                writel(irq_pending, &xhci->ir_set->irq_pending);
@@ -2757,7 +2755,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
        ret = IRQ_HANDLED;
 
 out:
-       spin_unlock(&xhci->lock);
+       spin_unlock_irqrestore(&xhci->lock, flags);
 
        return ret;
 }
index 2d1310220832c3792f7290f1095e8bd23ea71fd2..30f47d92a6104ef52ae5e782e1f305fa0a517cad 100644 (file)
@@ -359,9 +359,10 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
                /* fall back to msi*/
                ret = xhci_setup_msi(xhci);
 
-       if (!ret)
-               /* hcd->irq is 0, we have MSI */
+       if (!ret) {
+               hcd->msi_enabled = 1;
                return 0;
+       }
 
        if (!pdev->irq) {
                xhci_err(xhci, "No msi-x/msi found and no IRQ in BIOS\n");
@@ -1763,7 +1764,7 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
 
        switch (*cmd_status) {
        case COMP_COMMAND_ABORTED:
-       case COMP_STOPPED:
+       case COMP_COMMAND_RING_STOPPED:
                xhci_warn(xhci, "Timeout while waiting for configure endpoint command\n");
                ret = -ETIME;
                break;
@@ -1813,7 +1814,7 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
 
        switch (*cmd_status) {
        case COMP_COMMAND_ABORTED:
-       case COMP_STOPPED:
+       case COMP_COMMAND_RING_STOPPED:
                xhci_warn(xhci, "Timeout while waiting for evaluate context command\n");
                ret = -ETIME;
                break;
@@ -3432,7 +3433,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
        ret = reset_device_cmd->status;
        switch (ret) {
        case COMP_COMMAND_ABORTED:
-       case COMP_STOPPED:
+       case COMP_COMMAND_RING_STOPPED:
                xhci_warn(xhci, "Timeout waiting for reset device command\n");
                ret = -ETIME;
                goto command_cleanup;
@@ -3817,7 +3818,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
         */
        switch (command->status) {
        case COMP_COMMAND_ABORTED:
-       case COMP_STOPPED:
+       case COMP_COMMAND_RING_STOPPED:
                xhci_warn(xhci, "Timeout while waiting for setup device command\n");
                ret = -ETIME;
                break;
index e9cae4d82af2ec80a1bfa321871aa75895dda170..15d4e64d3b65277df6e9e5ac79454a9320d9d108 100644 (file)
@@ -192,7 +192,7 @@ static int chaoskey_probe(struct usb_interface *interface,
 
        dev->in_ep = in_ep;
 
-       if (udev->descriptor.idVendor != ALEA_VENDOR_ID)
+       if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID)
                dev->reads_started = 1;
 
        dev->size = size;
index 77569531b78a56d45fb43ee255a0a22e6da2979d..83b05a287b0c58f2b0b29f91fcddd0f307510b88 100644 (file)
@@ -554,7 +554,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
                        info.revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);
 
                        /* 0==UNKNOWN, 1==LOW(usb1.1) ,2=FULL(usb1.1), 3=HIGH(usb2.0) */
-                       info.speed = le16_to_cpu(dev->udev->speed);
+                       info.speed = dev->udev->speed;
                        info.if_num = dev->interface->cur_altsetting->desc.bInterfaceNumber;
                        info.report_size = dev->report_size;
 
index aa3c280fdf8d40662e375466dd3b2648ec037fe1..0782ac6f5edfaa0542dfe173bd6969c8bba77372 100644 (file)
@@ -926,6 +926,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
                 USB_MAJOR, dev->minor);
 
 exit:
+       kfree(get_version_reply);
        return retval;
 
 error:
index 3c6948af726aad38f9cf3a294ded3c7dfbac04ab..f019d80ca9e40451a8a3bbca0671b95935a7798f 100644 (file)
@@ -973,7 +973,7 @@ sisusbcon_set_origin(struct vc_data *c)
 
        mutex_unlock(&sisusb->lock);
 
-       return 1;
+       return true;
 }
 
 /* Interface routine */
index 9c7ee26ef388062bdc5e1f1fb2097fc010882950..bc6a9be2ccc55696cb703f04b97e3d0fb08ca59c 100644 (file)
@@ -245,6 +245,11 @@ static int dsps_check_status(struct musb *musb, void *unused)
                dsps_mod_timer_optional(glue);
                break;
        case OTG_STATE_A_WAIT_BCON:
+               /* keep VBUS on for host-only mode */
+               if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+                       dsps_mod_timer_optional(glue);
+                       break;
+               }
                musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
                skip_session = 1;
                /* fall */
index ac3a4952abb4b290b019ac59fbddd7004b50d949..dbe617a735d8400576e53a84e488ea4ff9fc8466 100644 (file)
@@ -2780,10 +2780,11 @@ int musb_host_setup(struct musb *musb, int power_budget)
        int ret;
        struct usb_hcd *hcd = musb->hcd;
 
-       MUSB_HST_MODE(musb);
-       musb->xceiv->otg->default_a = 1;
-       musb->xceiv->otg->state = OTG_STATE_A_IDLE;
-
+       if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+               MUSB_HST_MODE(musb);
+               musb->xceiv->otg->default_a = 1;
+               musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+       }
        otg_set_host(musb->xceiv->otg, &hcd->self);
        hcd->self.otg_port = 1;
        musb->xceiv->otg->host = &hcd->self;
index 8b43c4b99f045325fd5c7160ee28cca73f8738af..7870b37e0ea5c6b5a1767e9469193d791107071c 100644 (file)
@@ -219,6 +219,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
        u32                             dma_remaining;
        int                             src_burst, dst_burst;
        u16                             csr;
+       u32                             psize;
        int                             ch;
        s8                              dmareq;
        s8                              sync_dev;
@@ -390,15 +391,19 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
 
        if (chdat->tx) {
                /* Send transfer_packet_sz packets at a time */
-               musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-                       chdat->transfer_packet_sz);
+               psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+               psize &= ~0x7ff;
+               psize |= chdat->transfer_packet_sz;
+               musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
                musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
                        TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
        } else {
                /* Receive transfer_packet_sz packets at a time */
-               musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-                       chdat->transfer_packet_sz << 16);
+               psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+               psize &= ~(0x7ff << 16);
+               psize |= (chdat->transfer_packet_sz << 16);
+               musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
                musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
                        TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
index d38780fa87881a0ef3696e73e61527304271393c..aba74f817dc6594064241013b92e31138e587dce 100644 (file)
@@ -809,10 +809,10 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) },
        { USB_DEVICE(FTDI_VID, CYBER_CORTEX_AV_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-       { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
-               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-       { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
-               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_PID, 1) },
+       { USB_DEVICE_INTERFACE_NUMBER(OLIMEX_VID, OLIMEX_ARM_USB_TINY_H_PID, 1) },
        { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
@@ -1527,9 +1527,9 @@ static int set_serial_info(struct tty_struct *tty,
                                        (new_serial.flags & ASYNC_FLAGS));
        priv->custom_divisor = new_serial.custom_divisor;
 
+check_and_exit:
        write_latency_timer(port);
 
-check_and_exit:
        if ((old_priv.flags & ASYNC_SPD_MASK) !=
             (priv->flags & ASYNC_SPD_MASK)) {
                if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
index 71fb9e59db7125c845a9a1c23c4e33430a142a3e..4fcf1cecb6d721ad366666eec49774bcf9d00808 100644 (file)
 /* Olimex */
 #define OLIMEX_VID                     0x15BA
 #define OLIMEX_ARM_USB_OCD_PID         0x0003
+#define OLIMEX_ARM_USB_TINY_PID        0x0004
+#define OLIMEX_ARM_USB_TINY_H_PID      0x002a
 #define OLIMEX_ARM_USB_OCD_H_PID       0x002b
 
 /*
index 87798e625d6c827ed09b79a011eb46cdd770c864..6cefb9cb133d7bad8678e9b9400b077afc75474e 100644 (file)
@@ -2336,8 +2336,11 @@ static void change_port_settings(struct tty_struct *tty,
        if (!baud) {
                /* pick a default, any default... */
                baud = 9600;
-       } else
+       } else {
+               /* Avoid a zero divisor. */
+               baud = min(baud, 461550);
                tty_encode_baud_rate(tty, baud, baud);
+       }
 
        edge_port->baud_rate = baud;
        config->wBaudRate = (__u16)((461550L + baud/2) / baud);
index 73956d48a0c57bb5566fb0c1b47a581e438bb4a1..f9734a96d51681d689c5028e6777fec03c401d5a 100644 (file)
@@ -197,6 +197,7 @@ static u8 ir_xbof_change(u8 xbof)
 static int ir_startup(struct usb_serial *serial)
 {
        struct usb_irda_cs_descriptor *irda_desc;
+       int rates;
 
        irda_desc = irda_usb_find_class_desc(serial, 0);
        if (!irda_desc) {
@@ -205,18 +206,20 @@ static int ir_startup(struct usb_serial *serial)
                return -ENODEV;
        }
 
+       rates = le16_to_cpu(irda_desc->wBaudRate);
+
        dev_dbg(&serial->dev->dev,
                "%s - Baud rates supported:%s%s%s%s%s%s%s%s%s\n",
                __func__,
-               (irda_desc->wBaudRate & USB_IRDA_BR_2400) ? " 2400" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_9600) ? " 9600" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_19200) ? " 19200" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_38400) ? " 38400" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_57600) ? " 57600" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_115200) ? " 115200" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_576000) ? " 576000" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_1152000) ? " 1152000" : "",
-               (irda_desc->wBaudRate & USB_IRDA_BR_4000000) ? " 4000000" : "");
+               (rates & USB_IRDA_BR_2400) ? " 2400" : "",
+               (rates & USB_IRDA_BR_9600) ? " 9600" : "",
+               (rates & USB_IRDA_BR_19200) ? " 19200" : "",
+               (rates & USB_IRDA_BR_38400) ? " 38400" : "",
+               (rates & USB_IRDA_BR_57600) ? " 57600" : "",
+               (rates & USB_IRDA_BR_115200) ? " 115200" : "",
+               (rates & USB_IRDA_BR_576000) ? " 576000" : "",
+               (rates & USB_IRDA_BR_1152000) ? " 1152000" : "",
+               (rates & USB_IRDA_BR_4000000) ? " 4000000" : "");
 
        switch (irda_desc->bmAdditionalBOFs) {
        case USB_IRDA_AB_48:
index edbc81f205c253f41f7afa2d3375ef7818e0ae86..70f346f1aa86f4a7c9eb880cd725cd0d2e6fb1b5 100644 (file)
@@ -189,7 +189,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty,
                return -ENOMEM;
 
        divisor = mct_u232_calculate_baud_rate(serial, value, &speed);
-       put_unaligned_le32(cpu_to_le32(divisor), buf);
+       put_unaligned_le32(divisor, buf);
        rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                                MCT_U232_SET_BAUD_RATE_REQUEST,
                                MCT_U232_SET_REQUEST_TYPE,
index af67a0de6b5d475d2be95952ddfb2354546a0fbb..3bf61acfc26b9cfdee5496feeb64bdbcfd58015c 100644 (file)
@@ -281,6 +281,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_LE922_USBCFG0            0x1042
 #define TELIT_PRODUCT_LE922_USBCFG3            0x1043
 #define TELIT_PRODUCT_LE922_USBCFG5            0x1045
+#define TELIT_PRODUCT_ME910                    0x1100
 #define TELIT_PRODUCT_LE920                    0x1200
 #define TELIT_PRODUCT_LE910                    0x1201
 #define TELIT_PRODUCT_LE910_USBCFG4            0x1206
@@ -640,6 +641,11 @@ static const struct option_blacklist_info simcom_sim7100e_blacklist = {
        .reserved = BIT(5) | BIT(6),
 };
 
+static const struct option_blacklist_info telit_me910_blacklist = {
+       .sendsetup = BIT(0),
+       .reserved = BIT(1) | BIT(3),
+};
+
 static const struct option_blacklist_info telit_le910_blacklist = {
        .sendsetup = BIT(0),
        .reserved = BIT(1) | BIT(2),
@@ -1235,6 +1241,8 @@ static const struct usb_device_id option_ids[] = {
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff),
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
+               .driver_info = (kernel_ulong_t)&telit_me910_blacklist },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
                .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
index 38b3f0d8cd580f2366136003934d00a475b1d7f1..fd509ed6cf7065725c097ab1bc4eac84359be1f6 100644 (file)
@@ -162,6 +162,8 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x1199, 0x9071)},   /* Sierra Wireless MC74xx */
        {DEVICE_SWI(0x1199, 0x9078)},   /* Sierra Wireless EM74xx */
        {DEVICE_SWI(0x1199, 0x9079)},   /* Sierra Wireless EM74xx */
+       {DEVICE_SWI(0x1199, 0x907a)},   /* Sierra Wireless EM74xx QDL */
+       {DEVICE_SWI(0x1199, 0x907b)},   /* Sierra Wireless EM74xx */
        {DEVICE_SWI(0x413c, 0x81a2)},   /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a3)},   /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a4)},   /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
index 369f3c24815a1462f405f1a6bc3f2cbdd034e21b..44af719194b239f760c77919bf7cf5bad19ed9d7 100644 (file)
@@ -446,6 +446,10 @@ struct ms_lib_ctrl {
 #define SD_BLOCK_LEN  9
 
 struct ene_ub6250_info {
+
+       /* I/O bounce buffer */
+       u8              *bbuf;
+
        /* for 6250 code */
        struct SD_STATUS        SD_Status;
        struct MS_STATUS        MS_Status;
@@ -493,8 +497,11 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag);
 
 static void ene_ub6250_info_destructor(void *extra)
 {
+       struct ene_ub6250_info *info = (struct ene_ub6250_info *) extra;
+
        if (!extra)
                return;
+       kfree(info->bbuf);
 }
 
 static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
@@ -860,8 +867,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
                u8 PageNum, u32 *PageBuf, struct ms_lib_type_extdat *ExtraDat)
 {
        struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+       u8 *bbuf = info->bbuf;
        int result;
-       u8 ExtBuf[4];
        u32 bn = PhyBlockAddr * 0x20 + PageNum;
 
        result = ene_load_bincode(us, MS_RW_PATTERN);
@@ -901,7 +909,7 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
        bcb->CDB[2]     = (unsigned char)(PhyBlockAddr>>16);
        bcb->CDB[6]     = 0x01;
 
-       result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+       result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
@@ -910,9 +918,9 @@ static int ms_read_readpage(struct us_data *us, u32 PhyBlockAddr,
        ExtraDat->status0  = 0x10;  /* Not yet,fireware support */
 
        ExtraDat->status1  = 0x00;  /* Not yet,fireware support */
-       ExtraDat->ovrflg   = ExtBuf[0];
-       ExtraDat->mngflg   = ExtBuf[1];
-       ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+       ExtraDat->ovrflg   = bbuf[0];
+       ExtraDat->mngflg   = bbuf[1];
+       ExtraDat->logadr   = memstick_logaddr(bbuf[2], bbuf[3]);
 
        return USB_STOR_TRANSPORT_GOOD;
 }
@@ -1332,8 +1340,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
                                u8 PageNum, struct ms_lib_type_extdat *ExtraDat)
 {
        struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+       u8 *bbuf = info->bbuf;
        int result;
-       u8 ExtBuf[4];
 
        memset(bcb, 0, sizeof(struct bulk_cb_wrap));
        bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -1347,7 +1356,7 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
        bcb->CDB[2]     = (unsigned char)(PhyBlock>>16);
        bcb->CDB[6]     = 0x01;
 
-       result = ene_send_scsi_cmd(us, FDIR_READ, &ExtBuf, 0);
+       result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
@@ -1355,9 +1364,9 @@ static int ms_lib_read_extra(struct us_data *us, u32 PhyBlock,
        ExtraDat->intr     = 0x80;  /* Not yet, waiting for fireware support */
        ExtraDat->status0  = 0x10;  /* Not yet, waiting for fireware support */
        ExtraDat->status1  = 0x00;  /* Not yet, waiting for fireware support */
-       ExtraDat->ovrflg   = ExtBuf[0];
-       ExtraDat->mngflg   = ExtBuf[1];
-       ExtraDat->logadr   = memstick_logaddr(ExtBuf[2], ExtBuf[3]);
+       ExtraDat->ovrflg   = bbuf[0];
+       ExtraDat->mngflg   = bbuf[1];
+       ExtraDat->logadr   = memstick_logaddr(bbuf[2], bbuf[3]);
 
        return USB_STOR_TRANSPORT_GOOD;
 }
@@ -1556,9 +1565,9 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st)
        u16 PhyBlock, newblk, i;
        u16 LogStart, LogEnde;
        struct ms_lib_type_extdat extdat;
-       u8 buf[0x200];
        u32 count = 0, index = 0;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+       u8 *bbuf = info->bbuf;
 
        for (PhyBlock = 0; PhyBlock < info->MS_Lib.NumberOfPhyBlock;) {
                ms_lib_phy_to_log_range(PhyBlock, &LogStart, &LogEnde);
@@ -1572,14 +1581,16 @@ static int ms_lib_scan_logicalblocknumber(struct us_data *us, u16 btBlk1st)
                        }
 
                        if (count == PhyBlock) {
-                               ms_lib_read_extrablock(us, PhyBlock, 0, 0x80, &buf);
+                               ms_lib_read_extrablock(us, PhyBlock, 0, 0x80,
+                                               bbuf);
                                count += 0x80;
                        }
                        index = (PhyBlock % 0x80) * 4;
 
-                       extdat.ovrflg = buf[index];
-                       extdat.mngflg = buf[index+1];
-                       extdat.logadr = memstick_logaddr(buf[index+2], buf[index+3]);
+                       extdat.ovrflg = bbuf[index];
+                       extdat.mngflg = bbuf[index+1];
+                       extdat.logadr = memstick_logaddr(bbuf[index+2],
+                                       bbuf[index+3]);
 
                        if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK) {
                                ms_lib_setacquired_errorblock(us, PhyBlock);
@@ -2062,9 +2073,9 @@ static int ene_ms_init(struct us_data *us)
 {
        struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
        int result;
-       u8 buf[0x200];
        u16 MSP_BlockSize, MSP_UserAreaBlocks;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+       u8 *bbuf = info->bbuf;
 
        printk(KERN_INFO "transport --- ENE_MSInit\n");
 
@@ -2083,13 +2094,13 @@ static int ene_ms_init(struct us_data *us)
        bcb->CDB[0]     = 0xF1;
        bcb->CDB[1]     = 0x01;
 
-       result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+       result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
        if (result != USB_STOR_XFER_GOOD) {
                printk(KERN_ERR "Execution MS Init Code Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
        /* the same part to test ENE */
-       info->MS_Status = *(struct MS_STATUS *)&buf[0];
+       info->MS_Status = *(struct MS_STATUS *) bbuf;
 
        if (info->MS_Status.Insert && info->MS_Status.Ready) {
                printk(KERN_INFO "Insert     = %x\n", info->MS_Status.Insert);
@@ -2098,15 +2109,15 @@ static int ene_ms_init(struct us_data *us)
                printk(KERN_INFO "IsMSPHG    = %x\n", info->MS_Status.IsMSPHG);
                printk(KERN_INFO "WtP= %x\n", info->MS_Status.WtP);
                if (info->MS_Status.IsMSPro) {
-                       MSP_BlockSize      = (buf[6] << 8) | buf[7];
-                       MSP_UserAreaBlocks = (buf[10] << 8) | buf[11];
+                       MSP_BlockSize      = (bbuf[6] << 8) | bbuf[7];
+                       MSP_UserAreaBlocks = (bbuf[10] << 8) | bbuf[11];
                        info->MSP_TotalBlock = MSP_BlockSize * MSP_UserAreaBlocks;
                } else {
                        ms_card_init(us); /* Card is MS (to ms.c)*/
                }
                usb_stor_dbg(us, "MS Init Code OK !!\n");
        } else {
-               usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
+               usb_stor_dbg(us, "MS Card Not Ready --- %x\n", bbuf[0]);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -2116,9 +2127,9 @@ static int ene_ms_init(struct us_data *us)
 static int ene_sd_init(struct us_data *us)
 {
        int result;
-       u8  buf[0x200];
        struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+       u8 *bbuf = info->bbuf;
 
        usb_stor_dbg(us, "transport --- ENE_SDInit\n");
        /* SD Init Part-1 */
@@ -2152,17 +2163,17 @@ static int ene_sd_init(struct us_data *us)
        bcb->Flags              = US_BULK_FLAG_IN;
        bcb->CDB[0]             = 0xF1;
 
-       result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+       result = ene_send_scsi_cmd(us, FDIR_READ, bbuf, 0);
        if (result != USB_STOR_XFER_GOOD) {
                usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
-       info->SD_Status =  *(struct SD_STATUS *)&buf[0];
+       info->SD_Status =  *(struct SD_STATUS *) bbuf;
        if (info->SD_Status.Insert && info->SD_Status.Ready) {
                struct SD_STATUS *s = &info->SD_Status;
 
-               ene_get_card_status(us, (unsigned char *)&buf);
+               ene_get_card_status(us, bbuf);
                usb_stor_dbg(us, "Insert     = %x\n", s->Insert);
                usb_stor_dbg(us, "Ready      = %x\n", s->Ready);
                usb_stor_dbg(us, "IsMMC      = %x\n", s->IsMMC);
@@ -2170,7 +2181,7 @@ static int ene_sd_init(struct us_data *us)
                usb_stor_dbg(us, "HiSpeed    = %x\n", s->HiSpeed);
                usb_stor_dbg(us, "WtP        = %x\n", s->WtP);
        } else {
-               usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
+               usb_stor_dbg(us, "SD Card Not Ready --- %x\n", bbuf[0]);
                return USB_STOR_TRANSPORT_ERROR;
        }
        return USB_STOR_TRANSPORT_GOOD;
@@ -2180,13 +2191,15 @@ static int ene_sd_init(struct us_data *us)
 static int ene_init(struct us_data *us)
 {
        int result;
-       u8  misc_reg03 = 0;
+       u8  misc_reg03;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+       u8 *bbuf = info->bbuf;
 
-       result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+       result = ene_get_card_type(us, REG_CARD_STATUS, bbuf);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
+       misc_reg03 = bbuf[0];
        if (misc_reg03 & 0x01) {
                if (!info->SD_Status.Ready) {
                        result = ene_sd_init(us);
@@ -2303,8 +2316,9 @@ static int ene_ub6250_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
        int result;
-       u8  misc_reg03 = 0;
+       u8  misc_reg03;
        struct us_data *us;
+       struct ene_ub6250_info *info;
 
        result = usb_stor_probe1(&us, intf, id,
                   (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list,
@@ -2313,11 +2327,16 @@ static int ene_ub6250_probe(struct usb_interface *intf,
                return result;
 
        /* FIXME: where should the code alloc extra buf ? */
-       if (!us->extra) {
-               us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
-               if (!us->extra)
-                       return -ENOMEM;
-               us->extra_destructor = ene_ub6250_info_destructor;
+       us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
+       if (!us->extra)
+               return -ENOMEM;
+       us->extra_destructor = ene_ub6250_info_destructor;
+
+       info = (struct ene_ub6250_info *)(us->extra);
+       info->bbuf = kmalloc(512, GFP_KERNEL);
+       if (!info->bbuf) {
+               kfree(us->extra);
+               return -ENOMEM;
        }
 
        us->transport_name = "ene_ub6250";
@@ -2329,12 +2348,13 @@ static int ene_ub6250_probe(struct usb_interface *intf,
                return result;
 
        /* probe card type */
-       result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+       result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
        if (result != USB_STOR_XFER_GOOD) {
                usb_stor_disconnect(intf);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
+       misc_reg03 = info->bbuf[0];
        if (!(misc_reg03 & 0x01)) {
                pr_info("ums_eneub6250: This driver only supports SD/MS cards. "
                        "It does not support SM cards.\n");
index 5d8b2c261940d9a7785bc64a505f2959f57cb395..0585078638db7ebcf72a40fc9f9ecdf3ea362512 100644 (file)
@@ -235,14 +235,19 @@ done:
 
 static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 {
+       int width;
+
        memset(desc, 0, sizeof(*desc));
        desc->bDescriptorType = USB_DT_HUB;
-       desc->bDescLength = 9;
        desc->wHubCharacteristics = cpu_to_le16(
                HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
+
        desc->bNbrPorts = VHCI_HC_PORTS;
-       desc->u.hs.DeviceRemovable[0] = 0xff;
-       desc->u.hs.DeviceRemovable[1] = 0xff;
+       BUILD_BUG_ON(VHCI_HC_PORTS > USB_MAXCHILDREN);
+       width = desc->bNbrPorts / 8 + 1;
+       desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * width;
+       memset(&desc->u.hs.DeviceRemovable[0], 0, width);
+       memset(&desc->u.hs.DeviceRemovable[width], 0xff, width);
 }
 
 static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
index 6345e85822a42457f11c607effb3fbb66ce8c89f..a50cf45e530f7f0dcc76c111da56d919b9f1f1bf 100644 (file)
@@ -341,6 +341,7 @@ error_submit_ep1:
 static
 int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
 {
+       struct usb_device *udev = interface_to_usbdev(iface);
        struct i1480_usb *i1480_usb;
        struct i1480 *i1480;
        struct device *dev = &iface->dev;
@@ -352,8 +353,8 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
                        iface->cur_altsetting->desc.bInterfaceNumber);
                goto error;
        }
-       if (iface->num_altsetting > 1
-           && interface_to_usbdev(iface)->descriptor.idProduct == 0xbabe) {
+       if (iface->num_altsetting > 1 &&
+                       le16_to_cpu(udev->descriptor.idProduct) == 0xbabe) {
                /* Need altsetting #1 [HW QUIRK] or EP1 won't work */
                result = usb_set_interface(interface_to_usbdev(iface), 0, 1);
                if (result < 0)
index 687ebb053438b343d63c77881aeebcdc0ad7f857..41d7979d81c53df3d459d39939798659386444a8 100644 (file)
@@ -1048,7 +1048,7 @@ void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 
        for (i = 0; i < (128 - edid[2]) / DETAILED_TIMING_DESCRIPTION_SIZE;
             i++, block += DETAILED_TIMING_DESCRIPTION_SIZE)
-               if (PIXEL_CLOCK)
+               if (PIXEL_CLOCK != 0)
                        edt[num++] = block - edid;
 
        /* Yikes, EDID data is totally useless */
index ec2e7e3536859cae3294d484c5bb56b5330c6db5..449fceaf79d5505a0e2c409adeb968dbaad4413c 100644 (file)
@@ -1646,8 +1646,9 @@ static int ufx_usb_probe(struct usb_interface *interface,
        dev_dbg(dev->gdev, "%s %s - serial #%s\n",
                usbdev->manufacturer, usbdev->product, usbdev->serial);
        dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n",
-               usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-               usbdev->descriptor.bcdDevice, dev);
+               le16_to_cpu(usbdev->descriptor.idVendor),
+               le16_to_cpu(usbdev->descriptor.idProduct),
+               le16_to_cpu(usbdev->descriptor.bcdDevice), dev);
        dev_dbg(dev->gdev, "console enable=%d\n", console);
        dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio);
 
index 6a3c353de7c35468e68f271126dca1c0b447ae82..05ef657235df2eb72c68e8a892d70e3edadd17d8 100644 (file)
@@ -1105,8 +1105,8 @@ static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
        char *bufptr;
        struct urb *urb;
 
-       pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
-               info->node, dev->blank_mode, blank_mode);
+       pr_debug("/dev/fb%d FB_BLANK mode %d --> %d\n",
+                info->node, dev->blank_mode, blank_mode);
 
        if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
            (blank_mode != FB_BLANK_POWERDOWN)) {
@@ -1613,8 +1613,9 @@ static int dlfb_usb_probe(struct usb_interface *interface,
        pr_info("%s %s - serial #%s\n",
                usbdev->manufacturer, usbdev->product, usbdev->serial);
        pr_info("vid_%04x&pid_%04x&rev_%04x driver's dlfb_data struct at %p\n",
-               usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
-               usbdev->descriptor.bcdDevice, dev);
+               le16_to_cpu(usbdev->descriptor.idVendor),
+               le16_to_cpu(usbdev->descriptor.idProduct),
+               le16_to_cpu(usbdev->descriptor.bcdDevice), dev);
        pr_info("console enable=%d\n", console);
        pr_info("fb_defio enable=%d\n", fb_defio);
        pr_info("shadow enable=%d\n", shadow);
index f9718f012aae9be85a9568a2ce7be0740f08f5f6..badee04ef496cefd02b8f3f2faebb21fafb839b5 100644 (file)
@@ -1630,16 +1630,14 @@ static void viafb_init_proc(struct viafb_shared *shared)
 }
 static void viafb_remove_proc(struct viafb_shared *shared)
 {
-       struct proc_dir_entry *viafb_entry = shared->proc_entry,
-               *iga1_entry = shared->iga1_proc_entry,
-               *iga2_entry = shared->iga2_proc_entry;
+       struct proc_dir_entry *viafb_entry = shared->proc_entry;
 
        if (!viafb_entry)
                return;
 
-       remove_proc_entry("output_devices", iga2_entry);
+       remove_proc_entry("output_devices", shared->iga2_proc_entry);
        remove_proc_entry("iga2", viafb_entry);
-       remove_proc_entry("output_devices", iga1_entry);
+       remove_proc_entry("output_devices", shared->iga1_proc_entry);
        remove_proc_entry("iga1", viafb_entry);
        remove_proc_entry("supported_output_devices", viafb_entry);
 
index 408c174ef0d5c076dc2f51da612b8e0f3dfa8269..22caf808bfaba97e45662de0f4150632bcb85d2f 100644 (file)
@@ -663,6 +663,12 @@ static int virtballoon_restore(struct virtio_device *vdev)
 }
 #endif
 
+static int virtballoon_validate(struct virtio_device *vdev)
+{
+       __virtio_clear_bit(vdev, VIRTIO_F_IOMMU_PLATFORM);
+       return 0;
+}
+
 static unsigned int features[] = {
        VIRTIO_BALLOON_F_MUST_TELL_HOST,
        VIRTIO_BALLOON_F_STATS_VQ,
@@ -675,6 +681,7 @@ static struct virtio_driver virtio_balloon_driver = {
        .driver.name =  KBUILD_MODNAME,
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
+       .validate =     virtballoon_validate,
        .probe =        virtballoon_probe,
        .remove =       virtballoon_remove,
        .config_changed = virtballoon_changed,
index 52a70ee6014fa866762042f78b87f3a4c7c7e794..8b9049dac0948db6cc0fca2f25c9f4e5f5cae6bd 100644 (file)
@@ -452,7 +452,7 @@ config DAVINCI_WATCHDOG
 
 config ORION_WATCHDOG
        tristate "Orion watchdog"
-       depends on ARCH_ORION5X || ARCH_DOVE || MACH_DOVE || ARCH_MVEBU || COMPILE_TEST
+       depends on ARCH_ORION5X || ARCH_DOVE || MACH_DOVE || ARCH_MVEBU || (COMPILE_TEST && !ARCH_EBSA110)
        depends on ARM
        select WATCHDOG_CORE
        help
index 6fce17d5b9f1a27f94e711d0e69d9844c920a91d..a5775dfd8d5fc226e31ca59abb172f504f7efcda 100644 (file)
@@ -304,6 +304,8 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev)
        if (!wdt)
                return -ENOMEM;
 
+       spin_lock_init(&wdt->lock);
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        wdt->base = devm_ioremap_resource(dev, res);
        if (IS_ERR(wdt->base))
@@ -316,7 +318,6 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev)
                return ret;
        }
 
-       spin_lock_init(&wdt->lock);
        platform_set_drvdata(pdev, wdt);
        watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt);
        bcm_kona_wdt_wdd.parent = &pdev->dev;
index 8d61e8bfe60b1a418eab489e966652840dedccff..86e0b5d2e7616690007792833e96cc9086ee0144 100644 (file)
@@ -49,7 +49,7 @@
 /* Counter maximum value */
 #define CDNS_WDT_COUNTER_MAX 0xFFF
 
-static int wdt_timeout = CDNS_WDT_DEFAULT_TIMEOUT;
+static int wdt_timeout;
 static int nowayout = WATCHDOG_NOWAYOUT;
 
 module_param(wdt_timeout, int, 0);
index 347f0389b0899d4183021254203e0a0938600267..c4f65873bfa453b1385d2a1371ba10c741df2be9 100644 (file)
@@ -306,16 +306,15 @@ static int iTCO_wdt_ping(struct watchdog_device *wd_dev)
 
        iTCO_vendor_pre_keepalive(p->smi_res, wd_dev->timeout);
 
+       /* Reset the timeout status bit so that the timer
+        * needs to count down twice again before rebooting */
+       outw(0x0008, TCO1_STS(p));      /* write 1 to clear bit */
+
        /* Reload the timer by writing to the TCO Timer Counter register */
-       if (p->iTCO_version >= 2) {
+       if (p->iTCO_version >= 2)
                outw(0x01, TCO_RLD(p));
-       } else if (p->iTCO_version == 1) {
-               /* Reset the timeout status bit so that the timer
-                * needs to count down twice again before rebooting */
-               outw(0x0008, TCO1_STS(p));      /* write 1 to clear bit */
-
+       else if (p->iTCO_version == 1)
                outb(0x01, TCO_RLD(p));
-       }
 
        spin_unlock(&p->io_lock);
        return 0;
@@ -328,11 +327,8 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t)
        unsigned char val8;
        unsigned int tmrval;
 
-       tmrval = seconds_to_ticks(p, t);
-
-       /* For TCO v1 the timer counts down twice before rebooting */
-       if (p->iTCO_version == 1)
-               tmrval /= 2;
+       /* The timer counts down twice before rebooting */
+       tmrval = seconds_to_ticks(p, t) / 2;
 
        /* from the specs: */
        /* "Values of 0h-3h are ignored and should not be attempted" */
@@ -385,6 +381,8 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev)
                spin_lock(&p->io_lock);
                val16 = inw(TCO_RLD(p));
                val16 &= 0x3ff;
+               if (!(inw(TCO1_STS(p)) & 0x0008))
+                       val16 += (inw(TCOv2_TMR(p)) & 0x3ff);
                spin_unlock(&p->io_lock);
 
                time_left = ticks_to_seconds(p, val16);
index 99ebf6ea3de648d881de4ef1f609d1f4d29f5ca0..5615f40139246a19de1be39df6f6ca60b7a705b9 100644 (file)
@@ -630,6 +630,9 @@ static int usb_pcwd_probe(struct usb_interface *interface,
                return -ENODEV;
        }
 
+       if (iface_desc->desc.bNumEndpoints < 1)
+               return -ENODEV;
+
        /* check out the endpoint: it has to be Interrupt & IN */
        endpoint = &iface_desc->endpoint[0].desc;
 
index f709962018ac260107dd2c419c1fbcdfafd4599b..362fd229786df6cea1600108a9060b89b800f475 100644 (file)
@@ -6,6 +6,7 @@
  * Licensed under GPLv2.
  */
 
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -29,6 +30,7 @@ struct sama5d4_wdt {
        struct watchdog_device  wdd;
        void __iomem            *reg_base;
        u32                     mr;
+       unsigned long           last_ping;
 };
 
 static int wdt_timeout = WDT_DEFAULT_TIMEOUT;
@@ -44,11 +46,34 @@ MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
        __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
+#define wdt_enabled (!(wdt->mr & AT91_WDT_WDDIS))
+
 #define wdt_read(wdt, field) \
        readl_relaxed((wdt)->reg_base + (field))
 
-#define wdt_write(wtd, field, val) \
-       writel_relaxed((val), (wdt)->reg_base + (field))
+/* 4 slow clock periods is 4/32768 = 122.07µs*/
+#define WDT_DELAY      usecs_to_jiffies(123)
+
+static void wdt_write(struct sama5d4_wdt *wdt, u32 field, u32 val)
+{
+       /*
+        * WDT_CR and WDT_MR must not be modified within three slow clock
+        * periods following a restart of the watchdog performed by a write
+        * access in WDT_CR.
+        */
+       while (time_before(jiffies, wdt->last_ping + WDT_DELAY))
+               usleep_range(30, 125);
+       writel_relaxed(val, wdt->reg_base + field);
+       wdt->last_ping = jiffies;
+}
+
+static void wdt_write_nosleep(struct sama5d4_wdt *wdt, u32 field, u32 val)
+{
+       if (time_before(jiffies, wdt->last_ping + WDT_DELAY))
+               udelay(123);
+       writel_relaxed(val, wdt->reg_base + field);
+       wdt->last_ping = jiffies;
+}
 
 static int sama5d4_wdt_start(struct watchdog_device *wdd)
 {
@@ -89,7 +114,16 @@ static int sama5d4_wdt_set_timeout(struct watchdog_device *wdd,
        wdt->mr &= ~AT91_WDT_WDD;
        wdt->mr |= AT91_WDT_SET_WDV(value);
        wdt->mr |= AT91_WDT_SET_WDD(value);
-       wdt_write(wdt, AT91_WDT_MR, wdt->mr);
+
+       /*
+        * WDDIS has to be 0 when updating WDD/WDV. The datasheet states: When
+        * setting the WDDIS bit, and while it is set, the fields WDV and WDD
+        * must not be modified.
+        * If the watchdog is enabled, then the timeout can be updated. Else,
+        * wait that the user enables it.
+        */
+       if (wdt_enabled)
+               wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS);
 
        wdd->timeout = timeout;
 
@@ -145,23 +179,21 @@ static int of_sama5d4_wdt_init(struct device_node *np, struct sama5d4_wdt *wdt)
 
 static int sama5d4_wdt_init(struct sama5d4_wdt *wdt)
 {
-       struct watchdog_device *wdd = &wdt->wdd;
-       u32 value = WDT_SEC2TICKS(wdd->timeout);
        u32 reg;
-
        /*
-        * Because the fields WDV and WDD must not be modified when the WDDIS
-        * bit is set, so clear the WDDIS bit before writing the WDT_MR.
+        * When booting and resuming, the bootloader may have changed the
+        * watchdog configuration.
+        * If the watchdog is already running, we can safely update it.
+        * Else, we have to disable it properly.
         */
-       reg = wdt_read(wdt, AT91_WDT_MR);
-       reg &= ~AT91_WDT_WDDIS;
-       wdt_write(wdt, AT91_WDT_MR, reg);
-
-       wdt->mr |= AT91_WDT_SET_WDD(value);
-       wdt->mr |= AT91_WDT_SET_WDV(value);
-
-       wdt_write(wdt, AT91_WDT_MR, wdt->mr);
-
+       if (wdt_enabled) {
+               wdt_write_nosleep(wdt, AT91_WDT_MR, wdt->mr);
+       } else {
+               reg = wdt_read(wdt, AT91_WDT_MR);
+               if (!(reg & AT91_WDT_WDDIS))
+                       wdt_write_nosleep(wdt, AT91_WDT_MR,
+                                         reg | AT91_WDT_WDDIS);
+       }
        return 0;
 }
 
@@ -172,6 +204,7 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
        struct resource *res;
        void __iomem *regs;
        u32 irq = 0;
+       u32 timeout;
        int ret;
 
        wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
@@ -184,6 +217,7 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
        wdd->ops = &sama5d4_wdt_ops;
        wdd->min_timeout = MIN_WDT_TIMEOUT;
        wdd->max_timeout = MAX_WDT_TIMEOUT;
+       wdt->last_ping = jiffies;
 
        watchdog_set_drvdata(wdd, wdt);
 
@@ -221,6 +255,11 @@ static int sama5d4_wdt_probe(struct platform_device *pdev)
                return ret;
        }
 
+       timeout = WDT_SEC2TICKS(wdd->timeout);
+
+       wdt->mr |= AT91_WDT_SET_WDD(timeout);
+       wdt->mr |= AT91_WDT_SET_WDV(timeout);
+
        ret = sama5d4_wdt_init(wdt);
        if (ret)
                return ret;
@@ -263,9 +302,7 @@ static int sama5d4_wdt_resume(struct device *dev)
 {
        struct sama5d4_wdt *wdt = dev_get_drvdata(dev);
 
-       wdt_write(wdt, AT91_WDT_MR, wdt->mr & ~AT91_WDT_WDDIS);
-       if (wdt->mr & AT91_WDT_WDDIS)
-               wdt_write(wdt, AT91_WDT_MR, wdt->mr);
+       sama5d4_wdt_init(wdt);
 
        return 0;
 }
index 48b2c058b00910ffee5a313812b5cb4d0ee135c5..bc7addc2dc06d0f9ca4bfa09abdbedfb4252090f 100644 (file)
@@ -332,7 +332,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
                pr_crit("Would Reboot\n");
 #else
                pr_crit("Initiating system reboot\n");
-               emergency_restart(NULL);
+               emergency_restart();
 #endif
 #else
                pr_crit("Reset in 5ms\n");
index e290d5a13a6d5fa621f650ef03f3b8d7f00f7bb5..c98252733c3069dc5528691cecdee279c8f35c5a 100644 (file)
@@ -211,10 +211,8 @@ static int zx2967_wdt_probe(struct platform_device *pdev)
 
        base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        wdt->reg_base = devm_ioremap_resource(dev, base);
-       if (IS_ERR(wdt->reg_base)) {
-               dev_err(dev, "ioremap failed\n");
+       if (IS_ERR(wdt->reg_base))
                return PTR_ERR(wdt->reg_base);
-       }
 
        zx2967_wdt_reset_sysctrl(dev);
 
index 7a92a5e1d40c6f17227936ee2b6925286deab511..feca75b07fddce01e6e121542d3e0b74d321f85f 100644 (file)
@@ -362,8 +362,8 @@ static int mmap_batch_fn(void *data, int nr, void *state)
                                st->global_error = 1;
                }
        }
-       st->va += PAGE_SIZE * nr;
-       st->index += nr;
+       st->va += XEN_PAGE_SIZE * nr;
+       st->index += nr / XEN_PFN_PER_PAGE;
 
        return 0;
 }
index 734cbf8d9676bd6f6f26561249504ccffd9f8360..dd9f1bebb5a3a980b55e5d0fb758c93e4f694722 100644 (file)
@@ -344,7 +344,7 @@ static int autofs_dev_ioctl_fail(struct file *fp,
        int status;
 
        token = (autofs_wqt_t) param->fail.token;
-       status = param->fail.status ? param->fail.status : -ENOENT;
+       status = param->fail.status < 0 ? param->fail.status : -ENOENT;
        return autofs4_wait_release(sbi, token, status);
 }
 
index 519599dddd3692ee373a9eb00d95d5757556ad42..0a7404ef9335bf7ea19926e2896c9b737951afe5 100644 (file)
@@ -263,7 +263,10 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
                kfree(vecs);
 
        if (unlikely(bio.bi_error))
-               return bio.bi_error;
+               ret = bio.bi_error;
+
+       bio_uninit(&bio);
+
        return ret;
 }
 
index 643c70d2b2e65ab96a93ff4c022756ea7e59d179..4f8f75d9e83916c059902196ecab2aa6bbdf4b4d 100644 (file)
@@ -2563,7 +2563,7 @@ u64 btrfs_csum_bytes_to_leaves(struct btrfs_fs_info *fs_info, u64 csum_bytes);
 static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info,
                                                 unsigned num_items)
 {
-       return fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items;
+       return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * 2 * num_items;
 }
 
 /*
@@ -2573,7 +2573,7 @@ static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_fs_info *fs_info,
 static inline u64 btrfs_calc_trunc_metadata_size(struct btrfs_fs_info *fs_info,
                                                 unsigned num_items)
 {
-       return fs_info->nodesize * BTRFS_MAX_LEVEL * num_items;
+       return (u64)fs_info->nodesize * BTRFS_MAX_LEVEL * num_items;
 }
 
 int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans,
index 60a750678a82b335ab7fd0e9432288d013c52e64..c24d615e3d7f60694d25d6a5c34f2dff45121ca7 100644 (file)
@@ -468,7 +468,7 @@ int verify_dir_item(struct btrfs_fs_info *fs_info,
 
        if (btrfs_dir_name_len(leaf, dir_item) > namelen) {
                btrfs_crit(fs_info, "invalid dir item name len: %u",
-                      (unsigned)btrfs_dir_data_len(leaf, dir_item));
+                      (unsigned)btrfs_dir_name_len(leaf, dir_item));
                return 1;
        }
 
index 8685d67185d01bf90bcd2cf6d7cdd168e044c777..5f678dcb20e634d936c56f6bdcba0c86b624c21b 100644 (file)
@@ -3467,10 +3467,12 @@ static int write_dev_supers(struct btrfs_device *device,
                 * we fua the first super.  The others we allow
                 * to go down lazy.
                 */
-               if (i == 0)
-                       ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_FUA, bh);
-               else
+               if (i == 0) {
+                       ret = btrfsic_submit_bh(REQ_OP_WRITE,
+                                               REQ_SYNC | REQ_FUA, bh);
+               } else {
                        ret = btrfsic_submit_bh(REQ_OP_WRITE, REQ_SYNC, bh);
+               }
                if (ret)
                        errors++;
        }
@@ -3535,7 +3537,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
 
        bio->bi_end_io = btrfs_end_empty_barrier;
        bio->bi_bdev = device->bdev;
-       bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+       bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH;
        init_completion(&device->flush_wait);
        bio->bi_private = &device->flush_wait;
        device->flush_bio = bio;
index e390451c72e6cdb93492e519cea82d5d7b3dfaf9..33d979e9ea2a307802434f8425a6b3a33c5d59d6 100644 (file)
@@ -3993,6 +3993,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
                                    info->space_info_kobj, "%s",
                                    alloc_name(found->flags));
        if (ret) {
+               percpu_counter_destroy(&found->total_bytes_pinned);
                kfree(found);
                return ret;
        }
@@ -4844,7 +4845,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
        spin_unlock(&delayed_rsv->lock);
 
 commit:
-       trans = btrfs_join_transaction(fs_info->fs_root);
+       trans = btrfs_join_transaction(fs_info->extent_root);
        if (IS_ERR(trans))
                return -ENOSPC;
 
@@ -4862,7 +4863,7 @@ static int flush_space(struct btrfs_fs_info *fs_info,
                       struct btrfs_space_info *space_info, u64 num_bytes,
                       u64 orig_bytes, int state)
 {
-       struct btrfs_root *root = fs_info->fs_root;
+       struct btrfs_root *root = fs_info->extent_root;
        struct btrfs_trans_handle *trans;
        int nr;
        int ret = 0;
@@ -5062,7 +5063,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info,
        int flush_state = FLUSH_DELAYED_ITEMS_NR;
 
        spin_lock(&space_info->lock);
-       to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root,
+       to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root,
                                                      space_info);
        if (!to_reclaim) {
                spin_unlock(&space_info->lock);
index d8da3edf2ac39ebcc0bde0ede7da74f0f81ad9ea..d3619e01000551c42bf65bd6983801a0b04423e5 100644 (file)
@@ -2458,7 +2458,7 @@ void end_extent_writepage(struct page *page, int err, u64 start, u64 end)
        if (!uptodate) {
                ClearPageUptodate(page);
                SetPageError(page);
-               ret = ret < 0 ? ret : -EIO;
+               ret = err < 0 ? err : -EIO;
                mapping_set_error(page->mapping, ret);
        }
 }
@@ -4377,6 +4377,123 @@ static struct extent_map *get_extent_skip_holes(struct inode *inode,
        return NULL;
 }
 
+/*
+ * To cache previous fiemap extent
+ *
+ * Will be used for merging fiemap extent
+ */
+struct fiemap_cache {
+       u64 offset;
+       u64 phys;
+       u64 len;
+       u32 flags;
+       bool cached;
+};
+
+/*
+ * Helper to submit fiemap extent.
+ *
+ * Will try to merge current fiemap extent specified by @offset, @phys,
+ * @len and @flags with cached one.
+ * And only when we fails to merge, cached one will be submitted as
+ * fiemap extent.
+ *
+ * Return value is the same as fiemap_fill_next_extent().
+ */
+static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,
+                               struct fiemap_cache *cache,
+                               u64 offset, u64 phys, u64 len, u32 flags)
+{
+       int ret = 0;
+
+       if (!cache->cached)
+               goto assign;
+
+       /*
+        * Sanity check, extent_fiemap() should have ensured that new
+        * fiemap extent won't overlap with cahced one.
+        * Not recoverable.
+        *
+        * NOTE: Physical address can overlap, due to compression
+        */
+       if (cache->offset + cache->len > offset) {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       /*
+        * Only merges fiemap extents if
+        * 1) Their logical addresses are continuous
+        *
+        * 2) Their physical addresses are continuous
+        *    So truly compressed (physical size smaller than logical size)
+        *    extents won't get merged with each other
+        *
+        * 3) Share same flags except FIEMAP_EXTENT_LAST
+        *    So regular extent won't get merged with prealloc extent
+        */
+       if (cache->offset + cache->len  == offset &&
+           cache->phys + cache->len == phys  &&
+           (cache->flags & ~FIEMAP_EXTENT_LAST) ==
+                       (flags & ~FIEMAP_EXTENT_LAST)) {
+               cache->len += len;
+               cache->flags |= flags;
+               goto try_submit_last;
+       }
+
+       /* Not mergeable, need to submit cached one */
+       ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
+                                     cache->len, cache->flags);
+       cache->cached = false;
+       if (ret)
+               return ret;
+assign:
+       cache->cached = true;
+       cache->offset = offset;
+       cache->phys = phys;
+       cache->len = len;
+       cache->flags = flags;
+try_submit_last:
+       if (cache->flags & FIEMAP_EXTENT_LAST) {
+               ret = fiemap_fill_next_extent(fieinfo, cache->offset,
+                               cache->phys, cache->len, cache->flags);
+               cache->cached = false;
+       }
+       return ret;
+}
+
+/*
+ * Sanity check for fiemap cache
+ *
+ * All fiemap cache should be submitted by emit_fiemap_extent()
+ * Iteration should be terminated either by last fiemap extent or
+ * fieinfo->fi_extents_max.
+ * So no cached fiemap should exist.
+ */
+static int check_fiemap_cache(struct btrfs_fs_info *fs_info,
+                              struct fiemap_extent_info *fieinfo,
+                              struct fiemap_cache *cache)
+{
+       int ret;
+
+       if (!cache->cached)
+               return 0;
+
+       /* Small and recoverbale problem, only to info developer */
+#ifdef CONFIG_BTRFS_DEBUG
+       WARN_ON(1);
+#endif
+       btrfs_warn(fs_info,
+                  "unhandled fiemap cache detected: offset=%llu phys=%llu len=%llu flags=0x%x",
+                  cache->offset, cache->phys, cache->len, cache->flags);
+       ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
+                                     cache->len, cache->flags);
+       cache->cached = false;
+       if (ret > 0)
+               ret = 0;
+       return ret;
+}
+
 int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                __u64 start, __u64 len, get_extent_t *get_extent)
 {
@@ -4394,6 +4511,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        struct extent_state *cached_state = NULL;
        struct btrfs_path *path;
        struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct fiemap_cache cache = { 0 };
        int end = 0;
        u64 em_start = 0;
        u64 em_len = 0;
@@ -4573,8 +4691,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                        flags |= FIEMAP_EXTENT_LAST;
                        end = 1;
                }
-               ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
-                                             em_len, flags);
+               ret = emit_fiemap_extent(fieinfo, &cache, em_start, disko,
+                                          em_len, flags);
                if (ret) {
                        if (ret == 1)
                                ret = 0;
@@ -4582,6 +4700,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                }
        }
 out_free:
+       if (!ret)
+               ret = check_fiemap_cache(root->fs_info, fieinfo, &cache);
        free_extent_map(em);
 out:
        btrfs_free_path(path);
index a97fdc156a03512bf36df40dd1b4278df845115f..baacc18668611b778b9270256a8962b439e4b78e 100644 (file)
@@ -38,6 +38,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
 {
        SHASH_DESC_ON_STACK(shash, tfm);
        u32 *ctx = (u32 *)shash_desc_ctx(shash);
+       u32 retval;
        int err;
 
        shash->tfm = tfm;
@@ -47,5 +48,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
        err = crypto_shash_update(shash, address, length);
        BUG_ON(err);
 
-       return *ctx;
+       retval = *ctx;
+       barrier_data(ctx);
+       return retval;
 }
index 17cbe9306fafd9b9e7247bec4308494ed770b28b..ef3c98c527c136c89b081f5fb0c4ebd414105cbe 100644 (file)
@@ -2952,7 +2952,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
 
        ret = test_range_bit(io_tree, ordered_extent->file_offset,
                        ordered_extent->file_offset + ordered_extent->len - 1,
-                       EXTENT_DEFRAG, 1, cached_state);
+                       EXTENT_DEFRAG, 0, cached_state);
        if (ret) {
                u64 last_snapshot = btrfs_root_last_snapshot(&root->root_item);
                if (0 && last_snapshot >= BTRFS_I(inode)->generation)
@@ -7483,8 +7483,8 @@ bool btrfs_page_exists_in_range(struct inode *inode, loff_t start, loff_t end)
        int found = false;
        void **pagep = NULL;
        struct page *page = NULL;
-       int start_idx;
-       int end_idx;
+       unsigned long start_idx;
+       unsigned long end_idx;
 
        start_idx = start >> PAGE_SHIFT;
 
index 987044bca1c27176ab4d6fca34e5787ae3f9404c..59cb307b15fbea58eca82535b7a7b30ec6db5409 100644 (file)
@@ -131,6 +131,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        }
 
        if (new_mode != old_mode) {
+               newattrs.ia_ctime = current_time(inode);
                newattrs.ia_mode = new_mode;
                newattrs.ia_valid = ATTR_MODE;
                ret = __ceph_setattr(inode, &newattrs);
index e8f11fa565c53ac58fddf402f6ade6320d47d490..7df550c13d7f3e25c2f0f4d6259bd92255a44f58 100644 (file)
@@ -91,6 +91,10 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
                ceph_mdsc_put_request(req);
                if (!inode)
                        return ERR_PTR(-ESTALE);
+               if (inode->i_nlink == 0) {
+                       iput(inode);
+                       return ERR_PTR(-ESTALE);
+               }
        }
 
        return d_obtain_alias(inode);
index 3fdde0b283c9b86f7fa6aaa9585593699be29fca..29308a80d66ffa118b9aec996874d65a952c29aa 100644 (file)
@@ -1671,8 +1671,12 @@ static long ceph_fallocate(struct file *file, int mode,
        }
 
        size = i_size_read(inode);
-       if (!(mode & FALLOC_FL_KEEP_SIZE))
+       if (!(mode & FALLOC_FL_KEEP_SIZE)) {
                endoff = offset + length;
+               ret = inode_newsize_ok(inode, endoff);
+               if (ret)
+                       goto unlock;
+       }
 
        if (fi->fmode & CEPH_FILE_MODE_LAZY)
                want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
index dcce79b844064447af8e542fe34188a4f58e22d9..4de6cdddf05928a29051e9996e75245732fee618 100644 (file)
@@ -2022,7 +2022,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                    attr->ia_size > inode->i_size) {
                        i_size_write(inode, attr->ia_size);
                        inode->i_blocks = calc_inode_blocks(attr->ia_size);
-                       inode->i_ctime = attr->ia_ctime;
                        ci->i_reported_size = attr->ia_size;
                        dirtied |= CEPH_CAP_FILE_EXCL;
                } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
@@ -2044,7 +2043,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                     inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
                     attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
                     only ? "ctime only" : "ignored");
-               inode->i_ctime = attr->ia_ctime;
                if (only) {
                        /*
                         * if kernel wants to dirty ctime but nothing else,
@@ -2067,7 +2065,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
        if (dirtied) {
                inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied,
                                                           &prealloc_cf);
-               inode->i_ctime = current_time(inode);
+               inode->i_ctime = attr->ia_ctime;
        }
 
        release &= issued;
@@ -2085,6 +2083,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                req->r_inode_drop = release;
                req->r_args.setattr.mask = cpu_to_le32(mask);
                req->r_num_caps = 1;
+               req->r_stamp = attr->ia_ctime;
                err = ceph_mdsc_do_request(mdsc, NULL, req);
        }
        dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
index f38e56fa97129d646285fa2b433e8130c7b85312..0c05df44cc6c8888d56d32f53d54fba109f8508c 100644 (file)
@@ -1687,7 +1687,6 @@ struct ceph_mds_request *
 ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
 {
        struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
-       struct timespec ts;
 
        if (!req)
                return ERR_PTR(-ENOMEM);
@@ -1706,8 +1705,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
        init_completion(&req->r_safe_completion);
        INIT_LIST_HEAD(&req->r_unsafe_item);
 
-       ktime_get_real_ts(&ts);
-       req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
+       req->r_stamp = timespec_trunc(current_kernel_time(), mdsc->fsc->sb->s_time_gran);
 
        req->r_op = op;
        req->r_direct_mode = mode;
index 15bac390dff945d7fa5d785f666b2b0291fb9f65..b98436f5c7c74f9e773db0485bb9e80fcb43be99 100644 (file)
@@ -1135,20 +1135,19 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
        u32 acllen = 0;
        int rc = 0;
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-       struct cifs_tcon *tcon;
+       struct smb_version_operations *ops;
 
        cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       tcon = tlink_tcon(tlink);
 
-       if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
-               pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
-                                                         &acllen);
-       else if (tcon->ses->server->ops->get_acl)
-               pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
-                                                       &acllen);
+       ops = tlink_tcon(tlink)->ses->server->ops;
+
+       if (pfid && (ops->get_acl_by_fid))
+               pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
+       else if (ops->get_acl)
+               pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
        else {
                cifs_put_tlink(tlink);
                return -EOPNOTSUPP;
@@ -1181,23 +1180,23 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-       struct cifs_tcon *tcon;
+       struct smb_version_operations *ops;
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       tcon = tlink_tcon(tlink);
+
+       ops = tlink_tcon(tlink)->ses->server->ops;
 
        cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
 
        /* Get the security descriptor */
 
-       if (tcon->ses->server->ops->get_acl == NULL) {
+       if (ops->get_acl == NULL) {
                cifs_put_tlink(tlink);
                return -EOPNOTSUPP;
        }
 
-       pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
-                                               &secdesclen);
+       pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
@@ -1224,13 +1223,12 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
        cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
 
-       if (tcon->ses->server->ops->set_acl == NULL)
+       if (ops->set_acl == NULL)
                rc = -EOPNOTSUPP;
 
        if (!rc) {
                /* Set the security descriptor */
-               rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
-                                                    path, aclflag);
+               rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
                cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
        }
        cifs_put_tlink(tlink);
index 8be55be70faf6c278de7b7c623501385bf21acaf..bcc7d9acad64b3a59b9c966956accb2c51d9ac13 100644 (file)
@@ -418,7 +418,7 @@ struct smb_version_operations {
        int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
        ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
                        const unsigned char *, const unsigned char *, char *,
-                       size_t, const struct nls_table *, int);
+                       size_t, struct cifs_sb_info *);
        int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
                        const char *, const void *, const __u16,
                        const struct nls_table *, int);
index e49958c3f8bbded4265b71e47a87d736a34676da..6eb3147132e30c2225b610b01281111bb896c617 100644 (file)
@@ -480,8 +480,7 @@ extern int CIFSSMBCopy(unsigned int xid,
 extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
                        const unsigned char *searchName,
                        const unsigned char *ea_name, char *EAData,
-                       size_t bufsize, const struct nls_table *nls_codepage,
-                       int remap_special_chars);
+                       size_t bufsize, struct cifs_sb_info *cifs_sb);
 extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
                const char *fileName, const char *ea_name,
                const void *ea_value, const __u16 ea_value_len,
index 4c01b3f9abf02efb70648e030998220bab13bd55..fbb0d4cbda413e5349ab97c8fdfe65435efdc6ed 100644 (file)
@@ -697,9 +697,7 @@ cifs_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, 1, CIFS_ECHO_OP);
 }
 
@@ -1599,9 +1597,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
        }
 
        queue_work(cifsiod_wq, &rdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, 1, 0);
 }
 
@@ -2058,7 +2054,6 @@ cifs_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_writedata *wdata = mid->callback_data;
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
        unsigned int written;
        WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
 
@@ -2095,9 +2090,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
        }
 
        queue_work(cifsiod_wq, &wdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(tcon->ses->server, 1, 0);
 }
 
@@ -6076,11 +6069,13 @@ ssize_t
 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
                const unsigned char *searchName, const unsigned char *ea_name,
                char *EAData, size_t buf_size,
-               const struct nls_table *nls_codepage, int remap)
+               struct cifs_sb_info *cifs_sb)
 {
                /* BB assumes one setup word */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int remap = cifs_remap(cifs_sb);
+       struct nls_table *nls_codepage = cifs_sb->local_nls;
        int rc = 0;
        int bytes_returned;
        int list_len;
index 6ef78ad838e6e3e8b4cf24e72de24fcba8e4313c..fcef70602b278b48ffd74e97f10d2a57b6968cc3 100644 (file)
@@ -582,7 +582,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
-       down_read(&cinode->lock_sem);
+       down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
        if (cinode->can_cache_brlcks) {
                /* can cache locks - no need to relock */
                up_read(&cinode->lock_sem);
@@ -3271,7 +3271,7 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
        if (!is_sync_kiocb(iocb))
                ctx->iocb = iocb;
 
-       if (to->type & ITER_IOVEC)
+       if (to->type == ITER_IOVEC)
                ctx->should_dirty = true;
 
        rc = setup_aio_ctx_iter(ctx, to, READ);
index c3b2fa0b2ec8a6ceed83a74b65bd60cc1e1a7cee..4d1fcd76d022f6848c16294411d5a937e053e27a 100644 (file)
@@ -563,8 +563,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
 
        rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
                        "SETFILEBITS", ea_value, 4 /* size of buf */,
-                       cifs_sb->local_nls,
-                       cifs_remap(cifs_sb));
+                       cifs_sb);
        cifs_put_tlink(tlink);
        if (rc < 0)
                return (int)rc;
index b08531977daa4084f774c75de33204b2b6fa0902..3b147dc6af6344ee5c5e616466403f2cc211dbcb 100644 (file)
@@ -810,7 +810,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
 
        if (!pages) {
                pages = vmalloc(max_pages * sizeof(struct page *));
-               if (!bv) {
+               if (!pages) {
                        kvfree(bv);
                        return -ENOMEM;
                }
index 27bc360c7ffd7e1081f907c5f080dc4ba439fbfc..a723df3e01978cdca30afbf107772898ce66f33a 100644 (file)
@@ -849,8 +849,13 @@ cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
                     struct cifs_fid *fid, __u16 search_flags,
                     struct cifs_search_info *srch_inf)
 {
-       return CIFSFindFirst(xid, tcon, path, cifs_sb,
-                            &fid->netfid, search_flags, srch_inf, true);
+       int rc;
+
+       rc = CIFSFindFirst(xid, tcon, path, cifs_sb,
+                          &fid->netfid, search_flags, srch_inf, true);
+       if (rc)
+               cifs_dbg(FYI, "find first failed=%d\n", rc);
+       return rc;
 }
 
 static int
index c58691834eb2b74fa34f3fe2661ed3e211c4d22e..7e48561abd299012616428d28f256906a7c5381f 100644 (file)
@@ -982,7 +982,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
        rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
        kfree(utf16_path);
        if (rc) {
-               cifs_dbg(VFS, "open dir failed\n");
+               cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
                return rc;
        }
 
@@ -992,7 +992,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
        rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
                                  fid->volatile_fid, 0, srch_inf);
        if (rc) {
-               cifs_dbg(VFS, "query directory failed\n");
+               cifs_dbg(FYI, "query directory failed rc=%d\n", rc);
                SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
        }
        return rc;
@@ -1809,7 +1809,8 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
 
        sg = init_sg(rqst, sign);
        if (!sg) {
-               cifs_dbg(VFS, "%s: Failed to init sg %d", __func__, rc);
+               cifs_dbg(VFS, "%s: Failed to init sg", __func__);
+               rc = -ENOMEM;
                goto free_req;
        }
 
@@ -1817,6 +1818,7 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
        iv = kzalloc(iv_len, GFP_KERNEL);
        if (!iv) {
                cifs_dbg(VFS, "%s: Failed to alloc IV", __func__);
+               rc = -ENOMEM;
                goto free_sg;
        }
        iv[0] = 3;
index 48ff7703b91912c79b8412539919c3ce6fe76ac6..e4afdaae743f28cf2d1396faed88e7465f875d48 100644 (file)
@@ -1240,15 +1240,19 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
                goto tcon_exit;
        }
 
-       if (rsp->ShareType & SMB2_SHARE_TYPE_DISK)
+       switch (rsp->ShareType) {
+       case SMB2_SHARE_TYPE_DISK:
                cifs_dbg(FYI, "connection to disk share\n");
-       else if (rsp->ShareType & SMB2_SHARE_TYPE_PIPE) {
+               break;
+       case SMB2_SHARE_TYPE_PIPE:
                tcon->ipc = true;
                cifs_dbg(FYI, "connection to pipe share\n");
-       } else if (rsp->ShareType & SMB2_SHARE_TYPE_PRINT) {
-               tcon->print = true;
+               break;
+       case SMB2_SHARE_TYPE_PRINT:
+               tcon->ipc = true;
                cifs_dbg(FYI, "connection to printer\n");
-       } else {
+               break;
+       default:
                cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
                rc = -EOPNOTSUPP;
                goto tcon_error_exit;
@@ -2173,9 +2177,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
        if (mid->mid_state == MID_RESPONSE_RECEIVED)
                credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, credits_received, CIFS_ECHO_OP);
 }
 
@@ -2433,9 +2435,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
 
        queue_work(cifsiod_wq, &rdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, credits_received, 0);
 }
 
@@ -2594,7 +2594,6 @@ smb2_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_writedata *wdata = mid->callback_data;
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
        unsigned int credits_received = 1;
@@ -2634,9 +2633,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
 
        queue_work(cifsiod_wq, &wdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(tcon->ses->server, credits_received, 0);
 }
 
index 4d64b5b8fc9c6fae67f7f3e0ec74284548ff7c32..47a125ece11ea0d3e2daa0814c8cab28b4643bb1 100644 (file)
@@ -94,7 +94,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
        now = jiffies;
        /* commands taking longer than one second are indications that
           something is wrong, unless it is quite a slow link or server */
-       if ((now - midEntry->when_alloc) > HZ) {
+       if (time_after(now, midEntry->when_alloc + HZ)) {
                if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
                        pr_debug(" CIFS slow rsp: cmd %d mid %llu",
                               midEntry->command, midEntry->mid);
@@ -613,9 +613,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
        }
        spin_unlock(&GlobalMid_Lock);
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        return rc;
 }
 
index 20af5187ba63cc14150185952a3f7cdf9526556d..de50e749ff058d79c67f7462962614c8c835ecdb 100644 (file)
@@ -188,8 +188,6 @@ static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
        pcreatetime = (__u64 *)value;
        *pcreatetime = CIFS_I(inode)->createtime;
        return sizeof(__u64);
-
-       return rc;
 }
 
 
@@ -235,8 +233,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 
                if (pTcon->ses->server->ops->query_all_EAs)
                        rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-                               full_path, name, value, size,
-                               cifs_sb->local_nls, cifs_remap(cifs_sb));
+                               full_path, name, value, size, cifs_sb);
                break;
 
        case XATTR_CIFS_ACL: {
@@ -336,8 +333,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
 
        if (pTcon->ses->server->ops->query_all_EAs)
                rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-                               full_path, NULL, data, buf_size,
-                               cifs_sb->local_nls, cifs_remap(cifs_sb));
+                               full_path, NULL, data, buf_size, cifs_sb);
 list_ea_exit:
        kfree(full_path);
        free_xid(xid);
index 8b2a994042ddeb2d1b8c00bbee3436e79fff52ad..a66f6624d89943997d1d35ead214aee85857e5d7 100644 (file)
@@ -138,6 +138,14 @@ struct config_item *config_item_get(struct config_item *item)
 }
 EXPORT_SYMBOL(config_item_get);
 
+struct config_item *config_item_get_unless_zero(struct config_item *item)
+{
+       if (item && kref_get_unless_zero(&item->ci_kref))
+               return item;
+       return NULL;
+}
+EXPORT_SYMBOL(config_item_get_unless_zero);
+
 static void config_item_cleanup(struct config_item *item)
 {
        struct config_item_type *t = item->ci_type;
index a6ab012a2c6acf9815bb8d4d1e29fb4568084b08..c8aabba502f6d7f019890bcdeba2fcdd7a56717f 100644 (file)
@@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item,
        ret = -ENOMEM;
        sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
        if (sl) {
-               sl->sl_target = config_item_get(item);
                spin_lock(&configfs_dirent_lock);
                if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
                        spin_unlock(&configfs_dirent_lock);
-                       config_item_put(item);
                        kfree(sl);
                        return -ENOENT;
                }
+               sl->sl_target = config_item_get(item);
                list_add(&sl->sl_list, &target_sd->s_links);
                spin_unlock(&configfs_dirent_lock);
                ret = configfs_create_link(sl, parent_item->ci_dentry,
index c22eaf162f95c1456563b31a8362da9e531c9185..9187f3b07f3e7f7b8546724d83dd06f4d16e7d8b 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -859,6 +859,7 @@ int dax_writeback_mapping_range(struct address_space *mapping,
                        if (ret < 0)
                                goto out;
                }
+               start_index = indices[pvec.nr - 1] + 1;
        }
 out:
        put_dax(dax_dev);
@@ -1154,6 +1155,17 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf,
                goto out;
        }
 
+       /*
+        * It is possible, particularly with mixed reads & writes to private
+        * mappings, that we have raced with a PMD fault that overlaps with
+        * the PTE we need to set up.  If so just return and the fault will be
+        * retried.
+        */
+       if (pmd_trans_huge(*vmf->pmd) || pmd_devmap(*vmf->pmd)) {
+               vmf_ret = VM_FAULT_NOPAGE;
+               goto unlock_entry;
+       }
+
        /*
         * Note that we don't bother to use iomap_apply here: DAX required
         * the file system block size to be equal the page size, which means
@@ -1397,6 +1409,18 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf,
        if (IS_ERR(entry))
                goto fallback;
 
+       /*
+        * It is possible, particularly with mixed reads & writes to private
+        * mappings, that we have raced with a PTE fault that overlaps with
+        * the PMD we need to set up.  If so just return and the fault will be
+        * retried.
+        */
+       if (!pmd_none(*vmf->pmd) && !pmd_trans_huge(*vmf->pmd) &&
+                       !pmd_devmap(*vmf->pmd)) {
+               result = 0;
+               goto unlock_entry;
+       }
+
        /*
         * Note that we don't use iomap_apply here.  We aren't doing I/O, only
         * setting up a mapping, so really we're using iomap_begin() as a way
index cddf39777835d0d27a71862b244cec37528b195b..a9f995f6859eb19ea3c5cddac19d86512ccf1d1e 100644 (file)
@@ -1494,7 +1494,7 @@ static void check_and_drop(void *_data)
 {
        struct detach_data *data = _data;
 
-       if (!data->mountpoint && !data->select.found)
+       if (!data->mountpoint && list_empty(&data->select.dispose))
                __d_drop(data->select.start);
 }
 
@@ -1536,17 +1536,15 @@ void d_invalidate(struct dentry *dentry)
 
                d_walk(dentry, &data, detach_and_collect, check_and_drop);
 
-               if (data.select.found)
+               if (!list_empty(&data.select.dispose))
                        shrink_dentry_list(&data.select.dispose);
+               else if (!data.mountpoint)
+                       return;
 
                if (data.mountpoint) {
                        detach_mounts(data.mountpoint);
                        dput(data.mountpoint);
                }
-
-               if (!data.mountpoint && !data.select.found)
-                       break;
-
                cond_resched();
        }
 }
index 72934df6847150ba50dfbadad78fe10e01d2eadd..904199086490d5fdf05d0eda850d04a3ce572fa5 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -220,8 +220,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
 
        if (write) {
                unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
+               unsigned long ptr_size;
                struct rlimit *rlim;
 
+               /*
+                * Since the stack will hold pointers to the strings, we
+                * must account for them as well.
+                *
+                * The size calculation is the entire vma while each arg page is
+                * built, so each time we get here it's calculating how far it
+                * is currently (rather than each call being just the newly
+                * added size from the arg page).  As a result, we need to
+                * always add the entire size of the pointers, so that on the
+                * last call to get_arg_page() we'll actually have the entire
+                * correct size.
+                */
+               ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
+               if (ptr_size > ULONG_MAX - size)
+                       goto fail;
+               size += ptr_size;
+
                acct_arg_size(bprm, size / PAGE_SIZE);
 
                /*
@@ -239,13 +257,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
                 *    to work from.
                 */
                rlim = current->signal->rlim;
-               if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
-                       put_page(page);
-                       return NULL;
-               }
+               if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4)
+                       goto fail;
        }
 
        return page;
+
+fail:
+       put_page(page);
+       return NULL;
 }
 
 static void put_arg_page(struct page *page)
index 26d77f9f8c12e69f48bc6cc1c4f47bb6fab27ebd..2dcbd56988843ccdfb017c9b14ca8f5b05a31b62 100644 (file)
@@ -817,7 +817,7 @@ static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
        iomap->bdev = bdev;
        iomap->offset = (u64)first_block << blkbits;
        if (blk_queue_dax(bdev->bd_queue))
-               iomap->dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+               iomap->dax_dev = fs_dax_get_by_host(bdev->bd_disk->disk_name);
        else
                iomap->dax_dev = NULL;
 
@@ -841,7 +841,7 @@ static int
 ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
                ssize_t written, unsigned flags, struct iomap *iomap)
 {
-       put_dax(iomap->dax_dev);
+       fs_put_dax(iomap->dax_dev);
        if (iomap->type == IOMAP_MAPPED &&
            written < length &&
            (flags & IOMAP_WRITE))
index fd389935ecd1629f402128518f63fd7d851e2a84..3ec0e46de95fc8dece943c4d753eb401e6343cad 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
  */
 
+#include <linux/quotaops.h>
 #include "ext4_jbd2.h"
 #include "ext4.h"
 #include "xattr.h"
@@ -232,6 +233,9 @@ ext4_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        handle_t *handle;
        int error, retries = 0;
 
+       error = dquot_initialize(inode);
+       if (error)
+               return error;
 retry:
        handle = ext4_journal_start(inode, EXT4_HT_XATTR,
                                    ext4_jbd2_credits_xattr(inode));
index 8e8046104f4d8a945f2eae5e3bca7cb214d3cbb8..32191548abed3b02eb107bfd5a23196f40200a70 100644 (file)
@@ -2523,7 +2523,6 @@ extern int ext4_search_dir(struct buffer_head *bh,
                           int buf_size,
                           struct inode *dir,
                           struct ext4_filename *fname,
-                          const struct qstr *d_name,
                           unsigned int offset,
                           struct ext4_dir_entry_2 **res_dir);
 extern int ext4_generic_delete_entry(handle_t *handle,
@@ -3007,7 +3006,6 @@ extern int htree_inlinedir_to_tree(struct file *dir_file,
                                   int *has_inline_data);
 extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
                                        struct ext4_filename *fname,
-                                       const struct qstr *d_name,
                                        struct ext4_dir_entry_2 **res_dir,
                                        int *has_inline_data);
 extern int ext4_delete_inline_entry(handle_t *handle,
index 2a97dff87b961771383c33e97dc57997eb6586fb..3e36508610b796b6612cc1e670a0fc2c8c3c282a 100644 (file)
@@ -3413,13 +3413,13 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        struct ext4_sb_info *sbi;
        struct ext4_extent_header *eh;
        struct ext4_map_blocks split_map;
-       struct ext4_extent zero_ex;
+       struct ext4_extent zero_ex1, zero_ex2;
        struct ext4_extent *ex, *abut_ex;
        ext4_lblk_t ee_block, eof_block;
        unsigned int ee_len, depth, map_len = map->m_len;
        int allocated = 0, max_zeroout = 0;
        int err = 0;
-       int split_flag = 0;
+       int split_flag = EXT4_EXT_DATA_VALID2;
 
        ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical"
                "block %llu, max_blocks %u\n", inode->i_ino,
@@ -3436,7 +3436,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        ex = path[depth].p_ext;
        ee_block = le32_to_cpu(ex->ee_block);
        ee_len = ext4_ext_get_actual_len(ex);
-       zero_ex.ee_len = 0;
+       zero_ex1.ee_len = 0;
+       zero_ex2.ee_len = 0;
 
        trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);
 
@@ -3576,62 +3577,52 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        if (ext4_encrypted_inode(inode))
                max_zeroout = 0;
 
-       /* If extent is less than s_max_zeroout_kb, zeroout directly */
-       if (max_zeroout && (ee_len <= max_zeroout)) {
-               err = ext4_ext_zeroout(inode, ex);
-               if (err)
-                       goto out;
-               zero_ex.ee_block = ex->ee_block;
-               zero_ex.ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex));
-               ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex));
-
-               err = ext4_ext_get_access(handle, inode, path + depth);
-               if (err)
-                       goto out;
-               ext4_ext_mark_initialized(ex);
-               ext4_ext_try_to_merge(handle, inode, path, ex);
-               err = ext4_ext_dirty(handle, inode, path + path->p_depth);
-               goto out;
-       }
-
        /*
-        * four cases:
+        * five cases:
         * 1. split the extent into three extents.
-        * 2. split the extent into two extents, zeroout the first half.
-        * 3. split the extent into two extents, zeroout the second half.
+        * 2. split the extent into two extents, zeroout the head of the first
+        *    extent.
+        * 3. split the extent into two extents, zeroout the tail of the second
+        *    extent.
         * 4. split the extent into two extents with out zeroout.
+        * 5. no splitting needed, just possibly zeroout the head and / or the
+        *    tail of the extent.
         */
        split_map.m_lblk = map->m_lblk;
        split_map.m_len = map->m_len;
 
-       if (max_zeroout && (allocated > map->m_len)) {
+       if (max_zeroout && (allocated > split_map.m_len)) {
                if (allocated <= max_zeroout) {
-                       /* case 3 */
-                       zero_ex.ee_block =
-                                        cpu_to_le32(map->m_lblk);
-                       zero_ex.ee_len = cpu_to_le16(allocated);
-                       ext4_ext_store_pblock(&zero_ex,
-                               ext4_ext_pblock(ex) + map->m_lblk - ee_block);
-                       err = ext4_ext_zeroout(inode, &zero_ex);
+                       /* case 3 or 5 */
+                       zero_ex1.ee_block =
+                                cpu_to_le32(split_map.m_lblk +
+                                            split_map.m_len);
+                       zero_ex1.ee_len =
+                               cpu_to_le16(allocated - split_map.m_len);
+                       ext4_ext_store_pblock(&zero_ex1,
+                               ext4_ext_pblock(ex) + split_map.m_lblk +
+                               split_map.m_len - ee_block);
+                       err = ext4_ext_zeroout(inode, &zero_ex1);
                        if (err)
                                goto out;
-                       split_map.m_lblk = map->m_lblk;
                        split_map.m_len = allocated;
-               } else if (map->m_lblk - ee_block + map->m_len < max_zeroout) {
-                       /* case 2 */
-                       if (map->m_lblk != ee_block) {
-                               zero_ex.ee_block = ex->ee_block;
-                               zero_ex.ee_len = cpu_to_le16(map->m_lblk -
+               }
+               if (split_map.m_lblk - ee_block + split_map.m_len <
+                                                               max_zeroout) {
+                       /* case 2 or 5 */
+                       if (split_map.m_lblk != ee_block) {
+                               zero_ex2.ee_block = ex->ee_block;
+                               zero_ex2.ee_len = cpu_to_le16(split_map.m_lblk -
                                                        ee_block);
-                               ext4_ext_store_pblock(&zero_ex,
+                               ext4_ext_store_pblock(&zero_ex2,
                                                      ext4_ext_pblock(ex));
-                               err = ext4_ext_zeroout(inode, &zero_ex);
+                               err = ext4_ext_zeroout(inode, &zero_ex2);
                                if (err)
                                        goto out;
                        }
 
+                       split_map.m_len += split_map.m_lblk - ee_block;
                        split_map.m_lblk = ee_block;
-                       split_map.m_len = map->m_lblk - ee_block + map->m_len;
                        allocated = map->m_len;
                }
        }
@@ -3642,8 +3633,11 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                err = 0;
 out:
        /* If we have gotten a failure, don't zero out status tree */
-       if (!err)
-               err = ext4_zeroout_es(inode, &zero_ex);
+       if (!err) {
+               err = ext4_zeroout_es(inode, &zero_ex1);
+               if (!err)
+                       err = ext4_zeroout_es(inode, &zero_ex2);
+       }
        return err ? err : allocated;
 }
 
@@ -4883,6 +4877,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 
        /* Zero out partial block at the edges of the range */
        ret = ext4_zero_partial_blocks(handle, inode, offset, len);
+       if (ret >= 0)
+               ext4_update_inode_fsync_trans(handle, inode, 1);
 
        if (file->f_flags & O_SYNC)
                ext4_handle_sync(handle);
@@ -5569,6 +5565,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len)
                ext4_handle_sync(handle);
        inode->i_mtime = inode->i_ctime = current_time(inode);
        ext4_mark_inode_dirty(handle, inode);
+       ext4_update_inode_fsync_trans(handle, inode, 1);
 
 out_stop:
        ext4_journal_stop(handle);
@@ -5742,6 +5739,8 @@ int ext4_insert_range(struct inode *inode, loff_t offset, loff_t len)
        up_write(&EXT4_I(inode)->i_data_sem);
        if (IS_SYNC(inode))
                ext4_handle_sync(handle);
+       if (ret >= 0)
+               ext4_update_inode_fsync_trans(handle, inode, 1);
 
 out_stop:
        ext4_journal_stop(handle);
index 831fd6beebf01bfa65c1c4a3ae505ed84bd35526..02ce7e7bbdf5ba4da0db50e50d8d4cab49cde4a3 100644 (file)
@@ -474,57 +474,37 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
        endoff = (loff_t)end_blk << blkbits;
 
        index = startoff >> PAGE_SHIFT;
-       end = endoff >> PAGE_SHIFT;
+       end = (endoff - 1) >> PAGE_SHIFT;
 
        pagevec_init(&pvec, 0);
        do {
                int i, num;
                unsigned long nr_pages;
 
-               num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
+               num = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
                nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
                                          (pgoff_t)num);
-               if (nr_pages == 0) {
-                       if (whence == SEEK_DATA)
-                               break;
-
-                       BUG_ON(whence != SEEK_HOLE);
-                       /*
-                        * If this is the first time to go into the loop and
-                        * offset is not beyond the end offset, it will be a
-                        * hole at this offset
-                        */
-                       if (lastoff == startoff || lastoff < endoff)
-                               found = 1;
-                       break;
-               }
-
-               /*
-                * If this is the first time to go into the loop and
-                * offset is smaller than the first page offset, it will be a
-                * hole at this offset.
-                */
-               if (lastoff == startoff && whence == SEEK_HOLE &&
-                   lastoff < page_offset(pvec.pages[0])) {
-                       found = 1;
+               if (nr_pages == 0)
                        break;
-               }
 
                for (i = 0; i < nr_pages; i++) {
                        struct page *page = pvec.pages[i];
                        struct buffer_head *bh, *head;
 
                        /*
-                        * If the current offset is not beyond the end of given
-                        * range, it will be a hole.
+                        * If current offset is smaller than the page offset,
+                        * there is a hole at this offset.
                         */
-                       if (lastoff < endoff && whence == SEEK_HOLE &&
-                           page->index > end) {
+                       if (whence == SEEK_HOLE && lastoff < endoff &&
+                           lastoff < page_offset(pvec.pages[i])) {
                                found = 1;
                                *offset = lastoff;
                                goto out;
                        }
 
+                       if (page->index > end)
+                               goto out;
+
                        lock_page(page);
 
                        if (unlikely(page->mapping != inode->i_mapping)) {
@@ -564,20 +544,18 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
                        unlock_page(page);
                }
 
-               /*
-                * The no. of pages is less than our desired, that would be a
-                * hole in there.
-                */
-               if (nr_pages < num && whence == SEEK_HOLE) {
-                       found = 1;
-                       *offset = lastoff;
+               /* The no. of pages is less than our desired, we are done. */
+               if (nr_pages < num)
                        break;
-               }
 
                index = pvec.pages[i - 1]->index + 1;
                pagevec_release(&pvec);
        } while (index <= end);
 
+       if (whence == SEEK_HOLE && lastoff < endoff) {
+               found = 1;
+               *offset = lastoff;
+       }
 out:
        pagevec_release(&pvec);
        return found;
index d5dea4c293ef46be022c538d0465e60284b20fe4..8d141c0c8ff9de32a5be08a48f573de7fa618dc5 100644 (file)
@@ -1627,7 +1627,6 @@ out:
 
 struct buffer_head *ext4_find_inline_entry(struct inode *dir,
                                        struct ext4_filename *fname,
-                                       const struct qstr *d_name,
                                        struct ext4_dir_entry_2 **res_dir,
                                        int *has_inline_data)
 {
@@ -1649,7 +1648,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
                                                EXT4_INLINE_DOTDOT_SIZE;
        inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
        ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
-                             dir, fname, d_name, 0, res_dir);
+                             dir, fname, 0, res_dir);
        if (ret == 1)
                goto out_find;
        if (ret < 0)
@@ -1662,7 +1661,7 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
        inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE;
 
        ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
-                             dir, fname, d_name, 0, res_dir);
+                             dir, fname, 0, res_dir);
        if (ret == 1)
                goto out_find;
 
index 5834c4d76be80969125a9c2d56309e990ba07e84..5cf82d03968ca2c0eb240461fa696e784694c1ea 100644 (file)
@@ -2124,15 +2124,29 @@ static int ext4_writepage(struct page *page,
 static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page)
 {
        int len;
-       loff_t size = i_size_read(mpd->inode);
+       loff_t size;
        int err;
 
        BUG_ON(page->index != mpd->first_page);
+       clear_page_dirty_for_io(page);
+       /*
+        * We have to be very careful here!  Nothing protects writeback path
+        * against i_size changes and the page can be writeably mapped into
+        * page tables. So an application can be growing i_size and writing
+        * data through mmap while writeback runs. clear_page_dirty_for_io()
+        * write-protects our page in page tables and the page cannot get
+        * written to again until we release page lock. So only after
+        * clear_page_dirty_for_io() we are safe to sample i_size for
+        * ext4_bio_write_page() to zero-out tail of the written page. We rely
+        * on the barrier provided by TestClearPageDirty in
+        * clear_page_dirty_for_io() to make sure i_size is really sampled only
+        * after page tables are updated.
+        */
+       size = i_size_read(mpd->inode);
        if (page->index == size >> PAGE_SHIFT)
                len = size & ~PAGE_MASK;
        else
                len = PAGE_SIZE;
-       clear_page_dirty_for_io(page);
        err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false);
        if (!err)
                mpd->wbc->nr_to_write--;
@@ -3412,7 +3426,7 @@ retry:
        bdev = inode->i_sb->s_bdev;
        iomap->bdev = bdev;
        if (blk_queue_dax(bdev->bd_queue))
-               iomap->dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+               iomap->dax_dev = fs_dax_get_by_host(bdev->bd_disk->disk_name);
        else
                iomap->dax_dev = NULL;
        iomap->offset = first_block << blkbits;
@@ -3447,7 +3461,7 @@ static int ext4_iomap_end(struct inode *inode, loff_t offset, loff_t length,
        int blkbits = inode->i_blkbits;
        bool truncate = false;
 
-       put_dax(iomap->dax_dev);
+       fs_put_dax(iomap->dax_dev);
        if (!(flags & IOMAP_WRITE) || (flags & IOMAP_FAULT))
                return 0;
 
@@ -3629,9 +3643,6 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter)
                get_block_func = ext4_dio_get_block_unwritten_async;
                dio_flags = DIO_LOCKING;
        }
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-       BUG_ON(ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode));
-#endif
        ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter,
                                   get_block_func, ext4_end_io_dio, NULL,
                                   dio_flags);
@@ -3713,7 +3724,7 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter)
         */
        inode_lock_shared(inode);
        ret = filemap_write_and_wait_range(mapping, iocb->ki_pos,
-                                          iocb->ki_pos + count);
+                                          iocb->ki_pos + count - 1);
        if (ret)
                goto out_unlock;
        ret = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
@@ -4207,6 +4218,8 @@ int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length)
 
        inode->i_mtime = inode->i_ctime = current_time(inode);
        ext4_mark_inode_dirty(handle, inode);
+       if (ret >= 0)
+               ext4_update_inode_fsync_trans(handle, inode, 1);
 out_stop:
        ext4_journal_stop(handle);
 out_dio:
@@ -5637,8 +5650,9 @@ static int ext4_expand_extra_isize(struct inode *inode,
        /* No extended attributes present */
        if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) ||
            header->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC)) {
-               memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE, 0,
-                       new_extra_isize);
+               memset((void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
+                      EXT4_I(inode)->i_extra_isize, 0,
+                      new_extra_isize - EXT4_I(inode)->i_extra_isize);
                EXT4_I(inode)->i_extra_isize = new_extra_isize;
                return 0;
        }
index 5083bce20ac4dc2243ace1bba19ef506b90d9c29..b7928cddd539ee223584db33ab8cb3341faa2e86 100644 (file)
@@ -3887,7 +3887,8 @@ ext4_mb_discard_group_preallocations(struct super_block *sb,
 
        err = ext4_mb_load_buddy(sb, group, &e4b);
        if (err) {
-               ext4_error(sb, "Error loading buddy information for %u", group);
+               ext4_warning(sb, "Error %d loading buddy information for %u",
+                            err, group);
                put_bh(bitmap_bh);
                return 0;
        }
@@ -4044,10 +4045,11 @@ repeat:
                BUG_ON(pa->pa_type != MB_INODE_PA);
                group = ext4_get_group_number(sb, pa->pa_pstart);
 
-               err = ext4_mb_load_buddy(sb, group, &e4b);
+               err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
+                                            GFP_NOFS|__GFP_NOFAIL);
                if (err) {
-                       ext4_error(sb, "Error loading buddy information for %u",
-                                       group);
+                       ext4_error(sb, "Error %d loading buddy information for %u",
+                                  err, group);
                        continue;
                }
 
@@ -4303,11 +4305,14 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
        spin_unlock(&lg->lg_prealloc_lock);
 
        list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) {
+               int err;
 
                group = ext4_get_group_number(sb, pa->pa_pstart);
-               if (ext4_mb_load_buddy(sb, group, &e4b)) {
-                       ext4_error(sb, "Error loading buddy information for %u",
-                                       group);
+               err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
+                                            GFP_NOFS|__GFP_NOFAIL);
+               if (err) {
+                       ext4_error(sb, "Error %d loading buddy information for %u",
+                                  err, group);
                        continue;
                }
                ext4_lock_group(sb, group);
@@ -5127,8 +5132,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
 
        ret = ext4_mb_load_buddy(sb, group, &e4b);
        if (ret) {
-               ext4_error(sb, "Error in loading buddy "
-                               "information for %u", group);
+               ext4_warning(sb, "Error %d loading buddy information for %u",
+                            ret, group);
                return ret;
        }
        bitmap = e4b.bd_bitmap;
index b81f7d46f344d482d4a7ab15a5cc1ad3654b3259..404256caf9cff0df28517350113dff0d8b239cc9 100644 (file)
@@ -1155,12 +1155,11 @@ errout:
 static inline int search_dirblock(struct buffer_head *bh,
                                  struct inode *dir,
                                  struct ext4_filename *fname,
-                                 const struct qstr *d_name,
                                  unsigned int offset,
                                  struct ext4_dir_entry_2 **res_dir)
 {
        return ext4_search_dir(bh, bh->b_data, dir->i_sb->s_blocksize, dir,
-                              fname, d_name, offset, res_dir);
+                              fname, offset, res_dir);
 }
 
 /*
@@ -1262,7 +1261,6 @@ static inline bool ext4_match(const struct ext4_filename *fname,
  */
 int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
                    struct inode *dir, struct ext4_filename *fname,
-                   const struct qstr *d_name,
                    unsigned int offset, struct ext4_dir_entry_2 **res_dir)
 {
        struct ext4_dir_entry_2 * de;
@@ -1355,7 +1353,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
 
        if (ext4_has_inline_data(dir)) {
                int has_inline_data = 1;
-               ret = ext4_find_inline_entry(dir, &fname, d_name, res_dir,
+               ret = ext4_find_inline_entry(dir, &fname, res_dir,
                                             &has_inline_data);
                if (has_inline_data) {
                        if (inlined)
@@ -1447,7 +1445,7 @@ restart:
                        goto next;
                }
                set_buffer_verified(bh);
-               i = search_dirblock(bh, dir, &fname, d_name,
+               i = search_dirblock(bh, dir, &fname,
                            block << EXT4_BLOCK_SIZE_BITS(sb), res_dir);
                if (i == 1) {
                        EXT4_I(dir)->i_dir_start_lookup = block;
@@ -1488,7 +1486,6 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
 {
        struct super_block * sb = dir->i_sb;
        struct dx_frame frames[2], *frame;
-       const struct qstr *d_name = fname->usr_fname;
        struct buffer_head *bh;
        ext4_lblk_t block;
        int retval;
@@ -1505,7 +1502,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
                if (IS_ERR(bh))
                        goto errout;
 
-               retval = search_dirblock(bh, dir, fname, d_name,
+               retval = search_dirblock(bh, dir, fname,
                                         block << EXT4_BLOCK_SIZE_BITS(sb),
                                         res_dir);
                if (retval == 1)
@@ -1530,7 +1527,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
 
        bh = NULL;
 errout:
-       dxtrace(printk(KERN_DEBUG "%s not found\n", d_name->name));
+       dxtrace(printk(KERN_DEBUG "%s not found\n", fname->usr_fname->name));
 success:
        dx_release(frames);
        return bh;
index 0b177da9ea8271f4a46208937d3c43fd20c0e9b7..d37c81f327e790cc4a309fd0a12baef0dc2ff4ac 100644 (file)
@@ -848,14 +848,9 @@ static inline void ext4_quota_off_umount(struct super_block *sb)
 {
        int type;
 
-       if (ext4_has_feature_quota(sb)) {
-               dquot_disable(sb, -1,
-                             DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
-       } else {
-               /* Use our quota_off function to clear inode flags etc. */
-               for (type = 0; type < EXT4_MAXQUOTAS; type++)
-                       ext4_quota_off(sb, type);
-       }
+       /* Use our quota_off function to clear inode flags etc. */
+       for (type = 0; type < EXT4_MAXQUOTAS; type++)
+               ext4_quota_off(sb, type);
 }
 #else
 static inline void ext4_quota_off_umount(struct super_block *sb)
@@ -1179,6 +1174,9 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
                return res;
        }
 
+       res = dquot_initialize(inode);
+       if (res)
+               return res;
 retry:
        handle = ext4_journal_start(inode, EXT4_HT_MISC,
                        ext4_jbd2_credits_xattr(inode));
@@ -5485,7 +5483,7 @@ static int ext4_quota_off(struct super_block *sb, int type)
                goto out;
 
        err = dquot_quota_off(sb, type);
-       if (err)
+       if (err || ext4_has_feature_quota(sb))
                goto out_put;
 
        inode_lock(inode);
@@ -5505,6 +5503,7 @@ static int ext4_quota_off(struct super_block *sb, int type)
 out_unlock:
        inode_unlock(inode);
 out_put:
+       lockdep_set_quota_inode(inode, I_DATA_SEM_NORMAL);
        iput(inode);
        return err;
 out:
index 8fb7ce14e6ebe3a4ba1f2bd2da36b314819d24a5..5d3c2536641c7db6c1fa5b19b4ad10e630e09986 100644 (file)
@@ -888,6 +888,8 @@ inserted:
                        else {
                                u32 ref;
 
+                               WARN_ON_ONCE(dquot_initialize_needed(inode));
+
                                /* The old block is released after updating
                                   the inode. */
                                error = dquot_alloc_block(inode,
@@ -954,6 +956,8 @@ inserted:
                        /* We need to allocate a new block */
                        ext4_fsblk_t goal, block;
 
+                       WARN_ON_ONCE(dquot_initialize_needed(inode));
+
                        goal = ext4_group_first_block_no(sb,
                                                EXT4_I(inode)->i_block_group);
 
@@ -1166,6 +1170,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
                return -EINVAL;
        if (strlen(name) > 255)
                return -ERANGE;
+
        ext4_write_lock_xattr(inode, &no_expand);
 
        error = ext4_reserve_inode_write(handle, inode, &is.iloc);
@@ -1267,6 +1272,9 @@ ext4_xattr_set(struct inode *inode, int name_index, const char *name,
        int error, retries = 0;
        int credits = ext4_jbd2_credits_xattr(inode);
 
+       error = dquot_initialize(inode);
+       if (error)
+               return error;
 retry:
        handle = ext4_journal_start(inode, EXT4_HT_XATTR, credits);
        if (IS_ERR(handle)) {
index 2185c7a040a12cf8b6e190df97b58bc7eecc6299..fd2e651bad6d3c620b83f9dc32e25dfad22a4e7f 100644 (file)
@@ -1078,6 +1078,7 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
 {
        SHASH_DESC_ON_STACK(shash, sbi->s_chksum_driver);
        u32 *ctx = (u32 *)shash_desc_ctx(shash);
+       u32 retval;
        int err;
 
        shash->tfm = sbi->s_chksum_driver;
@@ -1087,7 +1088,9 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
        err = crypto_shash_update(shash, address, length);
        BUG_ON(err);
 
-       return *ctx;
+       retval = *ctx;
+       barrier_data(ctx);
+       return retval;
 }
 
 static inline bool f2fs_crc_valid(struct f2fs_sb_info *sbi, __u32 blk_crc,
index 5a1b58f8fef4d2437842b73d4c1c12b2e87a32c9..65c88379a3a14311cca68b8750d6bb0b9f107444 100644 (file)
@@ -975,8 +975,15 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
        int err;
        char *suffix = "";
 
-       if (sb->s_bdev)
+       if (sb->s_bdev) {
                suffix = "-fuseblk";
+               /*
+                * sb->s_bdi points to blkdev's bdi however we want to redirect
+                * it to our private bdi...
+                */
+               bdi_put(sb->s_bdi);
+               sb->s_bdi = &noop_backing_dev_info;
+       }
        err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev),
                                   MINOR(fc->dev), suffix);
        if (err)
index f865b96374df2b5c40ecfb13663154499ec09b31..d2955daf17a4fcefa2ded3a412f67732315de12a 100644 (file)
@@ -659,7 +659,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
        struct gfs2_log_header *lh;
        unsigned int tail;
        u32 hash;
-       int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META;
+       int op_flags = REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC;
        struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO);
        enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state);
        lh = page_address(page);
index dde861387a407810b35f73ff37c3ce6389048326..d44f5456eb9baf943186a2d145736c6435f891fb 100644 (file)
@@ -200,7 +200,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
                addr = ALIGN(addr, huge_page_size(h));
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)))
                        return addr;
        }
 
index 9ee4832b6f8b3664430e31bcf3775b412e1b81d8..2d30a6da7013112adafd08545b32cb00d179311c 100644 (file)
@@ -680,6 +680,12 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask)
 
        rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_);
        handle->h_buffer_credits = nblocks;
+       /*
+        * Restore the original nofs context because the journal restart
+        * is basically the same thing as journal stop and start.
+        * start_this_handle will start a new nofs context.
+        */
+       memalloc_nofs_restore(handle->saved_alloc_context);
        ret = start_this_handle(journal, handle, gfp_mask);
        return ret;
 }
index 8bd3e4d448b9f07a8aa148c8d08c092f45471a7c..5a4438445bf788e65ade26b741911861d7ea2084 100644 (file)
@@ -3488,6 +3488,8 @@ static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
                return err;
        }
 
+       put_mnt_ns(old_mnt_ns);
+
        /* Update the pwd and root */
        set_fs_pwd(fs, &root);
        set_fs_root(fs, &root);
index c14758e08d738eec44bf08c79acee71366ce0e70..390ac9c39c5932ef93f3ae8d3a5615f2737848af 100644 (file)
@@ -753,7 +753,6 @@ static void nfs4_callback_free_slot(struct nfs4_session *session,
         * A single slot, so highest used slotid is either 0 or -1
         */
        nfs4_free_slot(tbl, slot);
-       nfs4_slot_tbl_drain_complete(tbl);
        spin_unlock(&tbl->slot_tbl_lock);
 }
 
index 32ccd7754f8a2875933d1f9c532b54c656971bfd..2ac00bf4ecf146815bff44755f4406161e569007 100644 (file)
@@ -1946,29 +1946,6 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 }
 EXPORT_SYMBOL_GPL(nfs_link);
 
-static void
-nfs_complete_rename(struct rpc_task *task, struct nfs_renamedata *data)
-{
-       struct dentry *old_dentry = data->old_dentry;
-       struct dentry *new_dentry = data->new_dentry;
-       struct inode *old_inode = d_inode(old_dentry);
-       struct inode *new_inode = d_inode(new_dentry);
-
-       nfs_mark_for_revalidate(old_inode);
-
-       switch (task->tk_status) {
-       case 0:
-               if (new_inode != NULL)
-                       nfs_drop_nlink(new_inode);
-               d_move(old_dentry, new_dentry);
-               nfs_set_verifier(new_dentry,
-                                       nfs_save_change_attribute(data->new_dir));
-               break;
-       case -ENOENT:
-               nfs_dentry_handle_enoent(old_dentry);
-       }
-}
-
 /*
  * RENAME
  * FIXME: Some nfsds, like the Linux user space nfsd, may generate a
@@ -1999,7 +1976,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 {
        struct inode *old_inode = d_inode(old_dentry);
        struct inode *new_inode = d_inode(new_dentry);
-       struct dentry *dentry = NULL;
+       struct dentry *dentry = NULL, *rehash = NULL;
        struct rpc_task *task;
        int error = -EBUSY;
 
@@ -2022,8 +1999,10 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                 * To prevent any new references to the target during the
                 * rename, we unhash the dentry in advance.
                 */
-               if (!d_unhashed(new_dentry))
+               if (!d_unhashed(new_dentry)) {
                        d_drop(new_dentry);
+                       rehash = new_dentry;
+               }
 
                if (d_count(new_dentry) > 2) {
                        int err;
@@ -2040,6 +2019,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                goto out;
 
                        new_dentry = dentry;
+                       rehash = NULL;
                        new_inode = NULL;
                }
        }
@@ -2048,8 +2028,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (new_inode != NULL)
                NFS_PROTO(new_inode)->return_delegation(new_inode);
 
-       task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry,
-                                       nfs_complete_rename);
+       task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, NULL);
        if (IS_ERR(task)) {
                error = PTR_ERR(task);
                goto out;
@@ -2059,9 +2038,27 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (error == 0)
                error = task->tk_status;
        rpc_put_task(task);
+       nfs_mark_for_revalidate(old_inode);
 out:
+       if (rehash)
+               d_rehash(rehash);
        trace_nfs_rename_exit(old_dir, old_dentry,
                        new_dir, new_dentry, error);
+       if (!error) {
+               if (new_inode != NULL)
+                       nfs_drop_nlink(new_inode);
+               /*
+                * The d_move() should be here instead of in an async RPC completion
+                * handler because we need the proper locks to move the dentry.  If
+                * we're interrupted by a signal, the async RPC completion handler
+                * should mark the directories for revalidation.
+                */
+               d_move(old_dentry, new_dentry);
+               nfs_set_verifier(new_dentry,
+                                       nfs_save_change_attribute(new_dir));
+       } else if (error == -ENOENT)
+               nfs_dentry_handle_enoent(old_dentry);
+
        /* new dentry created? */
        if (dentry)
                dput(dentry);
index f5714ee01000de49c5efcd3675226a3a3b7a7074..23542dc44a25c9f398b8a2a69905bf9eafbe5270 100644 (file)
@@ -454,6 +454,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
                        goto out_err_free;
 
                /* fh */
+               rc = -EIO;
                p = xdr_inline_decode(&stream, 4);
                if (!p)
                        goto out_err_free;
index e9b4c3320e371a90020ea25f4be44d2d76508db7..3e24392f2caa1296c4475ed84701fdfabfff467f 100644 (file)
@@ -398,7 +398,6 @@ extern struct file_system_type nfs4_referral_fs_type;
 bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
 struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
                        struct nfs_subversion *);
-void nfs_initialise_sb(struct super_block *);
 int nfs_set_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
 int nfs_clone_sb_security(struct super_block *, struct dentry *, struct nfs_mount_info *);
 struct dentry *nfs_fs_mount_common(struct nfs_server *, int, const char *,
@@ -458,7 +457,6 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
 extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
 
 /* super.c */
-void nfs_clone_super(struct super_block *, struct nfs_mount_info *);
 void nfs_umount_begin(struct super_block *);
 int  nfs_statfs(struct dentry *, struct kstatfs *);
 int  nfs_show_options(struct seq_file *, struct dentry *);
index 1a224a33a6c23c362e1bbacb8150bb9bbf02b3fd..e5686be67be8d361a32344e3aaaae235d739ffd7 100644 (file)
@@ -246,7 +246,7 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
 
        devname = nfs_devname(dentry, page, PAGE_SIZE);
        if (IS_ERR(devname))
-               mnt = (struct vfsmount *)devname;
+               mnt = ERR_CAST(devname);
        else
                mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
 
index 929d09a5310ad7df79be527a45a9aa524825b7f0..319a47db218d133d36b749641b63e5fa4489014c 100644 (file)
@@ -177,7 +177,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
        if (status)
                goto out;
 
-       if (!nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
+       if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
                                    &res->commit_res.verf->verifier)) {
                status = -EAGAIN;
                goto out;
index 692a7a8bfc7afd05ad40d6e04a4a53db07e01753..66776f02211131bd003e31748dec6774a02a077f 100644 (file)
@@ -582,7 +582,6 @@ int nfs40_walk_client_list(struct nfs_client *new,
                         */
                        nfs4_schedule_path_down_recovery(pos);
                default:
-                       spin_lock(&nn->nfs_client_lock);
                        goto out;
                }
 
index c08c46a3b8cde00ef5aa40fae87ed2fce06faea1..dbfa18900e25a38a0998a2d429644a860c559ac2 100644 (file)
@@ -2589,7 +2589,8 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
 
        /* Except MODE, it seems harmless of setting twice. */
        if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
-               attrset[1] & FATTR4_WORD1_MODE)
+               (attrset[1] & FATTR4_WORD1_MODE ||
+                attrset[2] & FATTR4_WORD2_MODE_UMASK))
                sattr->ia_valid &= ~ATTR_MODE;
 
        if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
@@ -8416,6 +8417,7 @@ static void nfs4_layoutget_release(void *calldata)
        size_t max_pages = max_response_pages(server);
 
        dprintk("--> %s\n", __func__);
+       nfs4_sequence_free_slot(&lgp->res.seq_res);
        nfs4_free_pages(lgp->args.layout.pages, max_pages);
        pnfs_put_layout_hdr(NFS_I(inode)->layout);
        put_nfs_open_context(lgp->args.ctx);
@@ -8490,7 +8492,6 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
        /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
        if (status == 0 && lgp->res.layoutp->len)
                lseg = pnfs_layout_process(lgp);
-       nfs4_sequence_free_slot(&lgp->res.seq_res);
        rpc_put_task(task);
        dprintk("<-- %s status=%d\n", __func__, status);
        if (status)
index b34de036501bc90e48be043aec38485f7f755e55..cbf82b0d446759a4934fbf7329e6a767ad5530ce 100644 (file)
@@ -2134,6 +2134,8 @@ again:
        put_rpccred(cred);
        switch (status) {
        case 0:
+       case -EINTR:
+       case -ERESTARTSYS:
                break;
        case -ETIMEDOUT:
                if (clnt->cl_softrtry)
index adc6ec28d4b59d3181c76ca8f33a9fed25d68ce9..c383d0913b54c90fb96020a62faaf989a5d946b3 100644 (file)
@@ -2094,12 +2094,26 @@ pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio)
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout);
 
+/*
+ * Check for any intersection between the request and the pgio->pg_lseg,
+ * and if none, put this pgio->pg_lseg away.
+ */
+static void
+pnfs_generic_pg_check_range(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+{
+       if (pgio->pg_lseg && !pnfs_lseg_request_intersecting(pgio->pg_lseg, req)) {
+               pnfs_put_lseg(pgio->pg_lseg);
+               pgio->pg_lseg = NULL;
+       }
+}
+
 void
 pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        u64 rd_size = req->wb_bytes;
 
        pnfs_generic_pg_check_layout(pgio);
+       pnfs_generic_pg_check_range(pgio, req);
        if (pgio->pg_lseg == NULL) {
                if (pgio->pg_dreq == NULL)
                        rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
@@ -2131,6 +2145,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
                           struct nfs_page *req, u64 wb_size)
 {
        pnfs_generic_pg_check_layout(pgio);
+       pnfs_generic_pg_check_range(pgio, req);
        if (pgio->pg_lseg == NULL) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
@@ -2191,16 +2206,10 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio,
                seg_end = pnfs_end_offset(pgio->pg_lseg->pls_range.offset,
                                     pgio->pg_lseg->pls_range.length);
                req_start = req_offset(req);
-               WARN_ON_ONCE(req_start >= seg_end);
+
                /* start of request is past the last byte of this segment */
-               if (req_start >= seg_end) {
-                       /* reference the new lseg */
-                       if (pgio->pg_ops->pg_cleanup)
-                               pgio->pg_ops->pg_cleanup(pgio);
-                       if (pgio->pg_ops->pg_init)
-                               pgio->pg_ops->pg_init(pgio, req);
+               if (req_start >= seg_end)
                        return 0;
-               }
 
                /* adjust 'size' iff there are fewer bytes left in the
                 * segment than what nfs_generic_pg_test returned */
index 2d05b756a8d6504e79796d71eb5471a578d9ef5a..99731e3e332f3ec32eec26cca47556193dcf68fe 100644 (file)
@@ -593,6 +593,16 @@ pnfs_lseg_range_intersecting(const struct pnfs_layout_range *l1,
        return pnfs_is_range_intersecting(l1->offset, end1, l2->offset, end2);
 }
 
+static inline bool
+pnfs_lseg_request_intersecting(struct pnfs_layout_segment *lseg, struct nfs_page *req)
+{
+       u64 seg_last = pnfs_end_offset(lseg->pls_range.offset, lseg->pls_range.length);
+       u64 req_last = req_offset(req) + req->wb_bytes;
+
+       return pnfs_is_range_intersecting(lseg->pls_range.offset, seg_last,
+                               req_offset(req), req_last);
+}
+
 extern unsigned int layoutstats_timer;
 
 #ifdef NFS_DEBUG
index 2f3822a4a7d565e9e2e607b61d2c580c1befdd05..eceb4eabb064953f830d1bf97a5d0daeecdd27f0 100644 (file)
@@ -2301,7 +2301,7 @@ EXPORT_SYMBOL_GPL(nfs_remount);
 /*
  * Initialise the common bits of the superblock
  */
-inline void nfs_initialise_sb(struct super_block *sb)
+static void nfs_initialise_sb(struct super_block *sb)
 {
        struct nfs_server *server = NFS_SB(sb);
 
@@ -2348,7 +2348,8 @@ EXPORT_SYMBOL_GPL(nfs_fill_super);
 /*
  * Finish setting up a cloned NFS2/3/4 superblock
  */
-void nfs_clone_super(struct super_block *sb, struct nfs_mount_info *mount_info)
+static void nfs_clone_super(struct super_block *sb,
+                           struct nfs_mount_info *mount_info)
 {
        const struct super_block *old_sb = mount_info->cloned->sb;
        struct nfs_server *server = NFS_SB(sb);
index 12feac6ee2fd461a46c7b06b7a0ed0359fb4dfd1..452334694a5d1f37cc480e5d1cf2873c4246019d 100644 (file)
@@ -334,11 +334,8 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
        if (!p)
                return 0;
        p = xdr_decode_hyper(p, &args->offset);
-       args->count = ntohl(*p++);
-
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
 
+       args->count = ntohl(*p++);
        len = min(args->count, max_blocksize);
 
        /* set up the kvec */
@@ -352,7 +349,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
                v++;
        }
        args->vlen = v;
-       return 1;
+       return xdr_argsize_check(rqstp, p);
 }
 
 int
@@ -544,11 +541,9 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
        p = decode_fh(p, &args->fh);
        if (!p)
                return 0;
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return 1;
+       return xdr_argsize_check(rqstp, p);
 }
 
 int
@@ -574,14 +569,10 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
        args->verf   = p; p += 2;
        args->dircount = ~0;
        args->count  = ntohl(*p++);
-
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
-
        args->count  = min_t(u32, args->count, PAGE_SIZE);
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return 1;
+       return xdr_argsize_check(rqstp, p);
 }
 
 int
@@ -599,9 +590,6 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
        args->dircount = ntohl(*p++);
        args->count    = ntohl(*p++);
 
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
-
        len = args->count = min(args->count, max_blocksize);
        while (len > 0) {
                struct page *p = *(rqstp->rq_next_page++);
@@ -609,7 +597,8 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
                        args->buffer = page_address(p);
                len -= PAGE_SIZE;
        }
-       return 1;
+
+       return xdr_argsize_check(rqstp, p);
 }
 
 int
index c453a1998e003d3e900407b266f1a15de5d5d94b..dadb3bf305b22f352a3f91a2df06b30284b4891c 100644 (file)
@@ -1769,6 +1769,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
                        opdesc->op_get_currentstateid(cstate, &op->u);
                op->status = opdesc->op_func(rqstp, cstate, &op->u);
 
+               /* Only from SEQUENCE */
+               if (cstate->status == nfserr_replay_cache) {
+                       dprintk("%s NFS4.1 replay from cache\n", __func__);
+                       status = op->status;
+                       goto out;
+               }
                if (!op->status) {
                        if (opdesc->op_set_currentstateid)
                                opdesc->op_set_currentstateid(cstate, &op->u);
@@ -1779,14 +1785,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
                        if (need_wrongsec_check(rqstp))
                                op->status = check_nfsd_access(current_fh->fh_export, rqstp);
                }
-
 encode_op:
-               /* Only from SEQUENCE */
-               if (cstate->status == nfserr_replay_cache) {
-                       dprintk("%s NFS4.1 replay from cache\n", __func__);
-                       status = op->status;
-                       goto out;
-               }
                if (op->status == nfserr_replay_me) {
                        op->replay = &cstate->replay_owner->so_replay;
                        nfsd4_encode_replay(&resp->xdr, op);
index 6a4947a3f4fa82be4118e4ed538a171118f4baa8..de07ff625777820fefc98bfa56adea81962e8135 100644 (file)
@@ -257,9 +257,6 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
        len = args->count     = ntohl(*p++);
        p++; /* totalcount - unused */
 
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
-
        len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2);
 
        /* set up somewhere to store response.
@@ -275,7 +272,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
                v++;
        }
        args->vlen = v;
-       return 1;
+       return xdr_argsize_check(rqstp, p);
 }
 
 int
@@ -365,11 +362,9 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readli
        p = decode_fh(p, &args->fh);
        if (!p)
                return 0;
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return 1;
+       return xdr_argsize_check(rqstp, p);
 }
 
 int
@@ -407,11 +402,9 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
        args->cookie = ntohl(*p++);
        args->count  = ntohl(*p++);
        args->count  = min_t(u32, args->count, PAGE_SIZE);
-       if (!xdr_argsize_check(rqstp, p))
-               return 0;
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return 1;
+       return xdr_argsize_check(rqstp, p);
 }
 
 /*
index 358258364616cd3c2fee997daca2a192719cb045..4690cd75d8d7948a056fe899bc4600ade10b8566 100644 (file)
@@ -159,7 +159,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
                                        PTR_ERR(dent_inode));
                kfree(name);
                /* Return the error code. */
-               return (struct dentry *)dent_inode;
+               return ERR_CAST(dent_inode);
        }
        /* It is guaranteed that @name is no longer allocated at this point. */
        if (MREF_ERR(mref) == -ENOENT) {
index 3b7c937a36b528e67511a23b136215ffaab6d8e4..4689940a953c2f7fc3b3a0e07a7d01c8c09e7d9a 100644 (file)
@@ -2591,6 +2591,10 @@ void ocfs2_inode_unlock_tracker(struct inode *inode,
        struct ocfs2_lock_res *lockres;
 
        lockres = &OCFS2_I(inode)->ip_inode_lockres;
+       /* had_lock means that the currect process already takes the cluster
+        * lock previously. If had_lock is 1, we have nothing to do here, and
+        * it will get unlocked where we got the lock.
+        */
        if (!had_lock) {
                ocfs2_remove_holder(lockres, oh);
                ocfs2_inode_unlock(inode, ex);
index 827fc9809bc271f09b2c3b7abf4019c31d0e1636..9f88188060db9c7fa59e6882ecf33b55cf921788 100644 (file)
@@ -119,7 +119,7 @@ check_err:
 
        if (IS_ERR(inode)) {
                mlog_errno(PTR_ERR(inode));
-               result = (void *)inode;
+               result = ERR_CAST(inode);
                goto bail;
        }
 
index 3c5384d9b3a549f319b114a782c7daab966a2c28..f70c3778d600c6be63996572bee6fd46ac03440c 100644 (file)
@@ -1328,20 +1328,21 @@ static int ocfs2_xattr_get(struct inode *inode,
                           void *buffer,
                           size_t buffer_size)
 {
-       int ret;
+       int ret, had_lock;
        struct buffer_head *di_bh = NULL;
+       struct ocfs2_lock_holder oh;
 
-       ret = ocfs2_inode_lock(inode, &di_bh, 0);
-       if (ret < 0) {
-               mlog_errno(ret);
-               return ret;
+       had_lock = ocfs2_inode_lock_tracker(inode, &di_bh, 0, &oh);
+       if (had_lock < 0) {
+               mlog_errno(had_lock);
+               return had_lock;
        }
        down_read(&OCFS2_I(inode)->ip_xattr_sem);
        ret = ocfs2_xattr_get_nolock(inode, di_bh, name_index,
                                     name, buffer, buffer_size);
        up_read(&OCFS2_I(inode)->ip_xattr_sem);
 
-       ocfs2_inode_unlock(inode, 0);
+       ocfs2_inode_unlock_tracker(inode, 0, &oh, had_lock);
 
        brelse(di_bh);
 
@@ -3537,11 +3538,12 @@ int ocfs2_xattr_set(struct inode *inode,
 {
        struct buffer_head *di_bh = NULL;
        struct ocfs2_dinode *di;
-       int ret, credits, ref_meta = 0, ref_credits = 0;
+       int ret, credits, had_lock, ref_meta = 0, ref_credits = 0;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct inode *tl_inode = osb->osb_tl_inode;
        struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, NULL, };
        struct ocfs2_refcount_tree *ref_tree = NULL;
+       struct ocfs2_lock_holder oh;
 
        struct ocfs2_xattr_info xi = {
                .xi_name_index = name_index,
@@ -3572,8 +3574,9 @@ int ocfs2_xattr_set(struct inode *inode,
                return -ENOMEM;
        }
 
-       ret = ocfs2_inode_lock(inode, &di_bh, 1);
-       if (ret < 0) {
+       had_lock = ocfs2_inode_lock_tracker(inode, &di_bh, 1, &oh);
+       if (had_lock < 0) {
+               ret = had_lock;
                mlog_errno(ret);
                goto cleanup_nolock;
        }
@@ -3670,7 +3673,7 @@ cleanup:
                if (ret)
                        mlog_errno(ret);
        }
-       ocfs2_inode_unlock(inode, 1);
+       ocfs2_inode_unlock_tracker(inode, 1, &oh, had_lock);
 cleanup_nolock:
        brelse(di_bh);
        brelse(xbs.xattr_bh);
index 0daac5112f7a32384b5febd39bd8499f31da8c31..c0c9683934b7a7883ab59eb8bbcd412e07385d0b 100644 (file)
@@ -1,5 +1,6 @@
 config OVERLAY_FS
        tristate "Overlay filesystem support"
+       select EXPORTFS
        help
          An overlay filesystem combines two filesystems - an 'upper' filesystem
          and a 'lower' filesystem.  When a name exists in both filesystems, the
index 9008ab9fbd2ebe89d419c249455eb740c48a9eb1..a2a65120c9d04dbc0d4c5dd0de5baa1c133b8ad5 100644 (file)
@@ -300,7 +300,11 @@ static int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
                        return PTR_ERR(fh);
        }
 
-       err = ovl_do_setxattr(upper, OVL_XATTR_ORIGIN, fh, fh ? fh->len : 0, 0);
+       /*
+        * Do not fail when upper doesn't support xattrs.
+        */
+       err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh,
+                                fh ? fh->len : 0, 0);
        kfree(fh);
 
        return err;
@@ -326,15 +330,9 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
                .link = link
        };
 
-       upper = lookup_one_len(dentry->d_name.name, upperdir,
-                              dentry->d_name.len);
-       err = PTR_ERR(upper);
-       if (IS_ERR(upper))
-               goto out;
-
        err = security_inode_copy_up(dentry, &new_creds);
        if (err < 0)
-               goto out1;
+               goto out;
 
        if (new_creds)
                old_creds = override_creds(new_creds);
@@ -342,13 +340,14 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
        if (tmpfile)
                temp = ovl_do_tmpfile(upperdir, stat->mode);
        else
-               temp = ovl_lookup_temp(workdir, dentry);
-       err = PTR_ERR(temp);
-       if (IS_ERR(temp))
-               goto out1;
-
+               temp = ovl_lookup_temp(workdir);
        err = 0;
-       if (!tmpfile)
+       if (IS_ERR(temp)) {
+               err = PTR_ERR(temp);
+               temp = NULL;
+       }
+
+       if (!err && !tmpfile)
                err = ovl_create_real(wdir, temp, &cattr, NULL, true);
 
        if (new_creds) {
@@ -357,7 +356,7 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
        }
 
        if (err)
-               goto out2;
+               goto out;
 
        if (S_ISREG(stat->mode)) {
                struct path upperpath;
@@ -393,10 +392,23 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
        /*
         * Store identifier of lower inode in upper inode xattr to
         * allow lookup of the copy up origin inode.
+        *
+        * Don't set origin when we are breaking the association with a lower
+        * hard link.
         */
-       err = ovl_set_origin(dentry, lowerpath->dentry, temp);
-       if (err)
+       if (S_ISDIR(stat->mode) || stat->nlink == 1) {
+               err = ovl_set_origin(dentry, lowerpath->dentry, temp);
+               if (err)
+                       goto out_cleanup;
+       }
+
+       upper = lookup_one_len(dentry->d_name.name, upperdir,
+                              dentry->d_name.len);
+       if (IS_ERR(upper)) {
+               err = PTR_ERR(upper);
+               upper = NULL;
                goto out_cleanup;
+       }
 
        if (tmpfile)
                err = ovl_do_link(temp, udir, upper, true);
@@ -411,17 +423,15 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
 
        /* Restore timestamps on parent (best effort) */
        ovl_set_timestamps(upperdir, pstat);
-out2:
+out:
        dput(temp);
-out1:
        dput(upper);
-out:
        return err;
 
 out_cleanup:
        if (!tmpfile)
                ovl_cleanup(wdir, temp);
-       goto out2;
+       goto out;
 }
 
 /*
@@ -454,6 +464,11 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
        ovl_path_upper(parent, &parentpath);
        upperdir = parentpath.dentry;
 
+       /* Mark parent "impure" because it may now contain non-pure upper */
+       err = ovl_set_impure(parent, upperdir);
+       if (err)
+               return err;
+
        err = vfs_getattr(&parentpath, &pstat,
                          STATX_ATIME | STATX_MTIME, AT_STATX_SYNC_AS_STAT);
        if (err)
index 723b98b9069876d1656b74735dabcaf01484e26d..a63a71656e9bdaef6ed5cadf8acdb6d8002fe1b6 100644 (file)
@@ -41,7 +41,7 @@ void ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
        }
 }
 
-struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry)
+struct dentry *ovl_lookup_temp(struct dentry *workdir)
 {
        struct dentry *temp;
        char name[20];
@@ -68,7 +68,7 @@ static struct dentry *ovl_whiteout(struct dentry *workdir,
        struct dentry *whiteout;
        struct inode *wdir = workdir->d_inode;
 
-       whiteout = ovl_lookup_temp(workdir, dentry);
+       whiteout = ovl_lookup_temp(workdir);
        if (IS_ERR(whiteout))
                return whiteout;
 
@@ -127,17 +127,28 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
        return err;
 }
 
-static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
+static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper,
+                              int xerr)
 {
        int err;
 
-       err = ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0);
+       err = ovl_check_setxattr(dentry, upper, OVL_XATTR_OPAQUE, "y", 1, xerr);
        if (!err)
                ovl_dentry_set_opaque(dentry);
 
        return err;
 }
 
+static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
+{
+       /*
+        * Fail with -EIO when trying to create opaque dir and upper doesn't
+        * support xattrs. ovl_rename() calls ovl_set_opaque_xerr(-EXDEV) to
+        * return a specific error for noxattr case.
+        */
+       return ovl_set_opaque_xerr(dentry, upperdentry, -EIO);
+}
+
 /* Common operations required to be done after creation of file on upper */
 static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
                            struct dentry *newdentry, bool hardlink)
@@ -162,6 +173,11 @@ static bool ovl_type_merge(struct dentry *dentry)
        return OVL_TYPE_MERGE(ovl_path_type(dentry));
 }
 
+static bool ovl_type_origin(struct dentry *dentry)
+{
+       return OVL_TYPE_ORIGIN(ovl_path_type(dentry));
+}
+
 static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
                            struct cattr *attr, struct dentry *hardlink)
 {
@@ -250,7 +266,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
        if (upper->d_parent->d_inode != udir)
                goto out_unlock;
 
-       opaquedir = ovl_lookup_temp(workdir, dentry);
+       opaquedir = ovl_lookup_temp(workdir);
        err = PTR_ERR(opaquedir);
        if (IS_ERR(opaquedir))
                goto out_unlock;
@@ -382,7 +398,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
        if (err)
                goto out;
 
-       newdentry = ovl_lookup_temp(workdir, dentry);
+       newdentry = ovl_lookup_temp(workdir);
        err = PTR_ERR(newdentry);
        if (IS_ERR(newdentry))
                goto out_unlock;
@@ -846,18 +862,16 @@ static int ovl_set_redirect(struct dentry *dentry, bool samedir)
        if (IS_ERR(redirect))
                return PTR_ERR(redirect);
 
-       err = ovl_do_setxattr(ovl_dentry_upper(dentry), OVL_XATTR_REDIRECT,
-                             redirect, strlen(redirect), 0);
+       err = ovl_check_setxattr(dentry, ovl_dentry_upper(dentry),
+                                OVL_XATTR_REDIRECT,
+                                redirect, strlen(redirect), -EXDEV);
        if (!err) {
                spin_lock(&dentry->d_lock);
                ovl_dentry_set_redirect(dentry, redirect);
                spin_unlock(&dentry->d_lock);
        } else {
                kfree(redirect);
-               if (err == -EOPNOTSUPP)
-                       ovl_clear_redirect_dir(dentry->d_sb);
-               else
-                       pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err);
+               pr_warn_ratelimited("overlay: failed to set redirect (%i)\n", err);
                /* Fall back to userspace copy-up */
                err = -EXDEV;
        }
@@ -943,6 +957,25 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
        old_upperdir = ovl_dentry_upper(old->d_parent);
        new_upperdir = ovl_dentry_upper(new->d_parent);
 
+       if (!samedir) {
+               /*
+                * When moving a merge dir or non-dir with copy up origin into
+                * a new parent, we are marking the new parent dir "impure".
+                * When ovl_iterate() iterates an "impure" upper dir, it will
+                * lookup the origin inodes of the entries to fill d_ino.
+                */
+               if (ovl_type_origin(old)) {
+                       err = ovl_set_impure(new->d_parent, new_upperdir);
+                       if (err)
+                               goto out_revert_creds;
+               }
+               if (!overwrite && ovl_type_origin(new)) {
+                       err = ovl_set_impure(old->d_parent, old_upperdir);
+                       if (err)
+                               goto out_revert_creds;
+               }
+       }
+
        trap = lock_rename(new_upperdir, old_upperdir);
 
        olddentry = lookup_one_len(old->d_name.name, old_upperdir,
@@ -992,7 +1025,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
                if (ovl_type_merge_or_lower(old))
                        err = ovl_set_redirect(old, samedir);
                else if (!old_opaque && ovl_type_merge(new->d_parent))
-                       err = ovl_set_opaque(old, olddentry);
+                       err = ovl_set_opaque_xerr(old, olddentry, -EXDEV);
                if (err)
                        goto out_dput;
        }
@@ -1000,7 +1033,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
                if (ovl_type_merge_or_lower(new))
                        err = ovl_set_redirect(new, samedir);
                else if (!new_opaque && ovl_type_merge(old->d_parent))
-                       err = ovl_set_opaque(new, newdentry);
+                       err = ovl_set_opaque_xerr(new, newdentry, -EXDEV);
                if (err)
                        goto out_dput;
        }
index ad9547f82da57fa4bd51eb5738cb8f02235e4455..d613e2c41242a52a6c018f43f9987bdbf461e0bb 100644 (file)
@@ -240,6 +240,16 @@ int ovl_xattr_get(struct dentry *dentry, const char *name,
        return res;
 }
 
+static bool ovl_can_list(const char *s)
+{
+       /* List all non-trusted xatts */
+       if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0)
+               return true;
+
+       /* Never list trusted.overlay, list other trusted for superuser only */
+       return !ovl_is_private_xattr(s) && capable(CAP_SYS_ADMIN);
+}
+
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
 {
        struct dentry *realdentry = ovl_dentry_real(dentry);
@@ -263,7 +273,7 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
                        return -EIO;
 
                len -= slen;
-               if (ovl_is_private_xattr(s)) {
+               if (!ovl_can_list(s)) {
                        res -= slen;
                        memmove(s, s + slen, len);
                } else {
index bad0f665a63521efde00b4c488d4ed2ba85a5b75..f3136c31e72af24cbb9949449a12d292fc3bf11b 100644 (file)
@@ -169,17 +169,7 @@ invalid:
 
 static bool ovl_is_opaquedir(struct dentry *dentry)
 {
-       int res;
-       char val;
-
-       if (!d_is_dir(dentry))
-               return false;
-
-       res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1);
-       if (res == 1 && val == 'y')
-               return true;
-
-       return false;
+       return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE);
 }
 
 static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
@@ -351,6 +341,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
        unsigned int ctr = 0;
        struct inode *inode = NULL;
        bool upperopaque = false;
+       bool upperimpure = false;
        char *upperredirect = NULL;
        struct dentry *this;
        unsigned int i;
@@ -395,6 +386,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                                poe = roe;
                }
                upperopaque = d.opaque;
+               if (upperdentry && d.is_dir)
+                       upperimpure = ovl_is_impuredir(upperdentry);
        }
 
        if (!d.stop && poe->numlower) {
@@ -463,6 +456,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 
        revert_creds(old_cred);
        oe->opaque = upperopaque;
+       oe->impure = upperimpure;
        oe->redirect = upperredirect;
        oe->__upperdentry = upperdentry;
        memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
index caa36cb9c46de9838805dc40e21672217407d40e..0623cebeefff8661d49d65a228ceec6290cee877 100644 (file)
@@ -24,6 +24,7 @@ enum ovl_path_type {
 #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX "opaque"
 #define OVL_XATTR_REDIRECT OVL_XATTR_PREFIX "redirect"
 #define OVL_XATTR_ORIGIN OVL_XATTR_PREFIX "origin"
+#define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure"
 
 /*
  * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
@@ -203,10 +204,10 @@ struct dentry *ovl_dentry_real(struct dentry *dentry);
 struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry);
 void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache);
 bool ovl_dentry_is_opaque(struct dentry *dentry);
+bool ovl_dentry_is_impure(struct dentry *dentry);
 bool ovl_dentry_is_whiteout(struct dentry *dentry);
 void ovl_dentry_set_opaque(struct dentry *dentry);
 bool ovl_redirect_dir(struct super_block *sb);
-void ovl_clear_redirect_dir(struct super_block *sb);
 const char *ovl_dentry_get_redirect(struct dentry *dentry);
 void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
 void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry);
@@ -219,6 +220,17 @@ bool ovl_is_whiteout(struct dentry *dentry);
 struct file *ovl_path_open(struct path *path, int flags);
 int ovl_copy_up_start(struct dentry *dentry);
 void ovl_copy_up_end(struct dentry *dentry);
+bool ovl_check_dir_xattr(struct dentry *dentry, const char *name);
+int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
+                      const char *name, const void *value, size_t size,
+                      int xerr);
+int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry);
+
+static inline bool ovl_is_impuredir(struct dentry *dentry)
+{
+       return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE);
+}
+
 
 /* namei.c */
 int ovl_path_next(int idx, struct dentry *dentry, struct path *path);
@@ -263,7 +275,7 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
 
 /* dir.c */
 extern const struct inode_operations ovl_dir_inode_operations;
-struct dentry *ovl_lookup_temp(struct dentry *workdir, struct dentry *dentry);
+struct dentry *ovl_lookup_temp(struct dentry *workdir);
 struct cattr {
        dev_t rdev;
        umode_t mode;
index b2023ddb85323725b8bbfa687f31fc854c1ba5e9..34bc4a9f5c61d95f049b3f34ccd0de243aa27ddd 100644 (file)
@@ -28,6 +28,7 @@ struct ovl_fs {
        /* creds of process who forced instantiation of super block */
        const struct cred *creator_cred;
        bool tmpfile;
+       bool noxattr;
        wait_queue_head_t copyup_wq;
        /* sb common to all layers */
        struct super_block *same_sb;
@@ -42,6 +43,7 @@ struct ovl_entry {
                        u64 version;
                        const char *redirect;
                        bool opaque;
+                       bool impure;
                        bool copying;
                };
                struct rcu_head rcu;
index 9828b7de89992e64a1900a277b58423dde7b992a..4882ffb37baead1c4da41684158d22cbe58e5353 100644 (file)
@@ -891,6 +891,19 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                                dput(temp);
                        else
                                pr_warn("overlayfs: upper fs does not support tmpfile.\n");
+
+                       /*
+                        * Check if upper/work fs supports trusted.overlay.*
+                        * xattr
+                        */
+                       err = ovl_do_setxattr(ufs->workdir, OVL_XATTR_OPAQUE,
+                                             "0", 1, 0);
+                       if (err) {
+                               ufs->noxattr = true;
+                               pr_warn("overlayfs: upper fs does not support xattr.\n");
+                       } else {
+                               vfs_removexattr(ufs->workdir, OVL_XATTR_OPAQUE);
+                       }
                }
        }
 
@@ -961,7 +974,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        path_put(&workpath);
        kfree(lowertmp);
 
-       oe->__upperdentry = upperpath.dentry;
+       if (upperpath.dentry) {
+               oe->__upperdentry = upperpath.dentry;
+               oe->impure = ovl_is_impuredir(upperpath.dentry);
+       }
        for (i = 0; i < numlower; i++) {
                oe->lowerstack[i].dentry = stack[i].dentry;
                oe->lowerstack[i].mnt = ufs->lower_mnt[i];
index cfdea47313a10e22a9c06193e4cc422891badaae..809048913889189d083339d1d015ef4cad2af035 100644 (file)
@@ -175,6 +175,13 @@ bool ovl_dentry_is_opaque(struct dentry *dentry)
        return oe->opaque;
 }
 
+bool ovl_dentry_is_impure(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       return oe->impure;
+}
+
 bool ovl_dentry_is_whiteout(struct dentry *dentry)
 {
        return !dentry->d_inode && ovl_dentry_is_opaque(dentry);
@@ -191,14 +198,7 @@ bool ovl_redirect_dir(struct super_block *sb)
 {
        struct ovl_fs *ofs = sb->s_fs_info;
 
-       return ofs->config.redirect_dir;
-}
-
-void ovl_clear_redirect_dir(struct super_block *sb)
-{
-       struct ovl_fs *ofs = sb->s_fs_info;
-
-       ofs->config.redirect_dir = false;
+       return ofs->config.redirect_dir && !ofs->noxattr;
 }
 
 const char *ovl_dentry_get_redirect(struct dentry *dentry)
@@ -303,3 +303,59 @@ void ovl_copy_up_end(struct dentry *dentry)
        wake_up_locked(&ofs->copyup_wq);
        spin_unlock(&ofs->copyup_wq.lock);
 }
+
+bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)
+{
+       int res;
+       char val;
+
+       if (!d_is_dir(dentry))
+               return false;
+
+       res = vfs_getxattr(dentry, name, &val, 1);
+       if (res == 1 && val == 'y')
+               return true;
+
+       return false;
+}
+
+int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
+                      const char *name, const void *value, size_t size,
+                      int xerr)
+{
+       int err;
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+
+       if (ofs->noxattr)
+               return xerr;
+
+       err = ovl_do_setxattr(upperdentry, name, value, size, 0);
+
+       if (err == -EOPNOTSUPP) {
+               pr_warn("overlayfs: cannot set %s xattr on upper\n", name);
+               ofs->noxattr = true;
+               return xerr;
+       }
+
+       return err;
+}
+
+int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry)
+{
+       int err;
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       if (oe->impure)
+               return 0;
+
+       /*
+        * Do not fail when upper doesn't support xattrs.
+        * Upper inodes won't have origin nor redirect xattr anyway.
+        */
+       err = ovl_check_setxattr(dentry, upperdentry, OVL_XATTR_IMPURE,
+                                "y", 1, 0);
+       if (!err)
+               oe->impure = true;
+
+       return err;
+}
index 45f6bf68fff3ed30df0f85d98c0f644c320a9bf7..f1e1927ccd484e7372fe2a38db7455468bbf06e8 100644 (file)
@@ -821,7 +821,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
        if (!mmget_not_zero(mm))
                goto free;
 
-       flags = write ? FOLL_WRITE : 0;
+       flags = FOLL_FORCE | (write ? FOLL_WRITE : 0);
 
        while (count > 0) {
                int this_len = min_t(int, count, PAGE_SIZE);
index f0c8b33d99b137e0c607448237216c2826df3fe8..520802da059c25655eda0c1a421e963007b65ed7 100644 (file)
@@ -300,11 +300,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
 
        /* We don't show the stack guard page in /proc/maps */
        start = vma->vm_start;
-       if (stack_guard_page_start(vma, start))
-               start += PAGE_SIZE;
        end = vma->vm_end;
-       if (stack_guard_page_end(vma, end))
-               end -= PAGE_SIZE;
 
        seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
        seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
index ebf80c7739e15ebdd2bc55896d66943f3aecef9a..48813aeaab8067e921d67b110e28e2a8dd94a3c0 100644 (file)
@@ -1512,6 +1512,22 @@ int dquot_initialize(struct inode *inode)
 }
 EXPORT_SYMBOL(dquot_initialize);
 
+bool dquot_initialize_needed(struct inode *inode)
+{
+       struct dquot **dquots;
+       int i;
+
+       if (!dquot_active(inode))
+               return false;
+
+       dquots = i_dquot(inode);
+       for (i = 0; i < MAXQUOTAS; i++)
+               if (!dquots[i] && sb_has_quota_active(inode->i_sb, i))
+                       return true;
+       return false;
+}
+EXPORT_SYMBOL(dquot_initialize_needed);
+
 /*
  * Release all quotas referenced by inode.
  *
index 47c1d4484df9e6b69333215efc10d7a5db64210f..19d4d88fa285b39493d4b7793a69a23876a0988e 100644 (file)
@@ -1285,7 +1285,7 @@ static size_t compat_writev(struct file *file,
        if (!(file->f_mode & FMODE_CAN_WRITE))
                goto out;
 
-       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, 0);
+       ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, flags);
 
 out:
        if (ret > 0)
index da01f497180a165d163935c4744ef82521bf9151..39bb1e838d8da683fa64dadf7ff150b9369d699e 100644 (file)
@@ -1112,7 +1112,7 @@ static int flush_commit_list(struct super_block *s,
                depth = reiserfs_write_unlock_nested(s);
                if (reiserfs_barrier_flush(s))
                        __sync_dirty_buffer(jl->j_commit_bh,
-                                       REQ_PREFLUSH | REQ_FUA);
+                                       REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
                else
                        sync_dirty_buffer(jl->j_commit_bh);
                reiserfs_write_lock_nested(s, depth);
@@ -1271,7 +1271,7 @@ static int _update_journal_header_block(struct super_block *sb,
 
                if (reiserfs_barrier_flush(sb))
                        __sync_dirty_buffer(journal->j_header_bh,
-                                       REQ_PREFLUSH | REQ_FUA);
+                                       REQ_SYNC | REQ_PREFLUSH | REQ_FUA);
                else
                        sync_dirty_buffer(journal->j_header_bh);
 
index f494b182c7c785232b1d686aae893ebbd70937c7..c35610845ab19f8c17e4ef96e851cddc2205bba9 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -672,6 +672,7 @@ void __inode_add_bytes(struct inode *inode, loff_t bytes)
                inode->i_bytes -= 512;
        }
 }
+EXPORT_SYMBOL(__inode_add_bytes);
 
 void inode_add_bytes(struct inode *inode, loff_t bytes)
 {
index a0376a2c1c29c7adc4a7a60976efd0bf49c8c9dd..f80be4c5df9d13b7009602dd5be2f4c58a5de1ac 100644 (file)
@@ -82,7 +82,8 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
                        ufs_error (sb, "ufs_free_fragments",
                                   "bit already cleared for fragment %u", i);
        }
-       
+
+       inode_sub_bytes(inode, count << uspi->s_fshift);
        fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
        uspi->cs_total.cs_nffree += count;
        fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
@@ -184,6 +185,7 @@ do_more:
                        ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
                }
                ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
+               inode_sub_bytes(inode, uspi->s_fpb << uspi->s_fshift);
                if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
                        ufs_clusteracct (sb, ucpi, blkno, 1);
 
@@ -398,10 +400,12 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
        /*
         * There is not enough space for user on the device
         */
-       if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
-               mutex_unlock(&UFS_SB(sb)->s_lock);
-               UFSD("EXIT (FAILED)\n");
-               return 0;
+       if (unlikely(ufs_freefrags(uspi) <= uspi->s_root_blocks)) {
+               if (!capable(CAP_SYS_RESOURCE)) {
+                       mutex_unlock(&UFS_SB(sb)->s_lock);
+                       UFSD("EXIT (FAILED)\n");
+                       return 0;
+               }
        }
 
        if (goal >= uspi->s_size) 
@@ -419,12 +423,12 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
                if (result) {
                        ufs_clear_frags(inode, result + oldcount,
                                        newcount - oldcount, locked_page != NULL);
+                       *err = 0;
                        write_seqlock(&UFS_I(inode)->meta_lock);
                        ufs_cpu_to_data_ptr(sb, p, result);
-                       write_sequnlock(&UFS_I(inode)->meta_lock);
-                       *err = 0;
                        UFS_I(inode)->i_lastfrag =
                                max(UFS_I(inode)->i_lastfrag, fragment + count);
+                       write_sequnlock(&UFS_I(inode)->meta_lock);
                }
                mutex_unlock(&UFS_SB(sb)->s_lock);
                UFSD("EXIT, result %llu\n", (unsigned long long)result);
@@ -437,8 +441,10 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
        result = ufs_add_fragments(inode, tmp, oldcount, newcount);
        if (result) {
                *err = 0;
+               read_seqlock_excl(&UFS_I(inode)->meta_lock);
                UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
                                                fragment + count);
+               read_sequnlock_excl(&UFS_I(inode)->meta_lock);
                ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
                                locked_page != NULL);
                mutex_unlock(&UFS_SB(sb)->s_lock);
@@ -449,39 +455,29 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
        /*
         * allocate new block and move data
         */
-       switch (fs32_to_cpu(sb, usb1->fs_optim)) {
-           case UFS_OPTSPACE:
+       if (fs32_to_cpu(sb, usb1->fs_optim) == UFS_OPTSPACE) {
                request = newcount;
-               if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree
-                   > uspi->s_dsize * uspi->s_minfree / (2 * 100))
-                       break;
-               usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
-               break;
-           default:
-               usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
-       
-           case UFS_OPTTIME:
+               if (uspi->cs_total.cs_nffree < uspi->s_space_to_time)
+                       usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
+       } else {
                request = uspi->s_fpb;
-               if (uspi->cs_total.cs_nffree < uspi->s_dsize *
-                   (uspi->s_minfree - 2) / 100)
-                       break;
-               usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
-               break;
+               if (uspi->cs_total.cs_nffree > uspi->s_time_to_space)
+                       usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE);
        }
        result = ufs_alloc_fragments (inode, cgno, goal, request, err);
        if (result) {
                ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
                                locked_page != NULL);
+               mutex_unlock(&UFS_SB(sb)->s_lock);
                ufs_change_blocknr(inode, fragment - oldcount, oldcount,
                                   uspi->s_sbbase + tmp,
                                   uspi->s_sbbase + result, locked_page);
+               *err = 0;
                write_seqlock(&UFS_I(inode)->meta_lock);
                ufs_cpu_to_data_ptr(sb, p, result);
-               write_sequnlock(&UFS_I(inode)->meta_lock);
-               *err = 0;
                UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
                                                fragment + count);
-               mutex_unlock(&UFS_SB(sb)->s_lock);
+               write_sequnlock(&UFS_I(inode)->meta_lock);
                if (newcount < request)
                        ufs_free_fragments (inode, result + newcount, request - newcount);
                ufs_free_fragments (inode, tmp, oldcount);
@@ -494,6 +490,20 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
        return 0;
 }              
 
+static bool try_add_frags(struct inode *inode, unsigned frags)
+{
+       unsigned size = frags * i_blocksize(inode);
+       spin_lock(&inode->i_lock);
+       __inode_add_bytes(inode, size);
+       if (unlikely((u32)inode->i_blocks != inode->i_blocks)) {
+               __inode_sub_bytes(inode, size);
+               spin_unlock(&inode->i_lock);
+               return false;
+       }
+       spin_unlock(&inode->i_lock);
+       return true;
+}
+
 static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
                             unsigned oldcount, unsigned newcount)
 {
@@ -530,6 +540,9 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
        for (i = oldcount; i < newcount; i++)
                if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
                        return 0;
+
+       if (!try_add_frags(inode, count))
+               return 0;
        /*
         * Block can be extended
         */
@@ -647,6 +660,7 @@ cg_found:
                        ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
                i = uspi->s_fpb - count;
 
+               inode_sub_bytes(inode, i << uspi->s_fshift);
                fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
                uspi->cs_total.cs_nffree += i;
                fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
@@ -657,6 +671,8 @@ cg_found:
        result = ufs_bitmap_search (sb, ucpi, goal, allocsize);
        if (result == INVBLOCK)
                return 0;
+       if (!try_add_frags(inode, count))
+               return 0;
        for (i = 0; i < count; i++)
                ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
        
@@ -716,6 +732,8 @@ norot:
                return INVBLOCK;
        ucpi->c_rotor = result;
 gotit:
+       if (!try_add_frags(inode, uspi->s_fpb))
+               return 0;
        blkno = ufs_fragstoblks(result);
        ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
        if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
index 7e41aee7b69a660914e7cb26765714746929a306..f36d6a53687d13fd817f65f99913a54d425e8048 100644 (file)
@@ -235,7 +235,8 @@ ufs_extend_tail(struct inode *inode, u64 writes_to,
 
        p = ufs_get_direct_data_ptr(uspi, ufsi, block);
        tmp = ufs_new_fragments(inode, p, lastfrag, ufs_data_ptr_to_cpu(sb, p),
-                               new_size, err, locked_page);
+                               new_size - (lastfrag & uspi->s_fpbmask), err,
+                               locked_page);
        return tmp != 0;
 }
 
@@ -284,7 +285,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned index,
                        goal += uspi->s_fpb;
        }
        tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment),
-                               goal, uspi->s_fpb, err, locked_page);
+                               goal, nfrags, err, locked_page);
 
        if (!tmp) {
                *err = -ENOSPC;
@@ -400,11 +401,20 @@ static int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buff
        u64 phys64 = 0;
        unsigned frag = fragment & uspi->s_fpbmask;
 
-       if (!create) {
-               phys64 = ufs_frag_map(inode, offsets, depth);
-               goto out;
-       }
+       phys64 = ufs_frag_map(inode, offsets, depth);
+       if (!create)
+               goto done;
 
+       if (phys64) {
+               if (fragment >= UFS_NDIR_FRAGMENT)
+                       goto done;
+               read_seqlock_excl(&UFS_I(inode)->meta_lock);
+               if (fragment < UFS_I(inode)->i_lastfrag) {
+                       read_sequnlock_excl(&UFS_I(inode)->meta_lock);
+                       goto done;
+               }
+               read_sequnlock_excl(&UFS_I(inode)->meta_lock);
+       }
         /* This code entered only while writing ....? */
 
        mutex_lock(&UFS_I(inode)->truncate_mutex);
@@ -448,6 +458,11 @@ out:
        }
        mutex_unlock(&UFS_I(inode)->truncate_mutex);
        return err;
+
+done:
+       if (phys64)
+               map_bh(bh_result, sb, phys64 + frag);
+       return 0;
 }
 
 static int ufs_writepage(struct page *page, struct writeback_control *wbc)
@@ -551,10 +566,8 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
         */
        inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode);
        set_nlink(inode, fs16_to_cpu(sb, ufs_inode->ui_nlink));
-       if (inode->i_nlink == 0) {
-               ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
-               return -1;
-       }
+       if (inode->i_nlink == 0)
+               return -ESTALE;
 
        /*
         * Linux now has 32-bit uid and gid, so we can support EFT.
@@ -563,9 +576,9 @@ static int ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
        i_gid_write(inode, ufs_get_inode_gid(sb, ufs_inode));
 
        inode->i_size = fs64_to_cpu(sb, ufs_inode->ui_size);
-       inode->i_atime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
-       inode->i_ctime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
-       inode->i_mtime.tv_sec = fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
+       inode->i_atime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_atime.tv_sec);
+       inode->i_ctime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_ctime.tv_sec);
+       inode->i_mtime.tv_sec = (signed)fs32_to_cpu(sb, ufs_inode->ui_mtime.tv_sec);
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
@@ -599,10 +612,8 @@ static int ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
         */
        inode->i_mode = mode = fs16_to_cpu(sb, ufs2_inode->ui_mode);
        set_nlink(inode, fs16_to_cpu(sb, ufs2_inode->ui_nlink));
-       if (inode->i_nlink == 0) {
-               ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
-               return -1;
-       }
+       if (inode->i_nlink == 0)
+               return -ESTALE;
 
         /*
          * Linux now has 32-bit uid and gid, so we can support EFT.
@@ -642,7 +653,7 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
        struct buffer_head * bh;
        struct inode *inode;
-       int err;
+       int err = -EIO;
 
        UFSD("ENTER, ino %lu\n", ino);
 
@@ -677,9 +688,10 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
                err = ufs1_read_inode(inode,
                                      ufs_inode + ufs_inotofsbo(inode->i_ino));
        }
-
+       brelse(bh);
        if (err)
                goto bad_inode;
+
        inode->i_version++;
        ufsi->i_lastfrag =
                (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
@@ -688,15 +700,13 @@ struct inode *ufs_iget(struct super_block *sb, unsigned long ino)
 
        ufs_set_inode_ops(inode);
 
-       brelse(bh);
-
        UFSD("EXIT\n");
        unlock_new_inode(inode);
        return inode;
 
 bad_inode:
        iget_failed(inode);
-       return ERR_PTR(-EIO);
+       return ERR_PTR(err);
 }
 
 static void ufs1_update_inode(struct inode *inode, struct ufs_inode *ufs_inode)
@@ -841,8 +851,11 @@ void ufs_evict_inode(struct inode * inode)
        truncate_inode_pages_final(&inode->i_data);
        if (want_delete) {
                inode->i_size = 0;
-               if (inode->i_blocks)
+               if (inode->i_blocks &&
+                   (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+                    S_ISLNK(inode->i_mode)))
                        ufs_truncate_blocks(inode);
+               ufs_update_inode(inode, inode_needs_sync(inode));
        }
 
        invalidate_inode_buffers(inode);
@@ -868,7 +881,6 @@ static inline void free_data(struct to_free *ctx, u64 from, unsigned count)
        ctx->to = from + count;
 }
 
-#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
 #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
 
 static void ufs_trunc_direct(struct inode *inode)
@@ -1100,25 +1112,30 @@ out:
        return err;
 }
 
-static void __ufs_truncate_blocks(struct inode *inode)
+static void ufs_truncate_blocks(struct inode *inode)
 {
        struct ufs_inode_info *ufsi = UFS_I(inode);
        struct super_block *sb = inode->i_sb;
        struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
        unsigned offsets[4];
-       int depth = ufs_block_to_path(inode, DIRECT_BLOCK, offsets);
+       int depth;
        int depth2;
        unsigned i;
        struct ufs_buffer_head *ubh[3];
        void *p;
        u64 block;
 
-       if (!depth)
-               return;
+       if (inode->i_size) {
+               sector_t last = (inode->i_size - 1) >> uspi->s_bshift;
+               depth = ufs_block_to_path(inode, last, offsets);
+               if (!depth)
+                       return;
+       } else {
+               depth = 1;
+       }
 
-       /* find the last non-zero in offsets[] */
        for (depth2 = depth - 1; depth2; depth2--)
-               if (offsets[depth2])
+               if (offsets[depth2] != uspi->s_apb - 1)
                        break;
 
        mutex_lock(&ufsi->truncate_mutex);
@@ -1127,9 +1144,8 @@ static void __ufs_truncate_blocks(struct inode *inode)
                offsets[0] = UFS_IND_BLOCK;
        } else {
                /* get the blocks that should be partially emptied */
-               p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]);
+               p = ufs_get_direct_data_ptr(uspi, ufsi, offsets[0]++);
                for (i = 0; i < depth2; i++) {
-                       offsets[i]++;   /* next branch is fully freed */
                        block = ufs_data_ptr_to_cpu(sb, p);
                        if (!block)
                                break;
@@ -1140,7 +1156,7 @@ static void __ufs_truncate_blocks(struct inode *inode)
                                write_sequnlock(&ufsi->meta_lock);
                                break;
                        }
-                       p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]);
+                       p = ubh_get_data_ptr(uspi, ubh[i], offsets[i + 1]++);
                }
                while (i--)
                        free_branch_tail(inode, offsets[i + 1], ubh[i], depth - i - 1);
@@ -1155,7 +1171,9 @@ static void __ufs_truncate_blocks(struct inode *inode)
                        free_full_branch(inode, block, i - UFS_IND_BLOCK + 1);
                }
        }
+       read_seqlock_excl(&ufsi->meta_lock);
        ufsi->i_lastfrag = DIRECT_FRAGMENT;
+       read_sequnlock_excl(&ufsi->meta_lock);
        mark_inode_dirty(inode);
        mutex_unlock(&ufsi->truncate_mutex);
 }
@@ -1183,7 +1201,7 @@ static int ufs_truncate(struct inode *inode, loff_t size)
 
        truncate_setsize(inode, size);
 
-       __ufs_truncate_blocks(inode);
+       ufs_truncate_blocks(inode);
        inode->i_mtime = inode->i_ctime = current_time(inode);
        mark_inode_dirty(inode);
 out:
@@ -1191,16 +1209,6 @@ out:
        return err;
 }
 
-static void ufs_truncate_blocks(struct inode *inode)
-{
-       if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-             S_ISLNK(inode->i_mode)))
-               return;
-       if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-               return;
-       __ufs_truncate_blocks(inode);
-}
-
 int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = d_inode(dentry);
index 131b2b77c8185403dc3cdf0393e8e0c915f3a850..0a4f58a5073cb63feb94c2174c56d9889d2a37a4 100644 (file)
@@ -480,7 +480,7 @@ static void ufs_setup_cstotal(struct super_block *sb)
        usb3 = ubh_get_usb_third(uspi);
 
        if ((mtype == UFS_MOUNT_UFSTYPE_44BSD &&
-            (usb1->fs_flags & UFS_FLAGS_UPDATED)) ||
+            (usb2->fs_un.fs_u2.fs_maxbsize == usb1->fs_bsize)) ||
            mtype == UFS_MOUNT_UFSTYPE_UFS2) {
                /*we have statistic in different place, then usual*/
                uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir);
@@ -596,9 +596,7 @@ static void ufs_put_cstotal(struct super_block *sb)
        usb2 = ubh_get_usb_second(uspi);
        usb3 = ubh_get_usb_third(uspi);
 
-       if ((mtype == UFS_MOUNT_UFSTYPE_44BSD &&
-            (usb1->fs_flags & UFS_FLAGS_UPDATED)) ||
-           mtype == UFS_MOUNT_UFSTYPE_UFS2) {
+       if (mtype == UFS_MOUNT_UFSTYPE_UFS2) {
                /*we have statistic in different place, then usual*/
                usb2->fs_un.fs_u2.cs_ndir =
                        cpu_to_fs64(sb, uspi->cs_total.cs_ndir);
@@ -608,16 +606,26 @@ static void ufs_put_cstotal(struct super_block *sb)
                        cpu_to_fs64(sb, uspi->cs_total.cs_nifree);
                usb3->fs_un1.fs_u2.cs_nffree =
                        cpu_to_fs64(sb, uspi->cs_total.cs_nffree);
-       } else {
-               usb1->fs_cstotal.cs_ndir =
-                       cpu_to_fs32(sb, uspi->cs_total.cs_ndir);
-               usb1->fs_cstotal.cs_nbfree =
-                       cpu_to_fs32(sb, uspi->cs_total.cs_nbfree);
-               usb1->fs_cstotal.cs_nifree =
-                       cpu_to_fs32(sb, uspi->cs_total.cs_nifree);
-               usb1->fs_cstotal.cs_nffree =
-                       cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
+               goto out;
+       }
+
+       if (mtype == UFS_MOUNT_UFSTYPE_44BSD &&
+            (usb2->fs_un.fs_u2.fs_maxbsize == usb1->fs_bsize)) {
+               /* store stats in both old and new places */
+               usb2->fs_un.fs_u2.cs_ndir =
+                       cpu_to_fs64(sb, uspi->cs_total.cs_ndir);
+               usb2->fs_un.fs_u2.cs_nbfree =
+                       cpu_to_fs64(sb, uspi->cs_total.cs_nbfree);
+               usb3->fs_un1.fs_u2.cs_nifree =
+                       cpu_to_fs64(sb, uspi->cs_total.cs_nifree);
+               usb3->fs_un1.fs_u2.cs_nffree =
+                       cpu_to_fs64(sb, uspi->cs_total.cs_nffree);
        }
+       usb1->fs_cstotal.cs_ndir = cpu_to_fs32(sb, uspi->cs_total.cs_ndir);
+       usb1->fs_cstotal.cs_nbfree = cpu_to_fs32(sb, uspi->cs_total.cs_nbfree);
+       usb1->fs_cstotal.cs_nifree = cpu_to_fs32(sb, uspi->cs_total.cs_nifree);
+       usb1->fs_cstotal.cs_nffree = cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
+out:
        ubh_mark_buffer_dirty(USPI_UBH(uspi));
        ufs_print_super_stuff(sb, usb1, usb2, usb3);
        UFSD("EXIT\n");
@@ -746,6 +754,23 @@ static void ufs_put_super(struct super_block *sb)
        return;
 }
 
+static u64 ufs_max_bytes(struct super_block *sb)
+{
+       struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+       int bits = uspi->s_apbshift;
+       u64 res;
+
+       if (bits > 21)
+               res = ~0ULL;
+       else
+               res = UFS_NDADDR + (1LL << bits) + (1LL << (2*bits)) +
+                       (1LL << (3*bits));
+
+       if (res >= (MAX_LFS_FILESIZE >> uspi->s_bshift))
+               return MAX_LFS_FILESIZE;
+       return res << uspi->s_bshift;
+}
+
 static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct ufs_sb_info * sbi;
@@ -812,9 +837,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        uspi->s_dirblksize = UFS_SECTOR_SIZE;
        super_block_offset=UFS_SBLOCK;
 
-       /* Keep 2Gig file limit. Some UFS variants need to override 
-          this but as I don't know which I'll let those in the know loosen
-          the rules */
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
+
        switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
        case UFS_MOUNT_UFSTYPE_44BSD:
                UFSD("ufstype=44bsd\n");
@@ -980,6 +1004,13 @@ again:
                flags |=  UFS_ST_SUN;
        }
 
+       if ((flags & UFS_ST_MASK) == UFS_ST_44BSD &&
+           uspi->s_postblformat == UFS_42POSTBLFMT) {
+               if (!silent)
+                       pr_err("this is not a 44bsd filesystem");
+               goto failed;
+       }
+
        /*
         * Check ufs magic number
         */
@@ -1127,8 +1158,8 @@ magic_found:
        uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask);
 
        if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
-               uspi->s_u2_size  = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size);
-               uspi->s_u2_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
+               uspi->s_size  = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size);
+               uspi->s_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
        } else {
                uspi->s_size  =  fs32_to_cpu(sb, usb1->fs_size);
                uspi->s_dsize =  fs32_to_cpu(sb, usb1->fs_dsize);
@@ -1177,6 +1208,18 @@ magic_found:
        uspi->s_postbloff = fs32_to_cpu(sb, usb3->fs_postbloff);
        uspi->s_rotbloff = fs32_to_cpu(sb, usb3->fs_rotbloff);
 
+       uspi->s_root_blocks = mul_u64_u32_div(uspi->s_dsize,
+                                             uspi->s_minfree, 100);
+       if (uspi->s_minfree <= 5) {
+               uspi->s_time_to_space = ~0ULL;
+               uspi->s_space_to_time = 0;
+               usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTSPACE);
+       } else {
+               uspi->s_time_to_space = (uspi->s_root_blocks / 2) + 1;
+               uspi->s_space_to_time = mul_u64_u32_div(uspi->s_dsize,
+                                             uspi->s_minfree - 2, 100) - 1;
+       }
+
        /*
         * Compute another frequently used values
         */
@@ -1212,6 +1255,7 @@ magic_found:
                            "fast symlink size (%u)\n", uspi->s_maxsymlinklen);
                uspi->s_maxsymlinklen = maxsymlen;
        }
+       sb->s_maxbytes = ufs_max_bytes(sb);
        sb->s_max_links = UFS_LINK_MAX;
 
        inode = ufs_iget(sb, UFS_ROOTINO);
@@ -1365,19 +1409,17 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
        mutex_lock(&UFS_SB(sb)->s_lock);
        usb3 = ubh_get_usb_third(uspi);
        
-       if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+       if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
                buf->f_type = UFS2_MAGIC;
-               buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
-       } else {
+       else
                buf->f_type = UFS_MAGIC;
-               buf->f_blocks = uspi->s_dsize;
-       }
-       buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) +
-               uspi->cs_total.cs_nffree;
+
+       buf->f_blocks = uspi->s_dsize;
+       buf->f_bfree = ufs_freefrags(uspi);
        buf->f_ffree = uspi->cs_total.cs_nifree;
        buf->f_bsize = sb->s_blocksize;
-       buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree))
-               ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0;
+       buf->f_bavail = (buf->f_bfree > uspi->s_root_blocks)
+               ? (buf->f_bfree - uspi->s_root_blocks) : 0;
        buf->f_files = uspi->s_ncg * uspi->s_ipg;
        buf->f_namelen = UFS_MAXNAMLEN;
        buf->f_fsid.val[0] = (u32)id;
index 0cbd5d340b6705b9c6e22ff0a60a49891c302860..150eef6f12331a034dab0c48bee530fdc73c821e 100644 (file)
@@ -733,10 +733,8 @@ struct ufs_sb_private_info {
        __u32   s_dblkno;       /* offset of first data after cg */
        __u32   s_cgoffset;     /* cylinder group offset in cylinder */
        __u32   s_cgmask;       /* used to calc mod fs_ntrak */
-       __u32   s_size;         /* number of blocks (fragments) in fs */
-       __u32   s_dsize;        /* number of data blocks in fs */
-       __u64   s_u2_size;      /* ufs2: number of blocks (fragments) in fs */
-       __u64   s_u2_dsize;     /*ufs2:  number of data blocks in fs */
+       __u64   s_size;         /* number of blocks (fragments) in fs */
+       __u64   s_dsize;        /* number of data blocks in fs */
        __u32   s_ncg;          /* number of cylinder groups */
        __u32   s_bsize;        /* size of basic blocks */
        __u32   s_fsize;        /* size of fragments */
@@ -793,6 +791,9 @@ struct ufs_sb_private_info {
        __u32   s_maxsymlinklen;/* upper limit on fast symlinks' size */
        __s32   fs_magic;       /* filesystem magic */
        unsigned int s_dirblksize;
+       __u64   s_root_blocks;
+       __u64   s_time_to_space;
+       __u64   s_space_to_time;
 };
 
 /*
index f41ad0a6106f28a2165c94068f6c7c3d71a67b3e..02497a492eb25085fc7fcefc446ad0e9cd0f967a 100644 (file)
@@ -243,9 +243,8 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev
 struct page *ufs_get_locked_page(struct address_space *mapping,
                                 pgoff_t index)
 {
-       struct page *page;
-
-       page = find_lock_page(mapping, index);
+       struct inode *inode = mapping->host;
+       struct page *page = find_lock_page(mapping, index);
        if (!page) {
                page = read_mapping_page(mapping, index, NULL);
 
@@ -253,7 +252,7 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
                        printk(KERN_ERR "ufs_change_blocknr: "
                               "read_mapping_page error: ino %lu, index: %lu\n",
                               mapping->host->i_ino, index);
-                       goto out;
+                       return page;
                }
 
                lock_page(page);
@@ -262,8 +261,7 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
                        /* Truncate got there first */
                        unlock_page(page);
                        put_page(page);
-                       page = NULL;
-                       goto out;
+                       return NULL;
                }
 
                if (!PageUptodate(page) || PageError(page)) {
@@ -272,11 +270,12 @@ struct page *ufs_get_locked_page(struct address_space *mapping,
 
                        printk(KERN_ERR "ufs_change_blocknr: "
                               "can not read page: ino %lu, index: %lu\n",
-                              mapping->host->i_ino, index);
+                              inode->i_ino, index);
 
-                       page = ERR_PTR(-EIO);
+                       return ERR_PTR(-EIO);
                }
        }
-out:
+       if (!page_has_buffers(page))
+               create_empty_buffers(page, 1 << inode->i_blkbits, 0);
        return page;
 }
index b7fbf53dbc81a044e2bd10428bf2601b094cb750..9fc7119a1551f8ff82a02e9d89d05d6e60024c55 100644 (file)
@@ -350,16 +350,11 @@ static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi,
 #define ubh_blkmap(ubh,begin,bit) \
        ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
 
-/*
- * Determine the number of available frags given a
- * percentage to hold in reserve.
- */
 static inline u64
-ufs_freespace(struct ufs_sb_private_info *uspi, int percentreserved)
+ufs_freefrags(struct ufs_sb_private_info *uspi)
 {
        return ufs_blkstofrags(uspi->cs_total.cs_nbfree) +
-               uspi->cs_total.cs_nffree -
-               (uspi->s_dsize * (percentreserved) / 100);
+               uspi->cs_total.cs_nffree;
 }
 
 /*
@@ -473,15 +468,19 @@ static inline unsigned _ubh_find_last_zero_bit_(
 static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi,
        struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
 {
+       u8 mask;
        switch (uspi->s_fpb) {
        case 8:
                return (*ubh_get_addr (ubh, begin + block) == 0xff);
        case 4:
-               return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2)));
+               mask = 0x0f << ((block & 0x01) << 2);
+               return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask;
        case 2:
-               return (*ubh_get_addr (ubh, begin + (block >> 2)) == (0x03 << ((block & 0x03) << 1)));
+               mask = 0x03 << ((block & 0x03) << 1);
+               return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask;
        case 1:
-               return (*ubh_get_addr (ubh, begin + (block >> 3)) == (0x01 << (block & 0x07)));
+               mask = 0x01 << (block & 0x07);
+               return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask;
        }
        return 0;       
 }
index f7555fc25877435e13b65cbe597ae9bdb11c6528..1d622f276e3a2c0fba23d979d7ae18cf6a899f30 100644 (file)
@@ -340,9 +340,28 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
        bool must_wait, return_to_userland;
        long blocking_state;
 
-       BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
-
        ret = VM_FAULT_SIGBUS;
+
+       /*
+        * We don't do userfault handling for the final child pid update.
+        *
+        * We also don't do userfault handling during
+        * coredumping. hugetlbfs has the special
+        * follow_hugetlb_page() to skip missing pages in the
+        * FOLL_DUMP case, anon memory also checks for FOLL_DUMP with
+        * the no_page_table() helper in follow_page_mask(), but the
+        * shmem_vm_ops->fault method is invoked even during
+        * coredumping without mmap_sem and it ends up here.
+        */
+       if (current->flags & (PF_EXITING|PF_DUMPCORE))
+               goto out;
+
+       /*
+        * Coredumping runs without mmap_sem so we can only check that
+        * the mmap_sem is held, if PF_DUMPCORE was not set.
+        */
+       WARN_ON_ONCE(!rwsem_is_locked(&mm->mmap_sem));
+
        ctx = vmf->vma->vm_userfaultfd_ctx.ctx;
        if (!ctx)
                goto out;
@@ -360,12 +379,6 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
        if (unlikely(ACCESS_ONCE(ctx->released)))
                goto out;
 
-       /*
-        * We don't do userfault handling for the final child pid update.
-        */
-       if (current->flags & PF_EXITING)
-               goto out;
-
        /*
         * Check that we can return VM_FAULT_RETRY.
         *
index f02eb767339219e8e59418429c666b3934d795f4..a7048eafa8e6d8c92a0c6888017389d8562c75ba 100644 (file)
@@ -1280,7 +1280,6 @@ xfs_bmap_read_extents(
                xfs_bmbt_rec_t  *frp;
                xfs_fsblock_t   nextbno;
                xfs_extnum_t    num_recs;
-               xfs_extnum_t    start;
 
                num_recs = xfs_btree_get_numrecs(block);
                if (unlikely(i + num_recs > room)) {
@@ -1303,7 +1302,6 @@ xfs_bmap_read_extents(
                 * Copy records into the extent records.
                 */
                frp = XFS_BMBT_REC_ADDR(mp, block, 1);
-               start = i;
                for (j = 0; j < num_recs; j++, i++, frp++) {
                        xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
                        trp->l0 = be64_to_cpu(frp->l0);
@@ -2065,8 +2063,10 @@ xfs_bmap_add_extent_delay_real(
                }
                temp = xfs_bmap_worst_indlen(bma->ip, temp);
                temp2 = xfs_bmap_worst_indlen(bma->ip, temp2);
-               diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
-                       (bma->cur ? bma->cur->bc_private.b.allocated : 0));
+               diff = (int)(temp + temp2 -
+                            (startblockval(PREV.br_startblock) -
+                             (bma->cur ?
+                              bma->cur->bc_private.b.allocated : 0)));
                if (diff > 0) {
                        error = xfs_mod_fdblocks(bma->ip->i_mount,
                                                 -((int64_t)diff), false);
@@ -2123,7 +2123,6 @@ xfs_bmap_add_extent_delay_real(
                temp = da_new;
                if (bma->cur)
                        temp += bma->cur->bc_private.b.allocated;
-               ASSERT(temp <= da_old);
                if (temp < da_old)
                        xfs_mod_fdblocks(bma->ip->i_mount,
                                        (int64_t)(da_old - temp), false);
index 5392674bf8930550d949f6c01d0f47ec03228ba8..3a673ba201aae9f39c8190bfa2b8904120284ce5 100644 (file)
@@ -4395,7 +4395,7 @@ xfs_btree_visit_blocks(
                        xfs_btree_readahead_ptr(cur, ptr, 1);
 
                        /* save for the next iteration of the loop */
-                       lptr = *ptr;
+                       xfs_btree_copy_ptrs(cur, &lptr, ptr, 1);
                }
 
                /* for each buffer in the level */
index b177ef33cd4c3215de5f3bc228a467bcf73031e1..82a38d86ebad83346c441e802340a172402ef532 100644 (file)
@@ -1629,13 +1629,28 @@ xfs_refcount_recover_cow_leftovers(
        if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
                return -EOPNOTSUPP;
 
-       error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
+       INIT_LIST_HEAD(&debris);
+
+       /*
+        * In this first part, we use an empty transaction to gather up
+        * all the leftover CoW extents so that we can subsequently
+        * delete them.  The empty transaction is used to avoid
+        * a buffer lock deadlock if there happens to be a loop in the
+        * refcountbt because we're allowed to re-grab a buffer that is
+        * already attached to our transaction.  When we're done
+        * recording the CoW debris we cancel the (empty) transaction
+        * and everything goes away cleanly.
+        */
+       error = xfs_trans_alloc_empty(mp, &tp);
        if (error)
                return error;
-       cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL);
+
+       error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
+       if (error)
+               goto out_trans;
+       cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, NULL);
 
        /* Find all the leftover CoW staging extents. */
-       INIT_LIST_HEAD(&debris);
        memset(&low, 0, sizeof(low));
        memset(&high, 0, sizeof(high));
        low.rc.rc_startblock = XFS_REFC_COW_START;
@@ -1645,10 +1660,11 @@ xfs_refcount_recover_cow_leftovers(
        if (error)
                goto out_cursor;
        xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-       xfs_buf_relse(agbp);
+       xfs_trans_brelse(tp, agbp);
+       xfs_trans_cancel(tp);
 
        /* Now iterate the list to free the leftovers */
-       list_for_each_entry(rr, &debris, rr_list) {
+       list_for_each_entry_safe(rr, n, &debris, rr_list) {
                /* Set up transaction. */
                error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp);
                if (error)
@@ -1676,8 +1692,16 @@ xfs_refcount_recover_cow_leftovers(
                error = xfs_trans_commit(tp);
                if (error)
                        goto out_free;
+
+               list_del(&rr->rr_list);
+               kmem_free(rr);
        }
 
+       return error;
+out_defer:
+       xfs_defer_cancel(&dfops);
+out_trans:
+       xfs_trans_cancel(tp);
 out_free:
        /* Free the leftover list */
        list_for_each_entry_safe(rr, n, &debris, rr_list) {
@@ -1688,11 +1712,6 @@ out_free:
 
 out_cursor:
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
-       xfs_buf_relse(agbp);
-       goto out_free;
-
-out_defer:
-       xfs_defer_cancel(&dfops);
-       xfs_trans_cancel(tp);
-       goto out_free;
+       xfs_trans_brelse(tp, agbp);
+       goto out_trans;
 }
index 09af0f7cd55e278312881999755d3d8d0793d5c8..3b91faacc1baeaff2ac762e2438e5fcbe48cc76b 100644 (file)
@@ -1316,9 +1316,12 @@ xfs_vm_bmap(
         * The swap code (ab-)uses ->bmap to get a block mapping and then
         * bypasseÑ• the file system for actual I/O.  We really can't allow
         * that on reflinks inodes, so we have to skip out here.  And yes,
-        * 0 is the magic code for a bmap error..
+        * 0 is the magic code for a bmap error.
+        *
+        * Since we don't pass back blockdev info, we can't return bmap
+        * information for rt files either.
         */
-       if (xfs_is_reflink_inode(ip))
+       if (xfs_is_reflink_inode(ip) || XFS_IS_REALTIME_INODE(ip))
                return 0;
 
        filemap_write_and_wait(mapping);
index 2b954308a1d671e9f09d06a5353713297f11be76..9e3cc2146d5b03cdc84a4a0d92ce3c186314525d 100644 (file)
@@ -582,9 +582,13 @@ xfs_getbmap(
                }
                break;
        default:
+               /* Local format data forks report no extents. */
+               if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
+                       bmv->bmv_entries = 0;
+                       return 0;
+               }
                if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
-                   ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
-                   ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
+                   ip->i_d.di_format != XFS_DINODE_FMT_BTREE)
                        return -EINVAL;
 
                if (xfs_get_extsz_hint(ip) ||
@@ -712,7 +716,7 @@ xfs_getbmap(
                         * extents.
                         */
                        if (map[i].br_startblock == DELAYSTARTBLOCK &&
-                           map[i].br_startoff <= XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
+                           map[i].br_startoff < XFS_B_TO_FSB(mp, XFS_ISIZE(ip)))
                                ASSERT((iflags & BMV_IF_DELALLOC) != 0);
 
                         if (map[i].br_startblock == HOLESTARTBLOCK &&
index 62fa39276a24bd91c26e3aa18c9f162f19842b95..16d6a578fc160528651d522359eb6e9ccecac78d 100644 (file)
@@ -97,12 +97,16 @@ static inline void
 xfs_buf_ioacct_inc(
        struct xfs_buf  *bp)
 {
-       if (bp->b_flags & (XBF_NO_IOACCT|_XBF_IN_FLIGHT))
+       if (bp->b_flags & XBF_NO_IOACCT)
                return;
 
        ASSERT(bp->b_flags & XBF_ASYNC);
-       bp->b_flags |= _XBF_IN_FLIGHT;
-       percpu_counter_inc(&bp->b_target->bt_io_count);
+       spin_lock(&bp->b_lock);
+       if (!(bp->b_state & XFS_BSTATE_IN_FLIGHT)) {
+               bp->b_state |= XFS_BSTATE_IN_FLIGHT;
+               percpu_counter_inc(&bp->b_target->bt_io_count);
+       }
+       spin_unlock(&bp->b_lock);
 }
 
 /*
@@ -110,14 +114,24 @@ xfs_buf_ioacct_inc(
  * freed and unaccount from the buftarg.
  */
 static inline void
-xfs_buf_ioacct_dec(
+__xfs_buf_ioacct_dec(
        struct xfs_buf  *bp)
 {
-       if (!(bp->b_flags & _XBF_IN_FLIGHT))
-               return;
+       lockdep_assert_held(&bp->b_lock);
 
-       bp->b_flags &= ~_XBF_IN_FLIGHT;
-       percpu_counter_dec(&bp->b_target->bt_io_count);
+       if (bp->b_state & XFS_BSTATE_IN_FLIGHT) {
+               bp->b_state &= ~XFS_BSTATE_IN_FLIGHT;
+               percpu_counter_dec(&bp->b_target->bt_io_count);
+       }
+}
+
+static inline void
+xfs_buf_ioacct_dec(
+       struct xfs_buf  *bp)
+{
+       spin_lock(&bp->b_lock);
+       __xfs_buf_ioacct_dec(bp);
+       spin_unlock(&bp->b_lock);
 }
 
 /*
@@ -149,9 +163,9 @@ xfs_buf_stale(
         * unaccounted (released to LRU) before that occurs. Drop in-flight
         * status now to preserve accounting consistency.
         */
-       xfs_buf_ioacct_dec(bp);
-
        spin_lock(&bp->b_lock);
+       __xfs_buf_ioacct_dec(bp);
+
        atomic_set(&bp->b_lru_ref, 0);
        if (!(bp->b_state & XFS_BSTATE_DISPOSE) &&
            (list_lru_del(&bp->b_target->bt_lru, &bp->b_lru)))
@@ -979,12 +993,12 @@ xfs_buf_rele(
                 * ensures the decrement occurs only once per-buf.
                 */
                if ((atomic_read(&bp->b_hold) == 1) && !list_empty(&bp->b_lru))
-                       xfs_buf_ioacct_dec(bp);
+                       __xfs_buf_ioacct_dec(bp);
                goto out_unlock;
        }
 
        /* the last reference has been dropped ... */
-       xfs_buf_ioacct_dec(bp);
+       __xfs_buf_ioacct_dec(bp);
        if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) {
                /*
                 * If the buffer is added to the LRU take a new reference to the
index 8d1d44f87ce98834ad67cee6840d96d07d5666c0..1508121f29f29191da1a4efc7c8f12cf42eb0107 100644 (file)
@@ -63,7 +63,6 @@ typedef enum {
 #define _XBF_KMEM       (1 << 21)/* backed by heap memory */
 #define _XBF_DELWRI_Q   (1 << 22)/* buffer on a delwri queue */
 #define _XBF_COMPOUND   (1 << 23)/* compound buffer */
-#define _XBF_IN_FLIGHT  (1 << 25) /* I/O in flight, for accounting purposes */
 
 typedef unsigned int xfs_buf_flags_t;
 
@@ -84,14 +83,14 @@ typedef unsigned int xfs_buf_flags_t;
        { _XBF_PAGES,           "PAGES" }, \
        { _XBF_KMEM,            "KMEM" }, \
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
-       { _XBF_COMPOUND,        "COMPOUND" }, \
-       { _XBF_IN_FLIGHT,       "IN_FLIGHT" }
+       { _XBF_COMPOUND,        "COMPOUND" }
 
 
 /*
  * Internal state flags.
  */
 #define XFS_BSTATE_DISPOSE      (1 << 0)       /* buffer being discarded */
+#define XFS_BSTATE_IN_FLIGHT    (1 << 1)       /* I/O in flight */
 
 /*
  * The xfs_buftarg contains 2 notions of "sector size" -
index 35703a80137208b81cb38ab91ce50e28d80a19f2..5fb5a0958a1485db46a2f753446c11828ff1913e 100644 (file)
@@ -1043,49 +1043,17 @@ xfs_find_get_desired_pgoff(
 
        index = startoff >> PAGE_SHIFT;
        endoff = XFS_FSB_TO_B(mp, map->br_startoff + map->br_blockcount);
-       end = endoff >> PAGE_SHIFT;
+       end = (endoff - 1) >> PAGE_SHIFT;
        do {
                int             want;
                unsigned        nr_pages;
                unsigned int    i;
 
-               want = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
+               want = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
                nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
                                          want);
-               /*
-                * No page mapped into given range.  If we are searching holes
-                * and if this is the first time we got into the loop, it means
-                * that the given offset is landed in a hole, return it.
-                *
-                * If we have already stepped through some block buffers to find
-                * holes but they all contains data.  In this case, the last
-                * offset is already updated and pointed to the end of the last
-                * mapped page, if it does not reach the endpoint to search,
-                * that means there should be a hole between them.
-                */
-               if (nr_pages == 0) {
-                       /* Data search found nothing */
-                       if (type == DATA_OFF)
-                               break;
-
-                       ASSERT(type == HOLE_OFF);
-                       if (lastoff == startoff || lastoff < endoff) {
-                               found = true;
-                               *offset = lastoff;
-                       }
-                       break;
-               }
-
-               /*
-                * At lease we found one page.  If this is the first time we
-                * step into the loop, and if the first page index offset is
-                * greater than the given search offset, a hole was found.
-                */
-               if (type == HOLE_OFF && lastoff == startoff &&
-                   lastoff < page_offset(pvec.pages[0])) {
-                       found = true;
+               if (nr_pages == 0)
                        break;
-               }
 
                for (i = 0; i < nr_pages; i++) {
                        struct page     *page = pvec.pages[i];
@@ -1098,18 +1066,18 @@ xfs_find_get_desired_pgoff(
                         * file mapping. However, page->index will not change
                         * because we have a reference on the page.
                         *
-                        * Searching done if the page index is out of range.
-                        * If the current offset is not reaches the end of
-                        * the specified search range, there should be a hole
-                        * between them.
+                        * If current page offset is beyond where we've ended,
+                        * we've found a hole.
                         */
-                       if (page->index > end) {
-                               if (type == HOLE_OFF && lastoff < endoff) {
-                                       *offset = lastoff;
-                                       found = true;
-                               }
+                       if (type == HOLE_OFF && lastoff < endoff &&
+                           lastoff < page_offset(pvec.pages[i])) {
+                               found = true;
+                               *offset = lastoff;
                                goto out;
                        }
+                       /* Searching done if the page index is out of range. */
+                       if (page->index > end)
+                               goto out;
 
                        lock_page(page);
                        /*
@@ -1151,21 +1119,20 @@ xfs_find_get_desired_pgoff(
 
                /*
                 * The number of returned pages less than our desired, search
-                * done.  In this case, nothing was found for searching data,
-                * but we found a hole behind the last offset.
+                * done.
                 */
-               if (nr_pages < want) {
-                       if (type == HOLE_OFF) {
-                               *offset = lastoff;
-                               found = true;
-                       }
+               if (nr_pages < want)
                        break;
-               }
 
                index = pvec.pages[i - 1]->index + 1;
                pagevec_release(&pvec);
        } while (index <= end);
 
+       /* No page at lastoff and we are not done - we found a hole. */
+       if (type == HOLE_OFF && lastoff < endoff) {
+               *offset = lastoff;
+               found = true;
+       }
 out:
        pagevec_release(&pvec);
        return found;
index 3683819887a5658eff23d6e3258d21567bbdc0b4..814ed729881d9a4305c3dd5646d75ef0f112b87b 100644 (file)
@@ -828,6 +828,7 @@ xfs_getfsmap(
        struct xfs_fsmap                dkeys[2];       /* per-dev keys */
        struct xfs_getfsmap_dev         handlers[XFS_GETFSMAP_DEVS];
        struct xfs_getfsmap_info        info = { NULL };
+       bool                            use_rmap;
        int                             i;
        int                             error = 0;
 
@@ -837,12 +838,14 @@ xfs_getfsmap(
            !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
                return -EINVAL;
 
+       use_rmap = capable(CAP_SYS_ADMIN) &&
+                  xfs_sb_version_hasrmapbt(&mp->m_sb);
        head->fmh_entries = 0;
 
        /* Set up our device handlers. */
        memset(handlers, 0, sizeof(handlers));
        handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
-       if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+       if (use_rmap)
                handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
        else
                handlers[0].fn = xfs_getfsmap_datadev_bnobt;
index f61c84f8e31a363ce144424336359630647eac07..990210fcb9c326f923c0c25a86557a0aba3bb40f 100644 (file)
@@ -66,7 +66,6 @@ xfs_inode_alloc(
 
        XFS_STATS_INC(mp, vn_active);
        ASSERT(atomic_read(&ip->i_pincount) == 0);
-       ASSERT(!spin_is_locked(&ip->i_flags_lock));
        ASSERT(!xfs_isiflocked(ip));
        ASSERT(ip->i_ino == 0);
 
@@ -190,7 +189,7 @@ xfs_perag_set_reclaim_tag(
 {
        struct xfs_mount        *mp = pag->pag_mount;
 
-       ASSERT(spin_is_locked(&pag->pag_ici_lock));
+       lockdep_assert_held(&pag->pag_ici_lock);
        if (pag->pag_ici_reclaimable++)
                return;
 
@@ -212,7 +211,7 @@ xfs_perag_clear_reclaim_tag(
 {
        struct xfs_mount        *mp = pag->pag_mount;
 
-       ASSERT(spin_is_locked(&pag->pag_ici_lock));
+       lockdep_assert_held(&pag->pag_ici_lock);
        if (--pag->pag_ici_reclaimable)
                return;
 
index a63f61c256bdc54f0a8ee6088702dbd5e91ee9aa..94e5bdf7304cff79c9ad7784013520776e3086f8 100644 (file)
@@ -1068,7 +1068,7 @@ xfs_file_iomap_begin(
        /* optionally associate a dax device with the iomap bdev */
        bdev = iomap->bdev;
        if (blk_queue_dax(bdev->bd_queue))
-               iomap->dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+               iomap->dax_dev = fs_dax_get_by_host(bdev->bd_disk->disk_name);
        else
                iomap->dax_dev = NULL;
 
@@ -1149,7 +1149,7 @@ xfs_file_iomap_end(
        unsigned                flags,
        struct iomap            *iomap)
 {
-       put_dax(iomap->dax_dev);
+       fs_put_dax(iomap->dax_dev);
        if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC)
                return xfs_file_iomap_end_delalloc(XFS_I(inode), offset,
                                length, written, iomap);
index 197f3fffc9a7151ed61d0b960f5e452f6beccb5c..408c7820e200f99e50d978c342dd67cc55166d0c 100644 (file)
@@ -210,7 +210,8 @@ struct acpi_device_flags {
        u32 of_compatible_ok:1;
        u32 coherent_dma:1;
        u32 cca_seen:1;
-       u32 reserved:20;
+       u32 spi_i2c_slave:1;
+       u32 reserved:19;
 };
 
 /* File System */
index d92543f3bbfdcaaeac47252729af30ba428eb371..bdc55c0da19cd06c65e589d9071f65c2eb5c2332 100644 (file)
@@ -374,6 +374,20 @@ struct acpi_table_desc {
        u16 validation_count;
 };
 
+/*
+ * Maximum value of the validation_count field in struct acpi_table_desc.
+ * When reached, validation_count cannot be changed any more and the table will
+ * be permanently regarded as validated.
+ *
+ * This is to prevent situations in which unbalanced table get/put operations
+ * may cause premature table unmapping in the OS to happen.
+ *
+ * The maximum validation count can be defined to any value, but should be
+ * greater than the maximum number of OS early stage mapping slots to avoid
+ * leaking early stage table mappings to the late stage.
+ */
+#define ACPI_MAX_TABLE_VALIDATIONS          ACPI_UINT16_MAX
+
 /* Masks for Flags field above */
 
 #define ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL  (0)        /* Virtual address, external maintained */
index c0bd0d7651a947bf06407d7c680dde5c377b9b26..bb837310c07e98c529472abceda0a8b426d8c9a5 100644 (file)
@@ -913,4 +913,55 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux);
 int drm_dp_start_crc(struct drm_dp_aux *aux, struct drm_crtc *crtc);
 int drm_dp_stop_crc(struct drm_dp_aux *aux);
 
+struct drm_dp_dpcd_ident {
+       u8 oui[3];
+       u8 device_id[6];
+       u8 hw_rev;
+       u8 sw_major_rev;
+       u8 sw_minor_rev;
+} __packed;
+
+/**
+ * struct drm_dp_desc - DP branch/sink device descriptor
+ * @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch).
+ * @quirks: Quirks; use drm_dp_has_quirk() to query for the quirks.
+ */
+struct drm_dp_desc {
+       struct drm_dp_dpcd_ident ident;
+       u32 quirks;
+};
+
+int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,
+                    bool is_branch);
+
+/**
+ * enum drm_dp_quirk - Display Port sink/branch device specific quirks
+ *
+ * Display Port sink and branch devices in the wild have a variety of bugs, try
+ * to collect them here. The quirks are shared, but it's up to the drivers to
+ * implement workarounds for them.
+ */
+enum drm_dp_quirk {
+       /**
+        * @DP_DPCD_QUIRK_LIMITED_M_N:
+        *
+        * The device requires main link attributes Mvid and Nvid to be limited
+        * to 16 bits.
+        */
+       DP_DPCD_QUIRK_LIMITED_M_N,
+};
+
+/**
+ * drm_dp_has_quirk() - does the DP device have a specific quirk
+ * @desc: Device decriptor filled by drm_dp_read_desc()
+ * @quirk: Quirk to query for
+ *
+ * Return true if DP device identified by @desc has @quirk.
+ */
+static inline bool
+drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
+{
+       return desc->quirks & BIT(quirk);
+}
+
 #endif /* _DRM_DP_HELPER_H_ */
index 370c0a0473fcb80948decaeba03d092f1c24ca74..d66432c6e6759730fff0a705edacb88be94fd40b 100644 (file)
@@ -43,6 +43,8 @@
 #ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_
 #define _DT_BINDINGS_CLK_SUN50I_A64_H_
 
+#define CLK_PLL_PERIPH0                11
+
 #define CLK_BUS_MIPI_DSI       28
 #define CLK_BUS_CE             29
 #define CLK_BUS_DMA            30
index c2afc41d69644af3d9f920a56341d62003630883..e139fe5c62ecd5c8375e7bc8fd503465e475985b 100644 (file)
@@ -43,6 +43,8 @@
 #ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
 #define _DT_BINDINGS_CLK_SUN8I_H3_H_
 
+#define CLK_PLL_PERIPH0                9
+
 #define CLK_CPUX               14
 
 #define CLK_BUS_CE             20
index 97b8d3728b3103f1b54f711f15d06fa84691e372..ef718586321ce0dea03aabe8b114beca9cb71a74 100644 (file)
@@ -195,7 +195,10 @@ struct vgic_dist {
                /* either a GICv2 CPU interface */
                gpa_t                   vgic_cpu_base;
                /* or a number of GICv3 redistributor regions */
-               gpa_t                   vgic_redist_base;
+               struct {
+                       gpa_t           vgic_redist_base;
+                       gpa_t           vgic_redist_free_offset;
+               };
        };
 
        /* distributor enabled */
index d1b04b0e99cf8c293d4ded6eccb2b0aa2fce0d41..a7e29fa0981f148602dcb11dd53e07e1c46147d3 100644 (file)
@@ -426,6 +426,7 @@ extern void bio_advance(struct bio *, unsigned);
 
 extern void bio_init(struct bio *bio, struct bio_vec *table,
                     unsigned short max_vecs);
+extern void bio_uninit(struct bio *);
 extern void bio_reset(struct bio *);
 void bio_chain(struct bio *, struct bio *);
 
index c47aa248c640bc5ea806d5112ce7f7b5fb6b7a46..fcd641032f8d3a87162b0e9f1a63e08ae16d10df 100644 (file)
@@ -238,7 +238,6 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
                                bool kick_requeue_list);
 void blk_mq_kick_requeue_list(struct request_queue *q);
 void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs);
-void blk_mq_abort_requeue_list(struct request_queue *q);
 void blk_mq_complete_request(struct request *rq);
 
 bool blk_mq_queue_stopped(struct request_queue *q);
index ab92c4ea138b7c665c45b765c0e1f8a4958339ca..1ddd36bd2173b98e925eabdf083a796bfcabdd07 100644 (file)
@@ -391,6 +391,8 @@ struct request_queue {
        int                     nr_rqs[2];      /* # allocated [a]sync rqs */
        int                     nr_rqs_elvpriv; /* # allocated rqs w/ elvpriv */
 
+       atomic_t                shared_hctx_restart;
+
        struct blk_queue_stats  *stats;
        struct rq_wb            *rq_wb;
 
@@ -586,6 +588,8 @@ struct request_queue {
 
        size_t                  cmd_size;
        void                    *rq_alloc_data;
+
+       struct work_struct      release_work;
 };
 
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
index 5efb4db44e1ef3223d984296ccf1ca0737224d10..d5093b52b4855f5ec0fbd6d29df265da80945a68 100644 (file)
@@ -40,6 +40,9 @@ struct bpf_reg_state {
         */
        s64 min_value;
        u64 max_value;
+       u32 min_align;
+       u32 aux_off;
+       u32 aux_off_align;
 };
 
 enum bpf_stack_slot_type {
@@ -87,6 +90,7 @@ struct bpf_verifier_env {
        struct bpf_prog *prog;          /* eBPF program being verified */
        struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
        int stack_size;                 /* number of states to be processed */
+       bool strict_alignment;          /* perform strict pointer alignment checks */
        struct bpf_verifier_state cur_state; /* current verifier state */
        struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
        const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
index aa2e19182d990eedda70de69bf638db5856811d1..51c5bd64bd0022c8a3f197d846c23448e7bb6a6e 100644 (file)
@@ -3,6 +3,8 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/string.h>
+
 #ifdef CONFIG_CEPH_LIB_PRETTYDEBUG
 
 /*
  */
 
 # if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
-extern const char *ceph_file_part(const char *s, int len);
 #  define dout(fmt, ...)                                               \
        pr_debug("%.*s %12.12s:%-4d : " fmt,                            \
                 8 - (int)sizeof(KBUILD_MODNAME), "    ",               \
-                ceph_file_part(__FILE__, sizeof(__FILE__)),            \
-                __LINE__, ##__VA_ARGS__)
+                kbasename(__FILE__), __LINE__, ##__VA_ARGS__)
 # else
 /* faux printk call just to see any compiler warnings. */
 #  define dout(fmt, ...)       do {                            \
index 21745946cae154f53cd87311e9350465388f70a5..ec47101cb1bf80f0867dbcff1d6aa10878df7418 100644 (file)
@@ -48,6 +48,7 @@ enum {
        CSS_ONLINE      = (1 << 1), /* between ->css_online() and ->css_offline() */
        CSS_RELEASED    = (1 << 2), /* refcnt reached zero, released */
        CSS_VISIBLE     = (1 << 3), /* css is visible to userland */
+       CSS_DYING       = (1 << 4), /* css is dying */
 };
 
 /* bits in struct cgroup flags field */
index ed2573e149faf070714e04f8160f7056b2fb1d3e..710a005c6b7a652bb9c32b5457dbd64196f6f4a0 100644 (file)
@@ -343,6 +343,26 @@ static inline bool css_tryget_online(struct cgroup_subsys_state *css)
        return true;
 }
 
+/**
+ * css_is_dying - test whether the specified css is dying
+ * @css: target css
+ *
+ * Test whether @css is in the process of offlining or already offline.  In
+ * most cases, ->css_online() and ->css_offline() callbacks should be
+ * enough; however, the actual offline operations are RCU delayed and this
+ * test returns %true also when @css is scheduled to be offlined.
+ *
+ * This is useful, for example, when the use case requires synchronous
+ * behavior with respect to cgroup removal.  cgroup removal schedules css
+ * offlining but the css can seem alive while the operation is being
+ * delayed.  If the delay affects user visible semantics, this test can be
+ * used to resolve the situation.
+ */
+static inline bool css_is_dying(struct cgroup_subsys_state *css)
+{
+       return !(css->flags & CSS_NO_REF) && percpu_ref_is_dying(&css->refcnt);
+}
+
 /**
  * css_put - put a css reference
  * @css: target css
index de179993e039d41d7e9034b5744be40954f81c09..d614c5ea1b5ea4a1772594b35525f1e64aec68ff 100644 (file)
  * with any version that can compile the kernel
  */
 #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+
+/*
+ * GCC does not warn about unused static inline functions for
+ * -Wunused-function.  This turns out to avoid the need for complex #ifdef
+ * directives.  Suppress the warning in clang as well.
+ */
+#undef inline
+#define inline inline __attribute__((unused)) notrace
index 2319b8c108e87b9e87c11cc4c9aa314d24eb0364..c9670904968329ce3032825d55b28a72cb8b223c 100644 (file)
@@ -74,7 +74,8 @@ extern void config_item_init_type_name(struct config_item *item,
                                       const char *name,
                                       struct config_item_type *type);
 
-extern struct config_item * config_item_get(struct config_item *);
+extern struct config_item *config_item_get(struct config_item *);
+extern struct config_item *config_item_get_unless_zero(struct config_item *);
 extern void config_item_put(struct config_item *);
 
 struct config_item_type {
index 00ebac854bb79f16ed5b04d74c6dafa641de0bb7..5ec1f6c47716d6fe7c750456cef81cc0e321b1bc 100644 (file)
@@ -18,6 +18,20 @@ struct dax_operations {
                        void **, pfn_t *);
 };
 
+#if IS_ENABLED(CONFIG_DAX)
+struct dax_device *dax_get_by_host(const char *host);
+void put_dax(struct dax_device *dax_dev);
+#else
+static inline struct dax_device *dax_get_by_host(const char *host)
+{
+       return NULL;
+}
+
+static inline void put_dax(struct dax_device *dax_dev)
+{
+}
+#endif
+
 int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
 #if IS_ENABLED(CONFIG_FS_DAX)
 int __bdev_dax_supported(struct super_block *sb, int blocksize);
@@ -25,23 +39,29 @@ static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
 {
        return __bdev_dax_supported(sb, blocksize);
 }
+
+static inline struct dax_device *fs_dax_get_by_host(const char *host)
+{
+       return dax_get_by_host(host);
+}
+
+static inline void fs_put_dax(struct dax_device *dax_dev)
+{
+       put_dax(dax_dev);
+}
+
 #else
 static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
 {
        return -EOPNOTSUPP;
 }
-#endif
 
-#if IS_ENABLED(CONFIG_DAX)
-struct dax_device *dax_get_by_host(const char *host);
-void put_dax(struct dax_device *dax_dev);
-#else
-static inline struct dax_device *dax_get_by_host(const char *host)
+static inline struct dax_device *fs_dax_get_by_host(const char *host)
 {
        return NULL;
 }
 
-static inline void put_dax(struct dax_device *dax_dev)
+static inline void fs_put_dax(struct dax_device *dax_dev)
 {
 }
 #endif
index 4eac2670bfa1a016679971f36ad698fe1d9f6a4e..92f20832fd28770c16ab9d34c5560efce2a888c6 100644 (file)
@@ -78,6 +78,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
 
 struct iommu_domain;
 struct msi_msg;
+struct device;
 
 static inline int iommu_dma_init(void)
 {
index 5e9c74cf889481ddbf6ae3a9caef166bd6ae6dee..9bbf21a516e4aa339aff03e9c2091043bb265fba 100644 (file)
@@ -136,7 +136,7 @@ static inline int dmi_name_in_vendors(const char *s) { return 0; }
 static inline int dmi_name_in_serial(const char *s) { return 0; }
 #define dmi_available 0
 static inline int dmi_walk(void (*decode)(const struct dmi_header *, void *),
-       void *private_data) { return -1; }
+       void *private_data) { return -ENXIO; }
 static inline bool dmi_match(enum dmi_field f, const char *str)
        { return false; }
 static inline void dmi_memdev_name(u16 handle, const char **bank,
index 9ec5e22846e0f302e7e1b1d174d9ead17e619ee3..0e306c5a86d6ee90debc824aa5d18e8f6d078f4d 100644 (file)
@@ -153,7 +153,7 @@ struct elevator_type
 #endif
 
        /* managed by elevator core */
-       char icq_cache_name[ELV_NAME_MAX + 5];  /* elvname + "_io_cq" */
+       char icq_cache_name[ELV_NAME_MAX + 6];  /* elvname + "_io_cq" */
        struct list_head list;
 };
 
index 56197f82af45fb0f7cf492961fe1eb1956105735..62d948f80730fdd94c587b4f0235c72cf5d3399a 100644 (file)
@@ -272,6 +272,16 @@ struct bpf_prog_aux;
                .off   = OFF,                                   \
                .imm   = IMM })
 
+/* Unconditional jumps, goto pc + off16 */
+
+#define BPF_JMP_A(OFF)                                         \
+       ((struct bpf_insn) {                                    \
+               .code  = BPF_JMP | BPF_JA,                      \
+               .dst_reg = 0,                                   \
+               .src_reg = 0,                                   \
+               .off   = OFF,                                   \
+               .imm   = 0 })
+
 /* Function call */
 
 #define BPF_EMIT_CALL(FUNC)                                    \
index 2b1a44f5bdb60e6a28d874630f71dec7a0f4c40b..a89d37e8b3873cc8e6fa79389a6c0d3a2f4843ab 100644 (file)
@@ -41,7 +41,7 @@ struct vm_area_struct;
 #define ___GFP_WRITE           0x800000u
 #define ___GFP_KSWAPD_RECLAIM  0x1000000u
 #ifdef CONFIG_LOCKDEP
-#define ___GFP_NOLOCKDEP       0x4000000u
+#define ___GFP_NOLOCKDEP       0x2000000u
 #else
 #define ___GFP_NOLOCKDEP       0
 #endif
index c0d712d22b079ebc16129ef2618f41762276cf5e..f738d50cc17d3fcaa0b9b7cf681b70dd2646897d 100644 (file)
@@ -56,7 +56,14 @@ struct gpiod_lookup_table {
        .flags = _flags,                                                  \
 }
 
+#ifdef CONFIG_GPIOLIB
 void gpiod_add_lookup_table(struct gpiod_lookup_table *table);
 void gpiod_remove_lookup_table(struct gpiod_lookup_table *table);
+#else
+static inline
+void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {}
+static inline
+void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {}
+#endif
 
 #endif /* __LINUX_GPIO_MACHINE_H */
index 661e5c2a8e2a49e30d2fe3895f234e321ec81c71..082dc1bd0801c0b7f8fe61916d13a4c48a68f4c3 100644 (file)
@@ -167,7 +167,6 @@ static inline void hash_del_rcu(struct hlist_node *node)
 /**
  * hash_for_each_possible_rcu - iterate over all possible objects hashing to the
  * same bucket in an rcu enabled hashtable
- * in a rcu enabled hashtable
  * @name: hashtable to iterate
  * @obj: the type * to use as a loop cursor for each entry
  * @member: the name of the hlist_node within the struct
index 8d5fcd6284ce0f4702d9eb28703bf2ae80d7e399..283dc2f5364d77c13df5a16ed0474154ee6724ff 100644 (file)
@@ -614,14 +614,16 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb)
 static inline netdev_features_t vlan_features_check(const struct sk_buff *skb,
                                                    netdev_features_t features)
 {
-       if (skb_vlan_tagged_multi(skb))
-               features = netdev_intersect_features(features,
-                                                    NETIF_F_SG |
-                                                    NETIF_F_HIGHDMA |
-                                                    NETIF_F_FRAGLIST |
-                                                    NETIF_F_HW_CSUM |
-                                                    NETIF_F_HW_VLAN_CTAG_TX |
-                                                    NETIF_F_HW_VLAN_STAG_TX);
+       if (skb_vlan_tagged_multi(skb)) {
+               /* In the case of multi-tagged packets, use a direct mask
+                * instead of using netdev_interesect_features(), to make
+                * sure that only devices supporting NETIF_F_HW_CSUM will
+                * have checksum offloading support.
+                */
+               features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM |
+                           NETIF_F_FRAGLIST | NETIF_F_HW_VLAN_CTAG_TX |
+                           NETIF_F_HW_VLAN_STAG_TX;
+       }
 
        return features;
 }
index fffb91202bc9366a523002cc61fc074d12f84725..1fa293a37f4a7e18bff0b2989764454dd0732df7 100644 (file)
 #define ICH_HCR_EN                     (1 << 0)
 #define ICH_HCR_UIE                    (1 << 1)
 
+#define ICH_VMCR_ACK_CTL_SHIFT         2
+#define ICH_VMCR_ACK_CTL_MASK          (1 << ICH_VMCR_ACK_CTL_SHIFT)
+#define ICH_VMCR_FIQ_EN_SHIFT          3
+#define ICH_VMCR_FIQ_EN_MASK           (1 << ICH_VMCR_FIQ_EN_SHIFT)
 #define ICH_VMCR_CBPR_SHIFT            4
 #define ICH_VMCR_CBPR_MASK             (1 << ICH_VMCR_CBPR_SHIFT)
 #define ICH_VMCR_EOIM_SHIFT            9
index dc30f3d057eb0801e9ae8d22fc3ce11943d188d1..d3453ee072fc8aa859544e07598398884239d56f 100644 (file)
 #define GICC_ENABLE                    0x1
 #define GICC_INT_PRI_THRESHOLD         0xf0
 
-#define GIC_CPU_CTRL_EOImodeNS         (1 << 9)
+#define GIC_CPU_CTRL_EnableGrp0_SHIFT  0
+#define GIC_CPU_CTRL_EnableGrp0                (1 << GIC_CPU_CTRL_EnableGrp0_SHIFT)
+#define GIC_CPU_CTRL_EnableGrp1_SHIFT  1
+#define GIC_CPU_CTRL_EnableGrp1                (1 << GIC_CPU_CTRL_EnableGrp1_SHIFT)
+#define GIC_CPU_CTRL_AckCtl_SHIFT      2
+#define GIC_CPU_CTRL_AckCtl            (1 << GIC_CPU_CTRL_AckCtl_SHIFT)
+#define GIC_CPU_CTRL_FIQEn_SHIFT       3
+#define GIC_CPU_CTRL_FIQEn             (1 << GIC_CPU_CTRL_FIQEn_SHIFT)
+#define GIC_CPU_CTRL_CBPR_SHIFT                4
+#define GIC_CPU_CTRL_CBPR              (1 << GIC_CPU_CTRL_CBPR_SHIFT)
+#define GIC_CPU_CTRL_EOImodeNS_SHIFT   9
+#define GIC_CPU_CTRL_EOImodeNS         (1 << GIC_CPU_CTRL_EOImodeNS_SHIFT)
 
 #define GICC_IAR_INT_ID_MASK           0x3ff
 #define GICC_INT_SPURIOUS              1023
 #define GICH_LR_EOI                    (1 << 19)
 #define GICH_LR_HW                     (1 << 31)
 
-#define GICH_VMCR_CTRL_SHIFT           0
-#define GICH_VMCR_CTRL_MASK            (0x21f << GICH_VMCR_CTRL_SHIFT)
+#define GICH_VMCR_ENABLE_GRP0_SHIFT    0
+#define GICH_VMCR_ENABLE_GRP0_MASK     (1 << GICH_VMCR_ENABLE_GRP0_SHIFT)
+#define GICH_VMCR_ENABLE_GRP1_SHIFT    1
+#define GICH_VMCR_ENABLE_GRP1_MASK     (1 << GICH_VMCR_ENABLE_GRP1_SHIFT)
+#define GICH_VMCR_ACK_CTL_SHIFT                2
+#define GICH_VMCR_ACK_CTL_MASK         (1 << GICH_VMCR_ACK_CTL_SHIFT)
+#define GICH_VMCR_FIQ_EN_SHIFT         3
+#define GICH_VMCR_FIQ_EN_MASK          (1 << GICH_VMCR_FIQ_EN_SHIFT)
+#define GICH_VMCR_CBPR_SHIFT           4
+#define GICH_VMCR_CBPR_MASK            (1 << GICH_VMCR_CBPR_SHIFT)
+#define GICH_VMCR_EOI_MODE_SHIFT       9
+#define GICH_VMCR_EOI_MODE_MASK                (1 << GICH_VMCR_EOI_MODE_SHIFT)
+
 #define GICH_VMCR_PRIMASK_SHIFT                27
 #define GICH_VMCR_PRIMASK_MASK         (0x1f << GICH_VMCR_PRIMASK_SHIFT)
 #define GICH_VMCR_BINPOINT_SHIFT       21
index 36872fbb815d72203e14582e3dab6ba5051ee8a7..734377ad42e9f0e4719edc4750b57245fa2d3f17 100644 (file)
@@ -64,13 +64,17 @@ extern int register_refined_jiffies(long clock_tick_rate);
 /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
 #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
 
+#ifndef __jiffy_arch_data
+#define __jiffy_arch_data
+#endif
+
 /*
  * The 64-bit value is not atomic - you MUST NOT read it
  * without sampling the sequence number in jiffies_lock.
  * get_jiffies_64() will do this for you as appropriate.
  */
 extern u64 __cacheline_aligned_in_smp jiffies_64;
-extern unsigned long volatile __cacheline_aligned_in_smp jiffies;
+extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data jiffies;
 
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void);
index 0c9b93b0d1f7cd6133ea87515d3a83fb25f8258b..78e25aabedaf6696772347bb25b20c4cb61254db 100644 (file)
@@ -173,7 +173,6 @@ struct key {
 #ifdef KEY_DEBUGGING
        unsigned                magic;
 #define KEY_DEBUG_MAGIC                0x18273645u
-#define KEY_DEBUG_MAGIC_X      0xf8e9dacbu
 #endif
 
        unsigned long           flags;          /* status flags (change with bitops) */
index 30f90c1a0aaf923d2227ae5ba5323ea5da728005..541df0b5b81530741586d6eaf382e9d1a425ac06 100644 (file)
@@ -349,6 +349,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
                                             int write, void __user *buffer,
                                             size_t *length, loff_t *ppos);
 #endif
+extern void wait_for_kprobe_optimizer(void);
+#else
+static inline void wait_for_kprobe_optimizer(void) { }
 #endif /* CONFIG_OPTPROBES */
 #ifdef CONFIG_KPROBES_ON_FTRACE
 extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
index 4ce24a3762627be20e805da3eaab26ba1bc47578..8098695e5d8d9dfba3815fd359823f92833a5d61 100644 (file)
@@ -425,12 +425,20 @@ static inline void early_memtest(phys_addr_t start, phys_addr_t end)
 }
 #endif
 
+extern unsigned long memblock_reserved_memory_within(phys_addr_t start_addr,
+               phys_addr_t end_addr);
 #else
 static inline phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align)
 {
        return 0;
 }
 
+static inline unsigned long memblock_reserved_memory_within(phys_addr_t start_addr,
+               phys_addr_t end_addr)
+{
+       return 0;
+}
+
 #endif /* CONFIG_HAVE_MEMBLOCK */
 
 #endif /* __KERNEL__ */
index b4ee8f62ce8da82720cb79e7a9ea3ec97703b849..8e2828d48d7fcf6a7ba683bf51c8c91a1ad28ec0 100644 (file)
@@ -470,6 +470,7 @@ struct mlx4_update_qp_params {
        u16     rate_val;
 };
 
+struct mlx4_qp *mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn);
 int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
                   enum mlx4_update_qp_attr attr,
                   struct mlx4_update_qp_params *params);
index dd9a263ed368d5476b06a3464bbfada0436cf6e2..a940ec6a046cfd0dc8c3016226c71ea9e2c343e5 100644 (file)
@@ -787,8 +787,14 @@ enum {
 };
 
 enum {
-       CQE_RSS_HTYPE_IP        = 0x3 << 6,
-       CQE_RSS_HTYPE_L4        = 0x3 << 2,
+       CQE_RSS_HTYPE_IP        = 0x3 << 2,
+       /* cqe->rss_hash_type[3:2] - IP destination selected for hash
+        * (00 = none,  01 = IPv4, 10 = IPv6, 11 = Reserved)
+        */
+       CQE_RSS_HTYPE_L4        = 0x3 << 6,
+       /* cqe->rss_hash_type[7:6] - L4 destination selected for hash
+        * (00 = none, 01 = TCP. 10 = UDP, 11 = IPSEC.SPI
+        */
 };
 
 enum {
index bcdf739ee41a2cf38fe537e48172e9ca9053e3b9..93273d9ea4d145f125846f0c9a56a5a6e74915e4 100644 (file)
@@ -787,7 +787,12 @@ enum {
 
 typedef void (*mlx5_cmd_cbk_t)(int status, void *context);
 
+enum {
+       MLX5_CMD_ENT_STATE_PENDING_COMP,
+};
+
 struct mlx5_cmd_work_ent {
+       unsigned long           state;
        struct mlx5_cmd_msg    *in;
        struct mlx5_cmd_msg    *out;
        void                   *uout;
@@ -976,7 +981,7 @@ void mlx5_cq_completion(struct mlx5_core_dev *dev, u32 cqn);
 void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type);
 void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type);
 struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn);
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec);
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool forced);
 void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type);
 int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx,
                       int nent, u64 mask, const char *name,
index 1b166d2e19c57829279faa20a88796fabb5d3f5e..b25e7baa273e8d9db99fb1e2f33e3086ea875e89 100644 (file)
@@ -109,7 +109,6 @@ struct mlx5_flow_table_attr {
        int max_fte;
        u32 level;
        u32 flags;
-       u32 underlay_qpn;
 };
 
 struct mlx5_flow_table *
@@ -167,4 +166,7 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
 void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse);
+int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
+int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
+
 #endif
index 32de0724b40009adc2a802dcc5abafbb5505c0b1..edafedb7b509010c904fccf2cdeffea1afa9317b 100644 (file)
@@ -766,6 +766,12 @@ enum {
        MLX5_CAP_PORT_TYPE_ETH = 0x1,
 };
 
+enum {
+       MLX5_CAP_UMR_FENCE_STRONG       = 0x0,
+       MLX5_CAP_UMR_FENCE_SMALL        = 0x1,
+       MLX5_CAP_UMR_FENCE_NONE         = 0x2,
+};
+
 struct mlx5_ifc_cmd_hca_cap_bits {
        u8         reserved_at_0[0x80];
 
@@ -875,7 +881,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
        u8         reserved_at_202[0x1];
        u8         ipoib_enhanced_offloads[0x1];
        u8         ipoib_basic_offloads[0x1];
-       u8         reserved_at_205[0xa];
+       u8         reserved_at_205[0x5];
+       u8         umr_fence[0x2];
+       u8         reserved_at_20c[0x3];
        u8         drain_sigerr[0x1];
        u8         cmdif_checksum[0x2];
        u8         sigerr_cqe[0x1];
index 7cb17c6b97de38b1e8d55ca6d8c90b8415a9c3fa..6f543a47fc92ecc89cdd49c00f4c0e9acf0ea2eb 100644 (file)
@@ -1393,12 +1393,6 @@ int clear_page_dirty_for_io(struct page *page);
 
 int get_cmdline(struct task_struct *task, char *buffer, int buflen);
 
-/* Is the vma a continuation of the stack vma above it? */
-static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
-{
-       return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
-}
-
 static inline bool vma_is_anonymous(struct vm_area_struct *vma)
 {
        return !vma->vm_ops;
@@ -1414,28 +1408,6 @@ bool vma_is_shmem(struct vm_area_struct *vma);
 static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; }
 #endif
 
-static inline int stack_guard_page_start(struct vm_area_struct *vma,
-                                            unsigned long addr)
-{
-       return (vma->vm_flags & VM_GROWSDOWN) &&
-               (vma->vm_start == addr) &&
-               !vma_growsdown(vma->vm_prev, addr);
-}
-
-/* Is the vma a continuation of the stack vma below it? */
-static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
-{
-       return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
-}
-
-static inline int stack_guard_page_end(struct vm_area_struct *vma,
-                                          unsigned long addr)
-{
-       return (vma->vm_flags & VM_GROWSUP) &&
-               (vma->vm_end == addr) &&
-               !vma_growsup(vma->vm_next, addr);
-}
-
 int vma_is_stack_for_current(struct vm_area_struct *vma);
 
 extern unsigned long move_page_tables(struct vm_area_struct *vma,
@@ -2222,6 +2194,7 @@ void page_cache_async_readahead(struct address_space *mapping,
                                pgoff_t offset,
                                unsigned long size);
 
+extern unsigned long stack_guard_gap;
 /* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */
 extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
 
@@ -2250,6 +2223,30 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m
        return vma;
 }
 
+static inline unsigned long vm_start_gap(struct vm_area_struct *vma)
+{
+       unsigned long vm_start = vma->vm_start;
+
+       if (vma->vm_flags & VM_GROWSDOWN) {
+               vm_start -= stack_guard_gap;
+               if (vm_start > vma->vm_start)
+                       vm_start = 0;
+       }
+       return vm_start;
+}
+
+static inline unsigned long vm_end_gap(struct vm_area_struct *vma)
+{
+       unsigned long vm_end = vma->vm_end;
+
+       if (vma->vm_flags & VM_GROWSUP) {
+               vm_end += stack_guard_gap;
+               if (vm_end < vma->vm_end)
+                       vm_end = -PAGE_SIZE;
+       }
+       return vm_end;
+}
+
 static inline unsigned long vma_pages(struct vm_area_struct *vma)
 {
        return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
@@ -2327,6 +2324,17 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
 #define FOLL_REMOTE    0x2000  /* we are working on non-current tsk/mm */
 #define FOLL_COW       0x4000  /* internal GUP flag */
 
+static inline int vm_fault_to_errno(int vm_fault, int foll_flags)
+{
+       if (vm_fault & VM_FAULT_OOM)
+               return -ENOMEM;
+       if (vm_fault & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
+               return (foll_flags & FOLL_HWPOISON) ? -EHWPOISON : -EFAULT;
+       if (vm_fault & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
+               return -EFAULT;
+       return 0;
+}
+
 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
                        void *data);
 extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
index ebaccd4e7d8cdc5f5ef13fed1475a8b202d93628..ef6a13b7bd3e851385bea32434e207a5cf6eec7f 100644 (file)
@@ -678,6 +678,7 @@ typedef struct pglist_data {
         * is the first PFN that needs to be initialised.
         */
        unsigned long first_deferred_pfn;
+       unsigned long static_init_size;
 #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
index 566fda587fcf7a76af1c6a01e84ce33336606f3f..3f74ef2281e8afac1e4667b4fbf4abcc5f89ff17 100644 (file)
@@ -467,6 +467,7 @@ enum dmi_field {
        DMI_PRODUCT_VERSION,
        DMI_PRODUCT_SERIAL,
        DMI_PRODUCT_UUID,
+       DMI_PRODUCT_FAMILY,
        DMI_BOARD_VENDOR,
        DMI_BOARD_NAME,
        DMI_BOARD_VERSION,
index 6be1949ebcdff2dd2dcb5270618c7a56a42fdc40..1ee7b30dafecdb27067a2e83fa0bbaccad96e8d9 100644 (file)
@@ -457,7 +457,7 @@ enum hwparam_type {
        hwparam_ioport,         /* Module parameter configures an I/O port */
        hwparam_iomem,          /* Module parameter configures an I/O mem address */
        hwparam_ioport_or_iomem, /* Module parameter could be either, depending on other option */
-       hwparam_irq,            /* Module parameter configures an I/O port */
+       hwparam_irq,            /* Module parameter configures an IRQ */
        hwparam_dma,            /* Module parameter configures a DMA channel */
        hwparam_dma_addr,       /* Module parameter configures a DMA buffer address */
        hwparam_other,          /* Module parameter configures some other value */
index 9c23bd2efb56393e7c616d42d427101c3f5f51d2..4ed952c17fc7757965c26d2eba1c56c39d5b4ccc 100644 (file)
@@ -914,8 +914,7 @@ struct xfrmdev_ops {
  *
  * int (*ndo_change_mtu)(struct net_device *dev, int new_mtu);
  *     Called when a user wants to change the Maximum Transfer Unit
- *     of a device. If not defined, any request to change MTU will
- *     will return an error.
+ *     of a device.
  *
  * void (*ndo_tx_timeout)(struct net_device *dev);
  *     Callback used when the transmitter has not made any progress
@@ -1596,8 +1595,8 @@ enum netdev_priv_flags {
  *     @rtnl_link_state:       This enum represents the phases of creating
  *                             a new link
  *
- *     @destructor:            Called from unregister,
- *                             can be used to call free_netdev
+ *     @needs_free_netdev:     Should unregister perform free_netdev?
+ *     @priv_destructor:       Called from unregister
  *     @npinfo:                XXX: need comments on this one
  *     @nd_net:                Network namespace this network device is inside
  *
@@ -1858,7 +1857,8 @@ struct net_device {
                RTNL_LINK_INITIALIZING,
        } rtnl_link_state:16;
 
-       void (*destructor)(struct net_device *dev);
+       bool needs_free_netdev;
+       void (*priv_destructor)(struct net_device *dev);
 
 #ifdef CONFIG_NETPOLL
        struct netpoll_info __rcu       *npinfo;
@@ -3296,11 +3296,15 @@ int dev_get_phys_port_id(struct net_device *dev,
 int dev_get_phys_port_name(struct net_device *dev,
                           char *name, size_t len);
 int dev_change_proto_down(struct net_device *dev, bool proto_down);
-int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
-                     int fd, u32 flags);
 struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
 struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                                    struct netdev_queue *txq, int *ret);
+
+typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp);
+int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
+                     int fd, u32 flags);
+bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op);
+
 int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 bool is_skb_forwardable(const struct net_device *dev,
@@ -4257,6 +4261,11 @@ static inline const char *netdev_name(const struct net_device *dev)
        return dev->name;
 }
 
+static inline bool netdev_unregistering(const struct net_device *dev)
+{
+       return dev->reg_state == NETREG_UNREGISTERING;
+}
+
 static inline const char *netdev_reg_state(const struct net_device *dev)
 {
        switch (dev->reg_state) {
index be378cf47fcc93fa2c89c6cd870f0a9fecd65211..b3044c2c62cbe8e856605129aa17f111e2a21493 100644 (file)
@@ -294,7 +294,7 @@ int xt_match_to_user(const struct xt_entry_match *m,
 int xt_target_to_user(const struct xt_entry_target *t,
                      struct xt_entry_target __user *u);
 int xt_data_to_user(void __user *dst, const void *src,
-                   int usersize, int size);
+                   int usersize, int size, int aligned_size);
 
 void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
                                 struct xt_counters_info *info, bool compat);
index a30efb437e6d1cfa42a75ec72997bf12b9cdf59d..e0cbf17af780e1d3e4c2be6bba351c9a27cebf88 100644 (file)
@@ -125,4 +125,9 @@ extern unsigned int ebt_do_table(struct sk_buff *skb,
 /* True if the target is not a standard target */
 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
 
+static inline bool ebt_invalid_target(int target)
+{
+       return (target < -NUM_STANDARD_TARGETS || target >= 0);
+}
+
 #endif
index 0db37158a61d4e4e5af0d16d14c07510ef660330..6c8c5d8041b72ec01097d1c0563b793ea7449f1f 100644 (file)
@@ -27,8 +27,8 @@
 
 /* FC Port role bitmask - can merge with FC Port Roles in fc transport */
 #define FC_PORT_ROLE_NVME_INITIATOR    0x10
-#define FC_PORT_ROLE_NVME_TARGET       0x11
-#define FC_PORT_ROLE_NVME_DISCOVERY    0x12
+#define FC_PORT_ROLE_NVME_TARGET       0x20
+#define FC_PORT_ROLE_NVME_DISCOVERY    0x40
 
 
 /**
@@ -642,15 +642,7 @@ enum {
                 * sequence in one LLDD operation. Errors during Data
                 * sequence transmit must not allow RSP sequence to be sent.
                 */
-       NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED = (1 << 1),
-               /* Bit 1: When 0, the LLDD will deliver FCP CMD
-                * on the CPU it should be affinitized to. Thus work will
-                * be scheduled on the cpu received on. When 1, the LLDD
-                * may not deliver the CMD on the CPU it should be worked
-                * on. The transport should pick a cpu to schedule the work
-                * on.
-                */
-       NVMET_FCTGTFEAT_CMD_IN_ISR = (1 << 2),
+       NVMET_FCTGTFEAT_CMD_IN_ISR = (1 << 1),
                /* Bit 2: When 0, the LLDD is calling the cmd rcv handler
                 * in a non-isr context, allowing the transport to finish
                 * op completion in the calling context. When 1, the LLDD
@@ -658,7 +650,7 @@ enum {
                 * requiring the transport to transition to a workqueue
                 * for op completion.
                 */
-       NVMET_FCTGTFEAT_OPDONE_IN_ISR = (1 << 3),
+       NVMET_FCTGTFEAT_OPDONE_IN_ISR = (1 << 2),
                /* Bit 3: When 0, the LLDD is calling the op done handler
                 * in a non-isr context, allowing the transport to finish
                 * op completion in the calling context. When 1, the LLDD
index ec6b11deb77357444757691ec87d71d94b1b8953..1e0deb8e849458ca179c1df4734bb24f0e4cd748 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/ioport.h>
 #include <linux/of.h>
 
-typedef int const (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
+typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
 
 /*
  * Workarounds only applied to 32bit powermac machines
index dc8224ae28d5d9e6106dc0d06a8a9bc2eb85fd0a..e0d1946270f38e5238ddf0a3bb25cf03c3f3ebe4 100644 (file)
@@ -64,6 +64,7 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
                                                   const char *bus_id,
                                                   struct device *parent);
 
+extern int of_platform_device_destroy(struct device *dev, void *data);
 extern int of_platform_bus_probe(struct device_node *root,
                                 const struct of_device_id *matches,
                                 struct device *parent);
index 33c2b0b77429d09aaa31cb9735458db5762e08a7..8039f9f0ca054ba20fd9992b13b7926859d029b5 100644 (file)
@@ -183,6 +183,11 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
        /* Do not use FLR even if device advertises PCI_AF_CAP */
        PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10),
+       /*
+        * Resume before calling the driver's system suspend hooks, disabling
+        * the direct_complete optimization.
+        */
+       PCI_DEV_FLAGS_NEEDS_RESUME = (__force pci_dev_flags_t) (1 << 11),
 };
 
 enum pci_irq_reroute_variant {
@@ -1342,9 +1347,9 @@ pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                               unsigned int max_vecs, unsigned int flags,
                               const struct irq_affinity *aff_desc)
 {
-       if (min_vecs > 1)
-               return -EINVAL;
-       return 1;
+       if ((flags & PCI_IRQ_LEGACY) && min_vecs == 1 && dev->irq)
+               return 1;
+       return -ENOSPC;
 }
 
 static inline void pci_free_irq_vectors(struct pci_dev *dev)
index 279e3c5326e3a4e65bf6f86556ea984a69d0ca9c..7620eb127cffc5edbc475457732a042bac357055 100644 (file)
@@ -42,8 +42,6 @@
  * @PIN_CONFIG_BIAS_PULL_UP: the pin will be pulled up (usually with high
  *     impedance to VDD). If the argument is != 0 pull-up is enabled,
  *     if it is 0, pull-up is total, i.e. the pin is connected to VDD.
- * @PIN_CONFIG_BIDIRECTIONAL: the pin will be configured to allow simultaneous
- *     input and output operations.
  * @PIN_CONFIG_DRIVE_OPEN_DRAIN: the pin will be driven with open drain (open
  *     collector) which means it is usually wired with other output ports
  *     which are then pulled up with an external resistor. Setting this
@@ -98,7 +96,6 @@ enum pin_config_param {
        PIN_CONFIG_BIAS_PULL_DOWN,
        PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
        PIN_CONFIG_BIAS_PULL_UP,
-       PIN_CONFIG_BIDIRECTIONAL,
        PIN_CONFIG_DRIVE_OPEN_DRAIN,
        PIN_CONFIG_DRIVE_OPEN_SOURCE,
        PIN_CONFIG_DRIVE_PUSH_PULL,
index 422bc2e4cb6a6fc47571d28cb0602d59477d7caf..ef3eb8bbfee482e04aa06c83b21fbc2ce02d50b3 100644 (file)
@@ -54,7 +54,8 @@ extern int ptrace_request(struct task_struct *child, long request,
                          unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
 extern void __ptrace_link(struct task_struct *child,
-                         struct task_struct *new_parent);
+                         struct task_struct *new_parent,
+                         const struct cred *ptracer_cred);
 extern void __ptrace_unlink(struct task_struct *child);
 extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
 #define PTRACE_MODE_READ       0x01
@@ -206,7 +207,7 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
 
        if (unlikely(ptrace) && current->ptrace) {
                child->ptrace = current->ptrace;
-               __ptrace_link(child, current->parent);
+               __ptrace_link(child, current->parent, current->ptracer_cred);
 
                if (child->ptrace & PT_SEIZED)
                        task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
@@ -215,6 +216,8 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
 
                set_tsk_thread_flag(child, TIF_SIGPENDING);
        }
+       else
+               child->ptracer_cred = NULL;
 }
 
 /**
index 9c6f768b7d32f66db0b05e0b5500f4b71ecebde7..dda22f45fc1b2361b9b7c79d5fa39a98f09952be 100644 (file)
@@ -44,6 +44,7 @@ void inode_sub_rsv_space(struct inode *inode, qsize_t number);
 void inode_reclaim_rsv_space(struct inode *inode, qsize_t number);
 
 int dquot_initialize(struct inode *inode);
+bool dquot_initialize_needed(struct inode *inode);
 void dquot_drop(struct inode *inode);
 struct dquot *dqget(struct super_block *sb, struct kqid qid);
 static inline struct dquot *dqgrab(struct dquot *dquot)
@@ -207,6 +208,11 @@ static inline int dquot_initialize(struct inode *inode)
        return 0;
 }
 
+static inline bool dquot_initialize_needed(struct inode *inode)
+{
+       return false;
+}
+
 static inline void dquot_drop(struct inode *inode)
 {
 }
index cda76c6506ca411c42c5e1cdf6d287263d97dde6..e69402d4a8aecbdc6fe4a40e8ad7e01957badbd6 100644 (file)
@@ -195,6 +195,7 @@ int serdev_device_open(struct serdev_device *);
 void serdev_device_close(struct serdev_device *);
 unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
 void serdev_device_set_flow_control(struct serdev_device *, bool);
+int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
 void serdev_device_wait_until_sent(struct serdev_device *, long);
 int serdev_device_get_tiocm(struct serdev_device *);
 int serdev_device_set_tiocm(struct serdev_device *, int, int);
@@ -236,6 +237,12 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev
        return 0;
 }
 static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {}
+static inline int serdev_device_write_buf(struct serdev_device *serdev,
+                                         const unsigned char *buf,
+                                         size_t count)
+{
+       return -ENODEV;
+}
 static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {}
 static inline int serdev_device_get_tiocm(struct serdev_device *serdev)
 {
@@ -301,7 +308,7 @@ struct tty_driver;
 struct device *serdev_tty_port_register(struct tty_port *port,
                                        struct device *parent,
                                        struct tty_driver *drv, int idx);
-void serdev_tty_port_unregister(struct tty_port *port);
+int serdev_tty_port_unregister(struct tty_port *port);
 #else
 static inline struct device *serdev_tty_port_register(struct tty_port *port,
                                           struct device *parent,
@@ -309,14 +316,10 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port,
 {
        return ERR_PTR(-ENODEV);
 }
-static inline void serdev_tty_port_unregister(struct tty_port *port) {}
-#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
-
-static inline int serdev_device_write_buf(struct serdev_device *serdev,
-                                         const unsigned char *data,
-                                         size_t count)
+static inline int serdev_tty_port_unregister(struct tty_port *port)
 {
-       return serdev_device_write(serdev, data, count, 0);
+       return -ENODEV;
 }
+#endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
 
 #endif /*_LINUX_SERDEV_H */
index 07ef550c662708035459293fe39fa895cca9fce5..93315d6b21a85fea729970574eecd66027f8f520 100644 (file)
@@ -84,6 +84,7 @@ struct kmem_cache {
        int red_left_pad;       /* Left redzone padding size */
 #ifdef CONFIG_SYSFS
        struct kobject kobj;    /* For sysfs */
+       struct work_struct kobj_remove_work;
 #endif
 #ifdef CONFIG_MEMCG
        struct memcg_cache_params memcg_params;
index a18e0783946b66eccba6a5b5faf77f2662d0a51a..787e7ad53d45f61cb045c047c610996de1141a7a 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __LINUX_SOC_RENESAS_RCAR_RST_H__
 #define __LINUX_SOC_RENESAS_RCAR_RST_H__
 
+#if defined(CONFIG_ARCH_RCAR_GEN1) || defined(CONFIG_ARCH_RCAR_GEN2) || \
+    defined(CONFIG_ARCH_R8A7795) || defined(CONFIG_ARCH_R8A7796)
 int rcar_rst_read_mode_pins(u32 *mode);
+#else
+static inline int rcar_rst_read_mode_pins(u32 *mode) { return -ENODEV; }
+#endif
 
 #endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */
index 167ad8831aafe092a53f87b982acb45748973337..4c1d5f7e62c4f6aef8eded0ec9db4d812a4acd29 100644 (file)
@@ -172,9 +172,7 @@ static inline int srcu_read_lock(struct srcu_struct *sp) __acquires(sp)
 {
        int retval;
 
-       preempt_disable();
        retval = __srcu_read_lock(sp);
-       preempt_enable();
        rcu_lock_acquire(&(sp)->dep_map);
        return retval;
 }
index 94631026f79c56f022976a85dcde92379507e87c..11cef5a7bc87a9fe67a4bfbfca9f52e41d0abd88 100644 (file)
@@ -336,7 +336,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p)
 {
        char *cp = (char *)p;
        struct kvec *vec = &rqstp->rq_arg.head[0];
-       return cp == (char *)vec->iov_base + vec->iov_len;
+       return cp >= (char*)vec->iov_base
+               && cp <= (char*)vec->iov_base + vec->iov_len;
 }
 
 static inline int
index 0b1cf32edfd7ba1c456252124e23c68450d5bcc3..d9718378a8bee0b327d08c2e80a6fd3b5490b967 100644 (file)
@@ -189,8 +189,6 @@ struct platform_suspend_ops {
 struct platform_freeze_ops {
        int (*begin)(void);
        int (*prepare)(void);
-       void (*wake)(void);
-       void (*sync)(void);
        void (*restore)(void);
        void (*end)(void);
 };
@@ -430,8 +428,7 @@ extern unsigned int pm_wakeup_irq;
 
 extern bool pm_wakeup_pending(void);
 extern void pm_system_wakeup(void);
-extern void pm_system_cancel_wakeup(void);
-extern void pm_wakeup_clear(bool reset);
+extern void pm_wakeup_clear(void);
 extern void pm_system_irq_wakeup(unsigned int irq_number);
 extern bool pm_get_wakeup_count(unsigned int *count, bool block);
 extern bool pm_save_wakeup_count(unsigned int count);
@@ -481,7 +478,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
 
 static inline bool pm_wakeup_pending(void) { return false; }
 static inline void pm_system_wakeup(void) {}
-static inline void pm_wakeup_clear(bool reset) {}
+static inline void pm_wakeup_clear(void) {}
 static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
 
 static inline void lock_system_sleep(void) {}
index 110f4532188c7b6c50cf1ce4dcd5dc525beae9a1..f7043ccca81cc65f15c252158e745dc4c2948155 100644 (file)
@@ -29,7 +29,6 @@
  */
 struct tk_read_base {
        struct clocksource      *clock;
-       u64                     (*read)(struct clocksource *cs);
        u64                     mask;
        u64                     cycle_last;
        u32                     mult;
@@ -58,7 +57,7 @@ struct tk_read_base {
  *                     interval.
  * @xtime_remainder:   Shifted nano seconds left over when rounding
  *                     @cycle_interval
- * @raw_interval:      Raw nano seconds accumulated per NTP interval.
+ * @raw_interval:      Shifted raw nano seconds accumulated per NTP interval.
  * @ntp_error:         Difference between accumulated time and NTP time in ntp
  *                     shifted nano seconds.
  * @ntp_error_shift:   Shift conversion between clock shifted nano seconds and
@@ -100,7 +99,7 @@ struct timekeeper {
        u64                     cycle_interval;
        u64                     xtime_interval;
        s64                     xtime_remainder;
-       u32                     raw_interval;
+       u64                     raw_interval;
        /* The ntp_tick_length() value currently being used.
         * This cached copy ensures we consistently apply the tick
         * length for an entire tick, as ntp_tick_length may change
index d07cd2105a6c6a3bdcac20c918622c7ad4ea0840..eccb4ec30a8a7b94064ff1ede0645234b94ae49c 100644 (file)
@@ -558,6 +558,15 @@ extern struct device *tty_port_register_device_attr(struct tty_port *port,
                struct tty_driver *driver, unsigned index,
                struct device *device, void *drvdata,
                const struct attribute_group **attr_grp);
+extern struct device *tty_port_register_device_serdev(struct tty_port *port,
+               struct tty_driver *driver, unsigned index,
+               struct device *device);
+extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
+               struct tty_driver *driver, unsigned index,
+               struct device *device, void *drvdata,
+               const struct attribute_group **attr_grp);
+extern void tty_port_unregister_device(struct tty_port *port,
+               struct tty_driver *driver, unsigned index);
 extern int tty_port_alloc_xmit_buf(struct tty_port *port);
 extern void tty_port_free_xmit_buf(struct tty_port *port);
 extern void tty_port_destroy(struct tty_port *port);
index a469999a106dbc1869f7c90eccc313a90a6d17b0..50398b69ca4497401b7fae3ebc716655003f408c 100644 (file)
@@ -148,6 +148,7 @@ struct usb_hcd {
        unsigned                rh_registered:1;/* is root hub registered? */
        unsigned                rh_pollable:1;  /* may we poll the root hub? */
        unsigned                msix_enabled:1; /* driver has MSI-X enabled? */
+       unsigned                msi_enabled:1;  /* driver has MSI enabled? */
        unsigned                remove_phy:1;   /* auto-remove USB phy */
 
        /* The next flag is a stopgap, to be removed when all the HCDs
index 7dffa5624ea62bee992e547c44ed4a86a577b0a7..97116379db5ff6a850e078c35047fe995f45b265 100644 (file)
@@ -206,6 +206,7 @@ struct cdc_state {
 };
 
 extern int usbnet_generic_cdc_bind(struct usbnet *, struct usb_interface *);
+extern int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf);
 extern int usbnet_cdc_bind(struct usbnet *, struct usb_interface *);
 extern void usbnet_cdc_unbind(struct usbnet *, struct usb_interface *);
 extern void usbnet_cdc_status(struct usbnet *, struct urb *);
index eb50ce54b759154b99cf333e177adf8ca229c69b..298f996969df632ba41b6c68f3d815678c89e079 100644 (file)
@@ -29,7 +29,7 @@ struct edid;
 struct cec_adapter;
 struct cec_notifier;
 
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#if IS_REACHABLE(CONFIG_CEC_CORE) && IS_ENABLED(CONFIG_CEC_NOTIFIER)
 
 /**
  * cec_notifier_get - find or create a new cec_notifier for the given device.
@@ -106,6 +106,16 @@ static inline void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n,
 {
 }
 
+static inline void cec_notifier_register(struct cec_notifier *n,
+                        struct cec_adapter *adap,
+                        void (*callback)(struct cec_adapter *adap, u16 pa))
+{
+}
+
+static inline void cec_notifier_unregister(struct cec_notifier *n)
+{
+}
+
 #endif
 
 #endif
index b8eb895731d561a5f0ff4ec218055581ad6e21ee..201f060978da2d5f8f49ad3fb31ac514c55e60c2 100644 (file)
@@ -173,7 +173,7 @@ struct cec_adapter {
        bool passthrough;
        struct cec_log_addrs log_addrs;
 
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#ifdef CONFIG_CEC_NOTIFIER
        struct cec_notifier *notifier;
 #endif
 
@@ -206,7 +206,7 @@ static inline bool cec_is_sink(const struct cec_adapter *adap)
 #define cec_phys_addr_exp(pa) \
        ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf
 
-#if IS_ENABLED(CONFIG_CEC_CORE)
+#if IS_REACHABLE(CONFIG_CEC_CORE)
 struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
                void *priv, const char *name, u32 caps, u8 available_las);
 int cec_register_adapter(struct cec_adapter *adap, struct device *parent);
@@ -300,7 +300,7 @@ u16 cec_phys_addr_for_input(u16 phys_addr, u8 input);
  */
 int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port);
 
-#ifdef CONFIG_MEDIA_CEC_NOTIFIER
+#ifdef CONFIG_CEC_NOTIFIER
 void cec_register_cec_notifier(struct cec_adapter *adap,
                               struct cec_notifier *notifier);
 #endif
index 049af33da3b6c95897d544670cea65c542317673..cfc0437841665d7ed46a714915c50d723c24901c 100644 (file)
@@ -107,10 +107,16 @@ struct dst_entry {
        };
 };
 
+struct dst_metrics {
+       u32             metrics[RTAX_MAX];
+       atomic_t        refcnt;
+};
+extern const struct dst_metrics dst_default_metrics;
+
 u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
-extern const u32 dst_default_metrics[];
 
 #define DST_METRICS_READ_ONLY          0x1UL
+#define DST_METRICS_REFCOUNTED         0x2UL
 #define DST_METRICS_FLAGS              0x3UL
 #define __DST_METRICS_PTR(Y)   \
        ((u32 *)((Y) & ~DST_METRICS_FLAGS))
index 6692c5758b332d468f1e0611ecc4f3e03ae03b2b..f7f6aa789c6174c41ca9739206d586c559c1f3a1 100644 (file)
@@ -114,11 +114,11 @@ struct fib_info {
        __be32                  fib_prefsrc;
        u32                     fib_tb_id;
        u32                     fib_priority;
-       u32                     *fib_metrics;
-#define fib_mtu fib_metrics[RTAX_MTU-1]
-#define fib_window fib_metrics[RTAX_WINDOW-1]
-#define fib_rtt fib_metrics[RTAX_RTT-1]
-#define fib_advmss fib_metrics[RTAX_ADVMSS-1]
+       struct dst_metrics      *fib_metrics;
+#define fib_mtu fib_metrics->metrics[RTAX_MTU-1]
+#define fib_window fib_metrics->metrics[RTAX_WINDOW-1]
+#define fib_rtt fib_metrics->metrics[RTAX_RTT-1]
+#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1]
        int                     fib_nhs;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
        int                     fib_weight;
index dbf0abba33b8da21be05abf6e719f69542da80fc..3e505bbff8ca4a41f8d39fefcd59aa01b85424f4 100644 (file)
@@ -1007,6 +1007,7 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row,
  */
 extern const struct proto_ops inet6_stream_ops;
 extern const struct proto_ops inet6_dgram_ops;
+extern const struct proto_ops inet6_sockraw_ops;
 
 struct group_source_req;
 struct group_filter;
index e04fa7691e5d6873cd04e94816227d4a41275fa2..c519bb5b5bb8806089886caacaca4846fe3eeb98 100644 (file)
@@ -9,6 +9,7 @@
 
 #ifndef _NF_CONNTRACK_HELPER_H
 #define _NF_CONNTRACK_HELPER_H
+#include <linux/refcount.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 #include <net/netfilter/nf_conntrack_expect.h>
@@ -26,6 +27,7 @@ struct nf_conntrack_helper {
        struct hlist_node hnode;        /* Internal use. */
 
        char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
+       refcount_t refcnt;
        struct module *me;              /* pointer to self */
        const struct nf_conntrack_expect_policy *expect_policy;
 
@@ -79,6 +81,8 @@ struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
 struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
                                                               u16 l3num,
                                                               u8 protonum);
+void nf_conntrack_helper_put(struct nf_conntrack_helper *helper);
+
 void nf_ct_helper_init(struct nf_conntrack_helper *helper,
                       u16 l3num, u16 protonum, const char *name,
                       u16 default_port, u16 spec_port, u32 id,
index 028faec8fc2799b0c176ac88b54fc6700e89f896..8a8bab8d7b15a8e9c746a899dcf474740e9f6f25 100644 (file)
@@ -176,7 +176,7 @@ struct nft_data_desc {
 int nft_data_init(const struct nft_ctx *ctx,
                  struct nft_data *data, unsigned int size,
                  struct nft_data_desc *desc, const struct nlattr *nla);
-void nft_data_uninit(const struct nft_data *data, enum nft_data_types type);
+void nft_data_release(const struct nft_data *data, enum nft_data_types type);
 int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
                  enum nft_data_types type, unsigned int len);
 
index f31fb6331a532eed7258177d5cfbb48fde9a594a..3248beaf16b0513283cd3c863695a77d09793cdc 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <net/act_api.h>
+#include <linux/tc_act/tc_csum.h>
 
 struct tcf_csum {
        struct tc_action common;
@@ -11,4 +12,18 @@ struct tcf_csum {
 };
 #define to_tcf_csum(a) ((struct tcf_csum *)a)
 
+static inline bool is_tcf_csum(const struct tc_action *a)
+{
+#ifdef CONFIG_NET_CLS_ACT
+       if (a->ops && a->ops->type == TCA_ACT_CSUM)
+               return true;
+#endif
+       return false;
+}
+
+static inline u32 tcf_csum_update_flags(const struct tc_action *a)
+{
+       return to_tcf_csum(a)->update_flags;
+}
+
 #endif /* __NET_TC_CSUM_H */
index 38a7427ae902e35973a8b7fa0e95ff602ede0e87..be6223c586fa05b3ef1dbcb96e73cf7b5dae292d 100644 (file)
@@ -924,7 +924,7 @@ struct tcp_congestion_ops {
        void (*cwnd_event)(struct sock *sk, enum tcp_ca_event ev);
        /* call when ack arrives (optional) */
        void (*in_ack_event)(struct sock *sk, u32 flags);
-       /* new value of cwnd after loss (optional) */
+       /* new value of cwnd after loss (required) */
        u32  (*undo_cwnd)(struct sock *sk);
        /* hook for packet ack accounting (optional) */
        void (*pkts_acked)(struct sock *sk, const struct ack_sample *sample);
index 345911965dbb8f53289d63535828969454ae3333..454ff763eeba9b829051862d7cce278be7d77b42 100644 (file)
@@ -6,7 +6,7 @@
 struct net;
 
 #ifdef CONFIG_WEXT_CORE
-int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
                      void __user *arg);
 int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
                             unsigned long arg);
@@ -14,7 +14,7 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
 struct iw_statistics *get_wireless_stats(struct net_device *dev);
 int call_commit_handler(struct net_device *dev);
 #else
-static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+static inline int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
                                    void __user *arg)
 {
        return -EINVAL;
index c383aa4edbf0c27980ef7aad22ff160c72b41bbd..6d30a01d281d4faa824129cb3921dbc3a77e7da3 100644 (file)
@@ -298,10 +298,10 @@ void x25_check_rbuf(struct sock *);
 
 /* sysctl_net_x25.c */
 #ifdef CONFIG_SYSCTL
-void x25_register_sysctl(void);
+int x25_register_sysctl(void);
 void x25_unregister_sysctl(void);
 #else
-static inline void x25_register_sysctl(void) {};
+static inline int x25_register_sysctl(void) { return 0; };
 static inline void x25_unregister_sysctl(void) {};
 #endif /* CONFIG_SYSCTL */
 
index 6793a30c66b1f054516a27229c29037fcdfa2f6f..62f5a259e597572ad4b8981ca04dd44a790760bd 100644 (file)
@@ -979,10 +979,6 @@ struct xfrm_dst {
        struct flow_cache_object flo;
        struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
        int num_pols, num_xfrms;
-#ifdef CONFIG_XFRM_SUB_POLICY
-       struct flowi *origin;
-       struct xfrm_selector *partner;
-#endif
        u32 xfrm_genid;
        u32 policy_genid;
        u32 route_mtu_cached;
@@ -998,12 +994,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
        dst_release(xdst->route);
        if (likely(xdst->u.dst.xfrm))
                xfrm_state_put(xdst->u.dst.xfrm);
-#ifdef CONFIG_XFRM_SUB_POLICY
-       kfree(xdst->origin);
-       xdst->origin = NULL;
-       kfree(xdst->partner);
-       xdst->partner = NULL;
-#endif
 }
 #endif
 
@@ -1860,8 +1850,9 @@ static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
 }
 #endif
 
-#ifdef CONFIG_XFRM_OFFLOAD
 void __net_init xfrm_dev_init(void);
+
+#ifdef CONFIG_XFRM_OFFLOAD
 int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
 int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
                       struct xfrm_user_offload *xuo);
@@ -1887,10 +1878,6 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
        }
 }
 #else
-static inline void __net_init xfrm_dev_init(void)
-{
-}
-
 static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
 {
        return 0;
index f5f70e345318151356e022ce46b623a357031920..355b81f4242defd82a3802cd47e2a28abfb24ee5 100644 (file)
@@ -158,7 +158,6 @@ enum sa_path_rec_type {
 };
 
 struct sa_path_rec_ib {
-       __be64       service_id;
        __be16       dlid;
        __be16       slid;
        u8           raw_traffic;
@@ -174,7 +173,6 @@ struct sa_path_rec_roce {
 };
 
 struct sa_path_rec_opa {
-       __be64       service_id;
        __be32       dlid;
        __be32       slid;
        u8           raw_traffic;
@@ -189,6 +187,7 @@ struct sa_path_rec_opa {
 struct sa_path_rec {
        union ib_gid dgid;
        union ib_gid sgid;
+       __be64       service_id;
        /* reserved */
        __be32       flow_label;
        u8           hop_limit;
@@ -262,7 +261,7 @@ static inline void path_conv_opa_to_ib(struct sa_path_rec *ib,
                ib->ib.dlid     = htons(ntohl(opa->opa.dlid));
                ib->ib.slid     = htons(ntohl(opa->opa.slid));
        }
-       ib->ib.service_id       = opa->opa.service_id;
+       ib->service_id          = opa->service_id;
        ib->ib.raw_traffic      = opa->opa.raw_traffic;
 }
 
@@ -281,7 +280,7 @@ static inline void path_conv_ib_to_opa(struct sa_path_rec *opa,
        }
        opa->opa.slid           = slid;
        opa->opa.dlid           = dlid;
-       opa->opa.service_id     = ib->ib.service_id;
+       opa->service_id         = ib->service_id;
        opa->opa.raw_traffic    = ib->ib.raw_traffic;
 }
 
@@ -591,15 +590,6 @@ static inline bool sa_path_is_roce(struct sa_path_rec *rec)
                (rec->rec_type == SA_PATH_REC_TYPE_ROCE_V2));
 }
 
-static inline void sa_path_set_service_id(struct sa_path_rec *rec,
-                                         __be64 service_id)
-{
-       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
-               rec->ib.service_id = service_id;
-       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
-               rec->opa.service_id = service_id;
-}
-
 static inline void sa_path_set_slid(struct sa_path_rec *rec, __be32 slid)
 {
        if (rec->rec_type == SA_PATH_REC_TYPE_IB)
@@ -625,15 +615,6 @@ static inline void sa_path_set_raw_traffic(struct sa_path_rec *rec,
                rec->opa.raw_traffic = raw_traffic;
 }
 
-static inline __be64 sa_path_get_service_id(struct sa_path_rec *rec)
-{
-       if (rec->rec_type == SA_PATH_REC_TYPE_IB)
-               return rec->ib.service_id;
-       else if (rec->rec_type == SA_PATH_REC_TYPE_OPA)
-               return rec->opa.service_id;
-       return 0;
-}
-
 static inline __be32 sa_path_get_slid(struct sa_path_rec *rec)
 {
        if (rec->rec_type == SA_PATH_REC_TYPE_IB)
index 5852661443290d52eb8a3e719716452d752b6eaa..348c102cb5f6afdbe9f90a7c788431bac0219226 100644 (file)
@@ -10,9 +10,6 @@ struct ibnl_client_cbs {
        struct module *module;
 };
 
-int ibnl_init(void);
-void ibnl_cleanup(void);
-
 /**
  * Add a a client to the list of IB netlink exporters.
  * @index: Index of the added client
@@ -77,11 +74,4 @@ int ibnl_unicast(struct sk_buff *skb, struct nlmsghdr *nlh,
 int ibnl_multicast(struct sk_buff *skb, struct nlmsghdr *nlh,
                        unsigned int group, gfp_t flags);
 
-/**
- * Check if there are any listeners to the netlink group
- * @group: the netlink group ID
- * Returns 0 on success or a negative for no listeners.
- */
-int ibnl_chk_listeners(unsigned int group);
-
 #endif /* _RDMA_NETLINK_H */
index 275581d483ddd90d97c550ee8bf44d705833ecf8..5f17fb770477bbdfa2729a7b35cf21f70493515e 100644 (file)
@@ -557,6 +557,7 @@ struct iscsi_conn {
 #define LOGIN_FLAGS_READ_ACTIVE                1
 #define LOGIN_FLAGS_CLOSED             2
 #define LOGIN_FLAGS_READY              4
+#define LOGIN_FLAGS_INITIAL_PDU                8
        unsigned long           login_flags;
        struct delayed_work     login_work;
        struct delayed_work     login_cleanup_work;
index 7caf44c7fa51bcdec2b7db2efb7439beede648dc..295cd3ef633049cfc5baf00a2668da89e9ffc580 100644 (file)
@@ -112,24 +112,7 @@ enum machine_type {
 #define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
 #endif
 
-/* Address of data segment in memory after it is loaded.
-   Note that it is up to you to define SEGMENT_SIZE
-   on machines not listed here.  */
-#if defined(vax) || defined(hp300) || defined(pyr)
-#define SEGMENT_SIZE page_size
-#endif
-#ifdef sony
-#define        SEGMENT_SIZE    0x2000
-#endif /* Sony.  */
-#ifdef is68k
-#define SEGMENT_SIZE 0x20000
-#endif
-#if defined(m68k) && defined(PORTAR)
-#define PAGE_SIZE 0x400
-#define SEGMENT_SIZE PAGE_SIZE
-#endif
-
-#ifdef linux
+/* Address of data segment in memory after it is loaded. */
 #ifndef __KERNEL__
 #include <unistd.h>
 #endif
@@ -142,7 +125,6 @@ enum machine_type {
 #endif
 #endif
 #endif
-#endif
 
 #define _N_SEGMENT_ROUND(x) ALIGN(x, SEGMENT_SIZE)
 
@@ -260,13 +242,7 @@ struct relocation_info
   unsigned int r_extern:1;
   /* Four bits that aren't used, but when writing an object file
      it is desirable to clear them.  */
-#ifdef NS32K
-  unsigned r_bsr:1;
-  unsigned r_disp:1;
-  unsigned r_pad:2;
-#else
   unsigned int r_pad:4;
-#endif
 };
 #endif /* no N_RELOCATION_INFO_DECLARED.  */
 
index 945a1f5f63c546c5521da5254a80664344ebd0ad..94dfa9def355f7f52805bba5ade3a32c304f989a 100644 (file)
@@ -132,6 +132,13 @@ enum bpf_attach_type {
  */
 #define BPF_F_ALLOW_OVERRIDE   (1U << 0)
 
+/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+ * verifier will perform strict alignment checking as if the kernel
+ * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
+ * and NET_IP_ALIGN defined to 2.
+ */
+#define BPF_F_STRICT_ALIGNMENT (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
+               __u32           prog_flags;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
index d179d7767f519829a50395f47749360f88cd3d2d..7d4a594d5d58147e3cf4b56eb992268a619badf3 100644 (file)
@@ -1486,8 +1486,10 @@ enum ethtool_link_mode_bit_indices {
  * it was forced up into this mode or autonegotiated.
  */
 
-/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. */
-/* Update drivers/net/phy/phy.c:phy_speed_to_str() when adding new values */
+/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal.
+ * Update drivers/net/phy/phy.c:phy_speed_to_str() and
+ * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values.
+ */
 #define SPEED_10               10
 #define SPEED_100              100
 #define SPEED_1000             1000
index 8e56ac70e0d1a3536a43aff83370e5b3bd5bb0b4..15ac20382ababeecafe2a336aa59a45e50d879e6 100644 (file)
@@ -888,9 +888,18 @@ enum {
 /* XDP section */
 
 #define XDP_FLAGS_UPDATE_IF_NOEXIST    (1U << 0)
-#define XDP_FLAGS_SKB_MODE             (2U << 0)
+#define XDP_FLAGS_SKB_MODE             (1U << 1)
+#define XDP_FLAGS_DRV_MODE             (1U << 2)
 #define XDP_FLAGS_MASK                 (XDP_FLAGS_UPDATE_IF_NOEXIST | \
-                                        XDP_FLAGS_SKB_MODE)
+                                        XDP_FLAGS_SKB_MODE | \
+                                        XDP_FLAGS_DRV_MODE)
+
+/* These are stored into IFLA_XDP_ATTACHED on dump. */
+enum {
+       XDP_ATTACHED_NONE = 0,
+       XDP_ATTACHED_DRV,
+       XDP_ATTACHED_SKB,
+};
 
 enum {
        IFLA_XDP_UNSPEC,
index 201c6644b2376846f3fccf16bc64d99a5aabdfd4..ef16df06642a93462e1bd5d535ec3119af3adc22 100644 (file)
@@ -70,8 +70,8 @@ struct keyctl_dh_params {
 };
 
 struct keyctl_kdf_params {
-       char *hashname;
-       char *otherinfo;
+       char __user *hashname;
+       char __user *otherinfo;
        __u32 otherinfolen;
        __u32 __spare[8];
 };
index 61b7d36dfe34394f7cbed64217a8a9a1e7f55cfe..156ee4cab82e5e73bc2705a4707c04c1cf788b98 100644 (file)
@@ -343,6 +343,7 @@ enum ovs_key_attr {
 #define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1)
 
 enum ovs_tunnel_key_attr {
+       /* OVS_TUNNEL_KEY_ATTR_NONE, standard nl API requires this attribute! */
        OVS_TUNNEL_KEY_ATTR_ID,                 /* be64 Tunnel ID */
        OVS_TUNNEL_KEY_ATTR_IPV4_SRC,           /* be32 src IP address. */
        OVS_TUNNEL_KEY_ATTR_IPV4_DST,           /* be32 dst IP address. */
index 361297e96f5826360bb24f80de9089b83a9881ba..576c704e3fb8b13f358ae67b3a415417f2c37cb5 100644 (file)
@@ -22,6 +22,9 @@
  */
 #define USB_MAXCHILDREN                31
 
+/* See USB 3.1 spec Table 10-5 */
+#define USB_SS_MAXPORTS                15
+
 /*
  * Hub request types
  */
index 5e00b2333c26e3256a6f4dc51a2a58011a2c9db6..172dc8ee0e3bda95c39f7e037e7a33baf8012214 100644 (file)
@@ -86,6 +86,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
        array->map.key_size = attr->key_size;
        array->map.value_size = attr->value_size;
        array->map.max_entries = attr->max_entries;
+       array->map.map_flags = attr->map_flags;
        array->elem_size = elem_size;
 
        if (!percpu)
index 39cfafd895b80d2f0fb5054626af001949a8ad98..b09185f0f17d3428ac445de2ed52756004ca5368 100644 (file)
@@ -432,6 +432,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
        trie->map.key_size = attr->key_size;
        trie->map.value_size = attr->value_size;
        trie->map.max_entries = attr->max_entries;
+       trie->map.map_flags = attr->map_flags;
        trie->data_size = attr->key_size -
                          offsetof(struct bpf_lpm_trie_key, data);
        trie->max_prefixlen = trie->data_size * 8;
index 4dfd6f2ec2f9725681f490971e60acc8033c64b6..31147d730abf532cc8f10efc9a871b5dd498928d 100644 (file)
@@ -88,6 +88,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
        smap->map.key_size = attr->key_size;
        smap->map.value_size = value_size;
        smap->map.max_entries = attr->max_entries;
+       smap->map.map_flags = attr->map_flags;
        smap->n_buckets = n_buckets;
        smap->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
 
index fd2411fd69148cff375120316fba0a0e033541f6..265a0d854e3358c5c714af9cc3ab2bae8a4754b4 100644 (file)
@@ -783,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
 EXPORT_SYMBOL_GPL(bpf_prog_get_type);
 
 /* last field in 'union bpf_attr' used by this command */
-#define        BPF_PROG_LOAD_LAST_FIELD kern_version
+#define        BPF_PROG_LOAD_LAST_FIELD prog_flags
 
 static int bpf_prog_load(union bpf_attr *attr)
 {
@@ -796,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr)
        if (CHECK_ATTR(BPF_PROG_LOAD))
                return -EINVAL;
 
+       if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
+               return -EINVAL;
+
        /* copy eBPF program license from user space */
        if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
                              sizeof(license) - 1) < 0)
index c5b56c92f8e255d1b13634ad07c460969484f2f4..a8a725697bed693e8e77f225eea5dcc7db46dad0 100644 (file)
@@ -140,7 +140,7 @@ struct bpf_verifier_stack_elem {
        struct bpf_verifier_stack_elem *next;
 };
 
-#define BPF_COMPLEXITY_LIMIT_INSNS     65536
+#define BPF_COMPLEXITY_LIMIT_INSNS     98304
 #define BPF_COMPLEXITY_LIMIT_STACK     1024
 
 #define BPF_MAP_PTR_POISON ((void *)0xeB9F + POISON_POINTER_DELTA)
@@ -241,6 +241,12 @@ static void print_verifier_state(struct bpf_verifier_state *state)
                if (reg->max_value != BPF_REGISTER_MAX_RANGE)
                        verbose(",max_value=%llu",
                                (unsigned long long)reg->max_value);
+               if (reg->min_align)
+                       verbose(",min_align=%u", reg->min_align);
+               if (reg->aux_off)
+                       verbose(",aux_off=%u", reg->aux_off);
+               if (reg->aux_off_align)
+                       verbose(",aux_off_align=%u", reg->aux_off_align);
        }
        for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
                if (state->stack_slot_type[i] == STACK_SPILL)
@@ -457,16 +463,22 @@ static const int caller_saved[CALLER_SAVED_REGS] = {
        BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5
 };
 
+static void mark_reg_not_init(struct bpf_reg_state *regs, u32 regno)
+{
+       BUG_ON(regno >= MAX_BPF_REG);
+
+       memset(&regs[regno], 0, sizeof(regs[regno]));
+       regs[regno].type = NOT_INIT;
+       regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
+       regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
+}
+
 static void init_reg_state(struct bpf_reg_state *regs)
 {
        int i;
 
-       for (i = 0; i < MAX_BPF_REG; i++) {
-               regs[i].type = NOT_INIT;
-               regs[i].imm = 0;
-               regs[i].min_value = BPF_REGISTER_MIN_RANGE;
-               regs[i].max_value = BPF_REGISTER_MAX_RANGE;
-       }
+       for (i = 0; i < MAX_BPF_REG; i++)
+               mark_reg_not_init(regs, i);
 
        /* frame pointer */
        regs[BPF_REG_FP].type = FRAME_PTR;
@@ -492,6 +504,7 @@ static void reset_reg_range_values(struct bpf_reg_state *regs, u32 regno)
 {
        regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
        regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
+       regs[regno].min_align = 0;
 }
 
 static void mark_reg_unknown_value_and_range(struct bpf_reg_state *regs,
@@ -779,17 +792,37 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
 }
 
 static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
-                                  int off, int size)
+                                  int off, int size, bool strict)
 {
-       if (reg->id && size != 1) {
-               verbose("Unknown alignment. Only byte-sized access allowed in packet access.\n");
-               return -EACCES;
+       int ip_align;
+       int reg_off;
+
+       /* Byte size accesses are always allowed. */
+       if (!strict || size == 1)
+               return 0;
+
+       reg_off = reg->off;
+       if (reg->id) {
+               if (reg->aux_off_align % size) {
+                       verbose("Packet access is only %u byte aligned, %d byte access not allowed\n",
+                               reg->aux_off_align, size);
+                       return -EACCES;
+               }
+               reg_off += reg->aux_off;
        }
 
-       /* skb->data is NET_IP_ALIGN-ed */
-       if ((NET_IP_ALIGN + reg->off + off) % size != 0) {
+       /* For platforms that do not have a Kconfig enabling
+        * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS the value of
+        * NET_IP_ALIGN is universally set to '2'.  And on platforms
+        * that do set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS, we get
+        * to this code only in strict mode where we want to emulate
+        * the NET_IP_ALIGN==2 checking.  Therefore use an
+        * unconditional IP align value of '2'.
+        */
+       ip_align = 2;
+       if ((ip_align + reg_off + off) % size != 0) {
                verbose("misaligned packet access off %d+%d+%d size %d\n",
-                       NET_IP_ALIGN, reg->off, off, size);
+                       ip_align, reg_off, off, size);
                return -EACCES;
        }
 
@@ -797,9 +830,9 @@ static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
 }
 
 static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
-                                  int size)
+                                  int size, bool strict)
 {
-       if (size != 1) {
+       if (strict && size != 1) {
                verbose("Unknown alignment. Only byte-sized access allowed in value access.\n");
                return -EACCES;
        }
@@ -807,16 +840,17 @@ static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
        return 0;
 }
 
-static int check_ptr_alignment(const struct bpf_reg_state *reg,
+static int check_ptr_alignment(struct bpf_verifier_env *env,
+                              const struct bpf_reg_state *reg,
                               int off, int size)
 {
+       bool strict = env->strict_alignment;
+
        switch (reg->type) {
        case PTR_TO_PACKET:
-               return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ? 0 :
-                      check_pkt_ptr_alignment(reg, off, size);
+               return check_pkt_ptr_alignment(reg, off, size, strict);
        case PTR_TO_MAP_VALUE_ADJ:
-               return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ? 0 :
-                      check_val_ptr_alignment(reg, size);
+               return check_val_ptr_alignment(reg, size, strict);
        default:
                if (off % size != 0) {
                        verbose("misaligned access off %d size %d\n",
@@ -849,7 +883,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
        if (size < 0)
                return size;
 
-       err = check_ptr_alignment(reg, off, size);
+       err = check_ptr_alignment(env, reg, off, size);
        if (err)
                return err;
 
@@ -883,6 +917,8 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
                                                         value_regno);
                        /* note that reg.[id|off|range] == 0 */
                        state->regs[value_regno].type = reg_type;
+                       state->regs[value_regno].aux_off = 0;
+                       state->regs[value_regno].aux_off_align = 0;
                }
 
        } else if (reg->type == FRAME_PTR || reg->type == PTR_TO_STACK) {
@@ -953,6 +989,11 @@ static int check_xadd(struct bpf_verifier_env *env, struct bpf_insn *insn)
        if (err)
                return err;
 
+       if (is_pointer_value(env, insn->src_reg)) {
+               verbose("R%d leaks addr into mem\n", insn->src_reg);
+               return -EACCES;
+       }
+
        /* check whether atomic_add can read the memory */
        err = check_mem_access(env, insn->dst_reg, insn->off,
                               BPF_SIZE(insn->code), BPF_READ, -1);
@@ -1313,7 +1354,6 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
        struct bpf_verifier_state *state = &env->cur_state;
        const struct bpf_func_proto *fn = NULL;
        struct bpf_reg_state *regs = state->regs;
-       struct bpf_reg_state *reg;
        struct bpf_call_arg_meta meta;
        bool changes_data;
        int i, err;
@@ -1380,11 +1420,8 @@ static int check_call(struct bpf_verifier_env *env, int func_id, int insn_idx)
        }
 
        /* reset caller saved regs */
-       for (i = 0; i < CALLER_SAVED_REGS; i++) {
-               reg = regs + caller_saved[i];
-               reg->type = NOT_INIT;
-               reg->imm = 0;
-       }
+       for (i = 0; i < CALLER_SAVED_REGS; i++)
+               mark_reg_not_init(regs, caller_saved[i]);
 
        /* update return register */
        if (fn->ret_type == RET_INTEGER) {
@@ -1455,6 +1492,8 @@ add_imm:
                 */
                dst_reg->off += imm;
        } else {
+               bool had_id;
+
                if (src_reg->type == PTR_TO_PACKET) {
                        /* R6=pkt(id=0,off=0,r=62) R7=imm22; r7 += r6 */
                        tmp_reg = *dst_reg;  /* save r7 state */
@@ -1488,14 +1527,23 @@ add_imm:
                                src_reg->imm);
                        return -EACCES;
                }
+
+               had_id = (dst_reg->id != 0);
+
                /* dst_reg stays as pkt_ptr type and since some positive
                 * integer value was added to the pointer, increment its 'id'
                 */
                dst_reg->id = ++env->id_gen;
 
-               /* something was added to pkt_ptr, set range and off to zero */
+               /* something was added to pkt_ptr, set range to zero */
+               dst_reg->aux_off += dst_reg->off;
                dst_reg->off = 0;
                dst_reg->range = 0;
+               if (had_id)
+                       dst_reg->aux_off_align = min(dst_reg->aux_off_align,
+                                                    src_reg->min_align);
+               else
+                       dst_reg->aux_off_align = src_reg->min_align;
        }
        return 0;
 }
@@ -1669,6 +1717,13 @@ static void check_reg_overflow(struct bpf_reg_state *reg)
                reg->min_value = BPF_REGISTER_MIN_RANGE;
 }
 
+static u32 calc_align(u32 imm)
+{
+       if (!imm)
+               return 1U << 31;
+       return imm - ((imm - 1) & imm);
+}
+
 static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                                    struct bpf_insn *insn)
 {
@@ -1676,8 +1731,10 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
        s64 min_val = BPF_REGISTER_MIN_RANGE;
        u64 max_val = BPF_REGISTER_MAX_RANGE;
        u8 opcode = BPF_OP(insn->code);
+       u32 dst_align, src_align;
 
        dst_reg = &regs[insn->dst_reg];
+       src_align = 0;
        if (BPF_SRC(insn->code) == BPF_X) {
                check_reg_overflow(&regs[insn->src_reg]);
                min_val = regs[insn->src_reg].min_value;
@@ -1693,12 +1750,18 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                    regs[insn->src_reg].type != UNKNOWN_VALUE) {
                        min_val = BPF_REGISTER_MIN_RANGE;
                        max_val = BPF_REGISTER_MAX_RANGE;
+                       src_align = 0;
+               } else {
+                       src_align = regs[insn->src_reg].min_align;
                }
        } else if (insn->imm < BPF_REGISTER_MAX_RANGE &&
                   (s64)insn->imm > BPF_REGISTER_MIN_RANGE) {
                min_val = max_val = insn->imm;
+               src_align = calc_align(insn->imm);
        }
 
+       dst_align = dst_reg->min_align;
+
        /* We don't know anything about what was done to this register, mark it
         * as unknown.
         */
@@ -1723,18 +1786,21 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                        dst_reg->min_value += min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value += max_val;
+               dst_reg->min_align = min(src_align, dst_align);
                break;
        case BPF_SUB:
                if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
                        dst_reg->min_value -= min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value -= max_val;
+               dst_reg->min_align = min(src_align, dst_align);
                break;
        case BPF_MUL:
                if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
                        dst_reg->min_value *= min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value *= max_val;
+               dst_reg->min_align = max(src_align, dst_align);
                break;
        case BPF_AND:
                /* Disallow AND'ing of negative numbers, ain't nobody got time
@@ -1746,17 +1812,23 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                else
                        dst_reg->min_value = 0;
                dst_reg->max_value = max_val;
+               dst_reg->min_align = max(src_align, dst_align);
                break;
        case BPF_LSH:
                /* Gotta have special overflow logic here, if we're shifting
                 * more than MAX_RANGE then just assume we have an invalid
                 * range.
                 */
-               if (min_val > ilog2(BPF_REGISTER_MAX_RANGE))
+               if (min_val > ilog2(BPF_REGISTER_MAX_RANGE)) {
                        dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
-               else if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
-                       dst_reg->min_value <<= min_val;
-
+                       dst_reg->min_align = 1;
+               } else {
+                       if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
+                               dst_reg->min_value <<= min_val;
+                       if (!dst_reg->min_align)
+                               dst_reg->min_align = 1;
+                       dst_reg->min_align <<= min_val;
+               }
                if (max_val > ilog2(BPF_REGISTER_MAX_RANGE))
                        dst_reg->max_value = BPF_REGISTER_MAX_RANGE;
                else if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
@@ -1766,11 +1838,19 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                /* RSH by a negative number is undefined, and the BPF_RSH is an
                 * unsigned shift, so make the appropriate casts.
                 */
-               if (min_val < 0 || dst_reg->min_value < 0)
+               if (min_val < 0 || dst_reg->min_value < 0) {
                        dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
-               else
+               } else {
                        dst_reg->min_value =
                                (u64)(dst_reg->min_value) >> min_val;
+               }
+               if (min_val < 0) {
+                       dst_reg->min_align = 1;
+               } else {
+                       dst_reg->min_align >>= (u64) min_val;
+                       if (!dst_reg->min_align)
+                               dst_reg->min_align = 1;
+               }
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value >>= max_val;
                break;
@@ -1872,6 +1952,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        regs[insn->dst_reg].imm = insn->imm;
                        regs[insn->dst_reg].max_value = insn->imm;
                        regs[insn->dst_reg].min_value = insn->imm;
+                       regs[insn->dst_reg].min_align = calc_align(insn->imm);
                }
 
        } else if (opcode > BPF_END) {
@@ -2368,7 +2449,6 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
        struct bpf_reg_state *regs = env->cur_state.regs;
        u8 mode = BPF_MODE(insn->code);
-       struct bpf_reg_state *reg;
        int i, err;
 
        if (!may_access_skb(env->prog->type)) {
@@ -2401,11 +2481,8 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
        }
 
        /* reset caller saved regs to unreadable */
-       for (i = 0; i < CALLER_SAVED_REGS; i++) {
-               reg = regs + caller_saved[i];
-               reg->type = NOT_INIT;
-               reg->imm = 0;
-       }
+       for (i = 0; i < CALLER_SAVED_REGS; i++)
+               mark_reg_not_init(regs, caller_saved[i]);
 
        /* mark destination R0 register as readable, since it contains
         * the value fetched from the packet
@@ -2564,6 +2641,7 @@ peek_stack:
                                env->explored_states[t + 1] = STATE_LIST_MARK;
                } else {
                        /* conditional jump with two edges */
+                       env->explored_states[t] = STATE_LIST_MARK;
                        ret = push_insn(t, t + 1, FALLTHROUGH, env);
                        if (ret == 1)
                                goto peek_stack;
@@ -2615,7 +2693,8 @@ err_free:
 /* the following conditions reduce the number of explored insns
  * from ~140k to ~80k for ultra large programs that use a lot of ptr_to_packet
  */
-static bool compare_ptrs_to_packet(struct bpf_reg_state *old,
+static bool compare_ptrs_to_packet(struct bpf_verifier_env *env,
+                                  struct bpf_reg_state *old,
                                   struct bpf_reg_state *cur)
 {
        if (old->id != cur->id)
@@ -2658,7 +2737,7 @@ static bool compare_ptrs_to_packet(struct bpf_reg_state *old,
         * 'if (R4 > data_end)' and all further insn were already good with r=20,
         * so they will be good with r=30 and we can prune the search.
         */
-       if (old->off <= cur->off &&
+       if (!env->strict_alignment && old->off <= cur->off &&
            old->off >= old->range && cur->off >= cur->range)
                return true;
 
@@ -2722,8 +2801,14 @@ static bool states_equal(struct bpf_verifier_env *env,
                     rcur->type != NOT_INIT))
                        continue;
 
+               /* Don't care about the reg->id in this case. */
+               if (rold->type == PTR_TO_MAP_VALUE_OR_NULL &&
+                   rcur->type == PTR_TO_MAP_VALUE_OR_NULL &&
+                   rold->map_ptr == rcur->map_ptr)
+                       continue;
+
                if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET &&
-                   compare_ptrs_to_packet(rold, rcur))
+                   compare_ptrs_to_packet(env, rold, rcur))
                        continue;
 
                return false;
@@ -2856,8 +2941,15 @@ static int do_check(struct bpf_verifier_env *env)
                        goto process_bpf_exit;
                }
 
-               if (log_level && do_print_state) {
-                       verbose("\nfrom %d to %d:", prev_insn_idx, insn_idx);
+               if (need_resched())
+                       cond_resched();
+
+               if (log_level > 1 || (log_level && do_print_state)) {
+                       if (log_level > 1)
+                               verbose("%d:", insn_idx);
+                       else
+                               verbose("\nfrom %d to %d:",
+                                       prev_insn_idx, insn_idx);
                        print_verifier_state(&env->cur_state);
                        do_print_state = false;
                }
@@ -3495,6 +3587,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
                log_level = 0;
        }
 
+       env->strict_alignment = !!(attr->prog_flags & BPF_F_STRICT_ALIGNMENT);
+       if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
+               env->strict_alignment = true;
+
        ret = replace_map_fd_with_map_ptr(env);
        if (ret < 0)
                goto skip_full_check;
@@ -3600,6 +3696,10 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
 
        log_level = 0;
 
+       env->strict_alignment = false;
+       if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
+               env->strict_alignment = true;
+
        env->explored_states = kcalloc(env->prog->len,
                                       sizeof(struct bpf_verifier_state_list *),
                                       GFP_KERNEL);
index c3c9a0e1b3c9a474bd80b8cb10ea1049284474b0..8d4e85eae42c08481899e415075ee42c6d12f90f 100644 (file)
@@ -4265,6 +4265,11 @@ static void kill_css(struct cgroup_subsys_state *css)
 {
        lockdep_assert_held(&cgroup_mutex);
 
+       if (css->flags & CSS_DYING)
+               return;
+
+       css->flags |= CSS_DYING;
+
        /*
         * This must happen before css is disassociated with its cgroup.
         * See seq_css() for details.
index f6501f4f6040b5a9c21e84aeb57e20906ef1c614..ae643412948added94f05d7efb120631f7798b44 100644 (file)
@@ -176,9 +176,9 @@ typedef enum {
 } cpuset_flagbits_t;
 
 /* convenient tests for these bits */
-static inline bool is_cpuset_online(const struct cpuset *cs)
+static inline bool is_cpuset_online(struct cpuset *cs)
 {
-       return test_bit(CS_ONLINE, &cs->flags);
+       return test_bit(CS_ONLINE, &cs->flags) && !css_is_dying(&cs->css);
 }
 
 static inline int is_cpu_exclusive(const struct cpuset *cs)
index 9ae6fbe5b5cf5d70d5869e8efb00c61f47cf66d4..cb5103413bd8df5056b3eda682a8d93b08656dd8 100644 (file)
@@ -1658,13 +1658,13 @@ static ssize_t write_cpuhp_target(struct device *dev,
        ret = !sp->name || sp->cant_stop ? -EINVAL : 0;
        mutex_unlock(&cpuhp_state_mutex);
        if (ret)
-               return ret;
+               goto out;
 
        if (st->state < target)
                ret = do_cpu_up(dev->id, target);
        else
                ret = do_cpu_down(dev->id, target);
-
+out:
        unlock_device_hotplug();
        return ret ? ret : count;
 }
index 6e75a5c9412dee17daabc1cb131bb517ad431207..6c4e523dc1e2e6b53d44bf6a540bc168bcde1eca 100644 (file)
@@ -7316,6 +7316,21 @@ int perf_event_account_interrupt(struct perf_event *event)
        return __perf_event_account_interrupt(event, 1);
 }
 
+static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs)
+{
+       /*
+        * Due to interrupt latency (AKA "skid"), we may enter the
+        * kernel before taking an overflow, even if the PMU is only
+        * counting user events.
+        * To avoid leaking information to userspace, we must always
+        * reject kernel samples when exclude_kernel is set.
+        */
+       if (event->attr.exclude_kernel && !user_mode(regs))
+               return false;
+
+       return true;
+}
+
 /*
  * Generic event overflow handling, sampling.
  */
@@ -7336,6 +7351,12 @@ static int __perf_event_overflow(struct perf_event *event,
 
        ret = __perf_event_account_interrupt(event, throttle);
 
+       /*
+        * For security, drop the skid kernel samples if necessary.
+        */
+       if (!sample_is_allowed(event, regs))
+               return ret;
+
        /*
         * XXX event_limit might not quite work as expected on inherited
         * events
index 2831480c63a28b8e9b8cee1c0b30968860b3fcd0..ee97196bb1510e4f95cfd6ddc039fa9700cdc828 100644 (file)
@@ -580,7 +580,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
        int ret = -ENOMEM, max_order = 0;
 
        if (!has_aux(event))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        if (event->pmu->capabilities & PERF_PMU_CAP_AUX_NO_SG) {
                /*
index 06d759ab4c62ff090ab51715eaf0bc4fcabc250e..e53770d2bf956bf5bf6ec1a42c75121552713da6 100644 (file)
@@ -1577,6 +1577,18 @@ static __latent_entropy struct task_struct *copy_process(
        if (!p)
                goto fork_out;
 
+       /*
+        * This _must_ happen before we call free_task(), i.e. before we jump
+        * to any of the bad_fork_* labels. This is to avoid freeing
+        * p->set_child_tid which is (ab)used as a kthread's data pointer for
+        * kernel threads (PF_KTHREAD).
+        */
+       p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
+       /*
+        * Clear TID on mm_release()?
+        */
+       p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
+
        ftrace_graph_init_task(p);
 
        rt_mutex_init_task(p);
@@ -1743,11 +1755,6 @@ static __latent_entropy struct task_struct *copy_process(
                }
        }
 
-       p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
-       /*
-        * Clear TID on mm_release()?
-        */
-       p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
 #ifdef CONFIG_BLOCK
        p->plug = NULL;
 #endif
@@ -1845,11 +1852,13 @@ static __latent_entropy struct task_struct *copy_process(
        */
        recalc_sigpending();
        if (signal_pending(current)) {
-               spin_unlock(&current->sighand->siglock);
-               write_unlock_irq(&tasklist_lock);
                retval = -ERESTARTNOINTR;
                goto bad_fork_cancel_cgroup;
        }
+       if (unlikely(!(ns_of_pid(pid)->nr_hashed & PIDNS_HASH_ADDING))) {
+               retval = -ENOMEM;
+               goto bad_fork_cancel_cgroup;
+       }
 
        if (likely(p->pid)) {
                ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
@@ -1907,6 +1916,8 @@ static __latent_entropy struct task_struct *copy_process(
        return p;
 
 bad_fork_cancel_cgroup:
+       spin_unlock(&current->sighand->siglock);
+       write_unlock_irq(&tasklist_lock);
        cgroup_cancel_fork(p);
 bad_fork_free_pid:
        cgroup_threadgroup_change_end(current);
index 686be4b73018886d5b676d99cc5f5645cf408259..c94da688ee9b30ff9e746372b20a0c30f4c8cf5f 100644 (file)
@@ -880,8 +880,8 @@ irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
        if (!desc)
                return;
 
-       __irq_do_set_handler(desc, handle, 1, NULL);
        desc->irq_common_data.handler_data = data;
+       __irq_do_set_handler(desc, handle, 1, NULL);
 
        irq_put_desc_busunlock(desc, flags);
 }
index 070be980c37a57d91f86099d2be1b81db80176bc..425170d4439be5926a63ef9be50c71c1dd5878a9 100644 (file)
@@ -1312,8 +1312,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                        ret = __irq_set_trigger(desc,
                                                new->flags & IRQF_TRIGGER_MASK);
 
-                       if (ret)
+                       if (ret) {
+                               irq_release_resources(desc);
                                goto out_mask;
+                       }
                }
 
                desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
index 7367e0ec6f8188973a0ee63539cd9a8485e47585..adfe3b4cfe05a101bcee0da8e72db6fe6a10cf72 100644 (file)
@@ -122,7 +122,7 @@ static void *alloc_insn_page(void)
        return module_alloc(PAGE_SIZE);
 }
 
-static void free_insn_page(void *page)
+void __weak free_insn_page(void *page)
 {
        module_memfree(page);
 }
@@ -595,7 +595,7 @@ static void kprobe_optimizer(struct work_struct *work)
 }
 
 /* Wait for completing optimization and unoptimization */
-static void wait_for_kprobe_optimizer(void)
+void wait_for_kprobe_optimizer(void)
 {
        mutex_lock(&kprobe_mutex);
 
@@ -2183,6 +2183,12 @@ static int kprobes_module_callback(struct notifier_block *nb,
                                 * The vaddr this probe is installed will soon
                                 * be vfreed buy not synced to disk. Hence,
                                 * disarming the breakpoint isn't needed.
+                                *
+                                * Note, this will also move any optimized probes
+                                * that are pending to be removed from their
+                                * corresponding lists to the freeing_list and
+                                * will not be touched by the delayed
+                                * kprobe_optimizer work handler.
                                 */
                                kill_kprobe(p);
                        }
index 0450225579367eee10de6695679fffa7b963f013..ec4565122e6553f490dfb2434b6c14102b152bb2 100644 (file)
@@ -10,6 +10,7 @@ config LIVEPATCH
        depends on SYSFS
        depends on KALLSYMS_ALL
        depends on HAVE_LIVEPATCH
+       depends on !TRIM_UNUSED_KSYMS
        help
          Say Y here if you want to support kernel live patching.
          This option has no runtime impact until a kernel "patch"
index f8269036bf0b84f89faa2db3b5dc5fe4c259a019..52c4e907c14b0d4a7896d7ca9a6fa6fbc17451ba 100644 (file)
@@ -59,7 +59,11 @@ static void notrace klp_ftrace_handler(unsigned long ip,
 
        ops = container_of(fops, struct klp_ops, fops);
 
-       rcu_read_lock();
+       /*
+        * A variant of synchronize_sched() is used to allow patching functions
+        * where RCU is not watching, see klp_synchronize_transition().
+        */
+       preempt_disable_notrace();
 
        func = list_first_or_null_rcu(&ops->func_stack, struct klp_func,
                                      stack_node);
@@ -115,7 +119,7 @@ static void notrace klp_ftrace_handler(unsigned long ip,
 
        klp_arch_set_pc(regs, (unsigned long)func->new_func);
 unlock:
-       rcu_read_unlock();
+       preempt_enable_notrace();
 }
 
 /*
index adc0cc64aa4b6ae199e5f4a5b2af0ad59c382175..b004a1fb603236f31cd5780962c098bfcf8fe743 100644 (file)
@@ -48,6 +48,28 @@ static void klp_transition_work_fn(struct work_struct *work)
 }
 static DECLARE_DELAYED_WORK(klp_transition_work, klp_transition_work_fn);
 
+/*
+ * This function is just a stub to implement a hard force
+ * of synchronize_sched(). This requires synchronizing
+ * tasks even in userspace and idle.
+ */
+static void klp_sync(struct work_struct *work)
+{
+}
+
+/*
+ * We allow to patch also functions where RCU is not watching,
+ * e.g. before user_exit(). We can not rely on the RCU infrastructure
+ * to do the synchronization. Instead hard force the sched synchronization.
+ *
+ * This approach allows to use RCU functions for manipulating func_stack
+ * safely.
+ */
+static void klp_synchronize_transition(void)
+{
+       schedule_on_each_cpu(klp_sync);
+}
+
 /*
  * The transition to the target patch state is complete.  Clean up the data
  * structures.
@@ -73,7 +95,7 @@ static void klp_complete_transition(void)
                 * func->transition gets cleared, the handler may choose a
                 * removed function.
                 */
-               synchronize_rcu();
+               klp_synchronize_transition();
        }
 
        if (klp_transition_patch->immediate)
@@ -92,7 +114,7 @@ static void klp_complete_transition(void)
 
        /* Prevent klp_ftrace_handler() from seeing KLP_UNDEFINED state */
        if (klp_target_state == KLP_PATCHED)
-               synchronize_rcu();
+               klp_synchronize_transition();
 
        read_lock(&tasklist_lock);
        for_each_process_thread(g, task) {
@@ -136,7 +158,11 @@ void klp_cancel_transition(void)
  */
 void klp_update_patch_state(struct task_struct *task)
 {
-       rcu_read_lock();
+       /*
+        * A variant of synchronize_sched() is used to allow patching functions
+        * where RCU is not watching, see klp_synchronize_transition().
+        */
+       preempt_disable_notrace();
 
        /*
         * This test_and_clear_tsk_thread_flag() call also serves as a read
@@ -153,7 +179,7 @@ void klp_update_patch_state(struct task_struct *task)
        if (test_and_clear_tsk_thread_flag(task, TIF_PATCH_PENDING))
                task->patch_state = READ_ONCE(klp_target_state);
 
-       rcu_read_unlock();
+       preempt_enable_notrace();
 }
 
 /*
@@ -539,7 +565,7 @@ void klp_reverse_transition(void)
                clear_tsk_thread_flag(idle_task(cpu), TIF_PATCH_PENDING);
 
        /* Let any remaining calls to klp_update_patch_state() complete */
-       synchronize_rcu();
+       klp_synchronize_transition();
 
        klp_start_transition();
 }
index b9550941690915bc23323cd772e060cda7d3a704..28cd09e635ed669fe6c93b28eb1d59e46bbf4615 100644 (file)
@@ -1785,12 +1785,14 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
        int ret;
 
        raw_spin_lock_irq(&lock->wait_lock);
-
-       set_current_state(TASK_INTERRUPTIBLE);
-
        /* sleep on the mutex */
+       set_current_state(TASK_INTERRUPTIBLE);
        ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter);
-
+       /*
+        * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
+        * have to fix that up.
+        */
+       fixup_rt_mutex_waiters(lock);
        raw_spin_unlock_irq(&lock->wait_lock);
 
        return ret;
@@ -1821,16 +1823,26 @@ bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock,
        bool cleanup = false;
 
        raw_spin_lock_irq(&lock->wait_lock);
+       /*
+        * Do an unconditional try-lock, this deals with the lock stealing
+        * state where __rt_mutex_futex_unlock() -> mark_wakeup_next_waiter()
+        * sets a NULL owner.
+        *
+        * We're not interested in the return value, because the subsequent
+        * test on rt_mutex_owner() will infer that. If the trylock succeeded,
+        * we will own the lock and it will have removed the waiter. If we
+        * failed the trylock, we're still not owner and we need to remove
+        * ourselves.
+        */
+       try_to_take_rt_mutex(lock, current, waiter);
        /*
         * Unless we're the owner; we're still enqueued on the wait_list.
         * So check if we became owner, if not, take us off the wait_list.
         */
        if (rt_mutex_owner(lock) != current) {
                remove_waiter(lock, waiter);
-               fixup_rt_mutex_waiters(lock);
                cleanup = true;
        }
-
        /*
         * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
         * have to fix that up.
index d1f3e9f558b84058e4f8ec88fdfddc647d2f704e..74a5a7255b4d9cb473cc7708d851c64402cca942 100644 (file)
@@ -277,7 +277,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
         * if reparented.
         */
        for (;;) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
+               set_current_state(TASK_INTERRUPTIBLE);
                if (pid_ns->nr_hashed == init_pids)
                        break;
                schedule();
index 78672d324a6ef95394ad72a0b0ba29c7d1155d5d..c7209f060eeb7c8672cf8f07ba9c83ac6c9460ac 100644 (file)
@@ -132,7 +132,7 @@ int freeze_processes(void)
        if (!pm_freezing)
                atomic_inc(&system_freezing_cnt);
 
-       pm_wakeup_clear(true);
+       pm_wakeup_clear();
        pr_info("Freezing user space processes ... ");
        pm_freezing = true;
        error = try_to_freeze_tasks(true);
index 3b1e0f3ad07fa69d9524bcb72d1c6d0bab1a9ad8..fa46606f33565613d2ef13a1e948f2bae0dfaa8b 100644 (file)
@@ -1425,7 +1425,7 @@ static unsigned int nr_meta_pages;
  * Numbers of normal and highmem page frames allocated for hibernation image
  * before suspending devices.
  */
-unsigned int alloc_normal, alloc_highmem;
+static unsigned int alloc_normal, alloc_highmem;
 /*
  * Memory bitmap used for marking saveable pages (during hibernation) or
  * hibernation image pages (during restore)
index c0248c74d6d4cef6dbf09f485f36686862c29094..15e6baef5c73f90b6817c0b1c4e871ea40e30318 100644 (file)
@@ -72,8 +72,6 @@ static void freeze_begin(void)
 
 static void freeze_enter(void)
 {
-       trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true);
-
        spin_lock_irq(&suspend_freeze_lock);
        if (pm_wakeup_pending())
                goto out;
@@ -100,27 +98,6 @@ static void freeze_enter(void)
  out:
        suspend_freeze_state = FREEZE_STATE_NONE;
        spin_unlock_irq(&suspend_freeze_lock);
-
-       trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false);
-}
-
-static void s2idle_loop(void)
-{
-       do {
-               freeze_enter();
-
-               if (freeze_ops && freeze_ops->wake)
-                       freeze_ops->wake();
-
-               dpm_resume_noirq(PMSG_RESUME);
-               if (freeze_ops && freeze_ops->sync)
-                       freeze_ops->sync();
-
-               if (pm_wakeup_pending())
-                       break;
-
-               pm_wakeup_clear(false);
-       } while (!dpm_suspend_noirq(PMSG_SUSPEND));
 }
 
 void freeze_wake(void)
@@ -394,8 +371,10 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
         * all the devices are suspended.
         */
        if (state == PM_SUSPEND_FREEZE) {
-               s2idle_loop();
-               goto Platform_early_resume;
+               trace_suspend_resume(TPS("machine_suspend"), state, true);
+               freeze_enter();
+               trace_suspend_resume(TPS("machine_suspend"), state, false);
+               goto Platform_wake;
        }
 
        error = disable_nonboot_cpus();
index a1aecf44ab07c70ab9f33d455646559313926344..a1db38abac5b750e8ce228b441b27900360665ec 100644 (file)
@@ -269,7 +269,6 @@ static struct console *exclusive_console;
 #define MAX_CMDLINECONSOLES 8
 
 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
-static int console_cmdline_cnt;
 
 static int preferred_console = -1;
 int console_set_on_cmdline;
@@ -1906,25 +1905,12 @@ static int __add_preferred_console(char *name, int idx, char *options,
         *      See if this tty is not yet registered, and
         *      if we have a slot free.
         */
-       for (i = 0, c = console_cmdline; i < console_cmdline_cnt; i++, c++) {
+       for (i = 0, c = console_cmdline;
+            i < MAX_CMDLINECONSOLES && c->name[0];
+            i++, c++) {
                if (strcmp(c->name, name) == 0 && c->index == idx) {
-                       if (brl_options)
-                               return 0;
-
-                       /*
-                        * Maintain an invariant that will help to find if
-                        * the matching console is preferred, see
-                        * register_console():
-                        *
-                        * The last non-braille console is always
-                        * the preferred one.
-                        */
-                       if (i != console_cmdline_cnt - 1)
-                               swap(console_cmdline[i],
-                                    console_cmdline[console_cmdline_cnt - 1]);
-
-                       preferred_console = console_cmdline_cnt - 1;
-
+                       if (!brl_options)
+                               preferred_console = i;
                        return 0;
                }
        }
@@ -1937,7 +1923,6 @@ static int __add_preferred_console(char *name, int idx, char *options,
        braille_set_options(c, brl_options);
 
        c->index = idx;
-       console_cmdline_cnt++;
        return 0;
 }
 /*
@@ -2477,23 +2462,12 @@ void register_console(struct console *newcon)
        }
 
        /*
-        * See if this console matches one we selected on the command line.
-        *
-        * There may be several entries in the console_cmdline array matching
-        * with the same console, one with newcon->match(), another by
-        * name/index:
-        *
-        *      pl011,mmio,0x87e024000000,115200 -- added from SPCR
-        *      ttyAMA0 -- added from command line
-        *
-        * Traverse the console_cmdline array in reverse order to be
-        * sure that if this console is preferred then it will be the first
-        * matching entry.  We use the invariant that is maintained in
-        * __add_preferred_console().
+        *      See if this console matches one we selected on
+        *      the command line.
         */
-       for (i = console_cmdline_cnt - 1; i >= 0; i--) {
-               c = console_cmdline + i;
-
+       for (i = 0, c = console_cmdline;
+            i < MAX_CMDLINECONSOLES && c->name[0];
+            i++, c++) {
                if (!newcon->match ||
                    newcon->match(newcon, c->name, c->index, c->options) != 0) {
                        /* default matching */
index 266ddcc1d8bbbc6af7bceda3657618beef2a9c59..60f356d91060c8974268cc5bc02d57c75d359afc 100644 (file)
@@ -60,19 +60,25 @@ int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
 }
 
 
+void __ptrace_link(struct task_struct *child, struct task_struct *new_parent,
+                  const struct cred *ptracer_cred)
+{
+       BUG_ON(!list_empty(&child->ptrace_entry));
+       list_add(&child->ptrace_entry, &new_parent->ptraced);
+       child->parent = new_parent;
+       child->ptracer_cred = get_cred(ptracer_cred);
+}
+
 /*
  * ptrace a task: make the debugger its new parent and
  * move it to the ptrace list.
  *
  * Must be called with the tasklist lock write-held.
  */
-void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
+static void ptrace_link(struct task_struct *child, struct task_struct *new_parent)
 {
-       BUG_ON(!list_empty(&child->ptrace_entry));
-       list_add(&child->ptrace_entry, &new_parent->ptraced);
-       child->parent = new_parent;
        rcu_read_lock();
-       child->ptracer_cred = get_cred(__task_cred(new_parent));
+       __ptrace_link(child, new_parent, __task_cred(new_parent));
        rcu_read_unlock();
 }
 
@@ -386,7 +392,7 @@ static int ptrace_attach(struct task_struct *task, long request,
                flags |= PT_SEIZED;
        task->ptrace = flags;
 
-       __ptrace_link(task, current);
+       ptrace_link(task, current);
 
        /* SEIZE doesn't trap tracee on attach */
        if (!seize)
@@ -459,7 +465,7 @@ static int ptrace_traceme(void)
                 */
                if (!ret && !(current->real_parent->flags & PF_EXITING)) {
                        current->ptrace = PT_PTRACED;
-                       __ptrace_link(current, current->real_parent);
+                       ptrace_link(current, current->real_parent);
                }
        }
        write_unlock_irq(&tasklist_lock);
index 584d8a983883584dfa87ff0e36cf01465506c199..dea03614263fdc185fbdb3a7e3ec9ec8d1618888 100644 (file)
@@ -263,7 +263,7 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
 
 /*
  * Counts the new reader in the appropriate per-CPU element of the
- * srcu_struct.  Must be called from process context.
+ * srcu_struct.
  * Returns an index that must be passed to the matching srcu_read_unlock().
  */
 int __srcu_read_lock(struct srcu_struct *sp)
@@ -271,7 +271,7 @@ int __srcu_read_lock(struct srcu_struct *sp)
        int idx;
 
        idx = READ_ONCE(sp->completed) & 0x1;
-       __this_cpu_inc(sp->per_cpu_ref->lock_count[idx]);
+       this_cpu_inc(sp->per_cpu_ref->lock_count[idx]);
        smp_mb(); /* B */  /* Avoid leaking the critical section. */
        return idx;
 }
@@ -281,7 +281,6 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);
  * Removes the count for the old reader from the appropriate per-CPU
  * element of the srcu_struct.  Note that this may well be a different
  * CPU than that which was incremented by the corresponding srcu_read_lock().
- * Must be called from process context.
  */
 void __srcu_read_unlock(struct srcu_struct *sp, int idx)
 {
index 36e1f82faed15cb8e3bbfb3b7705bcdf29b5da71..32798eb14853d47b9b155bb4bd3c4007dd13736e 100644 (file)
@@ -97,8 +97,9 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
 
 /*
  * Counts the new reader in the appropriate per-CPU element of the
- * srcu_struct.  Must be called from process context.
- * Returns an index that must be passed to the matching srcu_read_unlock().
+ * srcu_struct.  Can be invoked from irq/bh handlers, but the matching
+ * __srcu_read_unlock() must be in the same handler instance.  Returns an
+ * index that must be passed to the matching srcu_read_unlock().
  */
 int __srcu_read_lock(struct srcu_struct *sp)
 {
@@ -112,7 +113,7 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);
 
 /*
  * Removes the count for the old reader from the appropriate element of
- * the srcu_struct.  Must be called from process context.
+ * the srcu_struct.
  */
 void __srcu_read_unlock(struct srcu_struct *sp, int idx)
 {
index 3ae8474557df3975398722ecd6c8793e271af4ad..157654fa436a2f2f0c9284aedf51315747d017d9 100644 (file)
@@ -357,7 +357,7 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
 
 /*
  * Counts the new reader in the appropriate per-CPU element of the
- * srcu_struct.  Must be called from process context.
+ * srcu_struct.
  * Returns an index that must be passed to the matching srcu_read_unlock().
  */
 int __srcu_read_lock(struct srcu_struct *sp)
@@ -365,7 +365,7 @@ int __srcu_read_lock(struct srcu_struct *sp)
        int idx;
 
        idx = READ_ONCE(sp->srcu_idx) & 0x1;
-       __this_cpu_inc(sp->sda->srcu_lock_count[idx]);
+       this_cpu_inc(sp->sda->srcu_lock_count[idx]);
        smp_mb(); /* B */  /* Avoid leaking the critical section. */
        return idx;
 }
@@ -375,7 +375,6 @@ EXPORT_SYMBOL_GPL(__srcu_read_lock);
  * Removes the count for the old reader from the appropriate per-CPU
  * element of the srcu_struct.  Note that this may well be a different
  * CPU than that which was incremented by the corresponding srcu_read_lock().
- * Must be called from process context.
  */
 void __srcu_read_unlock(struct srcu_struct *sp, int idx)
 {
index 759f4bd52cd6b3724b858d41f57ff305a3747c8b..326d4f88e2b1dbda470c7730c6ae1a67cc095f99 100644 (file)
@@ -3502,6 +3502,31 @@ asmlinkage __visible void __sched schedule(void)
 }
 EXPORT_SYMBOL(schedule);
 
+/*
+ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted
+ * state (have scheduled out non-voluntarily) by making sure that all
+ * tasks have either left the run queue or have gone into user space.
+ * As idle tasks do not do either, they must not ever be preempted
+ * (schedule out non-voluntarily).
+ *
+ * schedule_idle() is similar to schedule_preempt_disable() except that it
+ * never enables preemption because it does not call sched_submit_work().
+ */
+void __sched schedule_idle(void)
+{
+       /*
+        * As this skips calling sched_submit_work(), which the idle task does
+        * regardless because that function is a nop when the task is in a
+        * TASK_RUNNING state, make sure this isn't used someplace that the
+        * current task can be in any other state. Note, idle is always in the
+        * TASK_RUNNING state.
+        */
+       WARN_ON_ONCE(current->state);
+       do {
+               __schedule(false);
+       } while (need_resched());
+}
+
 #ifdef CONFIG_CONTEXT_TRACKING
 asmlinkage __visible void __sched schedule_user(void)
 {
@@ -5580,7 +5605,7 @@ void idle_task_exit(void)
        BUG_ON(cpu_online(smp_processor_id()));
 
        if (mm != &init_mm) {
-               switch_mm_irqs_off(mm, &init_mm, current);
+               switch_mm(mm, &init_mm, current);
                finish_arch_post_lock_switch();
        }
        mmdrop(mm);
index 76877a62b5fa374f0daa93f1180ce853ba32fc0c..076a2e31951ccbb538e8004a85cf1f247818d57e 100644 (file)
@@ -101,9 +101,6 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
        if (sg_policy->next_freq == next_freq)
                return;
 
-       if (sg_policy->next_freq > next_freq)
-               next_freq = (sg_policy->next_freq + next_freq) >> 1;
-
        sg_policy->next_freq = next_freq;
        sg_policy->last_freq_update_time = time;
 
@@ -245,11 +242,10 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
        sugov_update_commit(sg_policy, time, next_f);
 }
 
-static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu)
+static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
 {
        struct sugov_policy *sg_policy = sg_cpu->sg_policy;
        struct cpufreq_policy *policy = sg_policy->policy;
-       u64 last_freq_update_time = sg_policy->last_freq_update_time;
        unsigned long util = 0, max = 1;
        unsigned int j;
 
@@ -265,7 +261,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu)
                 * enough, don't take the CPU into account as it probably is
                 * idle now (and clear iowait_boost for it).
                 */
-               delta_ns = last_freq_update_time - j_sg_cpu->last_update;
+               delta_ns = time - j_sg_cpu->last_update;
                if (delta_ns > TICK_NSEC) {
                        j_sg_cpu->iowait_boost = 0;
                        continue;
@@ -309,7 +305,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time,
                if (flags & SCHED_CPUFREQ_RT_DL)
                        next_f = sg_policy->policy->cpuinfo.max_freq;
                else
-                       next_f = sugov_next_freq_shared(sg_cpu);
+                       next_f = sugov_next_freq_shared(sg_cpu, time);
 
                sugov_update_commit(sg_policy, time, next_f);
        }
index d711093218415d77ead6405004dd9e41323ad924..c77e4b1d51c09d1fc948d0bb105cd97b50fc6a42 100644 (file)
@@ -3563,7 +3563,7 @@ static inline void check_schedstat_required(void)
                        trace_sched_stat_runtime_enabled())  {
                printk_deferred_once("Scheduler tracepoints stat_sleep, stat_iowait, "
                             "stat_blocked and stat_runtime require the "
-                            "kernel parameter schedstats=enabled or "
+                            "kernel parameter schedstats=enable or "
                             "kernel.sched_schedstats=1\n");
        }
 #endif
index 2a25a9ec2c6e5806ad8528717c5b372d750dcf9e..ef63adce0c9cf98eecd9a6896e16d804c6bc1759 100644 (file)
@@ -265,7 +265,7 @@ static void do_idle(void)
        smp_mb__after_atomic();
 
        sched_ttwu_pending();
-       schedule_preempt_disabled();
+       schedule_idle();
 
        if (unlikely(klp_patch_pending(current)))
                klp_update_patch_state(current);
index 7808ab05059991a2dad05bf073f1fee539f0fbbd..6dda2aab731e04c5e1f88272f180f44df22e907a 100644 (file)
@@ -1467,6 +1467,8 @@ static inline struct cpuidle_state *idle_get_state(struct rq *rq)
 }
 #endif
 
+extern void schedule_idle(void);
+
 extern void sysrq_sched_debug_show(void);
 extern void sched_init_granularity(void);
 extern void update_max_interval(void);
index ca92bcfeb322f3f836031ec8b3ab21867f39adf5..45b4c1ffe14ef4334a918d0fc9ed407d801cafe6 100644 (file)
@@ -510,7 +510,8 @@ int unhandled_signal(struct task_struct *tsk, int sig)
        return !tsk->ptrace;
 }
 
-static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
+                          bool *resched_timer)
 {
        struct sigqueue *q, *first = NULL;
 
@@ -532,6 +533,12 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
 still_pending:
                list_del_init(&first->list);
                copy_siginfo(info, &first->info);
+
+               *resched_timer =
+                       (first->flags & SIGQUEUE_PREALLOC) &&
+                       (info->si_code == SI_TIMER) &&
+                       (info->si_sys_private);
+
                __sigqueue_free(first);
        } else {
                /*
@@ -548,12 +555,12 @@ still_pending:
 }
 
 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
-                       siginfo_t *info)
+                       siginfo_t *info, bool *resched_timer)
 {
        int sig = next_signal(pending, mask);
 
        if (sig)
-               collect_signal(sig, pending, info);
+               collect_signal(sig, pending, info, resched_timer);
        return sig;
 }
 
@@ -565,15 +572,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
  */
 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 {
+       bool resched_timer = false;
        int signr;
 
        /* We only dequeue private signals from ourselves, we don't let
         * signalfd steal them
         */
-       signr = __dequeue_signal(&tsk->pending, mask, info);
+       signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
        if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
-                                        mask, info);
+                                        mask, info, &resched_timer);
 #ifdef CONFIG_POSIX_TIMERS
                /*
                 * itimer signal ?
@@ -621,7 +629,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                current->jobctl |= JOBCTL_STOP_DEQUEUED;
        }
 #ifdef CONFIG_POSIX_TIMERS
-       if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
+       if (resched_timer) {
                /*
                 * Release the siglock to ensure proper locking order
                 * of timer locks outside of siglocks.  Note, we leave
index 5cb5b0008d9710c95c1af7ab8312b5e308b2c5d0..ee2f4202d82aa2acec5e438218a2405a4315f166 100644 (file)
@@ -387,7 +387,7 @@ void alarm_start_relative(struct alarm *alarm, ktime_t start)
 {
        struct alarm_base *base = &alarm_bases[alarm->type];
 
-       start = ktime_add(start, base->gettime());
+       start = ktime_add_safe(start, base->gettime());
        alarm_start(alarm, start);
 }
 EXPORT_SYMBOL_GPL(alarm_start_relative);
@@ -475,7 +475,7 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
                overrun++;
        }
 
-       alarm->node.expires = ktime_add(alarm->node.expires, interval);
+       alarm->node.expires = ktime_add_safe(alarm->node.expires, interval);
        return overrun;
 }
 EXPORT_SYMBOL_GPL(alarm_forward);
@@ -660,13 +660,21 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
 
        /* start the timer */
        timr->it.alarm.interval = timespec64_to_ktime(new_setting->it_interval);
+
+       /*
+        * Rate limit to the tick as a hot fix to prevent DOS. Will be
+        * mopped up later.
+        */
+       if (timr->it.alarm.interval < TICK_NSEC)
+               timr->it.alarm.interval = TICK_NSEC;
+
        exp = timespec64_to_ktime(new_setting->it_value);
        /* Convert (if necessary) to absolute time */
        if (flags != TIMER_ABSTIME) {
                ktime_t now;
 
                now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
-               exp = ktime_add(now, exp);
+               exp = ktime_add_safe(now, exp);
        }
 
        alarm_start(&timr->it.alarm.alarmtimer, exp);
index 1370f067fb51511f26d578cb3954032952a62027..d2a1e6dd02913f4beb58b1d79be12d72761deec3 100644 (file)
@@ -825,8 +825,10 @@ static void check_thread_timers(struct task_struct *tsk,
                         * At the hard limit, we just die.
                         * No need to calculate anything else now.
                         */
-                       pr_info("CPU Watchdog Timeout (hard): %s[%d]\n",
-                               tsk->comm, task_pid_nr(tsk));
+                       if (print_fatal_signals) {
+                               pr_info("CPU Watchdog Timeout (hard): %s[%d]\n",
+                                       tsk->comm, task_pid_nr(tsk));
+                       }
                        __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
                        return;
                }
@@ -838,8 +840,10 @@ static void check_thread_timers(struct task_struct *tsk,
                                soft += USEC_PER_SEC;
                                sig->rlim[RLIMIT_RTTIME].rlim_cur = soft;
                        }
-                       pr_info("RT Watchdog Timeout (soft): %s[%d]\n",
-                               tsk->comm, task_pid_nr(tsk));
+                       if (print_fatal_signals) {
+                               pr_info("RT Watchdog Timeout (soft): %s[%d]\n",
+                                       tsk->comm, task_pid_nr(tsk));
+                       }
                        __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
                }
        }
@@ -936,8 +940,10 @@ static void check_process_timers(struct task_struct *tsk,
                         * At the hard limit, we just die.
                         * No need to calculate anything else now.
                         */
-                       pr_info("RT Watchdog Timeout (hard): %s[%d]\n",
-                               tsk->comm, task_pid_nr(tsk));
+                       if (print_fatal_signals) {
+                               pr_info("RT Watchdog Timeout (hard): %s[%d]\n",
+                                       tsk->comm, task_pid_nr(tsk));
+                       }
                        __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
                        return;
                }
@@ -945,8 +951,10 @@ static void check_process_timers(struct task_struct *tsk,
                        /*
                         * At the soft limit, send a SIGXCPU every second.
                         */
-                       pr_info("CPU Watchdog Timeout (soft): %s[%d]\n",
-                               tsk->comm, task_pid_nr(tsk));
+                       if (print_fatal_signals) {
+                               pr_info("CPU Watchdog Timeout (soft): %s[%d]\n",
+                                       tsk->comm, task_pid_nr(tsk));
+                       }
                        __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
                        if (soft < hard) {
                                soft++;
index 987e496bb51a9cc84c92bedc62cf8d69e8e85668..b398c2ea69b290cdaec1769b7d11cbc501646652 100644 (file)
@@ -37,9 +37,11 @@ static int tick_broadcast_forced;
 static __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(tick_broadcast_lock);
 
 #ifdef CONFIG_TICK_ONESHOT
+static void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
 static void tick_broadcast_clear_oneshot(int cpu);
 static void tick_resume_broadcast_oneshot(struct clock_event_device *bc);
 #else
+static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline void tick_broadcast_clear_oneshot(int cpu) { }
 static inline void tick_resume_broadcast_oneshot(struct clock_event_device *bc) { }
 #endif
@@ -867,7 +869,7 @@ static void tick_broadcast_init_next_event(struct cpumask *mask,
 /**
  * tick_broadcast_setup_oneshot - setup the broadcast device
  */
-void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
+static void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
        int cpu = smp_processor_id();
 
index f738251000fe6b07de4f3d54ee78d8f78408c5d7..be0ac01f2e1225b6d4bb814029854dfdba3cd5cb 100644 (file)
@@ -126,7 +126,6 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 
 /* Functions related to oneshot broadcasting */
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
-extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
 extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int cpu);
 extern int tick_broadcast_oneshot_active(void);
@@ -134,7 +133,6 @@ extern void tick_check_oneshot_broadcast_this_cpu(void);
 bool tick_broadcast_oneshot_available(void);
 extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
 #else /* !(BROADCAST && ONESHOT): */
-static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int cpu) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
index 9652bc57fd09811fa4e3ffbabc81b9139e75f125..b602c48cb84123890dbdc40b9a3da94439ba3a9d 100644 (file)
@@ -118,6 +118,26 @@ static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)
        tk->offs_boot = ktime_add(tk->offs_boot, delta);
 }
 
+/*
+ * tk_clock_read - atomic clocksource read() helper
+ *
+ * This helper is necessary to use in the read paths because, while the
+ * seqlock ensures we don't return a bad value while structures are updated,
+ * it doesn't protect from potential crashes. There is the possibility that
+ * the tkr's clocksource may change between the read reference, and the
+ * clock reference passed to the read function.  This can cause crashes if
+ * the wrong clocksource is passed to the wrong read function.
+ * This isn't necessary to use when holding the timekeeper_lock or doing
+ * a read of the fast-timekeeper tkrs (which is protected by its own locking
+ * and update logic).
+ */
+static inline u64 tk_clock_read(struct tk_read_base *tkr)
+{
+       struct clocksource *clock = READ_ONCE(tkr->clock);
+
+       return clock->read(clock);
+}
+
 #ifdef CONFIG_DEBUG_TIMEKEEPING
 #define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */
 
@@ -175,7 +195,7 @@ static inline u64 timekeeping_get_delta(struct tk_read_base *tkr)
         */
        do {
                seq = read_seqcount_begin(&tk_core.seq);
-               now = tkr->read(tkr->clock);
+               now = tk_clock_read(tkr);
                last = tkr->cycle_last;
                mask = tkr->mask;
                max = tkr->clock->max_cycles;
@@ -209,7 +229,7 @@ static inline u64 timekeeping_get_delta(struct tk_read_base *tkr)
        u64 cycle_now, delta;
 
        /* read clocksource */
-       cycle_now = tkr->read(tkr->clock);
+       cycle_now = tk_clock_read(tkr);
 
        /* calculate the delta since the last update_wall_time */
        delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask);
@@ -238,12 +258,10 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
        ++tk->cs_was_changed_seq;
        old_clock = tk->tkr_mono.clock;
        tk->tkr_mono.clock = clock;
-       tk->tkr_mono.read = clock->read;
        tk->tkr_mono.mask = clock->mask;
-       tk->tkr_mono.cycle_last = tk->tkr_mono.read(clock);
+       tk->tkr_mono.cycle_last = tk_clock_read(&tk->tkr_mono);
 
        tk->tkr_raw.clock = clock;
-       tk->tkr_raw.read = clock->read;
        tk->tkr_raw.mask = clock->mask;
        tk->tkr_raw.cycle_last = tk->tkr_mono.cycle_last;
 
@@ -262,7 +280,7 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
        /* Go back from cycles -> shifted ns */
        tk->xtime_interval = interval * clock->mult;
        tk->xtime_remainder = ntpinterval - tk->xtime_interval;
-       tk->raw_interval = (interval * clock->mult) >> clock->shift;
+       tk->raw_interval = interval * clock->mult;
 
         /* if changing clocks, convert xtime_nsec shift units */
        if (old_clock) {
@@ -404,7 +422,7 @@ static __always_inline u64 __ktime_get_fast_ns(struct tk_fast *tkf)
 
                now += timekeeping_delta_to_ns(tkr,
                                clocksource_delta(
-                                       tkr->read(tkr->clock),
+                                       tk_clock_read(tkr),
                                        tkr->cycle_last,
                                        tkr->mask));
        } while (read_seqcount_retry(&tkf->seq, seq));
@@ -461,6 +479,10 @@ static u64 dummy_clock_read(struct clocksource *cs)
        return cycles_at_suspend;
 }
 
+static struct clocksource dummy_clock = {
+       .read = dummy_clock_read,
+};
+
 /**
  * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource.
  * @tk: Timekeeper to snapshot.
@@ -477,13 +499,13 @@ static void halt_fast_timekeeper(struct timekeeper *tk)
        struct tk_read_base *tkr = &tk->tkr_mono;
 
        memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
-       cycles_at_suspend = tkr->read(tkr->clock);
-       tkr_dummy.read = dummy_clock_read;
+       cycles_at_suspend = tk_clock_read(tkr);
+       tkr_dummy.clock = &dummy_clock;
        update_fast_timekeeper(&tkr_dummy, &tk_fast_mono);
 
        tkr = &tk->tkr_raw;
        memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
-       tkr_dummy.read = dummy_clock_read;
+       tkr_dummy.clock = &dummy_clock;
        update_fast_timekeeper(&tkr_dummy, &tk_fast_raw);
 }
 
@@ -649,11 +671,10 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
  */
 static void timekeeping_forward_now(struct timekeeper *tk)
 {
-       struct clocksource *clock = tk->tkr_mono.clock;
        u64 cycle_now, delta;
        u64 nsec;
 
-       cycle_now = tk->tkr_mono.read(clock);
+       cycle_now = tk_clock_read(&tk->tkr_mono);
        delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
        tk->tkr_mono.cycle_last = cycle_now;
        tk->tkr_raw.cycle_last  = cycle_now;
@@ -929,8 +950,7 @@ void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
 
        do {
                seq = read_seqcount_begin(&tk_core.seq);
-
-               now = tk->tkr_mono.read(tk->tkr_mono.clock);
+               now = tk_clock_read(&tk->tkr_mono);
                systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq;
                systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq;
                base_real = ktime_add(tk->tkr_mono.base,
@@ -1108,7 +1128,7 @@ int get_device_system_crosststamp(int (*get_time_fn)
                 * Check whether the system counter value provided by the
                 * device driver is on the current timekeeping interval.
                 */
-               now = tk->tkr_mono.read(tk->tkr_mono.clock);
+               now = tk_clock_read(&tk->tkr_mono);
                interval_start = tk->tkr_mono.cycle_last;
                if (!cycle_between(interval_start, cycles, now)) {
                        clock_was_set_seq = tk->clock_was_set_seq;
@@ -1629,7 +1649,7 @@ void timekeeping_resume(void)
         * The less preferred source will only be tried if there is no better
         * usable source. The rtc part is handled separately in rtc core code.
         */
-       cycle_now = tk->tkr_mono.read(clock);
+       cycle_now = tk_clock_read(&tk->tkr_mono);
        if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
                cycle_now > tk->tkr_mono.cycle_last) {
                u64 nsec, cyc_delta;
@@ -1976,7 +1996,7 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset,
                                    u32 shift, unsigned int *clock_set)
 {
        u64 interval = tk->cycle_interval << shift;
-       u64 raw_nsecs;
+       u64 snsec_per_sec;
 
        /* If the offset is smaller than a shifted interval, do nothing */
        if (offset < interval)
@@ -1991,14 +2011,15 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset,
        *clock_set |= accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
-       raw_nsecs = (u64)tk->raw_interval << shift;
-       raw_nsecs += tk->raw_time.tv_nsec;
-       if (raw_nsecs >= NSEC_PER_SEC) {
-               u64 raw_secs = raw_nsecs;
-               raw_nsecs = do_div(raw_secs, NSEC_PER_SEC);
-               tk->raw_time.tv_sec += raw_secs;
+       tk->tkr_raw.xtime_nsec += (u64)tk->raw_time.tv_nsec << tk->tkr_raw.shift;
+       tk->tkr_raw.xtime_nsec += tk->raw_interval << shift;
+       snsec_per_sec = (u64)NSEC_PER_SEC << tk->tkr_raw.shift;
+       while (tk->tkr_raw.xtime_nsec >= snsec_per_sec) {
+               tk->tkr_raw.xtime_nsec -= snsec_per_sec;
+               tk->raw_time.tv_sec++;
        }
-       tk->raw_time.tv_nsec = raw_nsecs;
+       tk->raw_time.tv_nsec = tk->tkr_raw.xtime_nsec >> tk->tkr_raw.shift;
+       tk->tkr_raw.xtime_nsec -= (u64)tk->raw_time.tv_nsec << tk->tkr_raw.shift;
 
        /* Accumulate error between NTP and clock interval */
        tk->ntp_error += tk->ntp_tick << shift;
@@ -2030,7 +2051,7 @@ void update_wall_time(void)
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
        offset = real_tk->cycle_interval;
 #else
-       offset = clocksource_delta(tk->tkr_mono.read(tk->tkr_mono.clock),
+       offset = clocksource_delta(tk_clock_read(&tk->tkr_mono),
                                   tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
 #endif
 
index bd8ae8d5ae9ca865f3738c6b4df579a3a1ca12cc..193c5f5e3f7988e8d27eed5c4292e2345e3c5bf7 100644 (file)
@@ -1662,14 +1662,14 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
                goto out;
 
        if (attr == &dev_attr_act_mask) {
-               if (sscanf(buf, "%llx", &value) != 1) {
+               if (kstrtoull(buf, 0, &value)) {
                        /* Assume it is a list of trace category names */
                        ret = blk_trace_str2mask(buf);
                        if (ret < 0)
                                goto out;
                        value = ret;
                }
-       } else if (sscanf(buf, "%llu", &value) != 1)
+       } else if (kstrtoull(buf, 0, &value))
                goto out;
 
        ret = -ENXIO;
index 39dca4e86a94f0867c29aaa29b47d881eefd02e8..b308be30dfb9b93307305a9c47d2156f6d90600a 100644 (file)
@@ -4144,9 +4144,9 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
        int i, ret = -ENODEV;
        int size;
 
-       if (glob && (strcmp(glob, "*") == 0 || !strlen(glob)))
+       if (!glob || !strlen(glob) || !strcmp(glob, "*"))
                func_g.search = NULL;
-       else if (glob) {
+       else {
                int not;
 
                func_g.type = filter_parse_regex(glob, strlen(glob),
@@ -4256,6 +4256,14 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
        return ret;
 }
 
+void clear_ftrace_function_probes(struct trace_array *tr)
+{
+       struct ftrace_func_probe *probe, *n;
+
+       list_for_each_entry_safe(probe, n, &tr->func_probes, list)
+               unregister_ftrace_function_probe_func(NULL, tr, probe->probe_ops);
+}
+
 static LIST_HEAD(ftrace_commands);
 static DEFINE_MUTEX(ftrace_cmd_mutex);
 
@@ -4329,9 +4337,6 @@ static int ftrace_process_regex(struct ftrace_iterator *iter,
 
        command = strsep(&next, ":");
 
-       if (WARN_ON_ONCE(!tr))
-               return -EINVAL;
-
        mutex_lock(&ftrace_cmd_mutex);
        list_for_each_entry(p, &ftrace_commands, list) {
                if (strcmp(p->name, command) == 0) {
@@ -5055,7 +5060,7 @@ ftrace_graph_release(struct inode *inode, struct file *file)
        }
 
  out:
-       kfree(fgd->new_hash);
+       free_ftrace_hash(fgd->new_hash);
        kfree(fgd);
 
        return ret;
index c4536c4490217a2e6b59e423c70c0f1836a34a9d..091e801145c9996812fbaedafae1e912c123ecd7 100644 (file)
@@ -1558,7 +1558,7 @@ static __init int init_trace_selftests(void)
 
        return 0;
 }
-early_initcall(init_trace_selftests);
+core_initcall(init_trace_selftests);
 #else
 static inline int run_tracer_selftest(struct tracer *type)
 {
@@ -2568,7 +2568,36 @@ static inline void ftrace_trace_stack(struct trace_array *tr,
 void __trace_stack(struct trace_array *tr, unsigned long flags, int skip,
                   int pc)
 {
-       __ftrace_trace_stack(tr->trace_buffer.buffer, flags, skip, pc, NULL);
+       struct ring_buffer *buffer = tr->trace_buffer.buffer;
+
+       if (rcu_is_watching()) {
+               __ftrace_trace_stack(buffer, flags, skip, pc, NULL);
+               return;
+       }
+
+       /*
+        * When an NMI triggers, RCU is enabled via rcu_nmi_enter(),
+        * but if the above rcu_is_watching() failed, then the NMI
+        * triggered someplace critical, and rcu_irq_enter() should
+        * not be called from NMI.
+        */
+       if (unlikely(in_nmi()))
+               return;
+
+       /*
+        * It is possible that a function is being traced in a
+        * location that RCU is not watching. A call to
+        * rcu_irq_enter() will make sure that it is, but there's
+        * a few internal rcu functions that could be traced
+        * where that wont work either. In those cases, we just
+        * do nothing.
+        */
+       if (unlikely(rcu_irq_enter_disabled()))
+               return;
+
+       rcu_irq_enter_irqson();
+       __ftrace_trace_stack(buffer, flags, skip, pc, NULL);
+       rcu_irq_exit_irqson();
 }
 
 /**
@@ -6852,6 +6881,9 @@ ftrace_trace_snapshot_callback(struct trace_array *tr, struct ftrace_hash *hash,
        char *number;
        int ret;
 
+       if (!tr)
+               return -ENODEV;
+
        /* hash funcs only work with set_ftrace_filter */
        if (!enable)
                return -EINVAL;
@@ -7550,6 +7582,7 @@ static int instance_rmdir(const char *name)
        }
 
        tracing_set_nop(tr);
+       clear_ftrace_function_probes(tr);
        event_trace_del_tracer(tr);
        ftrace_clear_pids(tr);
        ftrace_destroy_function_files(tr);
index 291a1bca5748870011c70e639fe802785945a0a6..39fd77330aabb12a68d2104d9c20e81ea739f20e 100644 (file)
@@ -980,6 +980,7 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr,
 extern int
 unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
                                      struct ftrace_probe_ops *ops);
+extern void clear_ftrace_function_probes(struct trace_array *tr);
 
 int register_ftrace_command(struct ftrace_func_command *cmd);
 int unregister_ftrace_command(struct ftrace_func_command *cmd);
@@ -998,6 +999,10 @@ static inline __init int unregister_ftrace_command(char *cmd_name)
 {
        return -EINVAL;
 }
+static inline void clear_ftrace_function_probes(struct trace_array *tr)
+{
+}
+
 /*
  * The ops parameter passed in is usually undefined.
  * This must be a macro.
index a3bddbfd0874a26bcdbc84b3b4713cb206a0998b..a0910c0cdf2eabfa690d7cf434a5467faa5e01e4 100644 (file)
@@ -654,6 +654,9 @@ ftrace_trace_onoff_callback(struct trace_array *tr, struct ftrace_hash *hash,
 {
        struct ftrace_probe_ops *ops;
 
+       if (!tr)
+               return -ENODEV;
+
        /* we register both traceon and traceoff to this callback */
        if (strcmp(cmd, "traceon") == 0)
                ops = param ? &traceon_count_probe_ops : &traceon_probe_ops;
@@ -670,6 +673,9 @@ ftrace_stacktrace_callback(struct trace_array *tr, struct ftrace_hash *hash,
 {
        struct ftrace_probe_ops *ops;
 
+       if (!tr)
+               return -ENODEV;
+
        ops = param ? &stacktrace_count_probe_ops : &stacktrace_probe_ops;
 
        return ftrace_trace_probe_callback(tr, ops, hash, glob, cmd,
@@ -682,6 +688,9 @@ ftrace_dump_callback(struct trace_array *tr, struct ftrace_hash *hash,
 {
        struct ftrace_probe_ops *ops;
 
+       if (!tr)
+               return -ENODEV;
+
        ops = &dump_probe_ops;
 
        /* Only dump once. */
@@ -695,6 +704,9 @@ ftrace_cpudump_callback(struct trace_array *tr, struct ftrace_hash *hash,
 {
        struct ftrace_probe_ops *ops;
 
+       if (!tr)
+               return -ENODEV;
+
        ops = &cpudump_probe_ops;
 
        /* Only dump once. */
index 8485f6738a87cba32a070543b4ae7b8c434ad04c..b53c8d36916351156d8042b05b13bc5b8b717388 100644 (file)
@@ -707,20 +707,16 @@ static int create_trace_kprobe(int argc, char **argv)
                pr_info("Probe point is not specified.\n");
                return -EINVAL;
        }
-       if (isdigit(argv[1][0])) {
-               /* an address specified */
-               ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
-               if (ret) {
-                       pr_info("Failed to parse address.\n");
-                       return ret;
-               }
-       } else {
+
+       /* try to parse an address. if that fails, try to read the
+        * input as a symbol. */
+       if (kstrtoul(argv[1], 0, (unsigned long *)&addr)) {
                /* a symbol specified */
                symbol = argv[1];
                /* TODO: support .init module functions */
                ret = traceprobe_split_symbol_offset(symbol, &offset);
                if (ret) {
-                       pr_info("Failed to parse symbol.\n");
+                       pr_info("Failed to parse either an address or a symbol.\n");
                        return ret;
                }
                if (offset && is_return &&
@@ -1535,6 +1531,11 @@ static __init int kprobe_trace_self_tests_init(void)
 
 end:
        release_all_trace_kprobes();
+       /*
+        * Wait for the optimizer work to finish. Otherwise it might fiddle
+        * with probes in already freed __init text.
+        */
+       wait_for_kprobe_optimizer();
        if (warn)
                pr_cont("NG: Some tests are failed. Please check them.\n");
        else
index 76aa04d4c9257482181c9b2885530fb4dc417edd..b4a751e8f9d69763c1d1fbd10083819b50db3ab4 100644 (file)
@@ -409,7 +409,9 @@ static const struct file_operations stack_trace_fops = {
 static int
 stack_trace_filter_open(struct inode *inode, struct file *file)
 {
-       return ftrace_regex_open(&trace_ops, FTRACE_ITER_FILTER,
+       struct ftrace_ops *ops = inode->i_private;
+
+       return ftrace_regex_open(ops, FTRACE_ITER_FILTER,
                                 inode, file);
 }
 
@@ -476,7 +478,7 @@ static __init int stack_trace_init(void)
                        NULL, &stack_trace_fops);
 
        trace_create_file("stack_trace_filter", 0444, d_tracer,
-                       NULL, &stack_trace_filter_fops);
+                         &trace_ops, &stack_trace_filter_fops);
 
        if (stack_trace_filter_buf[0])
                ftrace_set_early_filter(&trace_ops, stack_trace_filter_buf, 1);
index 3c6432df7e63466a24d41dead807c7ef14c0ab86..4c0888c4a68d9621717f9012d3ca4cc0b72df20b 100644 (file)
  *     the values[M, M+1, ..., N] into the ints array in get_options.
  */
 
-static int get_range(char **str, int *pint)
+static int get_range(char **str, int *pint, int n)
 {
        int x, inc_counter, upper_range;
 
        (*str)++;
        upper_range = simple_strtol((*str), NULL, 0);
        inc_counter = upper_range - *pint;
-       for (x = *pint; x < upper_range; x++)
+       for (x = *pint; n && x < upper_range; x++, n--)
                *pint++ = x;
        return inc_counter;
 }
@@ -97,7 +97,7 @@ char *get_options(const char *str, int nints, int *ints)
                        break;
                if (res == 3) {
                        int range_nums;
-                       range_nums = get_range((char **)&str, ints + i);
+                       range_nums = get_range((char **)&str, ints + i, nints - i);
                        if (range_nums < 0)
                                break;
                        /*
index 74a54b7f25626e8c6d224af2b7384f7dcbf2e72f..9f79547d1b9782237a563f6a2e838655f6adf6dc 100644 (file)
@@ -43,7 +43,7 @@ static struct crypto_shash *tfm;
 u32 crc32c(u32 crc, const void *address, unsigned int length)
 {
        SHASH_DESC_ON_STACK(shash, tfm);
-       u32 *ctx = (u32 *)shash_desc_ctx(shash);
+       u32 ret, *ctx = (u32 *)shash_desc_ctx(shash);
        int err;
 
        shash->tfm = tfm;
@@ -53,7 +53,9 @@ u32 crc32c(u32 crc, const void *address, unsigned int length)
        err = crypto_shash_update(shash, address, length);
        BUG_ON(err);
 
-       return *ctx;
+       ret = *ctx;
+       barrier_data(ctx);
+       return ret;
 }
 
 EXPORT_SYMBOL(crc32c);
index 889bc31785bee57901ae969f16a55390db8265c4..be88cbaadde3aeed809b2997e2ef683fba62dba4 100644 (file)
@@ -4504,6 +4504,44 @@ static struct bpf_test tests[] = {
                { },
                { { 0, 1 } },
        },
+       {
+               "JMP_JSGE_K: Signed jump: value walk 1",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_LD_IMM64(R1, -3),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 6),
+                       BPF_ALU64_IMM(BPF_ADD, R1, 1),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 4),
+                       BPF_ALU64_IMM(BPF_ADD, R1, 1),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 2),
+                       BPF_ALU64_IMM(BPF_ADD, R1, 1),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 1),
+                       BPF_EXIT_INSN(),                /* bad exit */
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),  /* good exit */
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
+       {
+               "JMP_JSGE_K: Signed jump: value walk 2",
+               .u.insns_int = {
+                       BPF_ALU32_IMM(BPF_MOV, R0, 0),
+                       BPF_LD_IMM64(R1, -3),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 4),
+                       BPF_ALU64_IMM(BPF_ADD, R1, 2),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 2),
+                       BPF_ALU64_IMM(BPF_ADD, R1, 2),
+                       BPF_JMP_IMM(BPF_JSGE, R1, 0, 1),
+                       BPF_EXIT_INSN(),                /* bad exit */
+                       BPF_ALU32_IMM(BPF_MOV, R0, 1),  /* good exit */
+                       BPF_EXIT_INSN(),
+               },
+               INTERNAL,
+               { },
+               { { 0, 1 } },
+       },
        /* BPF_JMP | BPF_JGT | BPF_K */
        {
                "JMP_JGT_K: if (3 > 2) return 1",
index d9e6fddcc51f06a1286c56a24c510c1a3efa8add..576c4df588823ab948c4a5d0dd12b6d54b94b430 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -387,11 +387,6 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
        /* mlock all present pages, but do not fault in new pages */
        if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
                return -ENOENT;
-       /* For mm_populate(), just skip the stack guard page. */
-       if ((*flags & FOLL_POPULATE) &&
-                       (stack_guard_page_start(vma, address) ||
-                        stack_guard_page_end(vma, address + PAGE_SIZE)))
-               return -ENOENT;
        if (*flags & FOLL_WRITE)
                fault_flags |= FAULT_FLAG_WRITE;
        if (*flags & FOLL_REMOTE)
@@ -407,12 +402,10 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
 
        ret = handle_mm_fault(vma, address, fault_flags);
        if (ret & VM_FAULT_ERROR) {
-               if (ret & VM_FAULT_OOM)
-                       return -ENOMEM;
-               if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
-                       return *flags & FOLL_HWPOISON ? -EHWPOISON : -EFAULT;
-               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
-                       return -EFAULT;
+               int err = vm_fault_to_errno(ret, *flags);
+
+               if (err)
+                       return err;
                BUG();
        }
 
@@ -723,12 +716,10 @@ retry:
        ret = handle_mm_fault(vma, address, fault_flags);
        major |= ret & VM_FAULT_MAJOR;
        if (ret & VM_FAULT_ERROR) {
-               if (ret & VM_FAULT_OOM)
-                       return -ENOMEM;
-               if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE))
-                       return -EHWPOISON;
-               if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV))
-                       return -EFAULT;
+               int err = vm_fault_to_errno(ret, 0);
+
+               if (err)
+                       return err;
                BUG();
        }
 
index a84909cf20d36b3d84f00d8529127f78f6b5981d..88c6167f194db0ec07d707329569c2d4a9d34876 100644 (file)
@@ -1426,8 +1426,11 @@ int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
         */
        if (unlikely(pmd_trans_migrating(*vmf->pmd))) {
                page = pmd_page(*vmf->pmd);
+               if (!get_page_unless_zero(page))
+                       goto out_unlock;
                spin_unlock(vmf->ptl);
                wait_on_page_locked(page);
+               put_page(page);
                goto out;
        }
 
@@ -1459,9 +1462,12 @@ int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
 
        /* Migration could have started since the pmd_trans_migrating check */
        if (!page_locked) {
+               page_nid = -1;
+               if (!get_page_unless_zero(page))
+                       goto out_unlock;
                spin_unlock(vmf->ptl);
                wait_on_page_locked(page);
-               page_nid = -1;
+               put_page(page);
                goto out;
        }
 
index e5828875f7bbd7a770d5c23334a0e3994ffe544f..3eedb187e5496f36f7f3186267f475254bcda5ab 100644 (file)
@@ -4170,6 +4170,11 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        }
                        ret = hugetlb_fault(mm, vma, vaddr, fault_flags);
                        if (ret & VM_FAULT_ERROR) {
+                               int err = vm_fault_to_errno(ret, flags);
+
+                               if (err)
+                                       return err;
+
                                remainder = 0;
                                break;
                        }
index 945fd1ca49b5af0bc3b87dbfe8098f0f602775a2..df4ebdb2b10a373723330dc0124957cd2cb1c021 100644 (file)
@@ -652,7 +652,6 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
                        spin_unlock(ptl);
                        free_page_and_swap_cache(src_page);
                }
-               cond_resched();
        }
 }
 
index d9fc0e4561283d9a351f6dd7c4cfb74ad26ab566..216184af0e192b5405efc5a594129fa7c53ae953 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1028,8 +1028,7 @@ static int try_to_merge_one_page(struct vm_area_struct *vma,
                goto out;
 
        if (PageTransCompound(page)) {
-               err = split_huge_page(page);
-               if (err)
+               if (split_huge_page(page))
                        goto out_unlock;
        }
 
index b049c9b2dba8718a6f57777591c2f2753d8d40ad..7b8a5db76a2fec7331f09048f3c19ebdfddf9f16 100644 (file)
@@ -1739,6 +1739,29 @@ static void __init_memblock memblock_dump(struct memblock_type *type)
        }
 }
 
+extern unsigned long __init_memblock
+memblock_reserved_memory_within(phys_addr_t start_addr, phys_addr_t end_addr)
+{
+       struct memblock_region *rgn;
+       unsigned long size = 0;
+       int idx;
+
+       for_each_memblock_type((&memblock.reserved), rgn) {
+               phys_addr_t start, end;
+
+               if (rgn->base + rgn->size < start_addr)
+                       continue;
+               if (rgn->base > end_addr)
+                       continue;
+
+               start = rgn->base;
+               end = start + rgn->size;
+               size += end - start;
+       }
+
+       return size;
+}
+
 void __init_memblock __memblock_dump_all(void)
 {
        pr_info("MEMBLOCK configuration:\n");
index 2527dfeddb003d245ac2e2bd964134030426f777..ecc183fd94f36f35e91b69c6a06930bb456a7e86 100644 (file)
@@ -1184,7 +1184,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
         * page_remove_rmap() in try_to_unmap_one(). So to determine page status
         * correctly, we save a copy of the page flags at this time.
         */
-       page_flags = p->flags;
+       if (PageHuge(p))
+               page_flags = hpage->flags;
+       else
+               page_flags = p->flags;
 
        /*
         * unpoison always clear PG_hwpoison inside page lock
@@ -1595,12 +1598,8 @@ static int soft_offline_huge_page(struct page *page, int flags)
        if (ret) {
                pr_info("soft offline: %#lx: migration failed %d, type %lx (%pGp)\n",
                        pfn, ret, page->flags, &page->flags);
-               /*
-                * We know that soft_offline_huge_page() tries to migrate
-                * only one hugepage pointed to by hpage, so we need not
-                * run through the pagelist here.
-                */
-               putback_active_hugepage(hpage);
+               if (!list_empty(&pagelist))
+                       putback_movable_pages(&pagelist);
                if (ret > 0)
                        ret = -EIO;
        } else {
index 6ff5d729ded0ecd3a5607d10248697a786091f7e..bb11c474857e5ff2a3756724ca30139ff41ebbab 100644 (file)
@@ -2854,40 +2854,6 @@ out_release:
        return ret;
 }
 
-/*
- * This is like a special single-page "expand_{down|up}wards()",
- * except we must first make sure that 'address{-|+}PAGE_SIZE'
- * doesn't hit another vma.
- */
-static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
-{
-       address &= PAGE_MASK;
-       if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
-               struct vm_area_struct *prev = vma->vm_prev;
-
-               /*
-                * Is there a mapping abutting this one below?
-                *
-                * That's only ok if it's the same stack mapping
-                * that has gotten split..
-                */
-               if (prev && prev->vm_end == address)
-                       return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
-
-               return expand_downwards(vma, address - PAGE_SIZE);
-       }
-       if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
-               struct vm_area_struct *next = vma->vm_next;
-
-               /* As VM_GROWSDOWN but s/below/above/ */
-               if (next && next->vm_start == address + PAGE_SIZE)
-                       return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
-
-               return expand_upwards(vma, address + PAGE_SIZE);
-       }
-       return 0;
-}
-
 /*
  * We enter with non-exclusive mmap_sem (to exclude vma changes,
  * but allow concurrent faults), and pte mapped but not yet locked.
@@ -2904,10 +2870,6 @@ static int do_anonymous_page(struct vm_fault *vmf)
        if (vma->vm_flags & VM_SHARED)
                return VM_FAULT_SIGBUS;
 
-       /* Check if we need to add a guard page to the stack */
-       if (check_stack_guard_page(vma, vmf->address) < 0)
-               return VM_FAULT_SIGSEGV;
-
        /*
         * Use pte_alloc() instead of pte_alloc_map().  We can't run
         * pte_offset_map() on pmds where a huge pmd might be created
@@ -3029,6 +2991,17 @@ static int __do_fault(struct vm_fault *vmf)
        return ret;
 }
 
+/*
+ * The ordering of these checks is important for pmds with _PAGE_DEVMAP set.
+ * If we check pmd_trans_unstable() first we will trip the bad_pmd() check
+ * inside of pmd_none_or_trans_huge_or_clear_bad(). This will end up correctly
+ * returning 1 but not before it spams dmesg with the pmd_clear_bad() output.
+ */
+static int pmd_devmap_trans_unstable(pmd_t *pmd)
+{
+       return pmd_devmap(*pmd) || pmd_trans_unstable(pmd);
+}
+
 static int pte_alloc_one_map(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
@@ -3052,18 +3025,27 @@ static int pte_alloc_one_map(struct vm_fault *vmf)
 map_pte:
        /*
         * If a huge pmd materialized under us just retry later.  Use
-        * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd
-        * didn't become pmd_trans_huge under us and then back to pmd_none, as
-        * a result of MADV_DONTNEED running immediately after a huge pmd fault
-        * in a different thread of this mm, in turn leading to a misleading
-        * pmd_trans_huge() retval.  All we have to ensure is that it is a
-        * regular pmd that we can walk with pte_offset_map() and we can do that
-        * through an atomic read in C, which is what pmd_trans_unstable()
-        * provides.
+        * pmd_trans_unstable() via pmd_devmap_trans_unstable() instead of
+        * pmd_trans_huge() to ensure the pmd didn't become pmd_trans_huge
+        * under us and then back to pmd_none, as a result of MADV_DONTNEED
+        * running immediately after a huge pmd fault in a different thread of
+        * this mm, in turn leading to a misleading pmd_trans_huge() retval.
+        * All we have to ensure is that it is a regular pmd that we can walk
+        * with pte_offset_map() and we can do that through an atomic read in
+        * C, which is what pmd_trans_unstable() provides.
         */
-       if (pmd_trans_unstable(vmf->pmd) || pmd_devmap(*vmf->pmd))
+       if (pmd_devmap_trans_unstable(vmf->pmd))
                return VM_FAULT_NOPAGE;
 
+       /*
+        * At this point we know that our vmf->pmd points to a page of ptes
+        * and it cannot become pmd_none(), pmd_devmap() or pmd_trans_huge()
+        * for the duration of the fault.  If a racing MADV_DONTNEED runs and
+        * we zap the ptes pointed to by our vmf->pmd, the vmf->ptl will still
+        * be valid and we will re-check to make sure the vmf->pte isn't
+        * pte_none() under vmf->ptl protection when we return to
+        * alloc_set_pte().
+        */
        vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address,
                        &vmf->ptl);
        return 0;
@@ -3690,7 +3672,7 @@ static int handle_pte_fault(struct vm_fault *vmf)
                vmf->pte = NULL;
        } else {
                /* See comment in pte_alloc_one_map() */
-               if (pmd_trans_unstable(vmf->pmd) || pmd_devmap(*vmf->pmd))
+               if (pmd_devmap_trans_unstable(vmf->pmd))
                        return 0;
                /*
                 * A regular pmd is established and it can't morph into a huge
index c483c5c20b4bd12bcca50972c9f74a0dbd3a713e..b562b5523a6544e6c0ae6e4f792943441f6217a3 100644 (file)
@@ -284,7 +284,7 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
 {
        int i;
        int nr = pagevec_count(pvec);
-       int delta_munlocked;
+       int delta_munlocked = -nr;
        struct pagevec pvec_putback;
        int pgrescued = 0;
 
@@ -304,6 +304,8 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
                                continue;
                        else
                                __munlock_isolation_failed(page);
+               } else {
+                       delta_munlocked++;
                }
 
                /*
@@ -315,7 +317,6 @@ static void __munlock_pagevec(struct pagevec *pvec, struct zone *zone)
                pagevec_add(&pvec_putback, pvec->pages[i]);
                pvec->pages[i] = NULL;
        }
-       delta_munlocked = -nr + pagevec_count(&pvec_putback);
        __mod_zone_page_state(zone, NR_MLOCK, delta_munlocked);
        spin_unlock_irq(zone_lru_lock(zone));
 
index f82741e199c0b06d971bd30d4503bc3e6e6f9dc5..a5e3dcd75e79f40557cefc1bd5338d34eb4fa2f2 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -183,6 +183,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
        unsigned long retval;
        unsigned long newbrk, oldbrk;
        struct mm_struct *mm = current->mm;
+       struct vm_area_struct *next;
        unsigned long min_brk;
        bool populate;
        LIST_HEAD(uf);
@@ -229,7 +230,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
        }
 
        /* Check against existing mmap mappings. */
-       if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
+       next = find_vma(mm, oldbrk);
+       if (next && newbrk + PAGE_SIZE > vm_start_gap(next))
                goto out;
 
        /* Ok, looks good - let it rip. */
@@ -253,10 +255,22 @@ out:
 
 static long vma_compute_subtree_gap(struct vm_area_struct *vma)
 {
-       unsigned long max, subtree_gap;
-       max = vma->vm_start;
-       if (vma->vm_prev)
-               max -= vma->vm_prev->vm_end;
+       unsigned long max, prev_end, subtree_gap;
+
+       /*
+        * Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we
+        * allow two stack_guard_gaps between them here, and when choosing
+        * an unmapped area; whereas when expanding we only require one.
+        * That's a little inconsistent, but keeps the code here simpler.
+        */
+       max = vm_start_gap(vma);
+       if (vma->vm_prev) {
+               prev_end = vm_end_gap(vma->vm_prev);
+               if (max > prev_end)
+                       max -= prev_end;
+               else
+                       max = 0;
+       }
        if (vma->vm_rb.rb_left) {
                subtree_gap = rb_entry(vma->vm_rb.rb_left,
                                struct vm_area_struct, vm_rb)->rb_subtree_gap;
@@ -352,7 +366,7 @@ static void validate_mm(struct mm_struct *mm)
                        anon_vma_unlock_read(anon_vma);
                }
 
-               highest_address = vma->vm_end;
+               highest_address = vm_end_gap(vma);
                vma = vma->vm_next;
                i++;
        }
@@ -541,7 +555,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
        if (vma->vm_next)
                vma_gap_update(vma->vm_next);
        else
-               mm->highest_vm_end = vma->vm_end;
+               mm->highest_vm_end = vm_end_gap(vma);
 
        /*
         * vma->vm_prev wasn't known when we followed the rbtree to find the
@@ -856,7 +870,7 @@ again:
                        vma_gap_update(vma);
                if (end_changed) {
                        if (!next)
-                               mm->highest_vm_end = end;
+                               mm->highest_vm_end = vm_end_gap(vma);
                        else if (!adjust_next)
                                vma_gap_update(next);
                }
@@ -941,7 +955,7 @@ again:
                         * mm->highest_vm_end doesn't need any update
                         * in remove_next == 1 case.
                         */
-                       VM_WARN_ON(mm->highest_vm_end != end);
+                       VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma));
                }
        }
        if (insert && file)
@@ -1787,7 +1801,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
 
        while (true) {
                /* Visit left subtree if it looks promising */
-               gap_end = vma->vm_start;
+               gap_end = vm_start_gap(vma);
                if (gap_end >= low_limit && vma->vm_rb.rb_left) {
                        struct vm_area_struct *left =
                                rb_entry(vma->vm_rb.rb_left,
@@ -1798,12 +1812,13 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
                        }
                }
 
-               gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
+               gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
 check_current:
                /* Check if current node has a suitable gap */
                if (gap_start > high_limit)
                        return -ENOMEM;
-               if (gap_end >= low_limit && gap_end - gap_start >= length)
+               if (gap_end >= low_limit &&
+                   gap_end > gap_start && gap_end - gap_start >= length)
                        goto found;
 
                /* Visit right subtree if it looks promising */
@@ -1825,8 +1840,8 @@ check_current:
                        vma = rb_entry(rb_parent(prev),
                                       struct vm_area_struct, vm_rb);
                        if (prev == vma->vm_rb.rb_left) {
-                               gap_start = vma->vm_prev->vm_end;
-                               gap_end = vma->vm_start;
+                               gap_start = vm_end_gap(vma->vm_prev);
+                               gap_end = vm_start_gap(vma);
                                goto check_current;
                        }
                }
@@ -1890,7 +1905,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
 
        while (true) {
                /* Visit right subtree if it looks promising */
-               gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
+               gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
                if (gap_start <= high_limit && vma->vm_rb.rb_right) {
                        struct vm_area_struct *right =
                                rb_entry(vma->vm_rb.rb_right,
@@ -1903,10 +1918,11 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
 
 check_current:
                /* Check if current node has a suitable gap */
-               gap_end = vma->vm_start;
+               gap_end = vm_start_gap(vma);
                if (gap_end < low_limit)
                        return -ENOMEM;
-               if (gap_start <= high_limit && gap_end - gap_start >= length)
+               if (gap_start <= high_limit &&
+                   gap_end > gap_start && gap_end - gap_start >= length)
                        goto found;
 
                /* Visit left subtree if it looks promising */
@@ -1929,7 +1945,7 @@ check_current:
                                       struct vm_area_struct, vm_rb);
                        if (prev == vma->vm_rb.rb_right) {
                                gap_start = vma->vm_prev ?
-                                       vma->vm_prev->vm_end : 0;
+                                       vm_end_gap(vma->vm_prev) : 0;
                                goto check_current;
                        }
                }
@@ -1967,7 +1983,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                unsigned long len, unsigned long pgoff, unsigned long flags)
 {
        struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
+       struct vm_area_struct *vma, *prev;
        struct vm_unmapped_area_info info;
 
        if (len > TASK_SIZE - mmap_min_addr)
@@ -1978,9 +1994,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 
        if (addr) {
                addr = PAGE_ALIGN(addr);
-               vma = find_vma(mm, addr);
+               vma = find_vma_prev(mm, addr, &prev);
                if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-                   (!vma || addr + len <= vma->vm_start))
+                   (!vma || addr + len <= vm_start_gap(vma)) &&
+                   (!prev || addr >= vm_end_gap(prev)))
                        return addr;
        }
 
@@ -2003,7 +2020,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
                          const unsigned long len, const unsigned long pgoff,
                          const unsigned long flags)
 {
-       struct vm_area_struct *vma;
+       struct vm_area_struct *vma, *prev;
        struct mm_struct *mm = current->mm;
        unsigned long addr = addr0;
        struct vm_unmapped_area_info info;
@@ -2018,9 +2035,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        /* requesting a specific address */
        if (addr) {
                addr = PAGE_ALIGN(addr);
-               vma = find_vma(mm, addr);
+               vma = find_vma_prev(mm, addr, &prev);
                if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
-                               (!vma || addr + len <= vma->vm_start))
+                               (!vma || addr + len <= vm_start_gap(vma)) &&
+                               (!prev || addr >= vm_end_gap(prev)))
                        return addr;
        }
 
@@ -2155,21 +2173,19 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr,
  * update accounting. This is shared with both the
  * grow-up and grow-down cases.
  */
-static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow)
+static int acct_stack_growth(struct vm_area_struct *vma,
+                            unsigned long size, unsigned long grow)
 {
        struct mm_struct *mm = vma->vm_mm;
        struct rlimit *rlim = current->signal->rlim;
-       unsigned long new_start, actual_size;
+       unsigned long new_start;
 
        /* address space limit tests */
        if (!may_expand_vm(mm, vma->vm_flags, grow))
                return -ENOMEM;
 
        /* Stack limit test */
-       actual_size = size;
-       if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
-               actual_size -= PAGE_SIZE;
-       if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
+       if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
                return -ENOMEM;
 
        /* mlock limit tests */
@@ -2207,16 +2223,32 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
 int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 {
        struct mm_struct *mm = vma->vm_mm;
+       struct vm_area_struct *next;
+       unsigned long gap_addr;
        int error = 0;
 
        if (!(vma->vm_flags & VM_GROWSUP))
                return -EFAULT;
 
-       /* Guard against wrapping around to address 0. */
-       if (address < PAGE_ALIGN(address+4))
-               address = PAGE_ALIGN(address+4);
-       else
+       /* Guard against exceeding limits of the address space. */
+       address &= PAGE_MASK;
+       if (address >= TASK_SIZE)
                return -ENOMEM;
+       address += PAGE_SIZE;
+
+       /* Enforce stack_guard_gap */
+       gap_addr = address + stack_guard_gap;
+
+       /* Guard against overflow */
+       if (gap_addr < address || gap_addr > TASK_SIZE)
+               gap_addr = TASK_SIZE;
+
+       next = vma->vm_next;
+       if (next && next->vm_start < gap_addr) {
+               if (!(next->vm_flags & VM_GROWSUP))
+                       return -ENOMEM;
+               /* Check that both stack segments have the same anon_vma? */
+       }
 
        /* We must make sure the anon_vma is allocated. */
        if (unlikely(anon_vma_prepare(vma)))
@@ -2261,7 +2293,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
                                if (vma->vm_next)
                                        vma_gap_update(vma->vm_next);
                                else
-                                       mm->highest_vm_end = address;
+                                       mm->highest_vm_end = vm_end_gap(vma);
                                spin_unlock(&mm->page_table_lock);
 
                                perf_event_mmap(vma);
@@ -2282,6 +2314,8 @@ int expand_downwards(struct vm_area_struct *vma,
                                   unsigned long address)
 {
        struct mm_struct *mm = vma->vm_mm;
+       struct vm_area_struct *prev;
+       unsigned long gap_addr;
        int error;
 
        address &= PAGE_MASK;
@@ -2289,6 +2323,17 @@ int expand_downwards(struct vm_area_struct *vma,
        if (error)
                return error;
 
+       /* Enforce stack_guard_gap */
+       gap_addr = address - stack_guard_gap;
+       if (gap_addr > address)
+               return -ENOMEM;
+       prev = vma->vm_prev;
+       if (prev && prev->vm_end > gap_addr) {
+               if (!(prev->vm_flags & VM_GROWSDOWN))
+                       return -ENOMEM;
+               /* Check that both stack segments have the same anon_vma? */
+       }
+
        /* We must make sure the anon_vma is allocated. */
        if (unlikely(anon_vma_prepare(vma)))
                return -ENOMEM;
@@ -2343,28 +2388,25 @@ int expand_downwards(struct vm_area_struct *vma,
        return error;
 }
 
-/*
- * Note how expand_stack() refuses to expand the stack all the way to
- * abut the next virtual mapping, *unless* that mapping itself is also
- * a stack mapping. We want to leave room for a guard page, after all
- * (the guard page itself is not added here, that is done by the
- * actual page faulting logic)
- *
- * This matches the behavior of the guard page logic (see mm/memory.c:
- * check_stack_guard_page()), which only allows the guard page to be
- * removed under these circumstances.
- */
+/* enforced gap between the expanding stack and other mappings. */
+unsigned long stack_guard_gap = 256UL<<PAGE_SHIFT;
+
+static int __init cmdline_parse_stack_guard_gap(char *p)
+{
+       unsigned long val;
+       char *endptr;
+
+       val = simple_strtoul(p, &endptr, 10);
+       if (!*endptr)
+               stack_guard_gap = val << PAGE_SHIFT;
+
+       return 0;
+}
+__setup("stack_guard_gap=", cmdline_parse_stack_guard_gap);
+
 #ifdef CONFIG_STACK_GROWSUP
 int expand_stack(struct vm_area_struct *vma, unsigned long address)
 {
-       struct vm_area_struct *next;
-
-       address &= PAGE_MASK;
-       next = vma->vm_next;
-       if (next && next->vm_start == address + PAGE_SIZE) {
-               if (!(next->vm_flags & VM_GROWSUP))
-                       return -ENOMEM;
-       }
        return expand_upwards(vma, address);
 }
 
@@ -2386,14 +2428,6 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
 #else
 int expand_stack(struct vm_area_struct *vma, unsigned long address)
 {
-       struct vm_area_struct *prev;
-
-       address &= PAGE_MASK;
-       prev = vma->vm_prev;
-       if (prev && prev->vm_end == address) {
-               if (!(prev->vm_flags & VM_GROWSDOWN))
-                       return -ENOMEM;
-       }
        return expand_downwards(vma, address);
 }
 
@@ -2491,7 +2525,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
                vma->vm_prev = prev;
                vma_gap_update(vma);
        } else
-               mm->highest_vm_end = prev ? prev->vm_end : 0;
+               mm->highest_vm_end = prev ? vm_end_gap(prev) : 0;
        tail_vma->vm_next = NULL;
 
        /* Kill the cache */
index f9e450c6b6e414d61b00d5a61be9cdea3b773e1b..2302f250d6b1ba150e3c2e4e17cfb6c99574ab5b 100644 (file)
@@ -292,6 +292,26 @@ int page_group_by_mobility_disabled __read_mostly;
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
 static inline void reset_deferred_meminit(pg_data_t *pgdat)
 {
+       unsigned long max_initialise;
+       unsigned long reserved_lowmem;
+
+       /*
+        * Initialise at least 2G of a node but also take into account that
+        * two large system hashes that can take up 1GB for 0.25TB/node.
+        */
+       max_initialise = max(2UL << (30 - PAGE_SHIFT),
+               (pgdat->node_spanned_pages >> 8));
+
+       /*
+        * Compensate the all the memblock reservations (e.g. crash kernel)
+        * from the initial estimation to make sure we will initialize enough
+        * memory to boot.
+        */
+       reserved_lowmem = memblock_reserved_memory_within(pgdat->node_start_pfn,
+                       pgdat->node_start_pfn + max_initialise);
+       max_initialise += reserved_lowmem;
+
+       pgdat->static_init_size = min(max_initialise, pgdat->node_spanned_pages);
        pgdat->first_deferred_pfn = ULONG_MAX;
 }
 
@@ -314,20 +334,11 @@ static inline bool update_defer_init(pg_data_t *pgdat,
                                unsigned long pfn, unsigned long zone_end,
                                unsigned long *nr_initialised)
 {
-       unsigned long max_initialise;
-
        /* Always populate low zones for address-contrained allocations */
        if (zone_end < pgdat_end_pfn(pgdat))
                return true;
-       /*
-        * Initialise at least 2G of a node but also take into account that
-        * two large system hashes that can take up 1GB for 0.25TB/node.
-        */
-       max_initialise = max(2UL << (30 - PAGE_SHIFT),
-               (pgdat->node_spanned_pages >> 8));
-
        (*nr_initialised)++;
-       if ((*nr_initialised > max_initialise) &&
+       if ((*nr_initialised > pgdat->static_init_size) &&
            (pfn & (PAGES_PER_SECTION - 1)) == 0) {
                pgdat->first_deferred_pfn = pfn;
                return false;
@@ -3870,7 +3881,9 @@ retry:
                goto got_pg;
 
        /* Avoid allocations with no watermarks from looping endlessly */
-       if (test_thread_flag(TIF_MEMDIE))
+       if (test_thread_flag(TIF_MEMDIE) &&
+           (alloc_flags == ALLOC_NO_WATERMARKS ||
+            (gfp_mask & __GFP_NOMEMALLOC)))
                goto nopage;
 
        /* Retry as long as the OOM killer is making progress */
@@ -6136,7 +6149,6 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
        /* pg_data_t should be reset to zero when it's allocated */
        WARN_ON(pgdat->nr_zones || pgdat->kswapd_classzone_idx);
 
-       reset_deferred_meminit(pgdat);
        pgdat->node_id = nid;
        pgdat->node_start_pfn = node_start_pfn;
        pgdat->per_cpu_nodestats = NULL;
@@ -6158,6 +6170,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
                (unsigned long)pgdat->node_mem_map);
 #endif
 
+       reset_deferred_meminit(pgdat);
        free_area_init_core(pgdat);
 }
 
index 57e5156f02be6bcc23e70ec801e9cc1c3bbdd631..8addc535bcdc58794fe40e72a729e4589d44d2b6 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5512,6 +5512,7 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
                char mbuf[64];
                char *buf;
                struct slab_attribute *attr = to_slab_attr(slab_attrs[i]);
+               ssize_t len;
 
                if (!attr || !attr->store || !attr->show)
                        continue;
@@ -5536,8 +5537,9 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s)
                        buf = buffer;
                }
 
-               attr->show(root_cache, buf);
-               attr->store(s, buf, strlen(buf));
+               len = attr->show(root_cache, buf);
+               if (len > 0)
+                       attr->store(s, buf, len);
        }
 
        if (buffer)
@@ -5623,6 +5625,28 @@ static char *create_unique_id(struct kmem_cache *s)
        return name;
 }
 
+static void sysfs_slab_remove_workfn(struct work_struct *work)
+{
+       struct kmem_cache *s =
+               container_of(work, struct kmem_cache, kobj_remove_work);
+
+       if (!s->kobj.state_in_sysfs)
+               /*
+                * For a memcg cache, this may be called during
+                * deactivation and again on shutdown.  Remove only once.
+                * A cache is never shut down before deactivation is
+                * complete, so no need to worry about synchronization.
+                */
+               return;
+
+#ifdef CONFIG_MEMCG
+       kset_unregister(s->memcg_kset);
+#endif
+       kobject_uevent(&s->kobj, KOBJ_REMOVE);
+       kobject_del(&s->kobj);
+       kobject_put(&s->kobj);
+}
+
 static int sysfs_slab_add(struct kmem_cache *s)
 {
        int err;
@@ -5630,6 +5654,8 @@ static int sysfs_slab_add(struct kmem_cache *s)
        struct kset *kset = cache_kset(s);
        int unmergeable = slab_unmergeable(s);
 
+       INIT_WORK(&s->kobj_remove_work, sysfs_slab_remove_workfn);
+
        if (!kset) {
                kobject_init(&s->kobj, &slab_ktype);
                return 0;
@@ -5693,20 +5719,8 @@ static void sysfs_slab_remove(struct kmem_cache *s)
                 */
                return;
 
-       if (!s->kobj.state_in_sysfs)
-               /*
-                * For a memcg cache, this may be called during
-                * deactivation and again on shutdown.  Remove only once.
-                * A cache is never shut down before deactivation is
-                * complete, so no need to worry about synchronization.
-                */
-               return;
-
-#ifdef CONFIG_MEMCG
-       kset_unregister(s->memcg_kset);
-#endif
-       kobject_uevent(&s->kobj, KOBJ_REMOVE);
-       kobject_del(&s->kobj);
+       kobject_get(&s->kobj);
+       schedule_work(&s->kobj_remove_work);
 }
 
 void sysfs_slab_release(struct kmem_cache *s)
index ac6318a064d35e6dcc5385d1dc8062ff6e46554c..3405b4ee1757e3deb196c93e49b9641dad8d56fb 100644 (file)
@@ -48,6 +48,9 @@ static int swap_cgroup_prepare(int type)
                if (!page)
                        goto not_enough_page;
                ctrl->map[idx] = page;
+
+               if (!(idx % SWAP_CLUSTER_MAX))
+                       cond_resched();
        }
        return 0;
 not_enough_page:
index 464df34899031d46058b7cbadc1c3be24ae8dc89..26be6407abd7efe452a585d341a8d7e5b53d2b32 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -357,8 +357,11 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
        WARN_ON_ONCE((flags & GFP_KERNEL) != GFP_KERNEL);
 
        /*
-        * Make sure that larger requests are not too disruptive - no OOM
-        * killer and no allocation failure warnings as we have a fallback
+        * We want to attempt a large physically contiguous block first because
+        * it is less likely to fragment multiple larger blocks and therefore
+        * contribute to a long term fragmentation less than vmalloc fallback.
+        * However make sure that larger requests are not too disruptive - no
+        * OOM killer and no allocation failure warnings as we have a fallback.
         */
        if (size > PAGE_SIZE) {
                kmalloc_flags |= __GFP_NOWARN;
index 34a1c3e46ed72594b499e7f61e8aacdd4c5fe818..ecc97f74ab182fe9aeb7d7eda5166dfdb5b03095 100644 (file)
@@ -287,10 +287,21 @@ struct page *vmalloc_to_page(const void *vmalloc_addr)
        if (p4d_none(*p4d))
                return NULL;
        pud = pud_offset(p4d, addr);
-       if (pud_none(*pud))
+
+       /*
+        * Don't dereference bad PUD or PMD (below) entries. This will also
+        * identify huge mappings, which we may encounter on architectures
+        * that define CONFIG_HAVE_ARCH_HUGE_VMAP=y. Such regions will be
+        * identified as vmalloc addresses by is_vmalloc_addr(), but are
+        * not [unambiguously] associated with a struct page, so there is
+        * no correct value to return for them.
+        */
+       WARN_ON_ONCE(pud_bad(*pud));
+       if (pud_none(*pud) || pud_bad(*pud))
                return NULL;
        pmd = pmd_offset(pud, addr);
-       if (pmd_none(*pmd))
+       WARN_ON_ONCE(pmd_bad(*pmd));
+       if (pmd_none(*pmd) || pmd_bad(*pmd))
                return NULL;
 
        ptep = pte_offset_map(pmd, addr);
index 6063581f705c48b97a78a087d8c67127af9c8d68..ce0618bfa8d0643d0e65263ad65a9e7a7a4c92ed 100644 (file)
@@ -115,9 +115,9 @@ static enum vmpressure_levels vmpressure_calc_level(unsigned long scanned,
        unsigned long pressure = 0;
 
        /*
-        * reclaimed can be greater than scanned in cases
-        * like THP, where the scanned is 1 and reclaimed
-        * could be 512
+        * reclaimed can be greater than scanned for things such as reclaimed
+        * slab pages. shrink_node() just adds reclaimed pages without a
+        * related increment to scanned pages.
         */
        if (reclaimed >= scanned)
                goto out;
index 467069b73ce1b89e5a7b72904a878ef1f3412c67..9649579b5b9f38aff6ce7a990d2dc1ddb1d85e12 100644 (file)
@@ -277,7 +277,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
        return 0;
 
 out_free_newdev:
-       free_netdev(new_dev);
+       if (new_dev->reg_state == NETREG_UNINITIALIZED)
+               free_netdev(new_dev);
        return err;
 }
 
index 953b6728bd00c8ca7a4a20f2d2036c6f8f27f8e3..abc5f400fc71f2f57f3a029d1c196890ee4e39e0 100644 (file)
@@ -813,7 +813,6 @@ static void vlan_dev_free(struct net_device *dev)
 
        free_percpu(vlan->vlan_pcpu_stats);
        vlan->vlan_pcpu_stats = NULL;
-       free_netdev(dev);
 }
 
 void vlan_setup(struct net_device *dev)
@@ -826,7 +825,8 @@ void vlan_setup(struct net_device *dev)
        netif_keep_dst(dev);
 
        dev->netdev_ops         = &vlan_netdev_ops;
-       dev->destructor         = vlan_dev_free;
+       dev->needs_free_netdev  = true;
+       dev->priv_destructor    = vlan_dev_free;
        dev->ethtool_ops        = &vlan_ethtool_ops;
 
        dev->min_mtu            = 0;
index 71e85643b3f96db09de3330263f556fedba65257..6ad3e043c6174ae97a82525688988e740d87fd29 100644 (file)
@@ -454,8 +454,8 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
                        goto error_xenbus;
        }
        priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL);
-       if (!priv->tag) {
-               ret = -EINVAL;
+       if (IS_ERR(priv->tag)) {
+               ret = PTR_ERR(priv->tag);
                goto error_xenbus;
        }
        ret = xenbus_transaction_end(xbt, 0);
@@ -525,7 +525,7 @@ static struct xenbus_driver xen_9pfs_front_driver = {
        .otherend_changed = xen_9pfs_front_changed,
 };
 
-int p9_trans_xen_init(void)
+static int p9_trans_xen_init(void)
 {
        if (!xen_domain())
                return -ENODEV;
@@ -537,7 +537,7 @@ int p9_trans_xen_init(void)
 }
 module_init(p9_trans_xen_init);
 
-void p9_trans_xen_exit(void)
+static void p9_trans_xen_exit(void)
 {
        v9fs_unregister_trans(&p9_xen_trans);
        return xenbus_unregister_driver(&xen_9pfs_front_driver);
index 013e970eff393e0550aa250f7e72c27301071552..000ca2f113ab857b4969a95b8fe1134806b05f15 100644 (file)
@@ -1064,8 +1064,9 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
 
                skb_new->protocol = eth_type_trans(skb_new, soft_iface);
 
-               soft_iface->stats.rx_packets++;
-               soft_iface->stats.rx_bytes += skb->len + ETH_HLEN + hdr_size;
+               batadv_inc_counter(bat_priv, BATADV_CNT_RX);
+               batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
+                                  skb->len + ETH_HLEN + hdr_size);
 
                netif_rx(skb_new);
                batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
index e1ebe14ee2a6e21cc8d6b4a42552cae4bd15061f..ae9f4d37d34f07182c3d2527186a0999fe5b639d 100644 (file)
@@ -987,7 +987,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
                                batadv_dbg(BATADV_DBG_BLA, bat_priv,
                                           "recv_unicast_packet(): Dropped unicast pkt received from another backbone gw %pM.\n",
                                           orig_addr_gw);
-                               return NET_RX_DROP;
+                               goto free_skb;
                        }
                }
 
index b25789abf7b9e10aec7af1dfc41a5c9ff805284a..10f7edfb176ebd49c680ff4132db87aa00d3f04e 100644 (file)
@@ -1034,8 +1034,6 @@ static void batadv_softif_free(struct net_device *dev)
         * netdev and its private data (bat_priv)
         */
        rcu_barrier();
-
-       free_netdev(dev);
 }
 
 /**
@@ -1047,7 +1045,8 @@ static void batadv_softif_init_early(struct net_device *dev)
        ether_setup(dev);
 
        dev->netdev_ops = &batadv_netdev_ops;
-       dev->destructor = batadv_softif_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = batadv_softif_free;
        dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_NETNS_LOCAL;
        dev->priv_flags |= IFF_NO_QUEUE;
 
index 608959989f8eddbfc9b97279a7fba61fd7381d04..ab3b654b05cc87e19a965d0419efb7d45bd4b94e 100644 (file)
@@ -598,7 +598,7 @@ static void netdev_setup(struct net_device *dev)
 
        dev->netdev_ops         = &netdev_ops;
        dev->header_ops         = &header_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 }
 
 static struct device_type bt_type = {
index 430b53e7d941def09220a1c97a2e82d288304595..f0f3447e8aa48ff02c3f11f6da0e65e79cb28e90 100644 (file)
@@ -379,7 +379,7 @@ void br_dev_setup(struct net_device *dev)
        ether_setup(dev);
 
        dev->netdev_ops = &br_netdev_ops;
-       dev->destructor = free_netdev;
+       dev->needs_free_netdev = true;
        dev->ethtool_ops = &br_ethtool_ops;
        SET_NETDEV_DEVTYPE(dev, &br_type);
        dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE;
index c5ce7745b230fa3e67b66ba211be00d66cdc52da..32bd3ead9ba14a0b42bda3fc959f9134a8c9cc36 100644 (file)
@@ -595,7 +595,7 @@ static int br_afspec(struct net_bridge *br,
                err = 0;
                switch (nla_type(attr)) {
                case IFLA_BRIDGE_VLAN_TUNNEL_INFO:
-                       if (!(p->flags & BR_VLAN_TUNNEL))
+                       if (!p || !(p->flags & BR_VLAN_TUNNEL))
                                return -EINVAL;
                        err = br_parse_vlan_tunnel_info(attr, &tinfo_curr);
                        if (err)
@@ -835,6 +835,13 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
                        return -EPROTONOSUPPORT;
                }
        }
+
+       if (data[IFLA_BR_VLAN_DEFAULT_PVID]) {
+               __u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]);
+
+               if (defpvid >= VLAN_VID_MASK)
+                       return -EINVAL;
+       }
 #endif
 
        return 0;
index 08341d2aa9c946d7bdd6e0d599e31ba96557a290..6f12a5271219f071ed2d0bacb263561cb9e0f605 100644 (file)
@@ -179,6 +179,8 @@ static void br_stp_start(struct net_bridge *br)
                br_debug(br, "using kernel STP\n");
 
                /* To start timers on any ports left in blocking */
+               if (br->dev->flags & IFF_UP)
+                       mod_timer(&br->hello_timer, jiffies + br->hello_time);
                br_port_state_selection(br);
        }
 
index c98b3e5c140a5f30a28fd748408cf5e949a032b6..60b6fe277a8b0c90faad0dfcda87f149ceaa5552 100644 (file)
@@ -40,7 +40,7 @@ static void br_hello_timer_expired(unsigned long arg)
        if (br->dev->flags & IFF_UP) {
                br_config_bpdu_generation(br);
 
-               if (br->stp_enabled != BR_USER_STP)
+               if (br->stp_enabled == BR_KERNEL_STP)
                        mod_timer(&br->hello_timer,
                                  round_jiffies(jiffies + br->hello_time));
        }
index 5929309beaa1d5d310a19029364693c0b0355772..db85230e49c3b7e97093d54a1d7625d9145dfeb4 100644 (file)
@@ -68,6 +68,9 @@ static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
        if (e->ethproto != htons(ETH_P_ARP) ||
            e->invflags & EBT_IPROTO)
                return -EINVAL;
+       if (ebt_invalid_target(info->target))
+               return -EINVAL;
+
        return 0;
 }
 
index 9ec0c9f908fa712b18bfa25c87aa7bce12cee786..9c6e619f452bc96770a8e340d3879adce6dadd2a 100644 (file)
@@ -1373,7 +1373,8 @@ static inline int ebt_obj_to_user(char __user *um, const char *_name,
        strlcpy(name, _name, sizeof(name));
        if (copy_to_user(um, name, EBT_FUNCTION_MAXNAMELEN) ||
            put_user(datasize, (int __user *)(um + EBT_FUNCTION_MAXNAMELEN)) ||
-           xt_data_to_user(um + entrysize, data, usersize, datasize))
+           xt_data_to_user(um + entrysize, data, usersize, datasize,
+                           XT_ALIGN(datasize)))
                return -EFAULT;
 
        return 0;
@@ -1658,7 +1659,8 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
                if (match->compat_to_user(cm->data, m->data))
                        return -EFAULT;
        } else {
-               if (xt_data_to_user(cm->data, m->data, match->usersize, msize))
+               if (xt_data_to_user(cm->data, m->data, match->usersize, msize,
+                                   COMPAT_XT_ALIGN(msize)))
                        return -EFAULT;
        }
 
@@ -1687,7 +1689,8 @@ static int compat_target_to_user(struct ebt_entry_target *t,
                if (target->compat_to_user(cm->data, t->data))
                        return -EFAULT;
        } else {
-               if (xt_data_to_user(cm->data, t->data, target->usersize, tsize))
+               if (xt_data_to_user(cm->data, t->data, target->usersize, tsize,
+                                   COMPAT_XT_ALIGN(tsize)))
                        return -EFAULT;
        }
 
index adcad344c843985435958890583761e865a25374..21f18ea2fce440c1a0c8dcddc335e327dbf9bced 100644 (file)
@@ -754,6 +754,10 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr,
 
        lock_sock(sk);
 
+       err = -EINVAL;
+       if (addr_len < offsetofend(struct sockaddr, sa_family))
+               goto out;
+
        err = -EAFNOSUPPORT;
        if (uaddr->sa_family != AF_CAIF)
                goto out;
index 59ce1fcc220ce0a71fb57733be7cc91e6b8ac7fc..71b6ab240dea26b228be35ba24ec3f43772f19f7 100644 (file)
@@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx)
 {
        struct sk_buff *skb;
 
-       if (likely(in_interrupt()))
-               skb = alloc_skb(len + pfx, GFP_ATOMIC);
-       else
-               skb = alloc_skb(len + pfx, GFP_KERNEL);
-
+       skb = alloc_skb(len + pfx, GFP_ATOMIC);
        if (unlikely(skb == NULL))
                return NULL;
 
index 1816fc9f1ee779f85874e886a9ba6db721c60680..fe3c53efb949ef29a3dc1f6278d9abc05b50f579 100644 (file)
@@ -392,14 +392,14 @@ static void chnl_net_destructor(struct net_device *dev)
 {
        struct chnl_net *priv = netdev_priv(dev);
        caif_free_client(&priv->chnl);
-       free_netdev(dev);
 }
 
 static void ipcaif_net_setup(struct net_device *dev)
 {
        struct chnl_net *priv;
        dev->netdev_ops = &netdev_ops;
-       dev->destructor = chnl_net_destructor;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = chnl_net_destructor;
        dev->flags |= IFF_NOARP;
        dev->flags |= IFF_POINTOPOINT;
        dev->mtu = GPRS_PDP_MTU;
index b6406fe33c76d1e7ca5f439e9b7409ad3a680e6d..88edac0f3e366398d0c1e0de023b90b0669498f9 100644 (file)
@@ -872,8 +872,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
 
 static int can_pernet_init(struct net *net)
 {
-       net->can.can_rcvlists_lock =
-               __SPIN_LOCK_UNLOCKED(net->can.can_rcvlists_lock);
+       spin_lock_init(&net->can.can_rcvlists_lock);
        net->can.can_rx_alldev_list =
                kzalloc(sizeof(struct dev_rcv_lists), GFP_KERNEL);
 
index 2034fb9266700e6b456b141db9b5d264aed77d62..8757fb87dab871faaaeccaed0ac11d76521ad594 100644 (file)
@@ -151,7 +151,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
        struct timespec validity;
        void *tp, *tpend;
        void **ptp;
-       struct ceph_crypto_key new_session_key;
+       struct ceph_crypto_key new_session_key = { 0 };
        struct ceph_buffer *new_ticket_blob;
        unsigned long new_expires, new_renew_after;
        u64 new_secret_id;
@@ -215,6 +215,9 @@ static int process_one_ticket(struct ceph_auth_client *ac,
        dout(" ticket blob is %d bytes\n", dlen);
        ceph_decode_need(ptp, tpend, 1 + sizeof(u64), bad);
        blob_struct_v = ceph_decode_8(ptp);
+       if (blob_struct_v != 1)
+               goto bad;
+
        new_secret_id = ceph_decode_64(ptp);
        ret = ceph_decode_buffer(&new_ticket_blob, ptp, tpend);
        if (ret)
@@ -234,13 +237,13 @@ static int process_one_ticket(struct ceph_auth_client *ac,
             type, ceph_entity_type_name(type), th->secret_id,
             (int)th->ticket_blob->vec.iov_len);
        xi->have_keys |= th->service;
-
-out:
-       return ret;
+       return 0;
 
 bad:
        ret = -EINVAL;
-       goto out;
+out:
+       ceph_crypto_key_destroy(&new_session_key);
+       return ret;
 }
 
 static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
index 4fd02831beed20fb3d98475c7da2a0b4f2818513..47e94b560ba0d37daf2fb801fa11b9aa39720013 100644 (file)
@@ -56,19 +56,6 @@ static const struct kernel_param_ops param_ops_supported_features = {
 module_param_cb(supported_features, &param_ops_supported_features, NULL,
                S_IRUGO);
 
-/*
- * find filename portion of a path (/foo/bar/baz -> baz)
- */
-const char *ceph_file_part(const char *s, int len)
-{
-       const char *e = s + len;
-
-       while (e != s && *(e-1) != '/')
-               e--;
-       return e;
-}
-EXPORT_SYMBOL(ceph_file_part);
-
 const char *ceph_msg_type_name(int type)
 {
        switch (type) {
index 5766a6c896c4fa7290fffdbee239701ca4e2eeef..588a919300514ad2cd4b843c528bb41e601fa7d8 100644 (file)
@@ -1174,8 +1174,8 @@ static struct page *ceph_msg_data_next(struct ceph_msg_data_cursor *cursor,
  * Returns true if the result moves the cursor on to the next piece
  * of the data item.
  */
-static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor,
-                               size_t bytes)
+static void ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor,
+                                 size_t bytes)
 {
        bool new_piece;
 
@@ -1207,8 +1207,6 @@ static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor,
                new_piece = true;
        }
        cursor->need_crc = new_piece;
-
-       return new_piece;
 }
 
 static size_t sizeof_footer(struct ceph_connection *con)
@@ -1577,7 +1575,6 @@ static int write_partial_message_data(struct ceph_connection *con)
                size_t page_offset;
                size_t length;
                bool last_piece;
-               bool need_crc;
                int ret;
 
                page = ceph_msg_data_next(cursor, &page_offset, &length,
@@ -1592,7 +1589,7 @@ static int write_partial_message_data(struct ceph_connection *con)
                }
                if (do_datacrc && cursor->need_crc)
                        crc = ceph_crc32c_page(crc, page, page_offset, length);
-               need_crc = ceph_msg_data_advance(cursor, (size_t)ret);
+               ceph_msg_data_advance(cursor, (size_t)ret);
        }
 
        dout("%s %p msg %p done\n", __func__, con, msg);
@@ -2231,10 +2228,18 @@ static void process_ack(struct ceph_connection *con)
        struct ceph_msg *m;
        u64 ack = le64_to_cpu(con->in_temp_ack);
        u64 seq;
+       bool reconnect = (con->in_tag == CEPH_MSGR_TAG_SEQ);
+       struct list_head *list = reconnect ? &con->out_queue : &con->out_sent;
 
-       while (!list_empty(&con->out_sent)) {
-               m = list_first_entry(&con->out_sent, struct ceph_msg,
-                                    list_head);
+       /*
+        * In the reconnect case, con_fault() has requeued messages
+        * in out_sent. We should cleanup old messages according to
+        * the reconnect seq.
+        */
+       while (!list_empty(list)) {
+               m = list_first_entry(list, struct ceph_msg, list_head);
+               if (reconnect && m->needs_out_seq)
+                       break;
                seq = le64_to_cpu(m->hdr.seq);
                if (seq > ack)
                        break;
@@ -2243,6 +2248,7 @@ static void process_ack(struct ceph_connection *con)
                m->ack_stamp = jiffies;
                ceph_msg_remove(m);
        }
+
        prepare_read_tag(con);
 }
 
@@ -2299,7 +2305,7 @@ static int read_partial_msg_data(struct ceph_connection *con)
 
                if (do_datacrc)
                        crc = ceph_crc32c_page(crc, page, page_offset, ret);
-               (void) ceph_msg_data_advance(cursor, (size_t)ret);
+               ceph_msg_data_advance(cursor, (size_t)ret);
        }
        if (do_datacrc)
                con->in_data_crc = crc;
index 29a0ef351c5e068838fc1ed8f634439853ff0a3a..250f11f786092d902b52da5af9a228d9786acf62 100644 (file)
@@ -43,15 +43,13 @@ struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
        int i, err = -EINVAL;
        struct ceph_fsid fsid;
        u32 epoch, num_mon;
-       u16 version;
        u32 len;
 
        ceph_decode_32_safe(&p, end, len, bad);
        ceph_decode_need(&p, end, len, bad);
 
        dout("monmap_decode %p %p len %d\n", p, end, (int)(end-p));
-
-       ceph_decode_16_safe(&p, end, version, bad);
+       p += sizeof(u16);  /* skip version */
 
        ceph_decode_need(&p, end, sizeof(fsid) + 2*sizeof(u32), bad);
        ceph_decode_copy(&p, &fsid, sizeof(fsid));
index ffe9e904d4d1d130b0353edbe45d50d236b4f74e..55e3a477f92d4cba92e342d13686b6e3b94204c0 100644 (file)
@@ -317,6 +317,7 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                u32 yes;
                struct crush_rule *r;
 
+               err = -EINVAL;
                ceph_decode_32_safe(p, end, yes, bad);
                if (!yes) {
                        dout("crush_decode NO rule %d off %x %p to %p\n",
index 96cf83da0d66b2db07d5504c4c3aec7da735ea46..416137c64bf809328898f42fff41cd27ccf036d6 100644 (file)
@@ -1253,8 +1253,9 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
        if (!new_ifalias)
                return -ENOMEM;
        dev->ifalias = new_ifalias;
+       memcpy(dev->ifalias, alias, len);
+       dev->ifalias[len] = 0;
 
-       strlcpy(dev->ifalias, alias, len+1);
        return len;
 }
 
@@ -4766,6 +4767,13 @@ struct packet_offload *gro_find_complete_by_type(__be16 type)
 }
 EXPORT_SYMBOL(gro_find_complete_by_type);
 
+static void napi_skb_free_stolen_head(struct sk_buff *skb)
+{
+       skb_dst_drop(skb);
+       secpath_reset(skb);
+       kmem_cache_free(skbuff_head_cache, skb);
+}
+
 static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
        switch (ret) {
@@ -4779,13 +4787,10 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
                break;
 
        case GRO_MERGED_FREE:
-               if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
-                       skb_dst_drop(skb);
-                       secpath_reset(skb);
-                       kmem_cache_free(skbuff_head_cache, skb);
-               } else {
+               if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
+                       napi_skb_free_stolen_head(skb);
+               else
                        __kfree_skb(skb);
-               }
                break;
 
        case GRO_HELD:
@@ -4857,10 +4862,16 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi,
                break;
 
        case GRO_DROP:
-       case GRO_MERGED_FREE:
                napi_reuse_skb(napi, skb);
                break;
 
+       case GRO_MERGED_FREE:
+               if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
+                       napi_skb_free_stolen_head(skb);
+               else
+                       napi_reuse_skb(napi, skb);
+               break;
+
        case GRO_MERGED:
        case GRO_CONSUMED:
                break;
@@ -4948,6 +4959,19 @@ __sum16 __skb_gro_checksum_complete(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(__skb_gro_checksum_complete);
 
+static void net_rps_send_ipi(struct softnet_data *remsd)
+{
+#ifdef CONFIG_RPS
+       while (remsd) {
+               struct softnet_data *next = remsd->rps_ipi_next;
+
+               if (cpu_online(remsd->cpu))
+                       smp_call_function_single_async(remsd->cpu, &remsd->csd);
+               remsd = next;
+       }
+#endif
+}
+
 /*
  * net_rps_action_and_irq_enable sends any pending IPI's for rps.
  * Note: called with local irq disabled, but exits with local irq enabled.
@@ -4963,14 +4987,7 @@ static void net_rps_action_and_irq_enable(struct softnet_data *sd)
                local_irq_enable();
 
                /* Send pending IPI's to kick RPS processing on remote cpus. */
-               while (remsd) {
-                       struct softnet_data *next = remsd->rps_ipi_next;
-
-                       if (cpu_online(remsd->cpu))
-                               smp_call_function_single_async(remsd->cpu,
-                                                          &remsd->csd);
-                       remsd = next;
-               }
+               net_rps_send_ipi(remsd);
        } else
 #endif
                local_irq_enable();
@@ -5199,8 +5216,6 @@ static void busy_poll_stop(struct napi_struct *napi, void *have_poll_lock)
        if (rc == BUSY_POLL_BUDGET)
                __napi_schedule(napi);
        local_bh_enable();
-       if (local_softirq_pending())
-               do_softirq();
 }
 
 void napi_busy_loop(unsigned int napi_id,
@@ -6852,6 +6867,32 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
 }
 EXPORT_SYMBOL(dev_change_proto_down);
 
+bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op)
+{
+       struct netdev_xdp xdp;
+
+       memset(&xdp, 0, sizeof(xdp));
+       xdp.command = XDP_QUERY_PROG;
+
+       /* Query must always succeed. */
+       WARN_ON(xdp_op(dev, &xdp) < 0);
+       return xdp.prog_attached;
+}
+
+static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
+                          struct netlink_ext_ack *extack,
+                          struct bpf_prog *prog)
+{
+       struct netdev_xdp xdp;
+
+       memset(&xdp, 0, sizeof(xdp));
+       xdp.command = XDP_SETUP_PROG;
+       xdp.extack = extack;
+       xdp.prog = prog;
+
+       return xdp_op(dev, &xdp);
+}
+
 /**
  *     dev_change_xdp_fd - set or clear a bpf program for a device rx path
  *     @dev: device
@@ -6864,41 +6905,34 @@ EXPORT_SYMBOL(dev_change_proto_down);
 int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
                      int fd, u32 flags)
 {
-       int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp);
        const struct net_device_ops *ops = dev->netdev_ops;
        struct bpf_prog *prog = NULL;
-       struct netdev_xdp xdp;
+       xdp_op_t xdp_op, xdp_chk;
        int err;
 
        ASSERT_RTNL();
 
-       xdp_op = ops->ndo_xdp;
+       xdp_op = xdp_chk = ops->ndo_xdp;
+       if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE))
+               return -EOPNOTSUPP;
        if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
                xdp_op = generic_xdp_install;
+       if (xdp_op == xdp_chk)
+               xdp_chk = generic_xdp_install;
 
        if (fd >= 0) {
-               if (flags & XDP_FLAGS_UPDATE_IF_NOEXIST) {
-                       memset(&xdp, 0, sizeof(xdp));
-                       xdp.command = XDP_QUERY_PROG;
-
-                       err = xdp_op(dev, &xdp);
-                       if (err < 0)
-                               return err;
-                       if (xdp.prog_attached)
-                               return -EBUSY;
-               }
+               if (xdp_chk && __dev_xdp_attached(dev, xdp_chk))
+                       return -EEXIST;
+               if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
+                   __dev_xdp_attached(dev, xdp_op))
+                       return -EBUSY;
 
                prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
                if (IS_ERR(prog))
                        return PTR_ERR(prog);
        }
 
-       memset(&xdp, 0, sizeof(xdp));
-       xdp.command = XDP_SETUP_PROG;
-       xdp.extack = extack;
-       xdp.prog = prog;
-
-       err = xdp_op(dev, &xdp);
+       err = dev_xdp_install(dev, xdp_op, extack, prog);
        if (err < 0 && prog)
                bpf_prog_put(prog);
 
@@ -7482,6 +7516,8 @@ out:
 err_uninit:
        if (dev->netdev_ops->ndo_uninit)
                dev->netdev_ops->ndo_uninit(dev);
+       if (dev->priv_destructor)
+               dev->priv_destructor(dev);
        goto out;
 }
 EXPORT_SYMBOL(register_netdevice);
@@ -7689,8 +7725,10 @@ void netdev_run_todo(void)
                WARN_ON(rcu_access_pointer(dev->ip6_ptr));
                WARN_ON(dev->dn_ptr);
 
-               if (dev->destructor)
-                       dev->destructor(dev);
+               if (dev->priv_destructor)
+                       dev->priv_destructor(dev);
+               if (dev->needs_free_netdev)
+                       free_netdev(dev);
 
                /* Report a network device has been unregistered */
                rtnl_lock();
@@ -7755,9 +7793,9 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
        } else {
                netdev_stats_to_stats64(storage, &dev->stats);
        }
-       storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
-       storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
-       storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
+       storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped);
+       storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped);
+       storage->rx_nohandler += (unsigned long)atomic_long_read(&dev->rx_nohandler);
        return storage;
 }
 EXPORT_SYMBOL(dev_get_stats);
@@ -8173,7 +8211,7 @@ static int dev_cpu_dead(unsigned int oldcpu)
        struct sk_buff **list_skb;
        struct sk_buff *skb;
        unsigned int cpu;
-       struct softnet_data *sd, *oldsd;
+       struct softnet_data *sd, *oldsd, *remsd = NULL;
 
        local_irq_disable();
        cpu = smp_processor_id();
@@ -8214,6 +8252,13 @@ static int dev_cpu_dead(unsigned int oldcpu)
        raise_softirq_irqoff(NET_TX_SOFTIRQ);
        local_irq_enable();
 
+#ifdef CONFIG_RPS
+       remsd = oldsd->rps_ipi_list;
+       oldsd->rps_ipi_list = NULL;
+#endif
+       /* send out pending IPI's on offline CPU */
+       net_rps_send_ipi(remsd);
+
        /* Process offline CPU's input_pkt_queue */
        while ((skb = __skb_dequeue(&oldsd->process_queue))) {
                netif_rx_ni(skb);
index b94b1d29350603e19c3db8e6fd740d3f89440771..27fad31784a83861f942f3b4f82f44985a946645 100644 (file)
@@ -410,6 +410,22 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        if (cmd == SIOCGIFNAME)
                return dev_ifname(net, (struct ifreq __user *)arg);
 
+       /*
+        * Take care of Wireless Extensions. Unfortunately struct iwreq
+        * isn't a proper subset of struct ifreq (it's 8 byte shorter)
+        * so we need to treat it specially, otherwise applications may
+        * fault if the struct they're passing happens to land at the
+        * end of a mapped page.
+        */
+       if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
+               struct iwreq iwr;
+
+               if (copy_from_user(&iwr, arg, sizeof(iwr)))
+                       return -EFAULT;
+
+               return wext_handle_ioctl(net, &iwr, cmd, arg);
+       }
+
        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
                return -EFAULT;
 
@@ -559,9 +575,6 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                                ret = -EFAULT;
                        return ret;
                }
-               /* Take care of Wireless Extensions */
-               if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
-                       return wext_handle_ioctl(net, &ifr, cmd, arg);
                return -ENOTTY;
        }
 }
index b0b87a292e7ccac2221a2425510b3c28e1df97f7..a0adfc31a3fe854cd52600f6b2924255aee521c2 100644 (file)
@@ -1680,8 +1680,10 @@ start_again:
 
        hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
                          &devlink_nl_family, NLM_F_MULTI, cmd);
-       if (!hdr)
+       if (!hdr) {
+               nlmsg_free(skb);
                return -EMSGSIZE;
+       }
 
        if (devlink_nl_put_handle(skb, devlink))
                goto nla_put_failure;
@@ -2098,8 +2100,10 @@ start_again:
 
        hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
                          &devlink_nl_family, NLM_F_MULTI, cmd);
-       if (!hdr)
+       if (!hdr) {
+               nlmsg_free(skb);
                return -EMSGSIZE;
+       }
 
        if (devlink_nl_put_handle(skb, devlink))
                goto nla_put_failure;
index 960e503b5a529a2c4f1866f49c150493ee98d7da..13ba4a090c410e40853178df4ffca85f02b71b03 100644 (file)
@@ -151,13 +151,13 @@ int dst_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(dst_discard_out);
 
-const u32 dst_default_metrics[RTAX_MAX + 1] = {
+const struct dst_metrics dst_default_metrics = {
        /* This initializer is needed to force linker to place this variable
         * into const section. Otherwise it might end into bss section.
         * We really want to avoid false sharing on this variable, and catch
         * any writes on it.
         */
-       [RTAX_MAX] = 0xdeadbeef,
+       .refcnt = ATOMIC_INIT(1),
 };
 
 void dst_init(struct dst_entry *dst, struct dst_ops *ops,
@@ -169,7 +169,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,
        if (dev)
                dev_hold(dev);
        dst->ops = ops;
-       dst_init_metrics(dst, dst_default_metrics, true);
+       dst_init_metrics(dst, dst_default_metrics.metrics, true);
        dst->expires = 0UL;
        dst->path = dst;
        dst->from = NULL;
@@ -314,25 +314,30 @@ EXPORT_SYMBOL(dst_release);
 
 u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old)
 {
-       u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC);
+       struct dst_metrics *p = kmalloc(sizeof(*p), GFP_ATOMIC);
 
        if (p) {
-               u32 *old_p = __DST_METRICS_PTR(old);
+               struct dst_metrics *old_p = (struct dst_metrics *)__DST_METRICS_PTR(old);
                unsigned long prev, new;
 
-               memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
+               atomic_set(&p->refcnt, 1);
+               memcpy(p->metrics, old_p->metrics, sizeof(p->metrics));
 
                new = (unsigned long) p;
                prev = cmpxchg(&dst->_metrics, old, new);
 
                if (prev != old) {
                        kfree(p);
-                       p = __DST_METRICS_PTR(prev);
+                       p = (struct dst_metrics *)__DST_METRICS_PTR(prev);
                        if (prev & DST_METRICS_READ_ONLY)
                                p = NULL;
+               } else if (prev & DST_METRICS_REFCOUNTED) {
+                       if (atomic_dec_and_test(&old_p->refcnt))
+                               kfree(old_p);
                }
        }
-       return p;
+       BUILD_BUG_ON(offsetof(struct dst_metrics, metrics) != 0);
+       return (u32 *)p;
 }
 EXPORT_SYMBOL(dst_cow_metrics_generic);
 
@@ -341,7 +346,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
 {
        unsigned long prev, new;
 
-       new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY;
+       new = ((unsigned long) &dst_default_metrics) | DST_METRICS_READ_ONLY;
        prev = cmpxchg(&dst->_metrics, old, new);
        if (prev == old)
                kfree(__DST_METRICS_PTR(old));
@@ -464,6 +469,20 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event,
                spin_lock_bh(&dst_garbage.lock);
                dst = dst_garbage.list;
                dst_garbage.list = NULL;
+               /* The code in dst_ifdown places a hold on the loopback device.
+                * If the gc entry processing is set to expire after a lengthy
+                * interval, this hold can cause netdev_wait_allrefs() to hang
+                * out and wait for a long time -- until the the loopback
+                * interface is released.  If we're really unlucky, it'll emit
+                * pr_emerg messages to console too.  Reset the interval here,
+                * so dst cleanups occur in a more timely fashion.
+                */
+               if (dst_garbage.timer_inc > DST_GC_INC) {
+                       dst_garbage.timer_inc = DST_GC_INC;
+                       dst_garbage.timer_expires = DST_GC_MIN;
+                       mod_delayed_work(system_wq, &dst_gc_work,
+                                        dst_garbage.timer_expires);
+               }
                spin_unlock_bh(&dst_garbage.lock);
 
                if (last)
index f21c4d3aeae0cf59a8d9239cf1e581e6d136c740..3bba291c6c32e4359a6d626fbd492f7d07fd3e4c 100644 (file)
@@ -568,7 +568,7 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct net *net = sock_net(skb->sk);
        struct fib_rule_hdr *frh = nlmsg_data(nlh);
        struct fib_rules_ops *ops = NULL;
-       struct fib_rule *rule, *tmp;
+       struct fib_rule *rule, *r;
        struct nlattr *tb[FRA_MAX+1];
        struct fib_kuid_range range;
        int err = -EINVAL;
@@ -668,16 +668,23 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
 
                /*
                 * Check if this rule is a target to any of them. If so,
+                * adjust to the next one with the same preference or
                 * disable them. As this operation is eventually very
-                * expensive, it is only performed if goto rules have
-                * actually been added.
+                * expensive, it is only performed if goto rules, except
+                * current if it is goto rule, have actually been added.
                 */
                if (ops->nr_goto_rules > 0) {
-                       list_for_each_entry(tmp, &ops->rules_list, list) {
-                               if (rtnl_dereference(tmp->ctarget) == rule) {
-                                       RCU_INIT_POINTER(tmp->ctarget, NULL);
+                       struct fib_rule *n;
+
+                       n = list_next_entry(rule, list);
+                       if (&n->list == &ops->rules_list || n->pref != rule->pref)
+                               n = NULL;
+                       list_for_each_entry(r, &ops->rules_list, list) {
+                               if (rtnl_dereference(r->ctarget) != rule)
+                                       continue;
+                               rcu_assign_pointer(r->ctarget, n);
+                               if (!n)
                                        ops->unresolved_rules++;
-                               }
                        }
                }
 
index a253a6197e6b37a7ae2fe451c646b01c861a3e22..a6bb95fa87b26a6627ba38cd9a94269c7e59f73d 100644 (file)
@@ -2281,6 +2281,7 @@ bool bpf_helper_changes_pkt_data(void *func)
            func == bpf_skb_change_head ||
            func == bpf_skb_change_tail ||
            func == bpf_skb_pull_data ||
+           func == bpf_clone_redirect ||
            func == bpf_l3_csum_replace ||
            func == bpf_l4_csum_replace ||
            func == bpf_xdp_adjust_head)
index 58b0bcc125b5559f299dc2f195deccb5c43d0844..d274f81fcc2c08f1e85df4ed00b9a034f3ae0739 100644 (file)
@@ -1132,10 +1132,6 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                lladdr = neigh->ha;
        }
 
-       if (new & NUD_CONNECTED)
-               neigh->confirmed = jiffies;
-       neigh->updated = jiffies;
-
        /* If entry was valid and address is not changed,
           do not change entry state, if new one is STALE.
         */
@@ -1157,6 +1153,16 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                }
        }
 
+       /* Update timestamps only once we know we will make a change to the
+        * neighbour entry. Otherwise we risk to move the locktime window with
+        * noop updates and ignore relevant ARP updates.
+        */
+       if (new != old || lladdr != neigh->ha) {
+               if (new & NUD_CONNECTED)
+                       neigh->confirmed = jiffies;
+               neigh->updated = jiffies;
+       }
+
        if (new != old) {
                neigh_del_timer(neigh);
                if (new & NUD_PROBE)
index 1934efd4a9d4986f3497abc40968fd08c91896b3..26bbfababff27cecc589bca69e3eb14739187f5b 100644 (file)
@@ -315,6 +315,25 @@ out_undo:
        goto out;
 }
 
+static int __net_init net_defaults_init_net(struct net *net)
+{
+       net->core.sysctl_somaxconn = SOMAXCONN;
+       return 0;
+}
+
+static struct pernet_operations net_defaults_ops = {
+       .init = net_defaults_init_net,
+};
+
+static __init int net_defaults_init(void)
+{
+       if (register_pernet_subsys(&net_defaults_ops))
+               panic("Cannot initialize net default settings");
+
+       return 0;
+}
+
+core_initcall(net_defaults_init);
 
 #ifdef CONFIG_NET_NS
 static struct ucounts *inc_net_namespaces(struct user_namespace *ns)
index bcb0f610ee422a12ad6b8ae41763296ba0fa3c6a..467a2f4510a74cad48209b696532838d1edcf96e 100644 (file)
@@ -899,8 +899,7 @@ static size_t rtnl_port_size(const struct net_device *dev,
 static size_t rtnl_xdp_size(void)
 {
        size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP */
-                         nla_total_size(1) +   /* XDP_ATTACHED */
-                         nla_total_size(4);    /* XDP_FLAGS */
+                         nla_total_size(1);    /* XDP_ATTACHED */
 
        return xdp_size;
 }
@@ -932,6 +931,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
               + nla_total_size(1) /* IFLA_LINKMODE */
               + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
               + nla_total_size(4) /* IFLA_LINK_NETNSID */
+              + nla_total_size(4) /* IFLA_GROUP */
               + nla_total_size(ext_filter_mask
                                & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
               + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -1125,6 +1125,8 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
        struct ifla_vf_mac vf_mac;
        struct ifla_vf_info ivi;
 
+       memset(&ivi, 0, sizeof(ivi));
+
        /* Not all SR-IOV capable drivers support the
         * spoofcheck and "RSS query enable" query.  Preset to
         * -1 so the user space tool can detect that the driver
@@ -1133,7 +1135,6 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
        ivi.spoofchk = -1;
        ivi.rss_query_en = -1;
        ivi.trusted = -1;
-       memset(ivi.mac, 0, sizeof(ivi.mac));
        /* The default value for VF link state is "auto"
         * IFLA_VF_LINK_STATE_AUTO which equals zero
         */
@@ -1247,37 +1248,34 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static u8 rtnl_xdp_attached_mode(struct net_device *dev)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       ASSERT_RTNL();
+
+       if (rcu_access_pointer(dev->xdp_prog))
+               return XDP_ATTACHED_SKB;
+       if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp))
+               return XDP_ATTACHED_DRV;
+
+       return XDP_ATTACHED_NONE;
+}
+
 static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
 {
        struct nlattr *xdp;
-       u32 xdp_flags = 0;
-       u8 val = 0;
        int err;
 
        xdp = nla_nest_start(skb, IFLA_XDP);
        if (!xdp)
                return -EMSGSIZE;
-       if (rcu_access_pointer(dev->xdp_prog)) {
-               xdp_flags = XDP_FLAGS_SKB_MODE;
-               val = 1;
-       } else if (dev->netdev_ops->ndo_xdp) {
-               struct netdev_xdp xdp_op = {};
-
-               xdp_op.command = XDP_QUERY_PROG;
-               err = dev->netdev_ops->ndo_xdp(dev, &xdp_op);
-               if (err)
-                       goto err_cancel;
-               val = xdp_op.prog_attached;
-       }
-       err = nla_put_u8(skb, IFLA_XDP_ATTACHED, val);
+
+       err = nla_put_u8(skb, IFLA_XDP_ATTACHED,
+                        rtnl_xdp_attached_mode(dev));
        if (err)
                goto err_cancel;
 
-       if (xdp_flags) {
-               err = nla_put_u32(skb, IFLA_XDP_FLAGS, xdp_flags);
-               if (err)
-                       goto err_cancel;
-       }
        nla_nest_end(skb, xdp);
        return 0;
 
@@ -1471,6 +1469,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
        [IFLA_LINK_NETNSID]     = { .type = NLA_S32 },
        [IFLA_PROTO_DOWN]       = { .type = NLA_U8 },
        [IFLA_XDP]              = { .type = NLA_NESTED },
+       [IFLA_GROUP]            = { .type = NLA_U32 },
 };
 
 static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -1631,13 +1630,13 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
                                               cb->nlh->nlmsg_seq, 0,
                                               flags,
                                               ext_filter_mask);
-                       /* If we ran out of room on the first message,
-                        * we're in trouble
-                        */
-                       WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
 
-                       if (err < 0)
-                               goto out;
+                       if (err < 0) {
+                               if (likely(skb->len))
+                                       goto out;
+
+                               goto out_err;
+                       }
 
                        nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
@@ -1645,10 +1644,12 @@ cont:
                }
        }
 out:
+       err = skb->len;
+out_err:
        cb->args[1] = idx;
        cb->args[0] = h;
 
-       return skb->len;
+       return err;
 }
 
 int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
@@ -2199,6 +2200,11 @@ static int do_setlink(const struct sk_buff *skb,
                                err = -EINVAL;
                                goto errout;
                        }
+                       if ((xdp_flags & XDP_FLAGS_SKB_MODE) &&
+                           (xdp_flags & XDP_FLAGS_DRV_MODE)) {
+                               err = -EINVAL;
+                               goto errout;
+                       }
                }
 
                if (xdp[IFLA_XDP_FD]) {
@@ -3228,8 +3234,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
        int err = 0;
        int fidx = 0;
 
-       if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb,
-                       IFLA_MAX, ifla_policy, NULL) == 0) {
+       err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb,
+                         IFLA_MAX, ifla_policy, NULL);
+       if (err < 0) {
+               return -EINVAL;
+       } else if (err == 0) {
                if (tb[IFLA_MASTER])
                        br_idx = nla_get_u32(tb[IFLA_MASTER]);
        }
@@ -3452,8 +3461,12 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                                err = br_dev->netdev_ops->ndo_bridge_getlink(
                                                skb, portid, seq, dev,
                                                filter_mask, NLM_F_MULTI);
-                               if (err < 0 && err != -EOPNOTSUPP)
-                                       break;
+                               if (err < 0 && err != -EOPNOTSUPP) {
+                                       if (likely(skb->len))
+                                               break;
+
+                                       goto out_err;
+                               }
                        }
                        idx++;
                }
@@ -3464,16 +3477,22 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                                                              seq, dev,
                                                              filter_mask,
                                                              NLM_F_MULTI);
-                               if (err < 0 && err != -EOPNOTSUPP)
-                                       break;
+                               if (err < 0 && err != -EOPNOTSUPP) {
+                                       if (likely(skb->len))
+                                               break;
+
+                                       goto out_err;
+                               }
                        }
                        idx++;
                }
        }
+       err = skb->len;
+out_err:
        rcu_read_unlock();
        cb->args[0] = idx;
 
-       return skb->len;
+       return err;
 }
 
 static inline size_t bridge_nlmsg_size(void)
index 346d3e85dfbc2eca1ded0442ecb78d31e1768523..b1be7c01efe269d2bc97be7dcd1cc5485d29fa7b 100644 (file)
@@ -3754,8 +3754,11 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
 
        spin_lock_irqsave(&q->lock, flags);
        skb = __skb_dequeue(q);
-       if (skb && (skb_next = skb_peek(q)))
+       if (skb && (skb_next = skb_peek(q))) {
                icmp_next = is_icmp_err_skb(skb_next);
+               if (icmp_next)
+                       sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_origin;
+       }
        spin_unlock_irqrestore(&q->lock, flags);
 
        if (is_icmp_err_skb(skb) && !icmp_next)
index 79c6aee6af9b817bd7086f04ae8f46342a3bf4b6..727f924b7f91f495d9e7a4e7297c9c937d3258ed 100644 (file)
 
 #include <trace/events/sock.h>
 
-#ifdef CONFIG_INET
 #include <net/tcp.h>
-#endif
-
 #include <net/busy_poll.h>
 
 static DEFINE_MUTEX(proto_list_mutex);
@@ -1803,28 +1800,24 @@ EXPORT_SYMBOL(skb_set_owner_w);
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
  * But we also want to keep skb->sk set because some packet schedulers
- * rely on it (sch_fq for example). So we set skb->truesize to a small
- * amount (1) and decrease sk_wmem_alloc accordingly.
+ * rely on it (sch_fq for example).
  */
 void skb_orphan_partial(struct sk_buff *skb)
 {
-       /* If this skb is a TCP pure ACK or already went here,
-        * we have nothing to do. 2 is already a very small truesize.
-        */
-       if (skb->truesize <= 2)
+       if (skb_is_tcp_pure_ack(skb))
                return;
 
-       /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
-        * so we do not completely orphan skb, but transfert all
-        * accounted bytes but one, to avoid unexpected reorders.
-        */
        if (skb->destructor == sock_wfree
 #ifdef CONFIG_INET
            || skb->destructor == tcp_wfree
 #endif
                ) {
-               atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
-               skb->truesize = 1;
+               struct sock *sk = skb->sk;
+
+               if (atomic_inc_not_zero(&sk->sk_refcnt)) {
+                       atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
+                       skb->destructor = sock_efree;
+               }
        } else {
                skb_orphan(skb);
        }
index ea23254b2457cf15eeae495130dab437090f8e2e..b7cd9aafe99e9b9216b13cce617133cdf832eeeb 100644 (file)
@@ -479,8 +479,6 @@ static __net_init int sysctl_core_net_init(struct net *net)
 {
        struct ctl_table *tbl;
 
-       net->core.sysctl_somaxconn = SOMAXCONN;
-
        tbl = netns_core_table;
        if (!net_eq(net, &init_net)) {
                tbl = kmemdup(tbl, sizeof(netns_core_table), GFP_KERNEL);
index 840f14aaa01635e0f6fb62232b67814736c84b5d..992621172220d136a1114a58f1c0e75219c57ea4 100644 (file)
@@ -426,6 +426,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
                newsk->sk_backlog_rcv = dccp_v4_do_rcv;
                newnp->pktoptions  = NULL;
                newnp->opt         = NULL;
+               newnp->ipv6_mc_list = NULL;
+               newnp->ipv6_ac_list = NULL;
+               newnp->ipv6_fl_list = NULL;
                newnp->mcast_oif   = inet6_iif(skb);
                newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
 
@@ -490,6 +493,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
        /* Clone RX bits */
        newnp->rxopt.all = np->rxopt.all;
 
+       newnp->ipv6_mc_list = NULL;
+       newnp->ipv6_ac_list = NULL;
+       newnp->ipv6_fl_list = NULL;
        newnp->pktoptions = NULL;
        newnp->opt        = NULL;
        newnp->mcast_oif  = inet6_iif(skb);
index 4b9518a0d2489494ed88b6808f95803cf1b543ad..6f95612b4d321d63e39b37f881f0e46331999ad2 100644 (file)
@@ -188,12 +188,6 @@ static inline void dnrt_free(struct dn_route *rt)
        call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
 }
 
-static inline void dnrt_drop(struct dn_route *rt)
-{
-       dst_release(&rt->dst);
-       call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
 static void dn_dst_check_expire(unsigned long dummy)
 {
        int i;
@@ -248,7 +242,7 @@ static int dn_dst_gc(struct dst_ops *ops)
                        }
                        *rtp = rt->dst.dn_next;
                        rt->dst.dn_next = NULL;
-                       dnrt_drop(rt);
+                       dnrt_free(rt);
                        break;
                }
                spin_unlock_bh(&dn_rt_hash_table[i].lock);
@@ -350,7 +344,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
                        dst_use(&rth->dst, now);
                        spin_unlock_bh(&dn_rt_hash_table[hash].lock);
 
-                       dnrt_drop(rt);
+                       dst_free(&rt->dst);
                        *rp = rth;
                        return 0;
                }
@@ -380,7 +374,7 @@ static void dn_run_flush(unsigned long dummy)
                for(; rt; rt = next) {
                        next = rcu_dereference_raw(rt->dst.dn_next);
                        RCU_INIT_POINTER(rt->dst.dn_next, NULL);
-                       dst_free((struct dst_entry *)rt);
+                       dnrt_free(rt);
                }
 
 nothing_to_declare:
@@ -1187,7 +1181,7 @@ make_route:
        if (dev_out->flags & IFF_LOOPBACK)
                flags |= RTCF_LOCAL;
 
-       rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST);
+       rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST);
        if (rt == NULL)
                goto e_nobufs;
 
index 1ed81ac6dd1a28b79dff9f9f4e8c1d0f99306a33..aa8ffecc46a439fa129dfea9c1f4d4e525ad3796 100644 (file)
@@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
 {
        struct nlmsghdr *nlh = nlmsg_hdr(skb);
 
-       if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+       if (skb->len < sizeof(*nlh) ||
+           nlh->nlmsg_len < sizeof(*nlh) ||
+           skb->len < nlh->nlmsg_len)
                return;
 
        if (!netlink_capable(skb, CAP_NET_ADMIN))
index 26130ae438da53f3f99a4e9fa712a572f40ca779..90038d45a54764df55017b46258dc772b0af1c96 100644 (file)
@@ -223,6 +223,53 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+int dsa_switch_suspend(struct dsa_switch *ds)
+{
+       int i, ret = 0;
+
+       /* Suspend slave network devices */
+       for (i = 0; i < ds->num_ports; i++) {
+               if (!dsa_is_port_initialized(ds, i))
+                       continue;
+
+               ret = dsa_slave_suspend(ds->ports[i].netdev);
+               if (ret)
+                       return ret;
+       }
+
+       if (ds->ops->suspend)
+               ret = ds->ops->suspend(ds);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dsa_switch_suspend);
+
+int dsa_switch_resume(struct dsa_switch *ds)
+{
+       int i, ret = 0;
+
+       if (ds->ops->resume)
+               ret = ds->ops->resume(ds);
+
+       if (ret)
+               return ret;
+
+       /* Resume slave network devices */
+       for (i = 0; i < ds->num_ports; i++) {
+               if (!dsa_is_port_initialized(ds, i))
+                       continue;
+
+               ret = dsa_slave_resume(ds->ports[i].netdev);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dsa_switch_resume);
+#endif
+
 static struct packet_type dsa_pack_type __read_mostly = {
        .type   = cpu_to_be16(ETH_P_XDSA),
        .func   = dsa_switch_rcv,
index 033b3bfb63dc1887b15b3e08f00a00f70b706ec4..7796580e99ee2c57cdd5503130c8ec2e121d879a 100644 (file)
@@ -484,8 +484,10 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
                dsa_ds_unapply(dst, ds);
        }
 
-       if (dst->cpu_switch)
+       if (dst->cpu_switch) {
                dsa_cpu_port_ethtool_restore(dst->cpu_switch);
+               dst->cpu_switch = NULL;
+       }
 
        pr_info("DSA: tree %d unapplied\n", dst->tree);
        dst->applied = false;
index ad345c8b0b0693cc214b212ccbb402859d910134..7281098df04ecd597b7824a9c0d2ec1d7f60e2b9 100644 (file)
@@ -289,53 +289,6 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
        dsa_switch_unregister_notifier(ds);
 }
 
-#ifdef CONFIG_PM_SLEEP
-int dsa_switch_suspend(struct dsa_switch *ds)
-{
-       int i, ret = 0;
-
-       /* Suspend slave network devices */
-       for (i = 0; i < ds->num_ports; i++) {
-               if (!dsa_is_port_initialized(ds, i))
-                       continue;
-
-               ret = dsa_slave_suspend(ds->ports[i].netdev);
-               if (ret)
-                       return ret;
-       }
-
-       if (ds->ops->suspend)
-               ret = ds->ops->suspend(ds);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(dsa_switch_suspend);
-
-int dsa_switch_resume(struct dsa_switch *ds)
-{
-       int i, ret = 0;
-
-       if (ds->ops->resume)
-               ret = ds->ops->resume(ds);
-
-       if (ret)
-               return ret;
-
-       /* Resume slave network devices */
-       for (i = 0; i < ds->num_ports; i++) {
-               if (!dsa_is_port_initialized(ds, i))
-                       continue;
-
-               ret = dsa_slave_resume(ds->ports[i].netdev);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(dsa_switch_resume);
-#endif
-
 /* platform driver init and cleanup *****************************************/
 static int dev_is_class(struct device *dev, void *class)
 {
index c73160fb11e7c666f8ac8ed4103b7312ff769a58..0a0a392dc2bd64b8c4202cc1361d828f9f984dd1 100644 (file)
@@ -378,7 +378,6 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
        del_timer_sync(&hsr->announce_timer);
 
        synchronize_rcu();
-       free_netdev(hsr_dev);
 }
 
 static const struct net_device_ops hsr_device_ops = {
@@ -404,7 +403,8 @@ void hsr_dev_setup(struct net_device *dev)
        SET_NETDEV_DEVTYPE(dev, &hsr_type);
        dev->priv_flags |= IFF_NO_QUEUE;
 
-       dev->destructor = hsr_dev_destroy;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = hsr_dev_destroy;
 
        dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
                           NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
index 4ebe2aa3e7d3e944295e9d53890e3cb9b7a90139..04b5450c5a5572e875f7900a3676fd80259b9b4b 100644 (file)
@@ -324,8 +324,7 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame,
        unsigned long irqflags;
 
        frame->is_supervision = is_supervision_frame(port->hsr, skb);
-       frame->node_src = hsr_get_node(&port->hsr->node_db, skb,
-                                      frame->is_supervision);
+       frame->node_src = hsr_get_node(port, skb, frame->is_supervision);
        if (frame->node_src == NULL)
                return -1; /* Unknown node and !is_supervision, or no mem */
 
index 7ea925816f79d8a0e547a0feb1257fda23097ba4..284a9b820df8db51a0dbee9737db5a8127eeaad7 100644 (file)
@@ -158,9 +158,10 @@ struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
 
 /* Get the hsr_node from which 'skb' was sent.
  */
-struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb,
+struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
                              bool is_sup)
 {
+       struct list_head *node_db = &port->hsr->node_db;
        struct hsr_node *node;
        struct ethhdr *ethhdr;
        u16 seq_out;
@@ -186,7 +187,11 @@ struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb,
                 */
                seq_out = hsr_get_skb_sequence_nr(skb) - 1;
        } else {
-               WARN_ONCE(1, "%s: Non-HSR frame\n", __func__);
+               /* this is called also for frames from master port and
+                * so warn only for non master ports
+                */
+               if (port->type != HSR_PT_MASTER)
+                       WARN_ONCE(1, "%s: Non-HSR frame\n", __func__);
                seq_out = HSR_SEQNR_START;
        }
 
index 438b40f98f5a986e50180c351d55c9dbb0b66977..4e04f0e868e95044ac27f77ca11d004d928326cd 100644 (file)
@@ -18,7 +18,7 @@ struct hsr_node;
 
 struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
                              u16 seq_out);
-struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb,
+struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
                              bool is_sup);
 void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
                          struct hsr_port *port);
index d7efbf0dad20f8c4d3c42d039eff528c678bc04c..0a866f3322901e357091955bf24ac16fc5f6b94f 100644 (file)
@@ -107,7 +107,7 @@ static void lowpan_setup(struct net_device *ldev)
 
        ldev->netdev_ops        = &lowpan_netdev_ops;
        ldev->header_ops        = &lowpan_header_ops;
-       ldev->destructor        = free_netdev;
+       ldev->needs_free_netdev = true;
        ldev->features          |= NETIF_F_NETNS_LOCAL;
 }
 
index f3dad16613437c0c7ac3e9c7518a0929cddb3ca7..58925b6597de83e7d643fb9b1c7e992c9748ae1c 100644 (file)
@@ -1043,7 +1043,7 @@ static struct inet_protosw inetsw_array[] =
                .type =       SOCK_DGRAM,
                .protocol =   IPPROTO_ICMP,
                .prot =       &ping_prot,
-               .ops =        &inet_dgram_ops,
+               .ops =        &inet_sockraw_ops,
                .flags =      INET_PROTOSW_REUSE,
        },
 
index 0937b34c27cacb2dec73a67a76ff11fe26722500..e9f3386a528b4a792839d5e50894a68d3097eb42 100644 (file)
@@ -641,6 +641,32 @@ void arp_xmit(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(arp_xmit);
 
+static bool arp_is_garp(struct net *net, struct net_device *dev,
+                       int *addr_type, __be16 ar_op,
+                       __be32 sip, __be32 tip,
+                       unsigned char *sha, unsigned char *tha)
+{
+       bool is_garp = tip == sip;
+
+       /* Gratuitous ARP _replies_ also require target hwaddr to be
+        * the same as source.
+        */
+       if (is_garp && ar_op == htons(ARPOP_REPLY))
+               is_garp =
+                       /* IPv4 over IEEE 1394 doesn't provide target
+                        * hardware address field in its ARP payload.
+                        */
+                       tha &&
+                       !memcmp(tha, sha, dev->addr_len);
+
+       if (is_garp) {
+               *addr_type = inet_addr_type_dev_table(net, dev, sip);
+               if (*addr_type != RTN_UNICAST)
+                       is_garp = false;
+       }
+       return is_garp;
+}
+
 /*
  *     Process an arp request.
  */
@@ -653,6 +679,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
        unsigned char *arp_ptr;
        struct rtable *rt;
        unsigned char *sha;
+       unsigned char *tha = NULL;
        __be32 sip, tip;
        u16 dev_type = dev->type;
        int addr_type;
@@ -724,6 +751,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
                break;
 #endif
        default:
+               tha = arp_ptr;
                arp_ptr += dev->addr_len;
        }
        memcpy(&tip, arp_ptr, 4);
@@ -835,19 +863,25 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
 
        n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
 
-       if (IN_DEV_ARP_ACCEPT(in_dev)) {
-               unsigned int addr_type = inet_addr_type_dev_table(net, dev, sip);
+       addr_type = -1;
+       if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
+               is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
+                                     sip, tip, sha, tha);
+       }
 
+       if (IN_DEV_ARP_ACCEPT(in_dev)) {
                /* Unsolicited ARP is not accepted by default.
                   It is possible, that this option should be enabled for some
                   devices (strip is candidate)
                 */
-               is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip &&
-                         addr_type == RTN_UNICAST;
-
                if (!n &&
-                   ((arp->ar_op == htons(ARPOP_REPLY)  &&
-                               addr_type == RTN_UNICAST) || is_garp))
+                   (is_garp ||
+                    (arp->ar_op == htons(ARPOP_REPLY) &&
+                     (addr_type == RTN_UNICAST ||
+                      (addr_type < 0 &&
+                       /* postpone calculation to as late as possible */
+                       inet_addr_type_dev_table(net, dev, sip) ==
+                               RTN_UNICAST)))))
                        n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
        }
 
index 65cc02bd82bc87991a29135a58c059c7916a5a35..93322f895eab6136adbe22aa37a4eedc9687a0e4 100644 (file)
@@ -248,6 +248,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
        u8 *tail;
        u8 *vaddr;
        int nfrags;
+       int esph_offset;
        struct page *page;
        struct sk_buff *trailer;
        int tailen = esp->tailen;
@@ -313,11 +314,13 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
        }
 
 cow:
+       esph_offset = (unsigned char *)esp->esph - skb_transport_header(skb);
+
        nfrags = skb_cow_data(skb, tailen, &trailer);
        if (nfrags < 0)
                goto out;
        tail = skb_tail_pointer(trailer);
-       esp->esph = ip_esp_hdr(skb);
+       esp->esph = (struct ip_esp_hdr *)(skb_transport_header(skb) + esph_offset);
 
 skip_cow:
        esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
index 39bd1edee67649af86eb582c0ea478713360a506..83e3ed258467dbfd620bd27d48a0b33f5ef7a067 100644 (file)
@@ -763,7 +763,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned int e = 0, s_e;
        struct fib_table *tb;
        struct hlist_head *head;
-       int dumped = 0;
+       int dumped = 0, err;
 
        if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
            ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
@@ -783,20 +783,27 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
                        if (dumped)
                                memset(&cb->args[2], 0, sizeof(cb->args) -
                                                 2 * sizeof(cb->args[0]));
-                       if (fib_table_dump(tb, skb, cb) < 0)
-                               goto out;
+                       err = fib_table_dump(tb, skb, cb);
+                       if (err < 0) {
+                               if (likely(skb->len))
+                                       goto out;
+
+                               goto out_err;
+                       }
                        dumped = 1;
 next:
                        e++;
                }
        }
 out:
+       err = skb->len;
+out_err:
        rcu_read_unlock();
 
        cb->args[1] = e;
        cb->args[0] = h;
 
-       return skb->len;
+       return err;
 }
 
 /* Prepare and feed intra-kernel routing request.
index da449ddb8cc172bd9091c00057a69a095f98b56d..ad9ad4aab5da7c7d11c3b80edbdfcbdd3d7153fe 100644 (file)
@@ -203,6 +203,7 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp)
 static void free_fib_info_rcu(struct rcu_head *head)
 {
        struct fib_info *fi = container_of(head, struct fib_info, rcu);
+       struct dst_metrics *m;
 
        change_nexthops(fi) {
                if (nexthop_nh->nh_dev)
@@ -213,8 +214,9 @@ static void free_fib_info_rcu(struct rcu_head *head)
                rt_fibinfo_free(&nexthop_nh->nh_rth_input);
        } endfor_nexthops(fi);
 
-       if (fi->fib_metrics != (u32 *) dst_default_metrics)
-               kfree(fi->fib_metrics);
+       m = fi->fib_metrics;
+       if (m != &dst_default_metrics && atomic_dec_and_test(&m->refcnt))
+               kfree(m);
        kfree(fi);
 }
 
@@ -971,11 +973,11 @@ fib_convert_metrics(struct fib_info *fi, const struct fib_config *cfg)
                        val = 255;
                if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
                        return -EINVAL;
-               fi->fib_metrics[type - 1] = val;
+               fi->fib_metrics->metrics[type - 1] = val;
        }
 
        if (ecn_ca)
-               fi->fib_metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
+               fi->fib_metrics->metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
 
        return 0;
 }
@@ -1033,11 +1035,12 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
                goto failure;
        fib_info_cnt++;
        if (cfg->fc_mx) {
-               fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
+               fi->fib_metrics = kzalloc(sizeof(*fi->fib_metrics), GFP_KERNEL);
                if (!fi->fib_metrics)
                        goto failure;
+               atomic_set(&fi->fib_metrics->refcnt, 1);
        } else
-               fi->fib_metrics = (u32 *) dst_default_metrics;
+               fi->fib_metrics = (struct dst_metrics *)&dst_default_metrics;
 
        fi->fib_net = net;
        fi->fib_protocol = cfg->fc_protocol;
@@ -1238,7 +1241,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
        if (fi->fib_priority &&
            nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority))
                goto nla_put_failure;
-       if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
+       if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0)
                goto nla_put_failure;
 
        if (fi->fib_prefsrc &&
index 1201409ba1dcb18ee028003b065410b87bf4a602..51182ff2b4415238210e83208bf7f45b5fb55326 100644 (file)
@@ -1983,6 +1983,8 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
 
        /* rcu_read_lock is hold by caller */
        hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) {
+               int err;
+
                if (i < s_i) {
                        i++;
                        continue;
@@ -1993,17 +1995,14 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
                        continue;
                }
 
-               if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
-                                 cb->nlh->nlmsg_seq,
-                                 RTM_NEWROUTE,
-                                 tb->tb_id,
-                                 fa->fa_type,
-                                 xkey,
-                                 KEYLENGTH - fa->fa_slen,
-                                 fa->fa_tos,
-                                 fa->fa_info, NLM_F_MULTI) < 0) {
+               err = fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
+                                   cb->nlh->nlmsg_seq, RTM_NEWROUTE,
+                                   tb->tb_id, fa->fa_type,
+                                   xkey, KEYLENGTH - fa->fa_slen,
+                                   fa->fa_tos, fa->fa_info, NLM_F_MULTI);
+               if (err < 0) {
                        cb->args[4] = i;
-                       return -1;
+                       return err;
                }
                i++;
        }
@@ -2025,10 +2024,13 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
        t_key key = cb->args[3];
 
        while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
-               if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
+               int err;
+
+               err = fn_trie_dump_leaf(l, tb, skb, cb);
+               if (err < 0) {
                        cb->args[3] = key;
                        cb->args[2] = count;
-                       return -1;
+                       return err;
                }
 
                ++count;
index 43318b5f56474bc15253e74e156962dd2c8df01f..9144fa7df2ad51372ba1c1debf54a41460a8cbec 100644 (file)
@@ -657,8 +657,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
        /* Needed by both icmp_global_allow and icmp_xmit_lock */
        local_bh_disable();
 
-       /* Check global sysctl_icmp_msgs_per_sec ratelimit */
-       if (!icmpv4_global_allow(net, type, code))
+       /* Check global sysctl_icmp_msgs_per_sec ratelimit, unless
+        * incoming dev is loopback.  If outgoing dev change to not be
+        * loopback, then peer ratelimit still work (in icmpv4_xrlim_allow)
+        */
+       if (!(skb_in->dev && (skb_in->dev->flags&IFF_LOOPBACK)) &&
+             !icmpv4_global_allow(net, type, code))
                goto out_bh_enable;
 
        sk = icmp_xmit_lock(net);
index 44fd86de2823dd17de16276a8ec01b190e69b8b4..ec9a396fa4660272f96602e78c5c3b0603068d66 100644 (file)
@@ -1112,6 +1112,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
        pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
        if (!pmc)
                return;
+       spin_lock_init(&pmc->lock);
        spin_lock_bh(&im->lock);
        pmc->interface = im->interface;
        in_dev_hold(in_dev);
@@ -2071,21 +2072,26 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
 
 static void ip_mc_clear_src(struct ip_mc_list *pmc)
 {
-       struct ip_sf_list *psf, *nextpsf;
+       struct ip_sf_list *psf, *nextpsf, *tomb, *sources;
 
-       for (psf = pmc->tomb; psf; psf = nextpsf) {
+       spin_lock_bh(&pmc->lock);
+       tomb = pmc->tomb;
+       pmc->tomb = NULL;
+       sources = pmc->sources;
+       pmc->sources = NULL;
+       pmc->sfmode = MCAST_EXCLUDE;
+       pmc->sfcount[MCAST_INCLUDE] = 0;
+       pmc->sfcount[MCAST_EXCLUDE] = 1;
+       spin_unlock_bh(&pmc->lock);
+
+       for (psf = tomb; psf; psf = nextpsf) {
                nextpsf = psf->sf_next;
                kfree(psf);
        }
-       pmc->tomb = NULL;
-       for (psf = pmc->sources; psf; psf = nextpsf) {
+       for (psf = sources; psf; psf = nextpsf) {
                nextpsf = psf->sf_next;
                kfree(psf);
        }
-       pmc->sources = NULL;
-       pmc->sfmode = MCAST_EXCLUDE;
-       pmc->sfcount[MCAST_INCLUDE] = 0;
-       pmc->sfcount[MCAST_EXCLUDE] = 1;
 }
 
 /* Join a multicast group
index 7a3fd25e8913a99d0fcbb256bc9001f6f1d4dd6f..532b36e9ce2a196805411cc2d1d2c26a2d83acfb 100644 (file)
@@ -964,7 +964,8 @@ static int __ip_append_data(struct sock *sk,
                csummode = CHECKSUM_PARTIAL;
 
        cork->length += length;
-       if ((((length + fragheaderlen) > mtu) || (skb && skb_is_gso(skb))) &&
+       if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) ||
+            (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
            (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
index b878ecbc0608fb433ae858b70e6e0101aa20fc4e..129d1a3616f838c9b487cf2392d1d9eb09dcfa5a 100644 (file)
@@ -446,6 +446,8 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
        return 0;
 
 drop:
+       if (tun_dst)
+               dst_release((struct dst_entry *)tun_dst);
        kfree_skb(skb);
        return 0;
 }
@@ -967,7 +969,6 @@ static void ip_tunnel_dev_free(struct net_device *dev)
        gro_cells_destroy(&tunnel->gro_cells);
        dst_cache_destroy(&tunnel->dst_cache);
        free_percpu(dev->tstats);
-       free_netdev(dev);
 }
 
 void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
@@ -1155,7 +1156,8 @@ int ip_tunnel_init(struct net_device *dev)
        struct iphdr *iph = &tunnel->parms.iph;
        int err;
 
-       dev->destructor = ip_tunnel_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ip_tunnel_dev_free;
        dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
index 3a02d52ed50ec54ce3f9f3eb07dc9f4133535a80..8ae425cad81858b3a79719d47b43f8baa346a06a 100644 (file)
@@ -101,8 +101,8 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id);
 static void ipmr_free_table(struct mr_table *mrt);
 
 static void ip_mr_forward(struct net *net, struct mr_table *mrt,
-                         struct sk_buff *skb, struct mfc_cache *cache,
-                         int local);
+                         struct net_device *dev, struct sk_buff *skb,
+                         struct mfc_cache *cache, int local);
 static int ipmr_cache_report(struct mr_table *mrt,
                             struct sk_buff *pkt, vifi_t vifi, int assert);
 static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
@@ -501,7 +501,7 @@ static void reg_vif_setup(struct net_device *dev)
        dev->mtu                = ETH_DATA_LEN - sizeof(struct iphdr) - 8;
        dev->flags              = IFF_NOARP;
        dev->netdev_ops         = &reg_vif_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->features           |= NETIF_F_NETNS_LOCAL;
 }
 
@@ -988,7 +988,7 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
 
                        rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
                } else {
-                       ip_mr_forward(net, mrt, skb, c, 0);
+                       ip_mr_forward(net, mrt, skb->dev, skb, c, 0);
                }
        }
 }
@@ -1073,7 +1073,7 @@ static int ipmr_cache_report(struct mr_table *mrt,
 
 /* Queue a packet for resolution. It gets locked cache entry! */
 static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi,
-                                struct sk_buff *skb)
+                                struct sk_buff *skb, struct net_device *dev)
 {
        const struct iphdr *iph = ip_hdr(skb);
        struct mfc_cache *c;
@@ -1130,6 +1130,10 @@ static int ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi,
                kfree_skb(skb);
                err = -ENOBUFS;
        } else {
+               if (dev) {
+                       skb->dev = dev;
+                       skb->skb_iif = dev->ifindex;
+               }
                skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
                err = 0;
        }
@@ -1828,10 +1832,10 @@ static int ipmr_find_vif(struct mr_table *mrt, struct net_device *dev)
 
 /* "local" means that we should preserve one skb (for local delivery) */
 static void ip_mr_forward(struct net *net, struct mr_table *mrt,
-                         struct sk_buff *skb, struct mfc_cache *cache,
-                         int local)
+                         struct net_device *dev, struct sk_buff *skb,
+                         struct mfc_cache *cache, int local)
 {
-       int true_vifi = ipmr_find_vif(mrt, skb->dev);
+       int true_vifi = ipmr_find_vif(mrt, dev);
        int psend = -1;
        int vif, ct;
 
@@ -1853,13 +1857,7 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
        }
 
        /* Wrong interface: drop packet and (maybe) send PIM assert. */
-       if (mrt->vif_table[vif].dev != skb->dev) {
-               struct net_device *mdev;
-
-               mdev = l3mdev_master_dev_rcu(mrt->vif_table[vif].dev);
-               if (mdev == skb->dev)
-                       goto forward;
-
+       if (mrt->vif_table[vif].dev != dev) {
                if (rt_is_output_route(skb_rtable(skb))) {
                        /* It is our own packet, looped back.
                         * Very complicated situation...
@@ -1980,6 +1978,20 @@ int ip_mr_input(struct sk_buff *skb)
        struct net *net = dev_net(skb->dev);
        int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL;
        struct mr_table *mrt;
+       struct net_device *dev;
+
+       /* skb->dev passed in is the loX master dev for vrfs.
+        * As there are no vifs associated with loopback devices,
+        * get the proper interface that does have a vif associated with it.
+        */
+       dev = skb->dev;
+       if (netif_is_l3_master(skb->dev)) {
+               dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
+               if (!dev) {
+                       kfree_skb(skb);
+                       return -ENODEV;
+               }
+       }
 
        /* Packet is looped back after forward, it should not be
         * forwarded second time, but still can be delivered locally.
@@ -2017,7 +2029,7 @@ int ip_mr_input(struct sk_buff *skb)
        /* already under rcu_read_lock() */
        cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
        if (!cache) {
-               int vif = ipmr_find_vif(mrt, skb->dev);
+               int vif = ipmr_find_vif(mrt, dev);
 
                if (vif >= 0)
                        cache = ipmr_cache_find_any(mrt, ip_hdr(skb)->daddr,
@@ -2037,9 +2049,9 @@ int ip_mr_input(struct sk_buff *skb)
                }
 
                read_lock(&mrt_lock);
-               vif = ipmr_find_vif(mrt, skb->dev);
+               vif = ipmr_find_vif(mrt, dev);
                if (vif >= 0) {
-                       int err2 = ipmr_cache_unresolved(mrt, vif, skb);
+                       int err2 = ipmr_cache_unresolved(mrt, vif, skb, dev);
                        read_unlock(&mrt_lock);
 
                        return err2;
@@ -2050,7 +2062,7 @@ int ip_mr_input(struct sk_buff *skb)
        }
 
        read_lock(&mrt_lock);
-       ip_mr_forward(net, mrt, skb, cache, local);
+       ip_mr_forward(net, mrt, dev, skb, cache, local);
        read_unlock(&mrt_lock);
 
        if (local)
@@ -2224,7 +2236,7 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
                iph->saddr = saddr;
                iph->daddr = daddr;
                iph->version = 0;
-               err = ipmr_cache_unresolved(mrt, vif, skb2);
+               err = ipmr_cache_unresolved(mrt, vif, skb2, dev);
                read_unlock(&mrt_lock);
                rcu_read_unlock();
                return err;
index 655d9eebe43e16a59102edcd3ea4bc177c6b341d..6883b3d4ba8f69de2cb924612d60f5671a219a84 100644 (file)
@@ -1385,8 +1385,12 @@ static void rt_add_uncached_list(struct rtable *rt)
 
 static void ipv4_dst_destroy(struct dst_entry *dst)
 {
+       struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst);
        struct rtable *rt = (struct rtable *) dst;
 
+       if (p != &dst_default_metrics && atomic_dec_and_test(&p->refcnt))
+               kfree(p);
+
        if (!list_empty(&rt->rt_uncached)) {
                struct uncached_list *ul = rt->rt_uncached_list;
 
@@ -1438,7 +1442,11 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
                        rt->rt_gateway = nh->nh_gw;
                        rt->rt_uses_gateway = 1;
                }
-               dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+               dst_init_metrics(&rt->dst, fi->fib_metrics->metrics, true);
+               if (fi->fib_metrics != &dst_default_metrics) {
+                       rt->dst._metrics |= DST_METRICS_REFCOUNTED;
+                       atomic_inc(&fi->fib_metrics->refcnt);
+               }
 #ifdef CONFIG_IP_ROUTE_CLASSID
                rt->dst.tclassid = nh->nh_tclassid;
 #endif
index 1e4c76d2b8278ba71d6cc2cf7ebfe483e241f76e..40aca7803cf2db25361dc7ef5c83ee6ea955c335 100644 (file)
@@ -1084,9 +1084,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct inet_sock *inet = inet_sk(sk);
+       struct sockaddr *uaddr = msg->msg_name;
        int err, flags;
 
-       if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE))
+       if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) ||
+           (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) &&
+            uaddr->sa_family == AF_UNSPEC))
                return -EOPNOTSUPP;
        if (tp->fastopen_req)
                return -EALREADY; /* Another Fast Open is in progress */
@@ -1108,7 +1111,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
                }
        }
        flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
-       err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
+       err = __inet_stream_connect(sk->sk_socket, uaddr,
                                    msg->msg_namelen, flags, 1);
        /* fastopen_req could already be freed in __inet_stream_connect
         * if the connection times out or gets rst
@@ -2320,9 +2323,15 @@ int tcp_disconnect(struct sock *sk, int flags)
        tcp_set_ca_state(sk, TCP_CA_Open);
        tcp_clear_retrans(tp);
        inet_csk_delack_init(sk);
+       /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0
+        * issue in __tcp_select_window()
+        */
+       icsk->icsk_ack.rcv_mss = TCP_MIN_MSS;
        tcp_init_send_head(sk);
        memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
        __sk_dst_reset(sk);
+       dst_release(sk->sk_rx_dst);
+       sk->sk_rx_dst = NULL;
        tcp_saved_syn_free(tp);
 
        /* Clean up fastopen related fields */
@@ -2374,9 +2383,10 @@ static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int l
        return 0;
 }
 
-static int tcp_repair_options_est(struct tcp_sock *tp,
+static int tcp_repair_options_est(struct sock *sk,
                struct tcp_repair_opt __user *optbuf, unsigned int len)
 {
+       struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_repair_opt opt;
 
        while (len >= sizeof(opt)) {
@@ -2389,6 +2399,7 @@ static int tcp_repair_options_est(struct tcp_sock *tp,
                switch (opt.opt_code) {
                case TCPOPT_MSS:
                        tp->rx_opt.mss_clamp = opt.opt_val;
+                       tcp_mtup_init(sk);
                        break;
                case TCPOPT_WINDOW:
                        {
@@ -2548,7 +2559,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
                if (!tp->repair)
                        err = -EINVAL;
                else if (sk->sk_state == TCP_ESTABLISHED)
-                       err = tcp_repair_options_est(tp,
+                       err = tcp_repair_options_est(sk,
                                        (struct tcp_repair_opt __user *)optval,
                                        optlen);
                else
index 6e3c512054a60715e8e2d16ffedd12cba6a3d2d9..324c9bcc5456b499b59cef40838b4e9829119e13 100644 (file)
@@ -180,6 +180,7 @@ void tcp_init_congestion_control(struct sock *sk)
 {
        const struct inet_connection_sock *icsk = inet_csk(sk);
 
+       tcp_sk(sk)->prior_ssthresh = 0;
        if (icsk->icsk_ca_ops->init)
                icsk->icsk_ca_ops->init(sk);
        if (tcp_ca_needs_ecn(sk))
index 5a3ad09e2786fb41ad12681d09938c645b69866d..174d4376baa5374c11caecc0e0452fa938d63561 100644 (file)
@@ -1179,13 +1179,14 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
                 */
                if (pkt_len > mss) {
                        unsigned int new_len = (pkt_len / mss) * mss;
-                       if (!in_sack && new_len < pkt_len) {
+                       if (!in_sack && new_len < pkt_len)
                                new_len += mss;
-                               if (new_len >= skb->len)
-                                       return 0;
-                       }
                        pkt_len = new_len;
                }
+
+               if (pkt_len >= skb->len && !in_sack)
+                       return 0;
+
                err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC);
                if (err < 0)
                        return err;
@@ -3189,7 +3190,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                        int delta;
 
                        /* Non-retransmitted hole got filled? That's reordering */
-                       if (reord < prior_fackets)
+                       if (reord < prior_fackets && reord <= tp->fackets_out)
                                tcp_update_reordering(sk, tp->fackets_out - reord, 0);
 
                        delta = tcp_is_fack(tp) ? pkts_acked :
index ea6e4cff9fafe99af23fd8ea666cd979d5af9104..1d6219bf2d6b48abaa73ad7f178049d95124cc90 100644 (file)
@@ -1612,7 +1612,7 @@ static void udp_v4_rehash(struct sock *sk)
        udp_lib_rehash(sk, new_hash);
 }
 
-int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
 
@@ -1657,7 +1657,7 @@ EXPORT_SYMBOL(udp_encap_enable);
  * Note that in the success and error cases, the skb is assumed to
  * have either been requeued or freed.
  */
-int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
        int is_udplite = IS_UDPLITE(sk);
index feb50a16398dfa856fd928fe823b4f6556d2caa1..a8cf8c6fb60ccf532fda1b109f902ead378acf22 100644 (file)
@@ -25,7 +25,6 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
                int flags, int *addr_len);
 int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
                 int flags);
-int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 void udp_destroy_sock(struct sock *sk);
 
 #ifdef CONFIG_PROC_FS
index 8d297a79b5680761b290aaa1bc947d05bcb60f3b..1d2dbace42ffadda98d6b324170101bd31d7c9a7 100644 (file)
@@ -332,9 +332,9 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev,
 static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
                                   unsigned long delay)
 {
-       if (!delayed_work_pending(&ifp->dad_work))
-               in6_ifa_hold(ifp);
-       mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
+       in6_ifa_hold(ifp);
+       if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay))
+               in6_ifa_put(ifp);
 }
 
 static int snmp6_alloc_dev(struct inet6_dev *idev)
@@ -1022,7 +1022,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        INIT_HLIST_NODE(&ifa->addr_lst);
        ifa->scope = scope;
        ifa->prefix_len = pfxlen;
-       ifa->flags = flags | IFA_F_TENTATIVE;
+       ifa->flags = flags;
+       /* No need to add the TENTATIVE flag for addresses with NODAD */
+       if (!(flags & IFA_F_NODAD))
+               ifa->flags |= IFA_F_TENTATIVE;
        ifa->valid_lft = valid_lft;
        ifa->prefered_lft = prefered_lft;
        ifa->cstamp = ifa->tstamp = jiffies;
@@ -3366,6 +3369,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct netdev_notifier_changeupper_info *info;
        struct inet6_dev *idev = __in6_dev_get(dev);
+       struct net *net = dev_net(dev);
        int run_pending = 0;
        int err;
 
@@ -3381,7 +3385,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
        case NETDEV_CHANGEMTU:
                /* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
                if (dev->mtu < IPV6_MIN_MTU) {
-                       addrconf_ifdown(dev, 1);
+                       addrconf_ifdown(dev, dev != net->loopback_dev);
                        break;
                }
 
@@ -3497,7 +3501,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                         * IPV6_MIN_MTU stop IPv6 on this interface.
                         */
                        if (dev->mtu < IPV6_MIN_MTU)
-                               addrconf_ifdown(dev, 1);
+                               addrconf_ifdown(dev, dev != net->loopback_dev);
                }
                break;
 
index 37ac9de713c69af30ae50d03e53ee472a7520b98..8d772fea1ddecd427a66c18f34d50f969186f02a 100644 (file)
@@ -1319,7 +1319,7 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
        struct ipv6hdr *ip6_hdr;
        struct ipv6_opt_hdr *hop;
        unsigned char buf[CALIPSO_MAX_BUFFER];
-       int len_delta, new_end, pad;
+       int len_delta, new_end, pad, payload;
        unsigned int start, end;
 
        ip6_hdr = ipv6_hdr(skb);
@@ -1346,6 +1346,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
        if (ret_val < 0)
                return ret_val;
 
+       ip6_hdr = ipv6_hdr(skb); /* Reset as skb_cow() may have moved it */
+
        if (len_delta) {
                if (len_delta > 0)
                        skb_push(skb, len_delta);
@@ -1355,6 +1357,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb,
                        sizeof(*ip6_hdr) + start);
                skb_reset_network_header(skb);
                ip6_hdr = ipv6_hdr(skb);
+               payload = ntohs(ip6_hdr->payload_len);
+               ip6_hdr->payload_len = htons(payload + len_delta);
        }
 
        hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1);
index e011122ebd43c190aec3812099345ec852444284..5c786f5ab961c5230ce325eebd465dcc5da93904 100644 (file)
@@ -250,8 +250,14 @@ ipv4_connected:
         */
 
        err = ip6_datagram_dst_update(sk, true);
-       if (err)
+       if (err) {
+               /* Reset daddr and dport so that udp_v6_early_demux()
+                * fails to find this socket
+                */
+               memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr));
+               inet->inet_dport = 0;
                goto out;
+       }
 
        sk->sk_state = TCP_ESTABLISHED;
        sk_set_txhash(sk);
index d950d43ba255442cf3079546a46b95693029f10c..f02f131f6435a967de395b9a7069051c93a039d7 100644 (file)
 #include <net/ipv6.h>
 #include <linux/icmpv6.h>
 
+static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
+{
+       int off = sizeof(struct ipv6hdr);
+       struct ipv6_opt_hdr *exthdr;
+
+       if (likely(ipv6_hdr->nexthdr == NEXTHDR_ESP))
+               return offsetof(struct ipv6hdr, nexthdr);
+
+       while (off < nhlen) {
+               exthdr = (void *)ipv6_hdr + off;
+               if (exthdr->nexthdr == NEXTHDR_ESP)
+                       return off;
+
+               off += ipv6_optlen(exthdr);
+       }
+
+       return 0;
+}
+
 static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
@@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
        struct xfrm_state *x;
        __be32 seq;
        __be32 spi;
+       int nhoff;
        int err;
 
        skb_pull(skb, offset);
@@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
 
        xo->flags |= XFRM_GRO;
 
+       nhoff = esp6_nexthdr_esp_offset(ipv6_hdr(skb), offset);
+       if (!nhoff)
+               goto out;
+
+       IP6CB(skb)->nhoff = nhoff;
        XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
        XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
        XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
index eea23b57c6a5a000aec234cc9bf6f9411d98001f..ec849d88a66205742b1a58c4959c08eeffc3f6d7 100644 (file)
@@ -32,7 +32,6 @@ struct fib6_rule {
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
                                   int flags, pol_lookup_t lookup)
 {
-       struct rt6_info *rt;
        struct fib_lookup_arg arg = {
                .lookup_ptr = lookup,
                .flags = FIB_LOOKUP_NOREF,
@@ -44,21 +43,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
        fib_rules_lookup(net->ipv6.fib6_rules_ops,
                         flowi6_to_flowi(fl6), flags, &arg);
 
-       rt = arg.result;
+       if (arg.result)
+               return arg.result;
 
-       if (!rt) {
-               dst_hold(&net->ipv6.ip6_null_entry->dst);
-               return &net->ipv6.ip6_null_entry->dst;
-       }
-
-       if (rt->rt6i_flags & RTF_REJECT &&
-           rt->dst.error == -EAGAIN) {
-               ip6_rt_put(rt);
-               rt = net->ipv6.ip6_null_entry;
-               dst_hold(&rt->dst);
-       }
-
-       return &rt->dst;
+       dst_hold(&net->ipv6.ip6_null_entry->dst);
+       return &net->ipv6.ip6_null_entry->dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -121,7 +110,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
                        flp6->saddr = saddr;
                }
                err = rt->dst.error;
-               goto out;
+               if (err != -EAGAIN)
+                       goto out;
        }
 again:
        ip6_rt_put(rt);
index 230b5aac9f03eadb775eea9cb3d9b4cce571cc32..8d7b113958b1332be11545069fafa8072a64e6a2 100644 (file)
@@ -491,7 +491,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
        local_bh_disable();
 
        /* Check global sysctl_icmp_msgs_per_sec ratelimit */
-       if (!icmpv6_global_allow(type))
+       if (!(skb->dev->flags&IFF_LOOPBACK) && !icmpv6_global_allow(type))
                goto out_bh_enable;
 
        mip6_addr_swap(skb);
index 2fd5ca151dcfca6034b0b0b27a3fe9abc7899e75..77f7f8c7d93d67483f241616123380f9d8e6ba84 100644 (file)
@@ -62,6 +62,7 @@ static inline u32 ila_locator_hash(struct ila_locator loc)
 {
        u32 *v = (u32 *)loc.v32;
 
+       __ila_hash_secret_init();
        return jhash_2words(v[0], v[1], hashrnd);
 }
 
index d4bf2c68a545b44873e433930e4e999920de78c9..e6b78ba0e6360ea40be58f07ea1c6657efcca93e 100644 (file)
@@ -289,8 +289,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
        struct rt6_info *rt;
 
        rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
-       if (rt->rt6i_flags & RTF_REJECT &&
-           rt->dst.error == -EAGAIN) {
+       if (rt->dst.error == -EAGAIN) {
                ip6_rt_put(rt);
                rt = net->ipv6.ip6_null_entry;
                dst_hold(&rt->dst);
index 8d128ba79b66de52d4d60628fe8df6cc9bccbc3b..64eea3962733a323fbae25b3c7b6de658a8cfdea 100644 (file)
@@ -537,11 +537,10 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
 
        memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
 
-       dsfield = ipv4_get_dsfield(iph);
-
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-               fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
-                                         & IPV6_TCLASS_MASK;
+               dsfield = ipv4_get_dsfield(iph);
+       else
+               dsfield = ip6_tclass(t->parms.flowinfo);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
                fl6.flowi6_mark = skb->mark;
        else
@@ -598,9 +597,11 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
 
        memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
 
-       dsfield = ipv6_get_dsfield(ipv6h);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-               fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
+               dsfield = ipv6_get_dsfield(ipv6h);
+       else
+               dsfield = ip6_tclass(t->parms.flowinfo);
+
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
                fl6.flowlabel |= ip6_flowlabel(ipv6h);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
@@ -990,13 +991,13 @@ static void ip6gre_dev_free(struct net_device *dev)
 
        dst_cache_destroy(&t->dst_cache);
        free_percpu(dev->tstats);
-       free_netdev(dev);
 }
 
 static void ip6gre_tunnel_setup(struct net_device *dev)
 {
        dev->netdev_ops = &ip6gre_netdev_ops;
-       dev->destructor = ip6gre_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ip6gre_dev_free;
 
        dev->type = ARPHRD_IP6GRE;
 
@@ -1147,7 +1148,7 @@ static int __net_init ip6gre_init_net(struct net *net)
        return 0;
 
 err_reg_dev:
-       ip6gre_dev_free(ign->fb_tunnel_dev);
+       free_netdev(ign->fb_tunnel_dev);
 err_alloc_dev:
        return err;
 }
@@ -1299,7 +1300,8 @@ static void ip6gre_tap_setup(struct net_device *dev)
        ether_setup(dev);
 
        dev->netdev_ops = &ip6gre_tap_netdev_ops;
-       dev->destructor = ip6gre_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ip6gre_dev_free;
 
        dev->features |= NETIF_F_NETNS_LOCAL;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
index 93e58a5e18374bee41f5a17f0c5911e381acb142..cdb3728faca7746d91e2430f6024f060a82b24fd 100644 (file)
@@ -63,7 +63,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        const struct net_offload *ops;
        int proto;
        struct frag_hdr *fptr;
-       unsigned int unfrag_ip6hlen;
        unsigned int payload_len;
        u8 *prevhdr;
        int offset = 0;
@@ -116,8 +115,12 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
                skb->network_header = (u8 *)ipv6h - skb->head;
 
                if (udpfrag) {
-                       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
-                       fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
+                       int err = ip6_find_1stfragopt(skb, &prevhdr);
+                       if (err < 0) {
+                               kfree_skb_list(segs);
+                               return ERR_PTR(err);
+                       }
+                       fptr = (struct frag_hdr *)((u8 *)ipv6h + err);
                        fptr->frag_off = htons(offset);
                        if (skb->next)
                                fptr->frag_off |= htons(IP6_MF);
index 58f6288e9ba53e6964b74d71dde7615ead695c06..1699acb2fa2c835cb9fb18cee9148f2732878c5d 100644 (file)
@@ -597,7 +597,10 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
        int ptr, offset = 0, err = 0;
        u8 *prevhdr, nexthdr = 0;
 
-       hlen = ip6_find_1stfragopt(skb, &prevhdr);
+       err = ip6_find_1stfragopt(skb, &prevhdr);
+       if (err < 0)
+               goto fail;
+       hlen = err;
        nexthdr = *prevhdr;
 
        mtu = ip6_skb_dst_mtu(skb);
@@ -1387,7 +1390,7 @@ emsgsize:
         */
 
        cork->length += length;
-       if ((((length + fragheaderlen) > mtu) ||
+       if ((((length + (skb ? skb->len : headersize)) > mtu) ||
             (skb && skb_is_gso(skb))) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
@@ -1463,6 +1466,11 @@ alloc_new_skb:
                         */
                        alloclen += sizeof(struct frag_hdr);
 
+                       copy = datalen - transhdrlen - fraggap;
+                       if (copy < 0) {
+                               err = -EINVAL;
+                               goto error;
+                       }
                        if (transhdrlen) {
                                skb = sock_alloc_send_skb(sk,
                                                alloclen + hh_len,
@@ -1512,13 +1520,9 @@ alloc_new_skb:
                                data += fraggap;
                                pskb_trim_unique(skb_prev, maxfraglen);
                        }
-                       copy = datalen - transhdrlen - fraggap;
-
-                       if (copy < 0) {
-                               err = -EINVAL;
-                               kfree_skb(skb);
-                               goto error;
-                       } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
+                       if (copy > 0 &&
+                           getfrag(from, data + transhdrlen, offset,
+                                   copy, fraggap, skb) < 0) {
                                err = -EFAULT;
                                kfree_skb(skb);
                                goto error;
index 6eb2ae507500b30959134aa3ed35c53c7b79aad9..8c6c3c8e7eef26899ea22ff85997230c8fd17e7e 100644 (file)
@@ -254,7 +254,6 @@ static void ip6_dev_free(struct net_device *dev)
        gro_cells_destroy(&t->gro_cells);
        dst_cache_destroy(&t->dst_cache);
        free_percpu(dev->tstats);
-       free_netdev(dev);
 }
 
 static int ip6_tnl_create2(struct net_device *dev)
@@ -322,7 +321,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
        return t;
 
 failed_free:
-       ip6_dev_free(dev);
+       free_netdev(dev);
 failed:
        return ERR_PTR(err);
 }
@@ -859,6 +858,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
        return 0;
 
 drop:
+       if (tun_dst)
+               dst_release((struct dst_entry *)tun_dst);
        kfree_skb(skb);
        return 0;
 }
@@ -1095,6 +1096,9 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
 
        if (!dst) {
 route_lookup:
+               /* add dsfield to flowlabel for route lookup */
+               fl6->flowlabel = ip6_make_flowinfo(dsfield, fl6->flowlabel);
+
                dst = ip6_route_output(net, NULL, fl6);
 
                if (dst->error)
@@ -1196,7 +1200,7 @@ route_lookup:
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        ipv6h = ipv6_hdr(skb);
-       ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield),
+       ip6_flow_hdr(ipv6h, dsfield,
                     ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6));
        ipv6h->hop_limit = hop_limit;
        ipv6h->nexthdr = proto;
@@ -1231,8 +1235,6 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        if (tproto != IPPROTO_IPIP && tproto != 0)
                return -1;
 
-       dsfield = ipv4_get_dsfield(iph);
-
        if (t->parms.collect_md) {
                struct ip_tunnel_info *tun_info;
                const struct ip_tunnel_key *key;
@@ -1246,6 +1248,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
                fl6.flowi6_proto = IPPROTO_IPIP;
                fl6.daddr = key->u.ipv6.dst;
                fl6.flowlabel = key->label;
+               dsfield =  key->tos;
        } else {
                if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                        encap_limit = t->parms.encap_limit;
@@ -1254,8 +1257,9 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
                fl6.flowi6_proto = IPPROTO_IPIP;
 
                if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-                       fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
-                                        & IPV6_TCLASS_MASK;
+                       dsfield = ipv4_get_dsfield(iph);
+               else
+                       dsfield = ip6_tclass(t->parms.flowinfo);
                if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
                        fl6.flowi6_mark = skb->mark;
                else
@@ -1267,6 +1271,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
                return -1;
 
+       dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
+
        skb_set_inner_ipproto(skb, IPPROTO_IPIP);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1300,8 +1306,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
            ip6_tnl_addr_conflict(t, ipv6h))
                return -1;
 
-       dsfield = ipv6_get_dsfield(ipv6h);
-
        if (t->parms.collect_md) {
                struct ip_tunnel_info *tun_info;
                const struct ip_tunnel_key *key;
@@ -1315,6 +1319,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
                fl6.flowi6_proto = IPPROTO_IPV6;
                fl6.daddr = key->u.ipv6.dst;
                fl6.flowlabel = key->label;
+               dsfield = key->tos;
        } else {
                offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
                /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
@@ -1337,7 +1342,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
                fl6.flowi6_proto = IPPROTO_IPV6;
 
                if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
-                       fl6.flowlabel |= (*(__be32 *)ipv6h & IPV6_TCLASS_MASK);
+                       dsfield = ipv6_get_dsfield(ipv6h);
+               else
+                       dsfield = ip6_tclass(t->parms.flowinfo);
                if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
                        fl6.flowlabel |= ip6_flowlabel(ipv6h);
                if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
@@ -1351,6 +1358,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
                return -1;
 
+       dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
+
        skb_set_inner_ipproto(skb, IPPROTO_IPV6);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1769,7 +1778,8 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
 static void ip6_tnl_dev_setup(struct net_device *dev)
 {
        dev->netdev_ops = &ip6_tnl_netdev_ops;
-       dev->destructor = ip6_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ip6_dev_free;
 
        dev->type = ARPHRD_TUNNEL6;
        dev->flags |= IFF_NOARP;
@@ -2216,7 +2226,7 @@ static int __net_init ip6_tnl_init_net(struct net *net)
        return 0;
 
 err_register:
-       ip6_dev_free(ip6n->fb_tnl_dev);
+       free_netdev(ip6n->fb_tnl_dev);
 err_alloc_dev:
        return err;
 }
index d67ef56454b25a088768e88fcd1f878a8c498f12..837ea1eefe7f8cc85924a9604d58cd702af94667 100644 (file)
@@ -180,7 +180,6 @@ vti6_tnl_unlink(struct vti6_net *ip6n, struct ip6_tnl *t)
 static void vti6_dev_free(struct net_device *dev)
 {
        free_percpu(dev->tstats);
-       free_netdev(dev);
 }
 
 static int vti6_tnl_create2(struct net_device *dev)
@@ -235,7 +234,7 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p
        return t;
 
 failed_free:
-       vti6_dev_free(dev);
+       free_netdev(dev);
 failed:
        return NULL;
 }
@@ -842,7 +841,8 @@ static const struct net_device_ops vti6_netdev_ops = {
 static void vti6_dev_setup(struct net_device *dev)
 {
        dev->netdev_ops = &vti6_netdev_ops;
-       dev->destructor = vti6_dev_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = vti6_dev_free;
 
        dev->type = ARPHRD_TUNNEL6;
        dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr);
@@ -1100,7 +1100,7 @@ static int __net_init vti6_init_net(struct net *net)
        return 0;
 
 err_register:
-       vti6_dev_free(ip6n->fb_tnl_dev);
+       free_netdev(ip6n->fb_tnl_dev);
 err_alloc_dev:
        return err;
 }
index 374997d26488ea38db7ed42ff7e6a55ede249021..2ecb39b943b5002e63bfa5b045919fbfd9fd64f6 100644 (file)
@@ -733,7 +733,7 @@ static void reg_vif_setup(struct net_device *dev)
        dev->mtu                = 1500 - sizeof(struct ipv6hdr) - 8;
        dev->flags              = IFF_NOARP;
        dev->netdev_ops         = &reg_vif_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->features           |= NETIF_F_NETNS_LOCAL;
 }
 
index cd4252346a32d90e8e133bd985811b6241e4bcd7..e9065b8d3af852c6e9a7359667f68a5ad00bfe75 100644 (file)
@@ -79,14 +79,13 @@ EXPORT_SYMBOL(ipv6_select_ident);
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
        u16 offset = sizeof(struct ipv6hdr);
-       struct ipv6_opt_hdr *exthdr =
-                               (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
        unsigned int packet_len = skb_tail_pointer(skb) -
                skb_network_header(skb);
        int found_rhdr = 0;
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
 
-       while (offset + 1 <= packet_len) {
+       while (offset <= packet_len) {
+               struct ipv6_opt_hdr *exthdr;
 
                switch (**nexthdr) {
 
@@ -107,13 +106,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
                        return offset;
                }
 
-               offset += ipv6_optlen(exthdr);
-               *nexthdr = &exthdr->nexthdr;
+               if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
+                       return -EINVAL;
+
                exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
                                                 offset);
+               offset += ipv6_optlen(exthdr);
+               *nexthdr = &exthdr->nexthdr;
        }
 
-       return offset;
+       return -EINVAL;
 }
 EXPORT_SYMBOL(ip6_find_1stfragopt);
 
index 9b522fa90e6d8f4a87ebed7cf574a36ceea89c61..ac826dd338ff0825eaf0d2d74cee92d008e018bb 100644 (file)
@@ -192,7 +192,7 @@ static struct inet_protosw pingv6_protosw = {
        .type =      SOCK_DGRAM,
        .protocol =  IPPROTO_ICMPV6,
        .prot =      &pingv6_prot,
-       .ops =       &inet6_dgram_ops,
+       .ops =       &inet6_sockraw_ops,
        .flags =     INET_PROTOSW_REUSE,
 };
 
index cc8e3ae9ca736490c3f689297d190f930fdd2ac9..e88bcb8ff0fd73b8377f5e0d3c3d1fa524ef1da8 100644 (file)
@@ -219,7 +219,7 @@ static void snmp6_seq_show_item64(struct seq_file *seq, void __percpu *mib,
        u64 buff64[SNMP_MIB_MAX];
        int i;
 
-       memset(buff64, 0, sizeof(unsigned long) * SNMP_MIB_MAX);
+       memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX);
 
        snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff);
        for (i = 0; itemlist[i].name; i++)
index 1f992d9e261d8b75226659a4cead95f8dc04dc4f..60be012fe7085cc7a199e84333cef5ee95ed1f04 100644 (file)
@@ -1338,7 +1338,7 @@ void raw6_proc_exit(void)
 #endif /* CONFIG_PROC_FS */
 
 /* Same as inet6_dgram_ops, sans udp_poll.  */
-static const struct proto_ops inet6_sockraw_ops = {
+const struct proto_ops inet6_sockraw_ops = {
        .family            = PF_INET6,
        .owner             = THIS_MODULE,
        .release           = inet6_release,
index dc61b0b5e64edf7bd69ab905573e38415abf2346..322bd62e688bfb5d2a88766a9537af51db0a69e8 100644 (file)
@@ -2804,6 +2804,7 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg)
        if ((rt->dst.dev == dev || !dev) &&
            rt != adn->net->ipv6.ip6_null_entry &&
            (rt->rt6i_nsiblings == 0 ||
+            (dev && netdev_unregistering(dev)) ||
             !rt->rt6i_idev->cnf.ignore_routes_with_linkdown))
                return -1;
 
@@ -3721,7 +3722,11 @@ static int ip6_route_dev_notify(struct notifier_block *this,
                net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
                net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
 #endif
-        } else if (event == NETDEV_UNREGISTER) {
+        } else if (event == NETDEV_UNREGISTER &&
+                   dev->reg_state != NETREG_UNREGISTERED) {
+               /* NETDEV_UNREGISTER could be fired for multiple times by
+                * netdev_wait_allrefs(). Make sure we only call this once.
+                */
                in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
                in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
index 61e5902f068732b10f734c7937c7539d418820d7..f8ad15891cd75576765560bd76b45417b5836f57 100644 (file)
@@ -265,7 +265,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
        return nt;
 
 failed_free:
-       ipip6_dev_free(dev);
+       free_netdev(dev);
 failed:
        return NULL;
 }
@@ -305,7 +305,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
         * we try harder to allocate.
         */
        kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ?
-               kcalloc(cmax, sizeof(*kp), GFP_KERNEL) :
+               kcalloc(cmax, sizeof(*kp), GFP_KERNEL | __GFP_NOWARN) :
                NULL;
 
        rcu_read_lock();
@@ -1336,7 +1336,6 @@ static void ipip6_dev_free(struct net_device *dev)
 
        dst_cache_destroy(&tunnel->dst_cache);
        free_percpu(dev->tstats);
-       free_netdev(dev);
 }
 
 #define SIT_FEATURES (NETIF_F_SG          | \
@@ -1351,7 +1350,8 @@ static void ipip6_tunnel_setup(struct net_device *dev)
        int t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
        dev->netdev_ops         = &ipip6_netdev_ops;
-       dev->destructor         = ipip6_dev_free;
+       dev->needs_free_netdev  = true;
+       dev->priv_destructor    = ipip6_dev_free;
 
        dev->type               = ARPHRD_SIT;
        dev->hard_header_len    = LL_MAX_HEADER + t_hlen;
index 7a8237acd210bf58cdc98f085fcf7fed433c3f24..4f4310a36a0481e2bd068e39285011ff28377ea5 100644 (file)
@@ -1062,6 +1062,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
 #endif
 
+               newnp->ipv6_mc_list = NULL;
                newnp->ipv6_ac_list = NULL;
                newnp->ipv6_fl_list = NULL;
                newnp->pktoptions  = NULL;
@@ -1131,6 +1132,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
           First: no IPv4 options.
         */
        newinet->inet_opt = NULL;
+       newnp->ipv6_mc_list = NULL;
        newnp->ipv6_ac_list = NULL;
        newnp->ipv6_fl_list = NULL;
 
index 04862abfe4ec27d978adadd27735a9d19e3c4365..75703fda23e7703b0df9f379d48208c0bf202c69 100644 (file)
@@ -526,7 +526,7 @@ out:
        return;
 }
 
-int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
 
@@ -569,7 +569,7 @@ void udpv6_encap_enable(void)
 }
 EXPORT_SYMBOL(udpv6_encap_enable);
 
-int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
        int is_udplite = IS_UDPLITE(sk);
@@ -879,7 +879,8 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
        struct sock *sk;
 
        udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
-               if (INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif))
+               if (sk->sk_state == TCP_ESTABLISHED &&
+                   INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif))
                        return sk;
                /* Only check first socket in chain */
                break;
index e78bdc76dcc33ceda888fb323a530f774057edbb..f180b3d85e3147facb487720bb3d98722ae76a45 100644 (file)
@@ -26,7 +26,6 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
 int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
 int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
                  int flags, int *addr_len);
-int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 void udpv6_destroy_sock(struct sock *sk);
 
 #ifdef CONFIG_PROC_FS
index ac858c480f2f272f37275cddfd9ffe889a91af97..a2267f80febbb6f31459097f27bd89d51d0f2b11 100644 (file)
@@ -29,6 +29,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
        u8 frag_hdr_sz = sizeof(struct frag_hdr);
        __wsum csum;
        int tnl_hlen;
+       int err;
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -90,7 +91,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                /* Find the unfragmentable header and shift it left by frag_hdr_sz
                 * bytes to insert fragment header.
                 */
-               unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+               err = ip6_find_1stfragopt(skb, &prevhdr);
+               if (err < 0)
+                       return ERR_PTR(err);
+               unfrag_ip6hlen = err;
                nexthdr = *prevhdr;
                *prevhdr = NEXTHDR_FRAGMENT;
                unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
index 08a807b29298f5a2c14c30eaedcba87f3057431d..3ef5d913e7a3b5a7407bb926d5ff354ae778ccb8 100644 (file)
@@ -43,8 +43,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
                return 1;
 #endif
 
-       ipv6_hdr(skb)->payload_len = htons(skb->len);
        __skb_push(skb, skb->data - skb_network_header(skb));
+       ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 
        if (xo && (xo->flags & XFRM_GRO)) {
                skb_mac_header_rebuild(skb);
index 0e015906f9ca91e11d3e9e124c532c6a7cb04c5d..07d36573f50b9451e4c2bfee331ac2c023791a7a 100644 (file)
@@ -47,6 +47,8 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
        iph = ipv6_hdr(skb);
 
        hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+       if (hdr_len < 0)
+               return hdr_len;
        skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
        skb_set_network_header(skb, -x->props.header_len);
        skb->transport_header = skb->network_header + hdr_len;
index 7a92c0f3191250118ce3572ca91ee9116460bce8..9ad07a91708ef7a1008d469766ab39b9b882883f 100644 (file)
@@ -30,6 +30,8 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
        skb_set_inner_transport_header(skb, skb_transport_offset(skb));
 
        hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
+       if (hdr_len < 0)
+               return hdr_len;
        skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
        skb_set_network_header(skb, -x->props.header_len);
        skb->transport_header = skb->network_header + hdr_len;
index 74d09f91709e6121ed80b8f089283615a5ffce5e..3be852808a9d1f7a2767f482b334279a95e90642 100644 (file)
@@ -65,7 +65,7 @@ static void irlan_eth_setup(struct net_device *dev)
        ether_setup(dev);
 
        dev->netdev_ops         = &irlan_eth_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
        dev->min_mtu            = 0;
        dev->max_mtu            = ETH_MAX_MTU;
 
index c1950bb14735bc914b53c0476342f2679ad50b87..b1432b6680338cf60942f3dd5567a6c7a11a603f 100644 (file)
@@ -1157,6 +1157,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                        goto out;
        }
 
+       err = -ENOBUFS;
        key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
        if (sa->sadb_sa_auth) {
                int keysize = 0;
@@ -1168,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                if (key)
                        keysize = (key->sadb_key_bits + 7) / 8;
                x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
-               if (!x->aalg)
+               if (!x->aalg) {
+                       err = -ENOMEM;
                        goto out;
+               }
                strcpy(x->aalg->alg_name, a->name);
                x->aalg->alg_key_len = 0;
                if (key) {
@@ -1188,8 +1191,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                                goto out;
                        }
                        x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
-                       if (!x->calg)
+                       if (!x->calg) {
+                               err = -ENOMEM;
                                goto out;
+                       }
                        strcpy(x->calg->alg_name, a->name);
                        x->props.calgo = sa->sadb_sa_encrypt;
                } else {
@@ -1203,8 +1208,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                        if (key)
                                keysize = (key->sadb_key_bits + 7) / 8;
                        x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
-                       if (!x->ealg)
+                       if (!x->ealg) {
+                               err = -ENOMEM;
                                goto out;
+                       }
                        strcpy(x->ealg->alg_name, a->name);
                        x->ealg->alg_key_len = 0;
                        if (key) {
@@ -1249,8 +1256,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                struct xfrm_encap_tmpl *natt;
 
                x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
-               if (!x->encap)
+               if (!x->encap) {
+                       err = -ENOMEM;
                        goto out;
+               }
 
                natt = x->encap;
                n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
@@ -2755,6 +2764,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
        int err, err2;
 
        err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
+       if (!err)
+               xfrm_garbage_collect(net);
        err2 = unicast_flush_resp(sk, hdr);
        if (err || err2) {
                if (err == -ESRCH) /* empty table - old silent behavior */
@@ -3285,7 +3296,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
                p += pol->sadb_x_policy_len*8;
                sec_ctx = (struct sadb_x_sec_ctx *)p;
                if (len < pol->sadb_x_policy_len*8 +
-                   sec_ctx->sadb_x_sec_len) {
+                   sec_ctx->sadb_x_sec_len*8) {
                        *dir = -EINVAL;
                        goto out;
                }
index 8b21af7321b928b4dcc5d7af3a6667380e9a949a..4de2ec94b08cbf5aba016da754b799c46d5f378a 100644 (file)
@@ -114,12 +114,13 @@ static void l2tp_eth_get_stats64(struct net_device *dev,
 {
        struct l2tp_eth *priv = netdev_priv(dev);
 
-       stats->tx_bytes   = atomic_long_read(&priv->tx_bytes);
-       stats->tx_packets = atomic_long_read(&priv->tx_packets);
-       stats->tx_dropped = atomic_long_read(&priv->tx_dropped);
-       stats->rx_bytes   = atomic_long_read(&priv->rx_bytes);
-       stats->rx_packets = atomic_long_read(&priv->rx_packets);
-       stats->rx_errors  = atomic_long_read(&priv->rx_errors);
+       stats->tx_bytes   = (unsigned long) atomic_long_read(&priv->tx_bytes);
+       stats->tx_packets = (unsigned long) atomic_long_read(&priv->tx_packets);
+       stats->tx_dropped = (unsigned long) atomic_long_read(&priv->tx_dropped);
+       stats->rx_bytes   = (unsigned long) atomic_long_read(&priv->rx_bytes);
+       stats->rx_packets = (unsigned long) atomic_long_read(&priv->rx_packets);
+       stats->rx_errors  = (unsigned long) atomic_long_read(&priv->rx_errors);
+
 }
 
 static const struct net_device_ops l2tp_eth_netdev_ops = {
@@ -141,7 +142,7 @@ static void l2tp_eth_dev_setup(struct net_device *dev)
        dev->priv_flags         &= ~IFF_TX_SKB_SHARING;
        dev->features           |= NETIF_F_LLTX;
        dev->netdev_ops         = &l2tp_eth_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 }
 
 static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len)
index 8364fe5b59e4ca01ef8d05b1038dbe96fedf657b..c38d16f22d2a7ff265b8729d43b164312598fd9f 100644 (file)
@@ -311,6 +311,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
        int rc = -EINVAL;
 
        dprintk("%s: binding %02X\n", __func__, addr->sllc_sap);
+
+       lock_sock(sk);
        if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
                goto out;
        rc = -EAFNOSUPPORT;
@@ -382,6 +384,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
 out_put:
        llc_sap_put(sap);
 out:
+       release_sock(sk);
        return rc;
 }
 
index 60e2a62f7bef2fbb014f3a40403cf498a75d429c..cf2392b2ac717972e4354346fd086ec802370de3 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
- * Copyright(c) 2015 Intel Deutschland GmbH
+ * Copyright(c) 2015-2017 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -741,46 +741,43 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
        ieee80211_agg_start_txq(sta, tid, true);
 }
 
-void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
+void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
+                             struct tid_ampdu_tx *tid_tx)
 {
-       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct ieee80211_local *local = sdata->local;
-       struct sta_info *sta;
-       struct tid_ampdu_tx *tid_tx;
 
-       trace_api_start_tx_ba_cb(sdata, ra, tid);
+       if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
+               return;
+
+       if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
+               ieee80211_agg_tx_operational(local, sta, tid);
+}
+
+static struct tid_ampdu_tx *
+ieee80211_lookup_tid_tx(struct ieee80211_sub_if_data *sdata,
+                       const u8 *ra, u16 tid, struct sta_info **sta)
+{
+       struct tid_ampdu_tx *tid_tx;
 
        if (tid >= IEEE80211_NUM_TIDS) {
                ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
                       tid, IEEE80211_NUM_TIDS);
-               return;
+               return NULL;
        }
 
-       mutex_lock(&local->sta_mtx);
-       sta = sta_info_get_bss(sdata, ra);
-       if (!sta) {
-               mutex_unlock(&local->sta_mtx);
+       *sta = sta_info_get_bss(sdata, ra);
+       if (!*sta) {
                ht_dbg(sdata, "Could not find station: %pM\n", ra);
-               return;
+               return NULL;
        }
 
-       mutex_lock(&sta->ampdu_mlme.mtx);
-       tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+       tid_tx = rcu_dereference((*sta)->ampdu_mlme.tid_tx[tid]);
 
-       if (WARN_ON(!tid_tx)) {
+       if (WARN_ON(!tid_tx))
                ht_dbg(sdata, "addBA was not requested!\n");
-               goto unlock;
-       }
 
-       if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
-               goto unlock;
-
-       if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
-               ieee80211_agg_tx_operational(local, sta, tid);
-
- unlock:
-       mutex_unlock(&sta->ampdu_mlme.mtx);
-       mutex_unlock(&local->sta_mtx);
+       return tid_tx;
 }
 
 void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
@@ -788,19 +785,20 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_ra_tid *ra_tid;
-       struct sk_buff *skb = dev_alloc_skb(0);
+       struct sta_info *sta;
+       struct tid_ampdu_tx *tid_tx;
 
-       if (unlikely(!skb))
-               return;
+       trace_api_start_tx_ba_cb(sdata, ra, tid);
 
-       ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
-       memcpy(&ra_tid->ra, ra, ETH_ALEN);
-       ra_tid->tid = tid;
+       rcu_read_lock();
+       tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
+       if (!tid_tx)
+               goto out;
 
-       skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START;
-       skb_queue_tail(&sdata->skb_queue, skb);
-       ieee80211_queue_work(&local->hw, &sdata->work);
+       set_bit(HT_AGG_STATE_START_CB, &tid_tx->state);
+       ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
+ out:
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
 
@@ -860,37 +858,18 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
 }
 EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
 
-void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
+void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
+                            struct tid_ampdu_tx *tid_tx)
 {
-       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-       struct ieee80211_local *local = sdata->local;
-       struct sta_info *sta;
-       struct tid_ampdu_tx *tid_tx;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
        bool send_delba = false;
 
-       trace_api_stop_tx_ba_cb(sdata, ra, tid);
-
-       if (tid >= IEEE80211_NUM_TIDS) {
-               ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
-                      tid, IEEE80211_NUM_TIDS);
-               return;
-       }
-
-       ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", ra, tid);
-
-       mutex_lock(&local->sta_mtx);
-
-       sta = sta_info_get_bss(sdata, ra);
-       if (!sta) {
-               ht_dbg(sdata, "Could not find station: %pM\n", ra);
-               goto unlock;
-       }
+       ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
+              sta->sta.addr, tid);
 
-       mutex_lock(&sta->ampdu_mlme.mtx);
        spin_lock_bh(&sta->lock);
-       tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
 
-       if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+       if (!test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
                ht_dbg(sdata,
                       "unexpected callback to A-MPDU stop for %pM tid %d\n",
                       sta->sta.addr, tid);
@@ -906,12 +885,8 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
        spin_unlock_bh(&sta->lock);
 
        if (send_delba)
-               ieee80211_send_delba(sdata, ra, tid,
+               ieee80211_send_delba(sdata, sta->sta.addr, tid,
                        WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
-
-       mutex_unlock(&sta->ampdu_mlme.mtx);
- unlock:
-       mutex_unlock(&local->sta_mtx);
 }
 
 void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
@@ -919,19 +894,20 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_ra_tid *ra_tid;
-       struct sk_buff *skb = dev_alloc_skb(0);
+       struct sta_info *sta;
+       struct tid_ampdu_tx *tid_tx;
 
-       if (unlikely(!skb))
-               return;
+       trace_api_stop_tx_ba_cb(sdata, ra, tid);
 
-       ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
-       memcpy(&ra_tid->ra, ra, ETH_ALEN);
-       ra_tid->tid = tid;
+       rcu_read_lock();
+       tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
+       if (!tid_tx)
+               goto out;
 
-       skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP;
-       skb_queue_tail(&sdata->skb_queue, skb);
-       ieee80211_queue_work(&local->hw, &sdata->work);
+       set_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state);
+       ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
+ out:
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
 
index 6c2e6060cd549e3c4c39e78cc20ca9302472c4ac..4a388fe8c2d1363b300becd61664d333b128e845 100644 (file)
@@ -902,6 +902,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        default:
                return -EINVAL;
        }
+       sdata->u.ap.req_smps = sdata->smps_mode;
+
        sdata->needed_rx_chains = sdata->local->rx_chains;
 
        sdata->vif.bss_conf.beacon_int = params->beacon_interval;
index f4a52877356349abed96d0a77d6ae75f301181e4..6ca5442b1e03b18aa81764089bf74c002d337690 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
+ * Copyright 2017      Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -289,8 +290,6 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
 {
        int i;
 
-       cancel_work_sync(&sta->ampdu_mlme.work);
-
        for (i = 0; i <  IEEE80211_NUM_TIDS; i++) {
                __ieee80211_stop_tx_ba_session(sta, i, reason);
                __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
@@ -298,6 +297,9 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
                                               reason != AGG_STOP_DESTROY_STA &&
                                               reason != AGG_STOP_PEER_REQUEST);
        }
+
+       /* stopping might queue the work again - so cancel only afterwards */
+       cancel_work_sync(&sta->ampdu_mlme.work);
 }
 
 void ieee80211_ba_session_work(struct work_struct *work)
@@ -352,10 +354,16 @@ void ieee80211_ba_session_work(struct work_struct *work)
                spin_unlock_bh(&sta->lock);
 
                tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
-               if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
-                                                &tid_tx->state))
+               if (!tid_tx)
+                       continue;
+
+               if (test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state))
+                       ieee80211_start_tx_ba_cb(sta, tid, tid_tx);
+               if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state))
                        ___ieee80211_stop_tx_ba_session(sta, tid,
                                                        AGG_STOP_LOCAL_REQUEST);
+               if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
+                       ieee80211_stop_tx_ba_cb(sta, tid, tid_tx);
        }
        mutex_unlock(&sta->ampdu_mlme.mtx);
 }
index f8f6c148f5545feeb78c16ca6f33ebf5e02d0ab5..5e002f62c235fbae4c5154ef9eab65c0e5f842b8 100644 (file)
@@ -1036,8 +1036,6 @@ struct ieee80211_rx_agg {
 
 enum sdata_queue_type {
        IEEE80211_SDATA_QUEUE_TYPE_FRAME        = 0,
-       IEEE80211_SDATA_QUEUE_AGG_START         = 1,
-       IEEE80211_SDATA_QUEUE_AGG_STOP          = 2,
        IEEE80211_SDATA_QUEUE_RX_AGG_START      = 3,
        IEEE80211_SDATA_QUEUE_RX_AGG_STOP       = 4,
 };
@@ -1427,12 +1425,6 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
        return local->hw.wiphy->bands[band];
 }
 
-/* this struct represents 802.11n's RA/TID combination */
-struct ieee80211_ra_tid {
-       u8 ra[ETH_ALEN];
-       u16 tid;
-};
-
 /* this struct holds the value parsing from channel switch IE  */
 struct ieee80211_csa_ie {
        struct cfg80211_chan_def chandef;
@@ -1539,7 +1531,7 @@ ieee80211_have_rx_timestamp(struct ieee80211_rx_status *status)
                return true;
        /* can't handle non-legacy preamble yet */
        if (status->flag & RX_FLAG_MACTIME_PLCP_START &&
-           status->encoding != RX_ENC_LEGACY)
+           status->encoding == RX_ENC_LEGACY)
                return true;
        return false;
 }
@@ -1794,8 +1786,10 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                                   enum ieee80211_agg_stop_reason reason);
 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                                    enum ieee80211_agg_stop_reason reason);
-void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
-void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
+void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
+                             struct tid_ampdu_tx *tid_tx);
+void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
+                            struct tid_ampdu_tx *tid_tx);
 void ieee80211_ba_session_work(struct work_struct *work);
 void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid);
 void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
index 3bd5b81f5d81ec7d73686043c2683630e24ecde4..f5f50150ba1cd7f53689a4e5efac3235f04679cf 100644 (file)
@@ -1213,7 +1213,6 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
 static void ieee80211_if_free(struct net_device *dev)
 {
        free_percpu(dev->tstats);
-       free_netdev(dev);
 }
 
 static void ieee80211_if_setup(struct net_device *dev)
@@ -1221,7 +1220,8 @@ static void ieee80211_if_setup(struct net_device *dev)
        ether_setup(dev);
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->netdev_ops = &ieee80211_dataif_ops;
-       dev->destructor = ieee80211_if_free;
+       dev->needs_free_netdev = true;
+       dev->priv_destructor = ieee80211_if_free;
 }
 
 static void ieee80211_if_setup_no_queue(struct net_device *dev)
@@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work)
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        struct sta_info *sta;
-       struct ieee80211_ra_tid *ra_tid;
        struct ieee80211_rx_agg *rx_agg;
 
        if (!ieee80211_sdata_running(sdata))
@@ -1253,15 +1252,7 @@ static void ieee80211_iface_work(struct work_struct *work)
        while ((skb = skb_dequeue(&sdata->skb_queue))) {
                struct ieee80211_mgmt *mgmt = (void *)skb->data;
 
-               if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) {
-                       ra_tid = (void *)&skb->cb;
-                       ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra,
-                                                ra_tid->tid);
-               } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_STOP) {
-                       ra_tid = (void *)&skb->cb;
-                       ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra,
-                                               ra_tid->tid);
-               } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
+               if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
                        rx_agg = (void *)&skb->cb;
                        mutex_lock(&local->sta_mtx);
                        sta = sta_info_get_bss(sdata, rx_agg->addr);
@@ -1825,6 +1816,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                ret = dev_alloc_name(ndev, ndev->name);
                if (ret < 0) {
                        ieee80211_if_free(ndev);
+                       free_netdev(ndev);
                        return ret;
                }
 
@@ -1914,7 +1906,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
                ret = register_netdevice(ndev);
                if (ret) {
-                       ieee80211_if_free(ndev);
+                       free_netdev(ndev);
                        return ret;
                }
        }
index 0ea9712bd99ea698f40b068d5ee31a69133224a3..cc8e6ea1b27e95e36412d840cd394039f5df4d5d 100644 (file)
@@ -601,7 +601,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        struct ieee80211_supported_band *sband;
        struct ieee80211_chanctx_conf *chanctx_conf;
        struct ieee80211_channel *chan;
-       u32 rate_flags, rates = 0;
+       u32 rates = 0;
 
        sdata_assert_lock(sdata);
 
@@ -612,7 +612,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                return;
        }
        chan = chanctx_conf->def.chan;
-       rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
        rcu_read_unlock();
        sband = local->hw.wiphy->bands[chan->band];
        shift = ieee80211_vif_get_shift(&sdata->vif);
@@ -636,9 +635,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
                 */
                rates_len = 0;
                for (i = 0; i < sband->n_bitrates; i++) {
-                       if ((rate_flags & sband->bitrates[i].flags)
-                           != rate_flags)
-                               continue;
                        rates |= BIT(i);
                        rates_len++;
                }
@@ -2818,7 +2814,7 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
                                u32 *rates, u32 *basic_rates,
                                bool *have_higher_than_11mbit,
                                int *min_rate, int *min_rate_index,
-                               int shift, u32 rate_flags)
+                               int shift)
 {
        int i, j;
 
@@ -2846,8 +2842,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
                        int brate;
 
                        br = &sband->bitrates[j];
-                       if ((rate_flags & br->flags) != rate_flags)
-                               continue;
 
                        brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
                        if (brate == rate) {
@@ -4398,40 +4392,32 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
                        return -ENOMEM;
        }
 
-       if (new_sta || override) {
-               err = ieee80211_prep_channel(sdata, cbss);
-               if (err) {
-                       if (new_sta)
-                               sta_info_free(local, new_sta);
-                       return -EINVAL;
-               }
-       }
-
+       /*
+        * Set up the information for the new channel before setting the
+        * new channel. We can't - completely race-free - change the basic
+        * rates bitmap and the channel (sband) that it refers to, but if
+        * we set it up before we at least avoid calling into the driver's
+        * bss_info_changed() method with invalid information (since we do
+        * call that from changing the channel - only for IDLE and perhaps
+        * some others, but ...).
+        *
+        * So to avoid that, just set up all the new information before the
+        * channel, but tell the driver to apply it only afterwards, since
+        * it might need the new channel for that.
+        */
        if (new_sta) {
                u32 rates = 0, basic_rates = 0;
                bool have_higher_than_11mbit;
                int min_rate = INT_MAX, min_rate_index = -1;
-               struct ieee80211_chanctx_conf *chanctx_conf;
                const struct cfg80211_bss_ies *ies;
                int shift = ieee80211_vif_get_shift(&sdata->vif);
-               u32 rate_flags;
-
-               rcu_read_lock();
-               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-               if (WARN_ON(!chanctx_conf)) {
-                       rcu_read_unlock();
-                       sta_info_free(local, new_sta);
-                       return -EINVAL;
-               }
-               rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def);
-               rcu_read_unlock();
 
                ieee80211_get_rates(sband, bss->supp_rates,
                                    bss->supp_rates_len,
                                    &rates, &basic_rates,
                                    &have_higher_than_11mbit,
                                    &min_rate, &min_rate_index,
-                                   shift, rate_flags);
+                                   shift);
 
                /*
                 * This used to be a workaround for basic rates missing
@@ -4489,8 +4475,22 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
                        sdata->vif.bss_conf.sync_dtim_count = 0;
                }
                rcu_read_unlock();
+       }
 
-               /* tell driver about BSSID, basic rates and timing */
+       if (new_sta || override) {
+               err = ieee80211_prep_channel(sdata, cbss);
+               if (err) {
+                       if (new_sta)
+                               sta_info_free(local, new_sta);
+                       return -EINVAL;
+               }
+       }
+
+       if (new_sta) {
+               /*
+                * tell driver about BSSID, basic rates and timing
+                * this was set up above, before setting the channel
+                */
                ieee80211_bss_info_change_notify(sdata,
                        BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
                        BSS_CHANGED_BEACON_INT);
index 35f4c7d7a50089e3998ff9860e86f6d26e1da600..3674fe3d67dc74ba9042e91920f43376325c6b6a 100644 (file)
@@ -1613,12 +1613,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
         */
        if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
            !ieee80211_has_morefrags(hdr->frame_control) &&
+           !ieee80211_is_back_req(hdr->frame_control) &&
            !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
            (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
             rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
-           /* PM bit is only checked in frames where it isn't reserved,
+           /*
+            * PM bit is only checked in frames where it isn't reserved,
             * in AP mode it's reserved in non-bufferable management frames
             * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
+            * BAR frames should be ignored as specified in
+            * IEEE 802.11-2012 10.2.1.2.
             */
            (!ieee80211_is_mgmt(hdr->frame_control) ||
             ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
@@ -2492,7 +2496,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                if (is_multicast_ether_addr(hdr->addr1)) {
                        mpp_addr = hdr->addr3;
                        proxied_addr = mesh_hdr->eaddr1;
-               } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
+               } else if ((mesh_hdr->flags & MESH_FLAGS_AE) ==
+                           MESH_FLAGS_AE_A5_A6) {
                        /* has_a4 already checked in ieee80211_rx_mesh_check */
                        mpp_addr = hdr->addr4;
                        proxied_addr = mesh_hdr->eaddr2;
index 7cdf7a835bb01e8fade3b9d9bb6efaa19158f72b..403e3cc58b573dc511c8ba399ddefdc7e8e24ba0 100644 (file)
@@ -2155,7 +2155,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
                        struct ieee80211_sta_rx_stats *cpurxs;
 
                        cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
-                       sinfo->rx_packets += cpurxs->dropped;
+                       sinfo->rx_dropped_misc += cpurxs->dropped;
                }
        }
 
index 5609cacb20d5f31e02ba877f88a6f0290e18ce8b..ea0747d6a6da194fec9116dc14b58a543f1accf2 100644 (file)
@@ -116,6 +116,8 @@ enum ieee80211_sta_info_flags {
 #define HT_AGG_STATE_STOPPING          3
 #define HT_AGG_STATE_WANT_START                4
 #define HT_AGG_STATE_WANT_STOP         5
+#define HT_AGG_STATE_START_CB          6
+#define HT_AGG_STATE_STOP_CB           7
 
 enum ieee80211_agg_stop_reason {
        AGG_STOP_DECLINED,
index c1ef22df865fe77bf7cf0a42d560f54db98a3edd..cc19614ff4e60bed9a351b8f8aa73792103665a0 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/unaligned.h>
 #include <net/mac80211.h>
 #include <crypto/aes.h>
+#include <crypto/algapi.h>
 
 #include "ieee80211_i.h"
 #include "michael.h"
@@ -153,7 +154,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
        data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
        key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
        michael_mic(key, hdr, data, data_len, mic);
-       if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0)
+       if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN))
                goto mic_fail;
 
        /* remove Michael MIC from payload */
@@ -1048,7 +1049,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
                bip_aad(skb, aad);
                ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
                                   skb->data + 24, skb->len - 24, mic);
-               if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+               if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
                        key->u.aes_cmac.icverrors++;
                        return RX_DROP_UNUSABLE;
                }
@@ -1098,7 +1099,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
                bip_aad(skb, aad);
                ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
                                       skb->data + 24, skb->len - 24, mic);
-               if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+               if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
                        key->u.aes_cmac.icverrors++;
                        return RX_DROP_UNUSABLE;
                }
@@ -1202,7 +1203,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
                if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
                                       skb->data + 24, skb->len - 24,
                                       mic) < 0 ||
-                   memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
+                   crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
                        key->u.aes_gmac.icverrors++;
                        return RX_DROP_UNUSABLE;
                }
index 06019dba4b10e3e0d079ee617707ae5412269144..bd88a9b80773e20e5de1f5a66ae7a3471387135e 100644 (file)
@@ -526,8 +526,6 @@ static void mac802154_wpan_free(struct net_device *dev)
        struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
 
        mac802154_llsec_destroy(&sdata->sec);
-
-       free_netdev(dev);
 }
 
 static void ieee802154_if_setup(struct net_device *dev)
@@ -593,7 +591,8 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
                                        sdata->dev->dev_addr);
 
                sdata->dev->header_ops = &mac802154_header_ops;
-               sdata->dev->destructor = mac802154_wpan_free;
+               sdata->dev->needs_free_netdev = true;
+               sdata->dev->priv_destructor = mac802154_wpan_free;
                sdata->dev->netdev_ops = &mac802154_wpan_ops;
                sdata->dev->ml_priv = &mac802154_mlme_wpan;
                wpan_dev->promiscuous_mode = false;
@@ -608,7 +607,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
 
                break;
        case NL802154_IFTYPE_MONITOR:
-               sdata->dev->destructor = free_netdev;
+               sdata->dev->needs_free_netdev = true;
                sdata->dev->netdev_ops = &mac802154_monitor_ops;
                wpan_dev->promiscuous_mode = true;
                break;
index 257ec66009da2dd7010d063c0ad29dbb9a32564e..7b05fd1497ceddea47c2c7917f5ee58f6ff2d560 100644 (file)
@@ -1418,7 +1418,7 @@ static void mpls_ifup(struct net_device *dev, unsigned int flags)
                                continue;
                        alive++;
                        nh_flags &= ~flags;
-                       WRITE_ONCE(nh->nh_flags, flags);
+                       WRITE_ONCE(nh->nh_flags, nh_flags);
                } endfor_nexthops(rt);
 
                WRITE_ONCE(rt->rt_nhn_alive, alive);
index d2d7bdf1d5104b6e68284bbbb533c30f159844e2..ad99c1ceea6f42bf3e52500a4452f7f74e730be5 100644 (file)
@@ -849,10 +849,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
 {
        unsigned int verdict = NF_DROP;
 
-       if (IP_VS_FWD_METHOD(cp) != 0) {
-               pr_err("shouldn't reach here, because the box is on the "
-                      "half connection in the tun/dr module.\n");
-       }
+       if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+               goto ignore_cp;
 
        /* Ensure the checksum is correct */
        if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
@@ -886,6 +884,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
                ip_vs_notrack(skb);
        else
                ip_vs_update_conntrack(skb, cp, 0);
+
+ignore_cp:
        verdict = NF_ACCEPT;
 
 out:
@@ -1385,8 +1385,11 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
         */
        cp = pp->conn_out_get(ipvs, af, skb, &iph);
 
-       if (likely(cp))
+       if (likely(cp)) {
+               if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+                       goto ignore_cp;
                return handle_response(af, skb, pd, cp, &iph, hooknum);
+       }
 
        /* Check for real-server-started requests */
        if (atomic_read(&ipvs->conn_out_counter)) {
@@ -1444,9 +1447,15 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
                        }
                }
        }
+
+out:
        IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
                      "ip_vs_out: packet continues traversal as normal");
        return NF_ACCEPT;
+
+ignore_cp:
+       __ip_vs_conn_put(cp);
+       goto out;
 }
 
 /*
index 3a60efa7799b2e4569af35ce943c67fc354dc68a..7f6100ca63be6dd4f37c24852fd16b9a71b8a823 100644 (file)
@@ -174,6 +174,10 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
 #endif
        if (h != NULL && !try_module_get(h->me))
                h = NULL;
+       if (h != NULL && !refcount_inc_not_zero(&h->refcnt)) {
+               module_put(h->me);
+               h = NULL;
+       }
 
        rcu_read_unlock();
 
@@ -181,6 +185,13 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
 
+void nf_conntrack_helper_put(struct nf_conntrack_helper *helper)
+{
+       refcount_dec(&helper->refcnt);
+       module_put(helper->me);
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_helper_put);
+
 struct nf_conn_help *
 nf_ct_helper_ext_add(struct nf_conn *ct,
                     struct nf_conntrack_helper *helper, gfp_t gfp)
@@ -417,6 +428,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
                        }
                }
        }
+       refcount_set(&me->refcnt, 1);
        hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
        nf_ct_helper_count++;
 out:
index dcf561b5c97a47e627ee00649d756635db0e6fb3..a8be9b72e6cd2ca34166bba49a532f4f92e86e9e 100644 (file)
@@ -45,6 +45,8 @@
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <net/netfilter/nf_conntrack_timestamp.h>
 #include <net/netfilter/nf_conntrack_labels.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
+#include <net/netfilter/nf_conntrack_synproxy.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_l4proto.h>
@@ -888,8 +890,13 @@ restart:
        }
 out:
        local_bh_enable();
-       if (last)
+       if (last) {
+               /* nf ct hash resize happened, now clear the leftover. */
+               if ((struct nf_conn *)cb->args[1] == last)
+                       cb->args[1] = 0;
+
                nf_ct_put(last);
+       }
 
        while (i) {
                i--;
@@ -1007,9 +1014,8 @@ static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
 
 static int
 ctnetlink_parse_tuple(const struct nlattr * const cda[],
-                     struct nf_conntrack_tuple *tuple,
-                     enum ctattr_type type, u_int8_t l3num,
-                     struct nf_conntrack_zone *zone)
+                     struct nf_conntrack_tuple *tuple, u32 type,
+                     u_int8_t l3num, struct nf_conntrack_zone *zone)
 {
        struct nlattr *tb[CTA_TUPLE_MAX+1];
        int err;
@@ -1828,6 +1834,8 @@ ctnetlink_create_conntrack(struct net *net,
        nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
        nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
        nf_ct_labels_ext_add(ct);
+       nfct_seqadj_ext_add(ct);
+       nfct_synproxy_ext_add(ct);
 
        /* we must add conntrack extensions before confirmation. */
        ct->status |= IPS_CONFIRMED;
@@ -2447,7 +2455,7 @@ static struct nfnl_ct_hook ctnetlink_glue_hook = {
 
 static int ctnetlink_exp_dump_tuple(struct sk_buff *skb,
                                    const struct nf_conntrack_tuple *tuple,
-                                   enum ctattr_expect type)
+                                   u32 type)
 {
        struct nlattr *nest_parms;
 
index 13875d599a85713bbfeb2fee7b8978fa498a10ed..1c5b14a6cab369591bd13e22b284a0737ad75c2e 100644 (file)
@@ -512,16 +512,19 @@ static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb,
                      u8 pf, unsigned int hooknum)
 {
        const struct sctphdr *sh;
-       struct sctphdr _sctph;
        const char *logmsg;
 
-       sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
-       if (!sh) {
+       if (skb->len < dataoff + sizeof(struct sctphdr)) {
                logmsg = "nf_ct_sctp: short packet ";
                goto out_invalid;
        }
        if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
            skb->ip_summed == CHECKSUM_NONE) {
+               if (!skb_make_writable(skb, dataoff + sizeof(struct sctphdr))) {
+                       logmsg = "nf_ct_sctp: failed to read header ";
+                       goto out_invalid;
+               }
+               sh = (const struct sctphdr *)(skb->data + dataoff);
                if (sh->checksum != sctp_compute_cksum(skb, dataoff)) {
                        logmsg = "nf_ct_sctp: bad CRC ";
                        goto out_invalid;
index b48d6b5aae8a87d4ea69cae0e025739ebe3f1658..6c72922d20caee83f498cb02cdce0c46899a1c22 100644 (file)
@@ -409,6 +409,10 @@ nf_nat_setup_info(struct nf_conn *ct,
 {
        struct nf_conntrack_tuple curr_tuple, new_tuple;
 
+       /* Can't setup nat info for confirmed ct. */
+       if (nf_ct_is_confirmed(ct))
+               return NF_ACCEPT;
+
        NF_CT_ASSERT(maniptype == NF_NAT_MANIP_SRC ||
                     maniptype == NF_NAT_MANIP_DST);
        BUG_ON(nf_nat_initialized(ct, maniptype));
@@ -562,7 +566,7 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
         * Else, when the conntrack is destoyed, nf_nat_cleanup_conntrack()
         * will delete entry from already-freed table.
         */
-       ct->status &= ~IPS_NAT_DONE_MASK;
+       clear_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
        rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
                        nf_nat_bysource_params);
 
index 5592250297402fe6e272f3213efa7e02ab230485..da314be0c048720172bbd153cd2f730b486603ce 100644 (file)
@@ -3367,35 +3367,50 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
        return nf_tables_fill_setelem(args->skb, set, elem);
 }
 
+struct nft_set_dump_ctx {
+       const struct nft_set    *set;
+       struct nft_ctx          ctx;
+};
+
 static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       struct nft_set_dump_ctx *dump_ctx = cb->data;
        struct net *net = sock_net(skb->sk);
-       u8 genmask = nft_genmask_cur(net);
+       struct nft_af_info *afi;
+       struct nft_table *table;
        struct nft_set *set;
        struct nft_set_dump_args args;
-       struct nft_ctx ctx;
-       struct nlattr *nla[NFTA_SET_ELEM_LIST_MAX + 1];
+       bool set_found = false;
        struct nfgenmsg *nfmsg;
        struct nlmsghdr *nlh;
        struct nlattr *nest;
        u32 portid, seq;
-       int event, err;
+       int event;
 
-       err = nlmsg_parse(cb->nlh, sizeof(struct nfgenmsg), nla,
-                         NFTA_SET_ELEM_LIST_MAX, nft_set_elem_list_policy,
-                         NULL);
-       if (err < 0)
-               return err;
+       rcu_read_lock();
+       list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
+               if (afi != dump_ctx->ctx.afi)
+                       continue;
 
-       err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
-                                        (void *)nla, genmask);
-       if (err < 0)
-               return err;
+               list_for_each_entry_rcu(table, &afi->tables, list) {
+                       if (table != dump_ctx->ctx.table)
+                               continue;
 
-       set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
-                                  genmask);
-       if (IS_ERR(set))
-               return PTR_ERR(set);
+                       list_for_each_entry_rcu(set, &table->sets, list) {
+                               if (set == dump_ctx->set) {
+                                       set_found = true;
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               break;
+       }
+
+       if (!set_found) {
+               rcu_read_unlock();
+               return -ENOENT;
+       }
 
        event  = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWSETELEM);
        portid = NETLINK_CB(cb->skb).portid;
@@ -3407,11 +3422,11 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
                goto nla_put_failure;
 
        nfmsg = nlmsg_data(nlh);
-       nfmsg->nfgen_family = ctx.afi->family;
+       nfmsg->nfgen_family = afi->family;
        nfmsg->version      = NFNETLINK_V0;
-       nfmsg->res_id       = htons(ctx.net->nft.base_seq & 0xffff);
+       nfmsg->res_id       = htons(net->nft.base_seq & 0xffff);
 
-       if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, ctx.table->name))
+       if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, table->name))
                goto nla_put_failure;
        if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name))
                goto nla_put_failure;
@@ -3422,12 +3437,13 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 
        args.cb                 = cb;
        args.skb                = skb;
-       args.iter.genmask       = nft_genmask_cur(ctx.net);
+       args.iter.genmask       = nft_genmask_cur(net);
        args.iter.skip          = cb->args[0];
        args.iter.count         = 0;
        args.iter.err           = 0;
        args.iter.fn            = nf_tables_dump_setelem;
-       set->ops->walk(&ctx, set, &args.iter);
+       set->ops->walk(&dump_ctx->ctx, set, &args.iter);
+       rcu_read_unlock();
 
        nla_nest_end(skb, nest);
        nlmsg_end(skb, nlh);
@@ -3441,9 +3457,16 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 
 nla_put_failure:
+       rcu_read_unlock();
        return -ENOSPC;
 }
 
+static int nf_tables_dump_set_done(struct netlink_callback *cb)
+{
+       kfree(cb->data);
+       return 0;
+}
+
 static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
                                struct sk_buff *skb, const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
@@ -3465,7 +3488,18 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
        if (nlh->nlmsg_flags & NLM_F_DUMP) {
                struct netlink_dump_control c = {
                        .dump = nf_tables_dump_set,
+                       .done = nf_tables_dump_set_done,
                };
+               struct nft_set_dump_ctx *dump_ctx;
+
+               dump_ctx = kmalloc(sizeof(*dump_ctx), GFP_KERNEL);
+               if (!dump_ctx)
+                       return -ENOMEM;
+
+               dump_ctx->set = set;
+               dump_ctx->ctx = ctx;
+
+               c.data = dump_ctx;
                return netlink_dump_start(nlsk, skb, nlh, &c);
        }
        return -EOPNOTSUPP;
@@ -3593,9 +3627,9 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
 {
        struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
 
-       nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE);
+       nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
        if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
-               nft_data_uninit(nft_set_ext_data(ext), set->dtype);
+               nft_data_release(nft_set_ext_data(ext), set->dtype);
        if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
                nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
        if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
@@ -3604,6 +3638,18 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
 }
 EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
 
+/* Only called from commit path, nft_set_elem_deactivate() already deals with
+ * the refcounting from the preparation phase.
+ */
+static void nf_tables_set_elem_destroy(const struct nft_set *set, void *elem)
+{
+       struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
+
+       if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
+               nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
+       kfree(elem);
+}
+
 static int nft_setelem_parse_flags(const struct nft_set *set,
                                   const struct nlattr *attr, u32 *flags)
 {
@@ -3815,9 +3861,9 @@ err4:
        kfree(elem.priv);
 err3:
        if (nla[NFTA_SET_ELEM_DATA] != NULL)
-               nft_data_uninit(&data, d2.type);
+               nft_data_release(&data, d2.type);
 err2:
-       nft_data_uninit(&elem.key.val, d1.type);
+       nft_data_release(&elem.key.val, d1.type);
 err1:
        return err;
 }
@@ -3862,6 +3908,53 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
        return err;
 }
 
+/**
+ *     nft_data_hold - hold a nft_data item
+ *
+ *     @data: struct nft_data to release
+ *     @type: type of data
+ *
+ *     Hold a nft_data item. NFT_DATA_VALUE types can be silently discarded,
+ *     NFT_DATA_VERDICT bumps the reference to chains in case of NFT_JUMP and
+ *     NFT_GOTO verdicts. This function must be called on active data objects
+ *     from the second phase of the commit protocol.
+ */
+static void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
+{
+       if (type == NFT_DATA_VERDICT) {
+               switch (data->verdict.code) {
+               case NFT_JUMP:
+               case NFT_GOTO:
+                       data->verdict.chain->use++;
+                       break;
+               }
+       }
+}
+
+static void nft_set_elem_activate(const struct net *net,
+                                 const struct nft_set *set,
+                                 struct nft_set_elem *elem)
+{
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+
+       if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
+               nft_data_hold(nft_set_ext_data(ext), set->dtype);
+       if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
+               (*nft_set_ext_obj(ext))->use++;
+}
+
+static void nft_set_elem_deactivate(const struct net *net,
+                                   const struct nft_set *set,
+                                   struct nft_set_elem *elem)
+{
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+
+       if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
+               nft_data_release(nft_set_ext_data(ext), set->dtype);
+       if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
+               (*nft_set_ext_obj(ext))->use--;
+}
+
 static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
                           const struct nlattr *attr)
 {
@@ -3927,6 +4020,8 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
        kfree(elem.priv);
        elem.priv = priv;
 
+       nft_set_elem_deactivate(ctx->net, set, &elem);
+
        nft_trans_elem(trans) = elem;
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
        return 0;
@@ -3936,7 +4031,7 @@ err4:
 err3:
        kfree(elem.priv);
 err2:
-       nft_data_uninit(&elem.key.val, desc.type);
+       nft_data_release(&elem.key.val, desc.type);
 err1:
        return err;
 }
@@ -4743,8 +4838,8 @@ static void nf_tables_commit_release(struct nft_trans *trans)
                nft_set_destroy(nft_trans_set(trans));
                break;
        case NFT_MSG_DELSETELEM:
-               nft_set_elem_destroy(nft_trans_elem_set(trans),
-                                    nft_trans_elem(trans).priv, true);
+               nf_tables_set_elem_destroy(nft_trans_elem_set(trans),
+                                          nft_trans_elem(trans).priv);
                break;
        case NFT_MSG_DELOBJ:
                nft_obj_destroy(nft_trans_obj(trans));
@@ -4979,6 +5074,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
                case NFT_MSG_DELSETELEM:
                        te = (struct nft_trans_elem *)trans->data;
 
+                       nft_set_elem_activate(net, te->set, &te->elem);
                        te->set->ops->activate(net, te->set, &te->elem);
                        te->set->ndeact--;
 
@@ -5464,7 +5560,7 @@ int nft_data_init(const struct nft_ctx *ctx,
 EXPORT_SYMBOL_GPL(nft_data_init);
 
 /**
- *     nft_data_uninit - release a nft_data item
+ *     nft_data_release - release a nft_data item
  *
  *     @data: struct nft_data to release
  *     @type: type of data
@@ -5472,7 +5568,7 @@ EXPORT_SYMBOL_GPL(nft_data_init);
  *     Release a nft_data item. NFT_DATA_VALUE types can be silently discarded,
  *     all others need to be released by calling this function.
  */
-void nft_data_uninit(const struct nft_data *data, enum nft_data_types type)
+void nft_data_release(const struct nft_data *data, enum nft_data_types type)
 {
        if (type < NFT_DATA_VERDICT)
                return;
@@ -5483,7 +5579,7 @@ void nft_data_uninit(const struct nft_data *data, enum nft_data_types type)
                WARN_ON(1);
        }
 }
-EXPORT_SYMBOL_GPL(nft_data_uninit);
+EXPORT_SYMBOL_GPL(nft_data_release);
 
 int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
                  enum nft_data_types type, unsigned int len)
index 950bf6eadc6578516ac92b50427fe682cba3976d..be678a323598c3237a2cae09e4e3ed4bdea46614 100644 (file)
@@ -686,6 +686,7 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
                tuple_set = true;
        }
 
+       ret = -ENOENT;
        list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) {
                cur = &nlcth->helper;
                j++;
@@ -699,16 +700,20 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
                     tuple.dst.protonum != cur->tuple.dst.protonum))
                        continue;
 
-               found = true;
-               nf_conntrack_helper_unregister(cur);
-               kfree(cur->expect_policy);
+               if (refcount_dec_if_one(&cur->refcnt)) {
+                       found = true;
+                       nf_conntrack_helper_unregister(cur);
+                       kfree(cur->expect_policy);
 
-               list_del(&nlcth->list);
-               kfree(nlcth);
+                       list_del(&nlcth->list);
+                       kfree(nlcth);
+               } else {
+                       ret = -EBUSY;
+               }
        }
 
        /* Make sure we return success if we flush and there is no helpers */
-       return (found || j == 0) ? 0 : -ENOENT;
+       return (found || j == 0) ? 0 : ret;
 }
 
 static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = {
index 877d9acd91ef5c616c43d00f265facbfe4c2d334..fff8073e2a5692c14037a77c5d8151cf0c1bbcb0 100644 (file)
@@ -83,17 +83,26 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
                            tb[NFTA_BITWISE_MASK]);
        if (err < 0)
                return err;
-       if (d1.len != priv->len)
-               return -EINVAL;
+       if (d1.len != priv->len) {
+               err = -EINVAL;
+               goto err1;
+       }
 
        err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2,
                            tb[NFTA_BITWISE_XOR]);
        if (err < 0)
-               return err;
-       if (d2.len != priv->len)
-               return -EINVAL;
+               goto err1;
+       if (d2.len != priv->len) {
+               err = -EINVAL;
+               goto err2;
+       }
 
        return 0;
+err2:
+       nft_data_release(&priv->xor, d2.type);
+err1:
+       nft_data_release(&priv->mask, d1.type);
+       return err;
 }
 
 static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
index 2b96effeadc1bc708a1f16e89342c8d39c4c4da7..c2945eb3397c8991ae05ea84abb2ba15591cbefb 100644 (file)
@@ -201,10 +201,18 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
        if (err < 0)
                return ERR_PTR(err);
 
+       if (desc.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               goto err1;
+       }
+
        if (desc.len <= sizeof(u32) && op == NFT_CMP_EQ)
                return &nft_cmp_fast_ops;
-       else
-               return &nft_cmp_ops;
+
+       return &nft_cmp_ops;
+err1:
+       nft_data_release(&data, desc.type);
+       return ERR_PTR(-EINVAL);
 }
 
 struct nft_expr_type nft_cmp_type __read_mostly = {
index a34ceb38fc55681962daad2c323f0011a5fe683d..1678e9e75e8ee7d22301d6083ddeb04dd39ab385 100644 (file)
@@ -826,9 +826,9 @@ static void nft_ct_helper_obj_destroy(struct nft_object *obj)
        struct nft_ct_helper_obj *priv = nft_obj_data(obj);
 
        if (priv->helper4)
-               module_put(priv->helper4->me);
+               nf_conntrack_helper_put(priv->helper4);
        if (priv->helper6)
-               module_put(priv->helper6->me);
+               nf_conntrack_helper_put(priv->helper6);
 }
 
 static void nft_ct_helper_obj_eval(struct nft_object *obj,
index 728baf88295aab3d4f0e1272d551672ae5a2fb13..4717d77969271c324087ed7677df636b414e54ad 100644 (file)
@@ -65,7 +65,7 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
        return 0;
 
 err1:
-       nft_data_uninit(&priv->data, desc.type);
+       nft_data_release(&priv->data, desc.type);
        return err;
 }
 
@@ -73,7 +73,8 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
                                  const struct nft_expr *expr)
 {
        const struct nft_immediate_expr *priv = nft_expr_priv(expr);
-       return nft_data_uninit(&priv->data, nft_dreg_to_type(priv->dreg));
+
+       return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
 }
 
 static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)
index 9edc74eedc1021e836bc767defc02fac1a63333f..cedb96c3619fa991395602dff1363314d3de13ea 100644 (file)
@@ -102,9 +102,9 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
        priv->len = desc_from.len;
        return 0;
 err2:
-       nft_data_uninit(&priv->data_to, desc_to.type);
+       nft_data_release(&priv->data_to, desc_to.type);
 err1:
-       nft_data_uninit(&priv->data_from, desc_from.type);
+       nft_data_release(&priv->data_from, desc_from.type);
        return err;
 }
 
index 8ec086b6b56b742485e34511b38a77af848d9f99..3d3a6df4ce70ea0950a4f07cab75b3c54680e09a 100644 (file)
@@ -222,7 +222,7 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
        struct nft_set_elem elem;
        int err;
 
-       err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL);
+       err = rhashtable_walk_init(&priv->ht, &hti, GFP_ATOMIC);
        iter->err = err;
        if (err)
                return;
index e97e2fb53f0a107b0361322be10f16b4ab4b5d32..fbdbaa00dd5fd751f6ab8f428de987017b5bdf79 100644 (file)
@@ -116,17 +116,17 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
                else if (d > 0)
                        p = &parent->rb_right;
                else {
-                       if (nft_set_elem_active(&rbe->ext, genmask)) {
-                               if (nft_rbtree_interval_end(rbe) &&
-                                   !nft_rbtree_interval_end(new))
-                                       p = &parent->rb_left;
-                               else if (!nft_rbtree_interval_end(rbe) &&
-                                        nft_rbtree_interval_end(new))
-                                       p = &parent->rb_right;
-                               else {
-                                       *ext = &rbe->ext;
-                                       return -EEXIST;
-                               }
+                       if (nft_rbtree_interval_end(rbe) &&
+                           !nft_rbtree_interval_end(new)) {
+                               p = &parent->rb_left;
+                       } else if (!nft_rbtree_interval_end(rbe) &&
+                                  nft_rbtree_interval_end(new)) {
+                               p = &parent->rb_right;
+                       } else if (nft_set_elem_active(&rbe->ext, genmask)) {
+                               *ext = &rbe->ext;
+                               return -EEXIST;
+                       } else {
+                               p = &parent->rb_left;
                        }
                }
        }
index 8876b7da6884c210393d1988032cbb5bd7018507..1770c1d9b37fc14be9d9d8cf4721d21c745826ad 100644 (file)
@@ -283,28 +283,30 @@ static int xt_obj_to_user(u16 __user *psize, u16 size,
                       &U->u.user.revision, K->u.kernel.TYPE->revision)
 
 int xt_data_to_user(void __user *dst, const void *src,
-                   int usersize, int size)
+                   int usersize, int size, int aligned_size)
 {
        usersize = usersize ? : size;
        if (copy_to_user(dst, src, usersize))
                return -EFAULT;
-       if (usersize != size && clear_user(dst + usersize, size - usersize))
+       if (usersize != aligned_size &&
+           clear_user(dst + usersize, aligned_size - usersize))
                return -EFAULT;
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(xt_data_to_user);
 
-#define XT_DATA_TO_USER(U, K, TYPE, C_SIZE)                            \
+#define XT_DATA_TO_USER(U, K, TYPE)                                    \
        xt_data_to_user(U->data, K->data,                               \
                        K->u.kernel.TYPE->usersize,                     \
-                       C_SIZE ? : K->u.kernel.TYPE->TYPE##size)
+                       K->u.kernel.TYPE->TYPE##size,                   \
+                       XT_ALIGN(K->u.kernel.TYPE->TYPE##size))
 
 int xt_match_to_user(const struct xt_entry_match *m,
                     struct xt_entry_match __user *u)
 {
        return XT_OBJ_TO_USER(u, m, match, 0) ||
-              XT_DATA_TO_USER(u, m, match, 0);
+              XT_DATA_TO_USER(u, m, match);
 }
 EXPORT_SYMBOL_GPL(xt_match_to_user);
 
@@ -312,7 +314,7 @@ int xt_target_to_user(const struct xt_entry_target *t,
                      struct xt_entry_target __user *u)
 {
        return XT_OBJ_TO_USER(u, t, target, 0) ||
-              XT_DATA_TO_USER(u, t, target, 0);
+              XT_DATA_TO_USER(u, t, target);
 }
 EXPORT_SYMBOL_GPL(xt_target_to_user);
 
@@ -611,6 +613,12 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
 }
 EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
 
+#define COMPAT_XT_DATA_TO_USER(U, K, TYPE, C_SIZE)                     \
+       xt_data_to_user(U->data, K->data,                               \
+                       K->u.kernel.TYPE->usersize,                     \
+                       C_SIZE,                                         \
+                       COMPAT_XT_ALIGN(C_SIZE))
+
 int xt_compat_match_to_user(const struct xt_entry_match *m,
                            void __user **dstptr, unsigned int *size)
 {
@@ -626,7 +634,7 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
                if (match->compat_to_user((void __user *)cm->data, m->data))
                        return -EFAULT;
        } else {
-               if (XT_DATA_TO_USER(cm, m, match, msize - sizeof(*cm)))
+               if (COMPAT_XT_DATA_TO_USER(cm, m, match, msize - sizeof(*cm)))
                        return -EFAULT;
        }
 
@@ -972,7 +980,7 @@ int xt_compat_target_to_user(const struct xt_entry_target *t,
                if (target->compat_to_user((void __user *)ct->data, t->data))
                        return -EFAULT;
        } else {
-               if (XT_DATA_TO_USER(ct, t, target, tsize - sizeof(*ct)))
+               if (COMPAT_XT_DATA_TO_USER(ct, t, target, tsize - sizeof(*ct)))
                        return -EFAULT;
        }
 
index bb7ad82dcd5603e810db8fba35f81d3f2c03a2b7..623ef37de886fa22fd508a1261f0c1934f767e5f 100644 (file)
@@ -96,7 +96,7 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
 
        help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
        if (help == NULL) {
-               module_put(helper->me);
+               nf_conntrack_helper_put(helper);
                return -ENOMEM;
        }
 
@@ -263,7 +263,7 @@ out:
 err4:
        help = nfct_help(ct);
        if (help)
-               module_put(help->helper->me);
+               nf_conntrack_helper_put(help->helper);
 err3:
        nf_ct_tmpl_free(ct);
 err2:
@@ -346,7 +346,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
        if (ct) {
                help = nfct_help(ct);
                if (help)
-                       module_put(help->helper->me);
+                       nf_conntrack_helper_put(help->helper);
 
                nf_ct_netns_put(par->net, par->family);
 
index ee841f00a6ec715914fb14bb31dc8405f8dd4c4e..7586d446d7dcafc5c44b43190398840b68107d1f 100644 (file)
@@ -62,6 +62,7 @@
 #include <asm/cacheflush.h>
 #include <linux/hash.h>
 #include <linux/genetlink.h>
+#include <linux/net_namespace.h>
 
 #include <net/net_namespace.h>
 #include <net/sock.h>
@@ -1415,7 +1416,8 @@ static void do_one_broadcast(struct sock *sk,
                goto out;
        }
        NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
-       NETLINK_CB(p->skb2).nsid_is_set = true;
+       if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+               NETLINK_CB(p->skb2).nsid_is_set = true;
        val = netlink_broadcast_deliver(sk, p->skb2);
        if (val < 0) {
                netlink_overrun(sk);
index bf602e33c40af4896240c9cc0566fa10126cf662..08679ebb3068298a58a081926c6a7dd5a2a73d17 100644 (file)
@@ -1123,7 +1123,7 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
 
        help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
        if (!help) {
-               module_put(helper->me);
+               nf_conntrack_helper_put(helper);
                return -ENOMEM;
        }
 
@@ -1584,7 +1584,7 @@ void ovs_ct_free_action(const struct nlattr *a)
 static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
 {
        if (ct_info->helper)
-               module_put(ct_info->helper->me);
+               nf_conntrack_helper_put(ct_info->helper);
        if (ct_info->ct)
                nf_ct_tmpl_free(ct_info->ct);
 }
index 89193a634da45bb78498ecd28ca39c455e32f2e4..04a3128adcf0adcc2603e45c9054cdd2fd0e7a0b 100644 (file)
@@ -94,7 +94,6 @@ static void internal_dev_destructor(struct net_device *dev)
        struct vport *vport = ovs_internal_dev_get_vport(dev);
 
        ovs_vport_free(vport);
-       free_netdev(dev);
 }
 
 static void
@@ -156,7 +155,8 @@ static void do_setup(struct net_device *netdev)
        netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
        netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH |
                              IFF_PHONY_HEADROOM | IFF_NO_QUEUE;
-       netdev->destructor = internal_dev_destructor;
+       netdev->needs_free_netdev = true;
+       netdev->priv_destructor = internal_dev_destructor;
        netdev->ethtool_ops = &internal_dev_ethtool_ops;
        netdev->rtnl_link_ops = &internal_dev_link_ops;
 
index f4001763134da35ed5f0f04bc2836015bb15a4af..e3eeed19cc7a130e80e24a3d67776a5b5a3c2698 100644 (file)
@@ -2658,13 +2658,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
        }
 
-       sockc.tsflags = po->sk.sk_tsflags;
-       if (msg->msg_controllen) {
-               err = sock_cmsg_send(&po->sk, msg, &sockc);
-               if (unlikely(err))
-                       goto out;
-       }
-
        err = -ENXIO;
        if (unlikely(dev == NULL))
                goto out;
@@ -2672,6 +2665,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
        if (unlikely(!(dev->flags & IFF_UP)))
                goto out_put;
 
+       sockc.tsflags = po->sk.sk_tsflags;
+       if (msg->msg_controllen) {
+               err = sock_cmsg_send(&po->sk, msg, &sockc);
+               if (unlikely(err))
+                       goto out_put;
+       }
+
        if (po->sk.sk_socket->type == SOCK_RAW)
                reserve = dev->hard_header_len;
        size_max = po->tx_ring.frame_size
index 21c28b51be9439b20369b48077ac8392db7c3150..2c9337946e3038f130d198bb51d061a648ef1ed4 100644 (file)
@@ -236,7 +236,7 @@ static void gprs_setup(struct net_device *dev)
        dev->tx_queue_len       = 10;
 
        dev->netdev_ops         = &gprs_netdev_ops;
-       dev->destructor         = free_netdev;
+       dev->needs_free_netdev  = true;
 }
 
 /*
index 0a4e28477ad94012b4e7aeb526711076e6259995..54369225766ef8e43ff94f21b4fd670b2cc233a3 100644 (file)
@@ -217,7 +217,7 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
                                       unsigned int *_toklen)
 {
        const __be32 *xdr = *_xdr;
-       unsigned int toklen = *_toklen, n_parts, loop, tmp;
+       unsigned int toklen = *_toklen, n_parts, loop, tmp, paddedlen;
 
        /* there must be at least one name, and at least #names+1 length
         * words */
@@ -247,16 +247,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
                toklen -= 4;
                if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
                        return -EINVAL;
-               if (tmp > toklen)
+               paddedlen = (tmp + 3) & ~3;
+               if (paddedlen > toklen)
                        return -EINVAL;
                princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
                if (!princ->name_parts[loop])
                        return -ENOMEM;
                memcpy(princ->name_parts[loop], xdr, tmp);
                princ->name_parts[loop][tmp] = 0;
-               tmp = (tmp + 3) & ~3;
-               toklen -= tmp;
-               xdr += tmp >> 2;
+               toklen -= paddedlen;
+               xdr += paddedlen >> 2;
        }
 
        if (toklen < 4)
@@ -265,16 +265,16 @@ static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
        toklen -= 4;
        if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
                return -EINVAL;
-       if (tmp > toklen)
+       paddedlen = (tmp + 3) & ~3;
+       if (paddedlen > toklen)
                return -EINVAL;
        princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
        if (!princ->realm)
                return -ENOMEM;
        memcpy(princ->realm, xdr, tmp);
        princ->realm[tmp] = 0;
-       tmp = (tmp + 3) & ~3;
-       toklen -= tmp;
-       xdr += tmp >> 2;
+       toklen -= paddedlen;
+       xdr += paddedlen >> 2;
 
        _debug("%s/...@%s", princ->name_parts[0], princ->realm);
 
@@ -293,7 +293,7 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
                                         unsigned int *_toklen)
 {
        const __be32 *xdr = *_xdr;
-       unsigned int toklen = *_toklen, len;
+       unsigned int toklen = *_toklen, len, paddedlen;
 
        /* there must be at least one tag and one length word */
        if (toklen <= 8)
@@ -307,15 +307,17 @@ static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
        toklen -= 8;
        if (len > max_data_size)
                return -EINVAL;
+       paddedlen = (len + 3) & ~3;
+       if (paddedlen > toklen)
+               return -EINVAL;
        td->data_len = len;
 
        if (len > 0) {
                td->data = kmemdup(xdr, len, GFP_KERNEL);
                if (!td->data)
                        return -ENOMEM;
-               len = (len + 3) & ~3;
-               toklen -= len;
-               xdr += len >> 2;
+               toklen -= paddedlen;
+               xdr += paddedlen >> 2;
        }
 
        _debug("tag %x len %x", td->tag, td->data_len);
@@ -387,7 +389,7 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
                                    const __be32 **_xdr, unsigned int *_toklen)
 {
        const __be32 *xdr = *_xdr;
-       unsigned int toklen = *_toklen, len;
+       unsigned int toklen = *_toklen, len, paddedlen;
 
        /* there must be at least one length word */
        if (toklen <= 4)
@@ -399,6 +401,9 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
        toklen -= 4;
        if (len > AFSTOKEN_K5_TIX_MAX)
                return -EINVAL;
+       paddedlen = (len + 3) & ~3;
+       if (paddedlen > toklen)
+               return -EINVAL;
        *_tktlen = len;
 
        _debug("ticket len %u", len);
@@ -407,9 +412,8 @@ static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen,
                *_ticket = kmemdup(xdr, len, GFP_KERNEL);
                if (!*_ticket)
                        return -ENOMEM;
-               len = (len + 3) & ~3;
-               toklen -= len;
-               xdr += len >> 2;
+               toklen -= paddedlen;
+               xdr += paddedlen >> 2;
        }
 
        *_xdr = xdr;
@@ -552,7 +556,7 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
 {
        const __be32 *xdr = prep->data, *token;
        const char *cp;
-       unsigned int len, tmp, loop, ntoken, toklen, sec_ix;
+       unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
        size_t datalen = prep->datalen;
        int ret;
 
@@ -578,22 +582,21 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
        if (len < 1 || len > AFSTOKEN_CELL_MAX)
                goto not_xdr;
        datalen -= 4;
-       tmp = (len + 3) & ~3;
-       if (tmp > datalen)
+       paddedlen = (len + 3) & ~3;
+       if (paddedlen > datalen)
                goto not_xdr;
 
        cp = (const char *) xdr;
        for (loop = 0; loop < len; loop++)
                if (!isprint(cp[loop]))
                        goto not_xdr;
-       if (len < tmp)
-               for (; loop < tmp; loop++)
-                       if (cp[loop])
-                               goto not_xdr;
+       for (; loop < paddedlen; loop++)
+               if (cp[loop])
+                       goto not_xdr;
        _debug("cellname: [%u/%u] '%*.*s'",
-              len, tmp, len, len, (const char *) xdr);
-       datalen -= tmp;
-       xdr += tmp >> 2;
+              len, paddedlen, len, len, (const char *) xdr);
+       datalen -= paddedlen;
+       xdr += paddedlen >> 2;
 
        /* get the token count */
        if (datalen < 12)
@@ -614,10 +617,11 @@ static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
                sec_ix = ntohl(*xdr);
                datalen -= 4;
                _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
-               if (toklen < 20 || toklen > datalen)
+               paddedlen = (toklen + 3) & ~3;
+               if (toklen < 20 || toklen > datalen || paddedlen > datalen)
                        goto not_xdr;
-               datalen -= (toklen + 3) & ~3;
-               xdr += (toklen + 3) >> 2;
+               datalen -= paddedlen;
+               xdr += paddedlen >> 2;
 
        } while (--loop > 0);
 
index 164b5ac094be6d8bbd7a04aa8aa962a3c693ab44..7dc5892671c818db55b024b10d56ec2252c2f826 100644 (file)
@@ -94,8 +94,10 @@ static struct tcf_pedit_key_ex *tcf_pedit_keys_ex_parse(struct nlattr *nla,
                k++;
        }
 
-       if (n)
+       if (n) {
+               err = -EINVAL;
                goto err_out;
+       }
 
        return keys_ex;
 
index f42008b293112d1a6da2bcf6ef8af564b382ba39..b062bc80c7cb11b0ea473916c58957b54db21594 100644 (file)
@@ -132,21 +132,21 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
                }
        }
 
-       spin_lock_bh(&police->tcf_lock);
        if (est) {
                err = gen_replace_estimator(&police->tcf_bstats, NULL,
                                            &police->tcf_rate_est,
                                            &police->tcf_lock,
                                            NULL, est);
                if (err)
-                       goto failure_unlock;
+                       goto failure;
        } else if (tb[TCA_POLICE_AVRATE] &&
                   (ret == ACT_P_CREATED ||
                    !gen_estimator_active(&police->tcf_rate_est))) {
                err = -EINVAL;
-               goto failure_unlock;
+               goto failure;
        }
 
+       spin_lock_bh(&police->tcf_lock);
        /* No failure allowed after this point */
        police->tcfp_mtu = parm->mtu;
        if (police->tcfp_mtu == 0) {
@@ -192,8 +192,6 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
 
        return ret;
 
-failure_unlock:
-       spin_unlock_bh(&police->tcf_lock);
 failure:
        qdisc_put_rtab(P_tab);
        qdisc_put_rtab(R_tab);
index dee469fed9671d518dbeddd6bd48d96cc9158675..51859b8edd7eff3845ca3d5b5b0d900583736d4a 100644 (file)
@@ -203,7 +203,6 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
 
        *arg = (unsigned long) head;
        rcu_assign_pointer(tp->root, new);
-       call_rcu(&head->rcu, mall_destroy_rcu);
        return 0;
 
 err_replace_hw_filter:
index bbe57d57b67fd498692bd41db49147511f1bb091..cfdbfa18a95eb01deceecdad56be7de07547db2a 100644 (file)
@@ -1019,7 +1019,8 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
                return sch;
        }
        /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
-       ops->destroy(sch);
+       if (ops->destroy)
+               ops->destroy(sch);
 err_out3:
        dev_put(dev);
        kfree((char *) sch - sch->padded);
@@ -1831,6 +1832,12 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
        if (!qdisc_dev(root))
                return 0;
 
+       if (tcm->tcm_parent) {
+               q = qdisc_match_from_root(root, TC_H_MAJ(tcm->tcm_parent));
+               if (q && tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
+                       return -1;
+               return 0;
+       }
        hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
                if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
                        return -1;
index a9708da28eb53ff2987264c6c7d7ca6ec2ff09e9..95238284c422e23fbd834a3aedc54c9243743d0f 100644 (file)
@@ -1176,7 +1176,9 @@ void sctp_assoc_update(struct sctp_association *asoc,
 
                asoc->ctsn_ack_point = asoc->next_tsn - 1;
                asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
-               if (!asoc->stream) {
+
+               if (sctp_state(asoc, COOKIE_WAIT)) {
+                       sctp_stream_free(asoc->stream);
                        asoc->stream = new->stream;
                        new->stream = NULL;
                }
index 8c589230794f9394406d2a0ad2157b7a47d75757..3dcd0ecf3d99f74ec8ed4aad149bd32950ab23ef 100644 (file)
@@ -275,6 +275,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
                if (sctp_sk(sk)->bind_hash)
                        sctp_put_port(sk);
 
+               sctp_sk(sk)->ep = NULL;
                sock_put(sk);
        }
 
index 0e06a278d2a911e2360e75e983b623e453284b7b..ba9ad32fc44740b9ec45d95e265d3d895148d7a7 100644 (file)
@@ -473,15 +473,14 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
                             struct sctp_association **app,
                             struct sctp_transport **tpp)
 {
+       struct sctp_init_chunk *chunkhdr, _chunkhdr;
        union sctp_addr saddr;
        union sctp_addr daddr;
        struct sctp_af *af;
        struct sock *sk = NULL;
        struct sctp_association *asoc;
        struct sctp_transport *transport = NULL;
-       struct sctp_init_chunk *chunkhdr;
        __u32 vtag = ntohl(sctphdr->vtag);
-       int len = skb->len - ((void *)sctphdr - (void *)skb->data);
 
        *app = NULL; *tpp = NULL;
 
@@ -516,13 +515,16 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
         * discard the packet.
         */
        if (vtag == 0) {
-               chunkhdr = (void *)sctphdr + sizeof(struct sctphdr);
-               if (len < sizeof(struct sctphdr) + sizeof(sctp_chunkhdr_t)
-                         + sizeof(__be32) ||
+               /* chunk header + first 4 octects of init header */
+               chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) +
+                                             sizeof(struct sctphdr),
+                                             sizeof(struct sctp_chunkhdr) +
+                                             sizeof(__be32), &_chunkhdr);
+               if (!chunkhdr ||
                    chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
-                   ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag) {
+                   ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag)
                        goto out;
-               }
+
        } else if (vtag != asoc->c.peer_vtag) {
                goto out;
        }
index 961ee59f696a0b0a8b6c2bade0031a073dff53ad..f5b45b8b8b16e6965d24cd79b150828a608c2121 100644 (file)
@@ -240,12 +240,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        struct sctp_bind_addr *bp;
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sctp_sockaddr_entry *laddr;
-       union sctp_addr *baddr = NULL;
        union sctp_addr *daddr = &t->ipaddr;
        union sctp_addr dst_saddr;
        struct in6_addr *final_p, final;
        __u8 matchlen = 0;
-       __u8 bmatchlen;
        sctp_scope_t scope;
 
        memset(fl6, 0, sizeof(struct flowi6));
@@ -312,23 +310,37 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
         */
        rcu_read_lock();
        list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-               if (!laddr->valid)
+               struct dst_entry *bdst;
+               __u8 bmatchlen;
+
+               if (!laddr->valid ||
+                   laddr->state != SCTP_ADDR_SRC ||
+                   laddr->a.sa.sa_family != AF_INET6 ||
+                   scope > sctp_scope(&laddr->a))
                        continue;
-               if ((laddr->state == SCTP_ADDR_SRC) &&
-                   (laddr->a.sa.sa_family == AF_INET6) &&
-                   (scope <= sctp_scope(&laddr->a))) {
-                       bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
-                       if (!baddr || (matchlen < bmatchlen)) {
-                               baddr = &laddr->a;
-                               matchlen = bmatchlen;
-                       }
-               }
-       }
-       if (baddr) {
-               fl6->saddr = baddr->v6.sin6_addr;
-               fl6->fl6_sport = baddr->v6.sin6_port;
+
+               fl6->saddr = laddr->a.v6.sin6_addr;
+               fl6->fl6_sport = laddr->a.v6.sin6_port;
                final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
-               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+               bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
+
+               if (!IS_ERR(bdst) &&
+                   ipv6_chk_addr(dev_net(bdst->dev),
+                                 &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
+                       if (!IS_ERR_OR_NULL(dst))
+                               dst_release(dst);
+                       dst = bdst;
+                       break;
+               }
+
+               bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
+               if (matchlen > bmatchlen)
+                       continue;
+
+               if (!IS_ERR_OR_NULL(dst))
+                       dst_release(dst);
+               dst = bdst;
+               matchlen = bmatchlen;
        }
        rcu_read_unlock();
 
@@ -665,6 +677,9 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
        newnp = inet6_sk(newsk);
 
        memcpy(newnp, np, sizeof(struct ipv6_pinfo));
+       newnp->ipv6_mc_list = NULL;
+       newnp->ipv6_ac_list = NULL;
+       newnp->ipv6_fl_list = NULL;
 
        rcu_read_lock();
        opt = rcu_dereference(np->opt);
index 048954eee984f28e599084b32fad87b2bd6989d0..9a647214a91ebc583660db320307e0df1e13e5be 100644 (file)
@@ -278,7 +278,6 @@ out:
 
 static int sctp_sock_dump(struct sock *sk, void *p)
 {
-       struct sctp_endpoint *ep = sctp_sk(sk)->ep;
        struct sctp_comm_param *commp = p;
        struct sk_buff *skb = commp->skb;
        struct netlink_callback *cb = commp->cb;
@@ -287,7 +286,9 @@ static int sctp_sock_dump(struct sock *sk, void *p)
        int err = 0;
 
        lock_sock(sk);
-       list_for_each_entry(assoc, &ep->asocs, asocs) {
+       if (!sctp_sk(sk)->ep)
+               goto release;
+       list_for_each_entry(assoc, &sctp_sk(sk)->ep->asocs, asocs) {
                if (cb->args[4] < cb->args[1])
                        goto next;
 
index 8a08f13469c4cc26aeec55de6793b2c2e3c562a6..92e332e173914f16c10ba54038dbb78dee0d0c49 100644 (file)
@@ -2454,16 +2454,11 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
         * stream sequence number shall be set to 0.
         */
 
-       /* Allocate storage for the negotiated streams if it is not a temporary
-        * association.
-        */
-       if (!asoc->temp) {
-               if (sctp_stream_init(asoc, gfp))
-                       goto clean_up;
+       if (sctp_stream_init(asoc, gfp))
+               goto clean_up;
 
-               if (sctp_assoc_set_id(asoc, gfp))
-                       goto clean_up;
-       }
+       if (!asoc->temp && sctp_assoc_set_id(asoc, gfp))
+               goto clean_up;
 
        /* ADDIP Section 4.1 ASCONF Chunk Procedures
         *
index 4f5e6cfc7f601b4de8db8802668d553f1af8491d..f863b5573e42d6f1c4908bf045af0079edc4b2d9 100644 (file)
@@ -2088,6 +2088,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net,
                }
        }
 
+       /* Set temp so that it won't be added into hashtable */
+       new_asoc->temp = 1;
+
        /* Compare the tie_tag in cookie with the verification tag of
         * current association.
         */
index f16c8d97b7f313e9f671d8bb8620b0f9566e619f..3a8318e518f1c10a375dc3ff6ba6596579bb85a1 100644 (file)
@@ -4622,13 +4622,13 @@ int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *),
 
        for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize;
             hash++, head++) {
-               read_lock(&head->lock);
+               read_lock_bh(&head->lock);
                sctp_for_each_hentry(epb, &head->chain) {
                        err = cb(sctp_ep(epb), p);
                        if (err)
                                break;
                }
-               read_unlock(&head->lock);
+               read_unlock_bh(&head->lock);
        }
 
        return err;
@@ -4666,9 +4666,8 @@ int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *),
        if (err)
                return err;
 
-       sctp_transport_get_idx(net, &hti, pos);
-       obj = sctp_transport_get_next(net, &hti);
-       for (; obj && !IS_ERR(obj); obj = sctp_transport_get_next(net, &hti)) {
+       obj = sctp_transport_get_idx(net, &hti, pos + 1);
+       for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) {
                struct sctp_transport *transport = obj;
 
                if (!sctp_transport_hold(transport))
index c717ef0896aa2accaee05e3cf4c10d066c61eeb3..33954852f3f89b3bd05595a159e5c2ed56d074ad 100644 (file)
@@ -8,6 +8,10 @@ config SMC
          The Linux implementation of the SMC-R solution is designed as
          a separate socket family SMC.
 
+         Warning: SMC will expose all memory for remote reads and writes
+         once a connection is established.  Don't enable this option except
+         for tightly controlled lab environment.
+
          Select this option if you want to run SMC socket applications
 
 config SMC_DIAG
index e41f594a1e1d0c3d47706e4c80f9de587f953c9b..03ec058d18df642ef7e219000a62e51bc6c0e6fe 100644 (file)
@@ -204,7 +204,7 @@ int smc_clc_send_confirm(struct smc_sock *smc)
        memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
        hton24(cclc.qpn, link->roce_qp->qp_num);
        cclc.rmb_rkey =
-               htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
+               htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
        cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
        cclc.rmbe_alert_token = htonl(conn->alert_token_local);
        cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
@@ -256,7 +256,7 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
        memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
        hton24(aclc.qpn, link->roce_qp->qp_num);
        aclc.rmb_rkey =
-               htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
+               htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
        aclc.conn_idx = 1;                      /* as long as 1 RMB = 1 RMBE */
        aclc.rmbe_alert_token = htonl(conn->alert_token_local);
        aclc.qp_mtu = link->path_mtu;
index 65020e93ff210bb7f5db079399984c55e54c80f1..3ac09a629ea1a4c38c6bc21d996a69611c1633b7 100644 (file)
@@ -613,19 +613,8 @@ int smc_rmb_create(struct smc_sock *smc)
                        rmb_desc = NULL;
                        continue; /* if mapping failed, try smaller one */
                }
-               rc = smc_ib_get_memory_region(lgr->lnk[SMC_SINGLE_LINK].roce_pd,
-                                             IB_ACCESS_REMOTE_WRITE |
-                                             IB_ACCESS_LOCAL_WRITE,
-                                            &rmb_desc->mr_rx[SMC_SINGLE_LINK]);
-               if (rc) {
-                       smc_ib_buf_unmap(lgr->lnk[SMC_SINGLE_LINK].smcibdev,
-                                        tmp_bufsize, rmb_desc,
-                                        DMA_FROM_DEVICE);
-                       kfree(rmb_desc->cpu_addr);
-                       kfree(rmb_desc);
-                       rmb_desc = NULL;
-                       continue;
-               }
+               rmb_desc->rkey[SMC_SINGLE_LINK] =
+                       lgr->lnk[SMC_SINGLE_LINK].roce_pd->unsafe_global_rkey;
                rmb_desc->used = 1;
                write_lock_bh(&lgr->rmbs_lock);
                list_add(&rmb_desc->list,
@@ -668,6 +657,7 @@ int smc_rmb_rtoken_handling(struct smc_connection *conn,
 
        for (i = 0; i < SMC_RMBS_PER_LGR_MAX; i++) {
                if ((lgr->rtokens[i][SMC_SINGLE_LINK].rkey == rkey) &&
+                   (lgr->rtokens[i][SMC_SINGLE_LINK].dma_addr == dma_addr) &&
                    test_bit(i, lgr->rtokens_used_mask)) {
                        conn->rtoken_idx = i;
                        return 0;
index 27eb38056a27fb07e3ce72afbacaffaf4ae55f73..b013cb43a327ea81cd8bc9e4a5ffff733f87f6a7 100644 (file)
@@ -93,7 +93,7 @@ struct smc_buf_desc {
        u64                     dma_addr[SMC_LINKS_PER_LGR_MAX];
                                                /* mapped address of buffer */
        void                    *cpu_addr;      /* virtual address of buffer */
-       struct ib_mr            *mr_rx[SMC_LINKS_PER_LGR_MAX];
+       u32                     rkey[SMC_LINKS_PER_LGR_MAX];
                                                /* for rmb only:
                                                 * rkey provided to peer
                                                 */
index cb69ab977cd73963fef1fe27b1407e58a6e7cadd..b31715505a358cd4e73d1af6c58a49ef7ef8ecbe 100644 (file)
@@ -37,24 +37,6 @@ u8 local_systemid[SMC_SYSTEMID_LEN] = SMC_LOCAL_SYSTEMID_RESET;      /* unique system
                                                                 * identifier
                                                                 */
 
-int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags,
-                            struct ib_mr **mr)
-{
-       int rc;
-
-       if (*mr)
-               return 0; /* already done */
-
-       /* obtain unique key -
-        * next invocation of get_dma_mr returns a different key!
-        */
-       *mr = pd->device->get_dma_mr(pd, access_flags);
-       rc = PTR_ERR_OR_ZERO(*mr);
-       if (IS_ERR(*mr))
-               *mr = NULL;
-       return rc;
-}
-
 static int smc_ib_modify_qp_init(struct smc_link *lnk)
 {
        struct ib_qp_attr qp_attr;
@@ -210,7 +192,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk)
 {
        int rc;
 
-       lnk->roce_pd = ib_alloc_pd(lnk->smcibdev->ibdev, 0);
+       lnk->roce_pd = ib_alloc_pd(lnk->smcibdev->ibdev,
+                                  IB_PD_UNSAFE_GLOBAL_RKEY);
        rc = PTR_ERR_OR_ZERO(lnk->roce_pd);
        if (IS_ERR(lnk->roce_pd))
                lnk->roce_pd = NULL;
index 7e1f0e24d17790f526aa50d07ff5e5d6596b6f3c..b567152a526d48c86110a9574833e8610684af4b 100644 (file)
@@ -61,8 +61,6 @@ void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
 int smc_ib_create_protection_domain(struct smc_link *lnk);
 void smc_ib_destroy_queue_pair(struct smc_link *lnk);
 int smc_ib_create_queue_pair(struct smc_link *lnk);
-int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags,
-                            struct ib_mr **mr);
 int smc_ib_ready_link(struct smc_link *lnk);
 int smc_ib_modify_qp_rts(struct smc_link *lnk);
 int smc_ib_modify_qp_reset(struct smc_link *lnk);
index 24fedd4b117e8f61cf500f629f2b47f2bc53e76f..03f6b5840764dcc2c486015edd8dc7de4cd84b26 100644 (file)
@@ -119,11 +119,9 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)
 
        for (i = 0; i < (reqs << 1); i++) {
                rqst = kzalloc(sizeof(*rqst), GFP_KERNEL);
-               if (!rqst) {
-                       pr_err("RPC:       %s: Failed to create bc rpc_rqst\n",
-                              __func__);
+               if (!rqst)
                        goto out_free;
-               }
+
                dprintk("RPC:       %s: new rqst %p\n", __func__, rqst);
 
                rqst->rq_xprt = &r_xprt->rx_xprt;
index 16aff8ddc16f8f3e66e31a86ce227b3ac49857bf..d5b54c020decdc2665d671f34d74dd809aa6682a 100644 (file)
@@ -2432,7 +2432,12 @@ static void xs_tcp_setup_socket(struct work_struct *work)
        case -ENETUNREACH:
        case -EADDRINUSE:
        case -ENOBUFS:
-               /* retry with existing socket, after a delay */
+               /*
+                * xs_tcp_force_close() wakes tasks with -EIO.
+                * We need to wake them first to ensure the
+                * correct error code.
+                */
+               xprt_wake_pending_tasks(xprt, status);
                xs_tcp_force_close(xprt);
                goto out;
        }
index 312ef7de57d7ba27c58533df9edb2f4dd61cc864..ab3087687a32446ffa3bbfaccf206028886e6945 100644 (file)
@@ -508,7 +508,7 @@ bool tipc_msg_reverse(u32 own_node,  struct sk_buff **skb, int err)
        }
 
        if (skb_cloned(_skb) &&
-           pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_KERNEL))
+           pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC))
                goto exit;
 
        /* Now reverse the concerned fields */
index 0d4f2f455a7c91a1d7ea2b0fd9c8d121e6da98af..1b92b72e812f942fc9826d8542f29bf1bd7c26c5 100644 (file)
@@ -362,25 +362,25 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
        return 0;
 }
 
-#define tipc_wait_for_cond(sock_, timeout_, condition_)                        \
-({                                                                     \
-       int rc_ = 0;                                                    \
-       int done_ = 0;                                                  \
-                                                                       \
-       while (!(condition_) && !done_) {                               \
-               struct sock *sk_ = sock->sk;                            \
-               DEFINE_WAIT_FUNC(wait_, woken_wake_function);           \
-                                                                       \
-               rc_ = tipc_sk_sock_err(sock_, timeout_);                \
-               if (rc_)                                                \
-                       break;                                          \
-               prepare_to_wait(sk_sleep(sk_), &wait_,                  \
-                               TASK_INTERRUPTIBLE);                    \
-               done_ = sk_wait_event(sk_, timeout_,                    \
-                                     (condition_), &wait_);            \
-               remove_wait_queue(sk_sleep(sk_), &wait_);               \
-       }                                                               \
-       rc_;                                                            \
+#define tipc_wait_for_cond(sock_, timeo_, condition_)                         \
+({                                                                             \
+       struct sock *sk_;                                                      \
+       int rc_;                                                               \
+                                                                              \
+       while ((rc_ = !(condition_))) {                                        \
+               DEFINE_WAIT_FUNC(wait_, woken_wake_function);                  \
+               sk_ = (sock_)->sk;                                             \
+               rc_ = tipc_sk_sock_err((sock_), timeo_);                       \
+               if (rc_)                                                       \
+                       break;                                                 \
+               prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE);    \
+               release_sock(sk_);                                             \
+               *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
+               sched_annotate_sleep();                                        \
+               lock_sock(sk_);                                                \
+               remove_wait_queue(sk_sleep(sk_), &wait_);                      \
+       }                                                                      \
+       rc_;                                                                   \
 })
 
 /**
index 6a7fe7660551f45c065a7f472b805c0b8073f6bb..1a0c961f4ffeef40abc5b980e004b01120e3c536 100644 (file)
@@ -999,7 +999,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct path path = { };
 
        err = -EINVAL;
-       if (sunaddr->sun_family != AF_UNIX)
+       if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
+           sunaddr->sun_family != AF_UNIX)
                goto out;
 
        if (addr_len == sizeof(short)) {
@@ -1110,6 +1111,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
        unsigned int hash;
        int err;
 
+       err = -EINVAL;
+       if (alen < offsetofend(struct sockaddr, sa_family))
+               goto out;
+
        if (addr->sa_family != AF_UNSPEC) {
                err = unix_mkname(sunaddr, alen, &hash);
                if (err < 0)
index 6f7f6757ceefb500551fafbf40c462835c4baf88..dfc8c51e4d74ec378a338ab9bb2560b3811f393b 100644 (file)
@@ -1540,8 +1540,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
        long timeout;
        int err;
        struct vsock_transport_send_notify_data send_data;
-
-       DEFINE_WAIT(wait);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
        sk = sock->sk;
        vsk = vsock_sk(sk);
@@ -1584,11 +1583,10 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
        if (err < 0)
                goto out;
 
-
        while (total_written < len) {
                ssize_t written;
 
-               prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+               add_wait_queue(sk_sleep(sk), &wait);
                while (vsock_stream_has_space(vsk) == 0 &&
                       sk->sk_err == 0 &&
                       !(sk->sk_shutdown & SEND_SHUTDOWN) &&
@@ -1597,33 +1595,30 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg,
                        /* Don't wait for non-blocking sockets. */
                        if (timeout == 0) {
                                err = -EAGAIN;
-                               finish_wait(sk_sleep(sk), &wait);
+                               remove_wait_queue(sk_sleep(sk), &wait);
                                goto out_err;
                        }
 
                        err = transport->notify_send_pre_block(vsk, &send_data);
                        if (err < 0) {
-                               finish_wait(sk_sleep(sk), &wait);
+                               remove_wait_queue(sk_sleep(sk), &wait);
                                goto out_err;
                        }
 
                        release_sock(sk);
-                       timeout = schedule_timeout(timeout);
+                       timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
                        lock_sock(sk);
                        if (signal_pending(current)) {
                                err = sock_intr_errno(timeout);
-                               finish_wait(sk_sleep(sk), &wait);
+                               remove_wait_queue(sk_sleep(sk), &wait);
                                goto out_err;
                        } else if (timeout == 0) {
                                err = -EAGAIN;
-                               finish_wait(sk_sleep(sk), &wait);
+                               remove_wait_queue(sk_sleep(sk), &wait);
                                goto out_err;
                        }
-
-                       prepare_to_wait(sk_sleep(sk), &wait,
-                                       TASK_INTERRUPTIBLE);
                }
-               finish_wait(sk_sleep(sk), &wait);
+               remove_wait_queue(sk_sleep(sk), &wait);
 
                /* These checks occur both as part of and after the loop
                 * conditional since we need to check before and after
index 14d5f0c8c45ff07224f2dc8e6310c2edc440874e..9f0901f3e42b60db2c6aee7927b2b0ddc0ab7759 100644 (file)
@@ -322,9 +322,9 @@ cfg80211_find_sched_scan_req(struct cfg80211_registered_device *rdev, u64 reqid)
 {
        struct cfg80211_sched_scan_request *pos;
 
-       ASSERT_RTNL();
+       WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held());
 
-       list_for_each_entry(pos, &rdev->sched_scan_req_list, list) {
+       list_for_each_entry_rcu(pos, &rdev->sched_scan_req_list, list) {
                if (pos->reqid == reqid)
                        return pos;
        }
@@ -398,13 +398,13 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid)
        trace_cfg80211_sched_scan_results(wiphy, reqid);
        /* ignore if we're not scanning */
 
-       rtnl_lock();
+       rcu_read_lock();
        request = cfg80211_find_sched_scan_req(rdev, reqid);
        if (request) {
                request->report_results = true;
                queue_work(cfg80211_wq, &rdev->sched_scan_res_wk);
        }
-       rtnl_unlock();
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL(cfg80211_sched_scan_results);
 
index 7198373e29206a0f19f006578596fea78e82f66e..4992f1025c9d3749bddd5f22948d2dad791aa9a9 100644 (file)
@@ -454,6 +454,8 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
        if (iftype == NL80211_IFTYPE_MESH_POINT)
                skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
 
+       mesh_flags &= MESH_FLAGS_AE;
+
        switch (hdr->frame_control &
                cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
        case cpu_to_le16(IEEE80211_FCTL_TODS):
@@ -469,9 +471,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
                             iftype != NL80211_IFTYPE_STATION))
                        return -1;
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
-                       if (mesh_flags & MESH_FLAGS_AE_A4)
+                       if (mesh_flags == MESH_FLAGS_AE_A4)
                                return -1;
-                       if (mesh_flags & MESH_FLAGS_AE_A5_A6) {
+                       if (mesh_flags == MESH_FLAGS_AE_A5_A6) {
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
                                        tmp.h_dest, 2 * ETH_ALEN);
@@ -487,9 +489,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
                     ether_addr_equal(tmp.h_source, addr)))
                        return -1;
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
-                       if (mesh_flags & MESH_FLAGS_AE_A5_A6)
+                       if (mesh_flags == MESH_FLAGS_AE_A5_A6)
                                return -1;
-                       if (mesh_flags & MESH_FLAGS_AE_A4)
+                       if (mesh_flags == MESH_FLAGS_AE_A4)
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
                                        tmp.h_source, ETH_ALEN);
index 1a4db6790e2077d4ea922d1c32cde5352543fa2c..6cdb054484d66d40e4523965457a619bd1c9154f 100644 (file)
@@ -914,13 +914,12 @@ int call_commit_handler(struct net_device *dev)
  * Main IOCTl dispatcher.
  * Check the type of IOCTL and call the appropriate wrapper...
  */
-static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
+static int wireless_process_ioctl(struct net *net, struct iwreq *iwr,
                                  unsigned int cmd,
                                  struct iw_request_info *info,
                                  wext_ioctl_func standard,
                                  wext_ioctl_func private)
 {
-       struct iwreq *iwr = (struct iwreq *) ifr;
        struct net_device *dev;
        iw_handler      handler;
 
@@ -928,7 +927,7 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
         * The copy_to/from_user() of ifr is also dealt with in there */
 
        /* Make sure the device exist */
-       if ((dev = __dev_get_by_name(net, ifr->ifr_name)) == NULL)
+       if ((dev = __dev_get_by_name(net, iwr->ifr_name)) == NULL)
                return -ENODEV;
 
        /* A bunch of special cases, then the generic case...
@@ -957,9 +956,6 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
                else if (private)
                        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);
        return -EOPNOTSUPP;
 }
 
@@ -977,7 +973,7 @@ static int wext_permission_check(unsigned int cmd)
 }
 
 /* entry point from dev ioctl */
-static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
+static int wext_ioctl_dispatch(struct net *net, struct iwreq *iwr,
                               unsigned int cmd, struct iw_request_info *info,
                               wext_ioctl_func standard,
                               wext_ioctl_func private)
@@ -987,9 +983,9 @@ static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
        if (ret)
                return ret;
 
-       dev_load(net, ifr->ifr_name);
+       dev_load(net, iwr->ifr_name);
        rtnl_lock();
-       ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
+       ret = wireless_process_ioctl(net, iwr, cmd, info, standard, private);
        rtnl_unlock();
 
        return ret;
@@ -1039,18 +1035,18 @@ static int ioctl_standard_call(struct net_device *      dev,
 }
 
 
-int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
+int wext_handle_ioctl(struct net *net, struct iwreq *iwr, unsigned int cmd,
                      void __user *arg)
 {
        struct iw_request_info info = { .cmd = cmd, .flags = 0 };
        int ret;
 
-       ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
+       ret = wext_ioctl_dispatch(net, iwr, cmd, &info,
                                  ioctl_standard_call,
                                  ioctl_private_call);
        if (ret >= 0 &&
            IW_IS_GET(cmd) &&
-           copy_to_user(arg, ifr, sizeof(struct iwreq)))
+           copy_to_user(arg, iwr, sizeof(struct iwreq)))
                return -EFAULT;
 
        return ret;
@@ -1107,7 +1103,7 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
        info.cmd = cmd;
        info.flags = IW_REQUEST_FLAG_COMPAT;
 
-       ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info,
+       ret = wext_ioctl_dispatch(net, &iwr, cmd, &info,
                                  compat_standard_call,
                                  compat_private_call);
 
index 8b911c29860e79f21b0ac8e1d3a80ed373fd537e..5a1a98df3499841172f47b71418f95d9558158d0 100644 (file)
@@ -1791,32 +1791,40 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
 
 static int __init x25_init(void)
 {
-       int rc = proto_register(&x25_proto, 0);
+       int rc;
 
-       if (rc != 0)
+       rc = proto_register(&x25_proto, 0);
+       if (rc)
                goto out;
 
        rc = sock_register(&x25_family_ops);
-       if (rc != 0)
+       if (rc)
                goto out_proto;
 
        dev_add_pack(&x25_packet_type);
 
        rc = register_netdevice_notifier(&x25_dev_notifier);
-       if (rc != 0)
+       if (rc)
                goto out_sock;
 
-       pr_info("Linux Version 0.2\n");
+       rc = x25_register_sysctl();
+       if (rc)
+               goto out_dev;
 
-       x25_register_sysctl();
        rc = x25_proc_init();
-       if (rc != 0)
-               goto out_dev;
+       if (rc)
+               goto out_sysctl;
+
+       pr_info("Linux Version 0.2\n");
+
 out:
        return rc;
+out_sysctl:
+       x25_unregister_sysctl();
 out_dev:
        unregister_netdevice_notifier(&x25_dev_notifier);
 out_sock:
+       dev_remove_pack(&x25_packet_type);
        sock_unregister(AF_X25);
 out_proto:
        proto_unregister(&x25_proto);
index a06dfe143c675039b57cdc5a83164228730d3e5e..ba078c85f0a1533ffbbadef1ab5789399dd1528a 100644 (file)
@@ -73,9 +73,12 @@ static struct ctl_table x25_table[] = {
        { },
 };
 
-void __init x25_register_sysctl(void)
+int __init x25_register_sysctl(void)
 {
        x25_table_header = register_net_sysctl(&init_net, "net/x25", x25_table);
+       if (!x25_table_header)
+               return -ENOMEM;
+       return 0;
 }
 
 void x25_unregister_sysctl(void)
index abf81b329dc1f3276e1cf5631ebae4ec31a229de..55b2ac3009955aacd09db22c7fc4d082807c3ed9 100644 (file)
@@ -4,8 +4,7 @@
 
 obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
                      xfrm_input.o xfrm_output.o \
-                     xfrm_sysctl.o xfrm_replay.o
-obj-$(CONFIG_XFRM_OFFLOAD) += xfrm_device.o
+                     xfrm_sysctl.o xfrm_replay.o xfrm_device.o
 obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
 obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
 obj-$(CONFIG_XFRM_USER) += xfrm_user.o
index 8ec8a3fcf8d4740670b16c2c1af099ef0beaa5c5..5aba03685d7da54931c9287c071a13403c6edec5 100644 (file)
@@ -22,6 +22,7 @@
 #include <net/xfrm.h>
 #include <linux/notifier.h>
 
+#ifdef CONFIG_XFRM_OFFLOAD
 int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
 {
        int err;
@@ -137,6 +138,7 @@ ok:
        return true;
 }
 EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok);
+#endif
 
 int xfrm_dev_register(struct net_device *dev)
 {
@@ -170,7 +172,7 @@ static int xfrm_dev_feat_change(struct net_device *dev)
 
 static int xfrm_dev_down(struct net_device *dev)
 {
-       if (dev->hw_features & NETIF_F_HW_ESP)
+       if (dev->features & NETIF_F_HW_ESP)
                xfrm_dev_state_flush(dev_net(dev), dev, true);
 
        xfrm_garbage_collect(dev_net(dev));
index b00a1d5a7f52e54f2ac454da3eeb14447f84d8b2..643a18f720321c52f0103baf010f3c5921d68482 100644 (file)
@@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
                err = -ESRCH;
 out:
        spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
-
-       if (cnt)
-               xfrm_garbage_collect(net);
-
        return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
@@ -1797,43 +1793,6 @@ free_dst:
        goto out;
 }
 
-#ifdef CONFIG_XFRM_SUB_POLICY
-static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
-{
-       if (!*target) {
-               *target = kmalloc(size, GFP_ATOMIC);
-               if (!*target)
-                       return -ENOMEM;
-       }
-
-       memcpy(*target, src, size);
-       return 0;
-}
-#endif
-
-static int xfrm_dst_update_parent(struct dst_entry *dst,
-                                 const struct xfrm_selector *sel)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
-       struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-       return xfrm_dst_alloc_copy((void **)&(xdst->partner),
-                                  sel, sizeof(*sel));
-#else
-       return 0;
-#endif
-}
-
-static int xfrm_dst_update_origin(struct dst_entry *dst,
-                                 const struct flowi *fl)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
-       struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
-       return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl));
-#else
-       return 0;
-#endif
-}
-
 static int xfrm_expand_policies(const struct flowi *fl, u16 family,
                                struct xfrm_policy **pols,
                                int *num_pols, int *num_xfrms)
@@ -1905,16 +1864,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
 
        xdst = (struct xfrm_dst *)dst;
        xdst->num_xfrms = err;
-       if (num_pols > 1)
-               err = xfrm_dst_update_parent(dst, &pols[1]->selector);
-       else
-               err = xfrm_dst_update_origin(dst, fl);
-       if (unlikely(err)) {
-               dst_free(dst);
-               XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
-               return ERR_PTR(err);
-       }
-
        xdst->num_pols = num_pols;
        memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
        xdst->policy_genid = atomic_read(&pols[0]->genid);
index fc3c5aa387543a63bf18955e60309207bf06e961..2e291bc5f1fc1003ca62e40f67da8a6a46875c02 100644 (file)
@@ -1383,6 +1383,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
        x->curlft.add_time = orig->curlft.add_time;
        x->km.state = orig->km.state;
        x->km.seq = orig->km.seq;
+       x->replay = orig->replay;
+       x->preplay = orig->preplay;
 
        return x;
 
index 38614df33ec8d5751bd88a48d0068926b9032556..86116e9aaf3d9cee13b7c96d4d420e33842c1270 100644 (file)
@@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                        return 0;
                return err;
        }
+       xfrm_garbage_collect(net);
 
        c.data.type = type;
        c.event = nlh->nlmsg_type;
index b08ab4e889293c30f64b717065e6860603063f7c..9d751e209f313ca8f20a07e6d578cfb98c23defd 100644 (file)
@@ -306,7 +306,9 @@ int main(int argc, char *argv[])
        prog_attach_iptables(argv[2]);
        if (cfg_test_traffic) {
                if (signal(SIGINT, finish) == SIG_ERR)
-                       error(1, errno, "register handler failed");
+                       error(1, errno, "register SIGINT handler failed");
+               if (signal(SIGTERM, finish) == SIG_ERR)
+                       error(1, errno, "register SIGTERM handler failed");
                while (!test_finish) {
                        print_table();
                        printf("\n");
index 9cce2a66bd664c40668b3c8ca0dd12bd148bb21b..512f87a5fd20e08d0b97893b17e20e971425830e 100644 (file)
@@ -100,6 +100,7 @@ int main(int argc, char **argv)
        setrlimit(RLIMIT_MEMLOCK, &r);
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (load_kallsyms()) {
                printf("failed to process /proc/kallsyms\n");
index be59d7dcbdde3664c573a78d6d27adee03234a16..4ed690b907ff844961499d492350746065e423fb 100644 (file)
@@ -180,6 +180,7 @@ int main(int argc, char **argv)
                return 1;
        }
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        /* do sampling */
        printf("Sampling at %d Hertz for %d seconds. Ctrl-C also ends.\n",
index 0c5561d193a487f2257ccece359530b97b06a170..fa4336423da569f31fc432b9adc61f0835bb3f69 100644 (file)
@@ -192,6 +192,7 @@ int main(int argc, char **argv)
        setrlimit(RLIMIT_MEMLOCK, &r);
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (load_kallsyms()) {
                printf("failed to process /proc/kallsyms\n");
index 7fee0f1ba9a313baf2d233b3bf705994c183755e..7321a3f253c991f88e96f2a53e6ffa3e7c5f1719 100644 (file)
@@ -127,6 +127,7 @@ int main(int ac, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        /* start 'ping' in the background to have some kfree_skb events */
        f = popen("ping -c5 localhost", "r");
index 378850c70eb81afdbc5283611573f89ea4d8923e..2431c0321b712ce54d15414836b148d483a8a632 100644 (file)
@@ -62,13 +62,14 @@ static void usage(const char *prog)
        fprintf(stderr,
                "usage: %s [OPTS] IFINDEX\n\n"
                "OPTS:\n"
-               "    -S    use skb-mode\n",
+               "    -S    use skb-mode\n"
+               "    -N    enforce native mode\n",
                prog);
 }
 
 int main(int argc, char **argv)
 {
-       const char *optstr = "S";
+       const char *optstr = "SN";
        char filename[256];
        int opt;
 
@@ -77,6 +78,9 @@ int main(int argc, char **argv)
                case 'S':
                        xdp_flags |= XDP_FLAGS_SKB_MODE;
                        break;
+               case 'N':
+                       xdp_flags |= XDP_FLAGS_DRV_MODE;
+                       break;
                default:
                        usage(basename(argv[0]));
                        return 1;
@@ -102,6 +106,7 @@ int main(int argc, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
                printf("link set xdp fd failed\n");
index 92b8bde9337c8cec6128e73d23d307b628ba5a38..715cd12eaca5c0729d11e0918e564db9e2fa980f 100644 (file)
@@ -79,6 +79,8 @@ static void usage(const char *cmd)
        printf("    -m <dest-MAC> Used in sending the IP Tunneled pkt\n");
        printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
        printf("    -P <IP-Protocol> Default is TCP\n");
+       printf("    -S use skb-mode\n");
+       printf("    -N enforce native mode\n");
        printf("    -h Display this help\n");
 }
 
@@ -138,7 +140,7 @@ int main(int argc, char **argv)
 {
        unsigned char opt_flags[256] = {};
        unsigned int kill_after_s = 0;
-       const char *optstr = "i:a:p:s:d:m:T:P:Sh";
+       const char *optstr = "i:a:p:s:d:m:T:P:SNh";
        int min_port = 0, max_port = 0;
        struct iptnl_info tnl = {};
        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
@@ -206,6 +208,9 @@ int main(int argc, char **argv)
                case 'S':
                        xdp_flags |= XDP_FLAGS_SKB_MODE;
                        break;
+               case 'N':
+                       xdp_flags |= XDP_FLAGS_DRV_MODE;
+                       break;
                default:
                        usage(argv[0]);
                        return 1;
@@ -239,6 +244,7 @@ int main(int argc, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        while (min_port <= max_port) {
                vip.dport = htons(min_port++);
index 6ba97a1f9c5a26304abdf0f043211efe6c273ffc..c583a1e1bd3c16356cf67a772a3e680adec9681a 100644 (file)
@@ -8,6 +8,37 @@
 #
 # ==========================================================================
 
+PHONY := __headers
+__headers:
+
+include scripts/Kbuild.include
+
+srcdir        := $(srctree)/$(obj)
+
+# When make is run under a fakechroot environment, the function
+# $(wildcard $(srcdir)/*/.) doesn't only return directories, but also regular
+# files. So, we are using a combination of sort/dir/wildcard which works
+# with fakechroot.
+subdirs       := $(patsubst $(srcdir)/%/,%,\
+                $(filter-out $(srcdir)/,\
+                $(sort $(dir $(wildcard $(srcdir)/*/)))))
+
+# caller may set destination dir (when installing to asm/)
+_dst          := $(if $(dst),$(dst),$(obj))
+
+# Recursion
+__headers: $(subdirs)
+
+.PHONY: $(subdirs)
+$(subdirs):
+       $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
+
+# Skip header install/check for include/uapi and arch/$(hdr-arch)/include/uapi.
+# We have only sub-directories there.
+skip-inst := $(if $(filter %/uapi,$(obj)),1)
+
+ifeq ($(skip-inst),)
+
 # generated header directory
 gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
 
@@ -15,21 +46,14 @@ gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
 kbuild-file := $(srctree)/$(obj)/Kbuild
 -include $(kbuild-file)
 
-# called may set destination dir (when installing to asm/)
-_dst := $(if $(dst),$(dst),$(obj))
-
 old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
 ifneq ($(wildcard $(old-kbuild-file)),)
 include $(old-kbuild-file)
 endif
 
-include scripts/Kbuild.include
-
 installdir    := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst))
 
-srcdir        := $(srctree)/$(obj)
 gendir        := $(objtree)/$(gen)
-subdirs       := $(patsubst $(srcdir)/%/.,%,$(wildcard $(srcdir)/*/.))
 header-files  := $(notdir $(wildcard $(srcdir)/*.h))
 header-files  += $(notdir $(wildcard $(srcdir)/*.agh))
 header-files  := $(filter-out $(no-export-headers), $(header-files))
@@ -88,11 +112,9 @@ quiet_cmd_check = CHECK   $(printdir) ($(words $(all-files)) files)
                   $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
                  touch $@
 
-PHONY += __headersinst __headerscheck
-
 ifndef HDRCHECK
 # Rules for installing headers
-__headersinst: $(subdirs) $(install-file)
+__headers: $(install-file)
        @:
 
 targets += $(install-file)
@@ -104,7 +126,7 @@ $(install-file): scripts/headers_install.sh \
        $(call if_changed,install)
 
 else
-__headerscheck: $(subdirs) $(check-file)
+__headers: $(check-file)
        @:
 
 targets += $(check-file)
@@ -113,11 +135,6 @@ $(check-file): scripts/headers_check.pl $(output-files) FORCE
 
 endif
 
-# Recursion
-.PHONY: $(subdirs)
-$(subdirs):
-       $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
-
 targets := $(wildcard $(sort $(targets)))
 cmd_files := $(wildcard \
              $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
@@ -126,6 +143,8 @@ ifneq ($(cmd_files),)
        include $(cmd_files)
 endif
 
+endif # skip-inst
+
 .PHONY: $(PHONY)
 PHONY += FORCE
 FORCE: ;
index 6dc1eda13b8e841d8cdbdd2b0ec664df84607801..58c05e5d9870b6c18a72da7dc44ff3112994946d 100644 (file)
@@ -175,7 +175,7 @@ ld_flags       = $(LDFLAGS) $(ldflags-y)
 
 dtc_cpp_flags  = -Wp,-MD,$(depfile).pre.tmp -nostdinc                    \
                 -I$(srctree)/arch/$(SRCARCH)/boot/dts                   \
-                -I$(srctree)/arch/$(SRCARCH)/boot/dts/include           \
+                -I$(srctree)/scripts/dtc/include-prefixes               \
                 -I$(srctree)/drivers/of/testcase-data                   \
                 -undef -D__DTS__
 
index 5adfc8f52b4fd23e0533cb2084cc893753dd9abf..4b72b530c84f1f4b4e98d8342d9d62fefe8d34d6 100644 (file)
@@ -873,7 +873,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
        while (size--)
                reg = (reg << 32) | fdt32_to_cpu(*(cells++));
 
-       snprintf(unit_addr, sizeof(unit_addr), "%lx", reg);
+       snprintf(unit_addr, sizeof(unit_addr), "%zx", reg);
        if (!streq(unitname, unit_addr))
                FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
                     node->fullpath, unit_addr);
diff --git a/scripts/dtc/include-prefixes/arc b/scripts/dtc/include-prefixes/arc
new file mode 120000 (symlink)
index 0000000..5d21b5a
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/arc/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/arm b/scripts/dtc/include-prefixes/arm
new file mode 120000 (symlink)
index 0000000..eb14d45
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/arm/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/arm64 b/scripts/dtc/include-prefixes/arm64
new file mode 120000 (symlink)
index 0000000..275c42c
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/arm64/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/c6x b/scripts/dtc/include-prefixes/c6x
new file mode 120000 (symlink)
index 0000000..49ded4c
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/c6x/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/cris b/scripts/dtc/include-prefixes/cris
new file mode 120000 (symlink)
index 0000000..736d998
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/cris/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/dt-bindings b/scripts/dtc/include-prefixes/dt-bindings
new file mode 120000 (symlink)
index 0000000..04fdbb3
--- /dev/null
@@ -0,0 +1 @@
+../../../include/dt-bindings
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/h8300 b/scripts/dtc/include-prefixes/h8300
new file mode 120000 (symlink)
index 0000000..3bdaa33
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/h8300/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/metag b/scripts/dtc/include-prefixes/metag
new file mode 120000 (symlink)
index 0000000..87a3c84
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/metag/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/microblaze b/scripts/dtc/include-prefixes/microblaze
new file mode 120000 (symlink)
index 0000000..d983033
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/microblaze/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/mips b/scripts/dtc/include-prefixes/mips
new file mode 120000 (symlink)
index 0000000..ae8d494
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/mips/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/nios2 b/scripts/dtc/include-prefixes/nios2
new file mode 120000 (symlink)
index 0000000..5177233
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/nios2/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/openrisc b/scripts/dtc/include-prefixes/openrisc
new file mode 120000 (symlink)
index 0000000..71c3bc7
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/openrisc/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/powerpc b/scripts/dtc/include-prefixes/powerpc
new file mode 120000 (symlink)
index 0000000..7cd6ec1
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/powerpc/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/sh b/scripts/dtc/include-prefixes/sh
new file mode 120000 (symlink)
index 0000000..67d3780
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/sh/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/xtensa b/scripts/dtc/include-prefixes/xtensa
new file mode 120000 (symlink)
index 0000000..d1eaf6e
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/xtensa/boot/dts
\ No newline at end of file
index f9b92ece78343a463a37d33e3f73fa8621b84444..5afd1098e33a173a18b2310aa24d205534df711c 100644 (file)
@@ -23,10 +23,11 @@ class LxDmesg(gdb.Command):
         super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
-        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
-        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
-        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
-        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+        log_buf_addr = int(str(gdb.parse_and_eval(
+            "'printk.c'::log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
 
         inf = gdb.inferiors()[0]
         start = log_buf_addr + log_first_idx
index 3bffdcaaa274e82271a98c65fa0bc43cef53ffe2..b724a0290c75e45cbc89134f2b9ae03166ff27a5 100644 (file)
@@ -75,7 +75,7 @@ struct string_list *copy_list_range(struct string_list *start,
 int yylex(void);
 int yyparse(void);
 
-void error_with_pos(const char *, ...);
+void error_with_pos(const char *, ...) __attribute__ ((format(printf, 1, 2)));
 
 /*----------------------------------------------------------------------*/
 #define xmalloc(size) ({ void *__ptr = malloc(size);           \
index 90a091b6ae4de74e6c070d77255b9f4b5655629a..eb8144643b78355cea07f301531333001cd1d608 100644 (file)
@@ -196,7 +196,7 @@ clean-files     += config.pot linux.pot
 
 # Check that we have the required ncurses stuff installed for lxdialog (menuconfig)
 PHONY += $(obj)/dochecklxdialog
-$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog
+$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/dochecklxdialog
 $(obj)/dochecklxdialog:
        $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
 
index a9bc5334a478d6774d1409a837665b4f143d8597..0031147798153bdd06aa5c1f3d6f2015298b5b5d 100644 (file)
@@ -271,7 +271,7 @@ static struct mitem k_menu_items[MAX_MENU_ITEMS];
 static int items_num;
 static int global_exit;
 /* the currently selected button */
-const char *current_instructions = menu_instructions;
+static const char *current_instructions = menu_instructions;
 
 static char *dialog_input_result;
 static int dialog_input_result_len;
@@ -305,7 +305,7 @@ struct function_keys {
 };
 
 static const int function_keys_num = 9;
-struct function_keys function_keys[] = {
+static struct function_keys function_keys[] = {
        {
                .key_str = "F1",
                .func = "Help",
@@ -508,7 +508,7 @@ static int get_mext_match(const char *match_str, match_f flag)
        index = (index + items_num) % items_num;
        while (true) {
                char *str = k_menu_items[index].str;
-               if (strcasestr(str, match_str) != 0)
+               if (strcasestr(str, match_str) != NULL)
                        return index;
                if (flag == FIND_NEXT_MATCH_UP ||
                    flag == MATCH_TINKER_PATTERN_UP)
@@ -1067,7 +1067,7 @@ static int do_match(int key, struct match_state *state, int *ans)
 
 static void conf(struct menu *menu)
 {
-       struct menu *submenu = 0;
+       struct menu *submenu = NULL;
        const char *prompt = menu_get_prompt(menu);
        struct symbol *sym;
        int res;
@@ -1234,7 +1234,7 @@ static void show_help(struct menu *menu)
 static void conf_choice(struct menu *menu)
 {
        const char *prompt = _(menu_get_prompt(menu));
-       struct menu *child = 0;
+       struct menu *child = NULL;
        struct symbol *active;
        int selected_index = 0;
        int last_top_row = 0;
@@ -1456,7 +1456,7 @@ static void conf_save(void)
        }
 }
 
-void setup_windows(void)
+static void setup_windows(void)
 {
        int lines, columns;
 
index 4b2f44c20caf8941d150f261074b40d589a10376..a64b1c31253e13b918fefe509e1cccf5b4ac248d 100644 (file)
@@ -129,7 +129,7 @@ static void no_colors_theme(void)
        mkattrn(FUNCTION_TEXT, A_REVERSE);
 }
 
-void set_colors()
+void set_colors(void)
 {
        start_color();
        use_default_colors();
@@ -192,7 +192,7 @@ const char *get_line(const char *text, int line_no)
        int lines = 0;
 
        if (!text)
-               return 0;
+               return NULL;
 
        for (i = 0; text[i] != '\0' && lines < line_no; i++)
                if (text[i] == '\n')
index d661f2f3ef614c41e22f2346ee9b41b238266715..d23dcbf17457c2c16cf56c73a1ffb3d07e03a257 100755 (executable)
@@ -106,6 +106,7 @@ all_compiled_sources()
                case "$i" in
                        *.[cS])
                                j=${i/\.[cS]/\.o}
+                               j="${j#$tree}"
                                if [ -e $j ]; then
                                        echo $i
                                fi
index 6fd95f76bfaeaf4a300219ee290048c3913632a5..a7a23b5541f85a4994e0cc83d7d132e8a5681938 100644 (file)
@@ -20,6 +20,10 @@ config KEYS
 
          If you are unsure as to whether this is required, answer N.
 
+config KEYS_COMPAT
+       def_bool y
+       depends on COMPAT && KEYS
+
 config PERSISTENT_KEYRINGS
        bool "Enable register of persistent per-UID keyrings"
        depends on KEYS
@@ -89,9 +93,9 @@ config ENCRYPTED_KEYS
 config KEY_DH_OPERATIONS
        bool "Diffie-Hellman operations on retained keys"
        depends on KEYS
-       select MPILIB
        select CRYPTO
        select CRYPTO_HASH
+       select CRYPTO_DH
        help
         This option provides support for calculating Diffie-Hellman
         public keys and shared secrets using values stored as keys
index e603bd912e4c2300287e98248449a55b2e0b4ea4..4755d4b4f94544236cd2b8cca1b2169b895579b7 100644 (file)
@@ -8,34 +8,17 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/mpi.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/scatterlist.h>
 #include <linux/crypto.h>
 #include <crypto/hash.h>
+#include <crypto/kpp.h>
+#include <crypto/dh.h>
 #include <keys/user-type.h>
 #include "internal.h"
 
-/*
- * Public key or shared secret generation function [RFC2631 sec 2.1.1]
- *
- * ya = g^xa mod p;
- * or
- * ZZ = yb^xa mod p;
- *
- * where xa is the local private key, ya is the local public key, g is
- * the generator, p is the prime, yb is the remote public key, and ZZ
- * is the shared secret.
- *
- * Both are the same calculation, so g or yb are the "base" and ya or
- * ZZ are the "result".
- */
-static int do_dh(MPI result, MPI base, MPI xa, MPI p)
-{
-       return mpi_powm(result, base, xa, p);
-}
-
-static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi)
+static ssize_t dh_data_from_key(key_serial_t keyid, void **data)
 {
        struct key *key;
        key_ref_t key_ref;
@@ -56,19 +39,17 @@ static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi)
                status = key_validate(key);
                if (status == 0) {
                        const struct user_key_payload *payload;
+                       uint8_t *duplicate;
 
                        payload = user_key_payload_locked(key);
 
-                       if (maxlen == 0) {
-                               *mpi = NULL;
+                       duplicate = kmemdup(payload->data, payload->datalen,
+                                           GFP_KERNEL);
+                       if (duplicate) {
+                               *data = duplicate;
                                ret = payload->datalen;
-                       } else if (payload->datalen <= maxlen) {
-                               *mpi = mpi_read_raw_data(payload->data,
-                                                        payload->datalen);
-                               if (*mpi)
-                                       ret = payload->datalen;
                        } else {
-                               ret = -EINVAL;
+                               ret = -ENOMEM;
                        }
                }
                up_read(&key->sem);
@@ -79,6 +60,29 @@ error:
        return ret;
 }
 
+static void dh_free_data(struct dh *dh)
+{
+       kzfree(dh->key);
+       kzfree(dh->p);
+       kzfree(dh->g);
+}
+
+struct dh_completion {
+       struct completion completion;
+       int err;
+};
+
+static void dh_crypto_done(struct crypto_async_request *req, int err)
+{
+       struct dh_completion *compl = req->data;
+
+       if (err == -EINPROGRESS)
+               return;
+
+       compl->err = err;
+       complete(&compl->completion);
+}
+
 struct kdf_sdesc {
        struct shash_desc shash;
        char ctx[];
@@ -89,6 +93,7 @@ static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname)
        struct crypto_shash *tfm;
        struct kdf_sdesc *sdesc;
        int size;
+       int err;
 
        /* allocate synchronous hash */
        tfm = crypto_alloc_shash(hashname, 0, 0);
@@ -97,16 +102,25 @@ static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname)
                return PTR_ERR(tfm);
        }
 
+       err = -EINVAL;
+       if (crypto_shash_digestsize(tfm) == 0)
+               goto out_free_tfm;
+
+       err = -ENOMEM;
        size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm);
        sdesc = kmalloc(size, GFP_KERNEL);
        if (!sdesc)
-               return -ENOMEM;
+               goto out_free_tfm;
        sdesc->shash.tfm = tfm;
        sdesc->shash.flags = 0x0;
 
        *sdesc_ret = sdesc;
 
        return 0;
+
+out_free_tfm:
+       crypto_free_shash(tfm);
+       return err;
 }
 
 static void kdf_dealloc(struct kdf_sdesc *sdesc)
@@ -120,14 +134,6 @@ static void kdf_dealloc(struct kdf_sdesc *sdesc)
        kzfree(sdesc);
 }
 
-/* convert 32 bit integer into its string representation */
-static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf)
-{
-       __be32 *a = (__be32 *)buf;
-
-       *a = cpu_to_be32(val);
-}
-
 /*
  * Implementation of the KDF in counter mode according to SP800-108 section 5.1
  * as well as SP800-56A section 5.8.1 (Single-step KDF).
@@ -138,25 +144,39 @@ static inline void crypto_kw_cpu_to_be32(u32 val, u8 *buf)
  * 5.8.1.2).
  */
 static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
-                  u8 *dst, unsigned int dlen)
+                  u8 *dst, unsigned int dlen, unsigned int zlen)
 {
        struct shash_desc *desc = &sdesc->shash;
        unsigned int h = crypto_shash_digestsize(desc->tfm);
        int err = 0;
        u8 *dst_orig = dst;
-       u32 i = 1;
-       u8 iteration[sizeof(u32)];
+       __be32 counter = cpu_to_be32(1);
 
        while (dlen) {
                err = crypto_shash_init(desc);
                if (err)
                        goto err;
 
-               crypto_kw_cpu_to_be32(i, iteration);
-               err = crypto_shash_update(desc, iteration, sizeof(u32));
+               err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32));
                if (err)
                        goto err;
 
+               if (zlen && h) {
+                       u8 tmpbuffer[h];
+                       size_t chunk = min_t(size_t, zlen, h);
+                       memset(tmpbuffer, 0, chunk);
+
+                       do {
+                               err = crypto_shash_update(desc, tmpbuffer,
+                                                         chunk);
+                               if (err)
+                                       goto err;
+
+                               zlen -= chunk;
+                               chunk = min_t(size_t, zlen, h);
+                       } while (zlen);
+               }
+
                if (src && slen) {
                        err = crypto_shash_update(desc, src, slen);
                        if (err)
@@ -179,7 +199,7 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
 
                        dlen -= h;
                        dst += h;
-                       i++;
+                       counter = cpu_to_be32(be32_to_cpu(counter) + 1);
                }
        }
 
@@ -192,7 +212,7 @@ err:
 
 static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
                                 char __user *buffer, size_t buflen,
-                                uint8_t *kbuf, size_t kbuflen)
+                                uint8_t *kbuf, size_t kbuflen, size_t lzero)
 {
        uint8_t *outbuf = NULL;
        int ret;
@@ -203,7 +223,7 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
                goto err;
        }
 
-       ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen);
+       ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen, lzero);
        if (ret)
                goto err;
 
@@ -221,21 +241,26 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
                         struct keyctl_kdf_params *kdfcopy)
 {
        long ret;
-       MPI base, private, prime, result;
-       unsigned nbytes;
+       ssize_t dlen;
+       int secretlen;
+       int outlen;
        struct keyctl_dh_params pcopy;
-       uint8_t *kbuf;
-       ssize_t keylen;
-       size_t resultlen;
+       struct dh dh_inputs;
+       struct scatterlist outsg;
+       struct dh_completion compl;
+       struct crypto_kpp *tfm;
+       struct kpp_request *req;
+       uint8_t *secret;
+       uint8_t *outbuf;
        struct kdf_sdesc *sdesc = NULL;
 
        if (!params || (!buffer && buflen)) {
                ret = -EINVAL;
-               goto out;
+               goto out1;
        }
        if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) {
                ret = -EFAULT;
-               goto out;
+               goto out1;
        }
 
        if (kdfcopy) {
@@ -244,104 +269,147 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
                if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN ||
                    kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) {
                        ret = -EMSGSIZE;
-                       goto out;
+                       goto out1;
                }
 
                /* get KDF name string */
                hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME);
                if (IS_ERR(hashname)) {
                        ret = PTR_ERR(hashname);
-                       goto out;
+                       goto out1;
                }
 
                /* allocate KDF from the kernel crypto API */
                ret = kdf_alloc(&sdesc, hashname);
                kfree(hashname);
                if (ret)
-                       goto out;
+                       goto out1;
        }
 
-       /*
-        * If the caller requests postprocessing with a KDF, allow an
-        * arbitrary output buffer size since the KDF ensures proper truncation.
-        */
-       keylen = mpi_from_key(pcopy.prime, kdfcopy ? SIZE_MAX : buflen, &prime);
-       if (keylen < 0 || !prime) {
-               /* buflen == 0 may be used to query the required buffer size,
-                * which is the prime key length.
-                */
-               ret = keylen;
-               goto out;
+       memset(&dh_inputs, 0, sizeof(dh_inputs));
+
+       dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p);
+       if (dlen < 0) {
+               ret = dlen;
+               goto out1;
+       }
+       dh_inputs.p_size = dlen;
+
+       dlen = dh_data_from_key(pcopy.base, &dh_inputs.g);
+       if (dlen < 0) {
+               ret = dlen;
+               goto out2;
        }
+       dh_inputs.g_size = dlen;
 
-       /* The result is never longer than the prime */
-       resultlen = keylen;
+       dlen = dh_data_from_key(pcopy.private, &dh_inputs.key);
+       if (dlen < 0) {
+               ret = dlen;
+               goto out2;
+       }
+       dh_inputs.key_size = dlen;
 
-       keylen = mpi_from_key(pcopy.base, SIZE_MAX, &base);
-       if (keylen < 0 || !base) {
-               ret = keylen;
-               goto error1;
+       secretlen = crypto_dh_key_len(&dh_inputs);
+       secret = kmalloc(secretlen, GFP_KERNEL);
+       if (!secret) {
+               ret = -ENOMEM;
+               goto out2;
        }
+       ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs);
+       if (ret)
+               goto out3;
 
-       keylen = mpi_from_key(pcopy.private, SIZE_MAX, &private);
-       if (keylen < 0 || !private) {
-               ret = keylen;
-               goto error2;
+       tfm = crypto_alloc_kpp("dh", CRYPTO_ALG_TYPE_KPP, 0);
+       if (IS_ERR(tfm)) {
+               ret = PTR_ERR(tfm);
+               goto out3;
+       }
+
+       ret = crypto_kpp_set_secret(tfm, secret, secretlen);
+       if (ret)
+               goto out4;
+
+       outlen = crypto_kpp_maxsize(tfm);
+
+       if (!kdfcopy) {
+               /*
+                * When not using a KDF, buflen 0 is used to read the
+                * required buffer length
+                */
+               if (buflen == 0) {
+                       ret = outlen;
+                       goto out4;
+               } else if (outlen > buflen) {
+                       ret = -EOVERFLOW;
+                       goto out4;
+               }
        }
 
-       result = mpi_alloc(0);
-       if (!result) {
+       outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen,
+                        GFP_KERNEL);
+       if (!outbuf) {
                ret = -ENOMEM;
-               goto error3;
+               goto out4;
        }
 
-       /* allocate space for DH shared secret and SP800-56A otherinfo */
-       kbuf = kmalloc(kdfcopy ? (resultlen + kdfcopy->otherinfolen) : resultlen,
-                      GFP_KERNEL);
-       if (!kbuf) {
+       sg_init_one(&outsg, outbuf, outlen);
+
+       req = kpp_request_alloc(tfm, GFP_KERNEL);
+       if (!req) {
                ret = -ENOMEM;
-               goto error4;
+               goto out5;
        }
 
+       kpp_request_set_input(req, NULL, 0);
+       kpp_request_set_output(req, &outsg, outlen);
+       init_completion(&compl.completion);
+       kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+                                CRYPTO_TFM_REQ_MAY_SLEEP,
+                                dh_crypto_done, &compl);
+
        /*
-        * Concatenate SP800-56A otherinfo past DH shared secret -- the
-        * input to the KDF is (DH shared secret || otherinfo)
+        * For DH, generate_public_key and generate_shared_secret are
+        * the same calculation
         */
-       if (kdfcopy && kdfcopy->otherinfo &&
-           copy_from_user(kbuf + resultlen, kdfcopy->otherinfo,
-                          kdfcopy->otherinfolen) != 0) {
-               ret = -EFAULT;
-               goto error5;
+       ret = crypto_kpp_generate_public_key(req);
+       if (ret == -EINPROGRESS) {
+               wait_for_completion(&compl.completion);
+               ret = compl.err;
+               if (ret)
+                       goto out6;
        }
 
-       ret = do_dh(result, base, private, prime);
-       if (ret)
-               goto error5;
-
-       ret = mpi_read_buffer(result, kbuf, resultlen, &nbytes, NULL);
-       if (ret != 0)
-               goto error5;
-
        if (kdfcopy) {
-               ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, kbuf,
-                                           resultlen + kdfcopy->otherinfolen);
-       } else {
-               ret = nbytes;
-               if (copy_to_user(buffer, kbuf, nbytes) != 0)
+               /*
+                * Concatenate SP800-56A otherinfo past DH shared secret -- the
+                * input to the KDF is (DH shared secret || otherinfo)
+                */
+               if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo,
+                                  kdfcopy->otherinfolen) != 0) {
                        ret = -EFAULT;
+                       goto out6;
+               }
+
+               ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, outbuf,
+                                           req->dst_len + kdfcopy->otherinfolen,
+                                           outlen - req->dst_len);
+       } else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) {
+               ret = req->dst_len;
+       } else {
+               ret = -EFAULT;
        }
 
-error5:
-       kzfree(kbuf);
-error4:
-       mpi_free(result);
-error3:
-       mpi_free(private);
-error2:
-       mpi_free(base);
-error1:
-       mpi_free(prime);
-out:
+out6:
+       kpp_request_free(req);
+out5:
+       kzfree(outbuf);
+out4:
+       crypto_free_kpp(tfm);
+out3:
+       kzfree(secret);
+out2:
+       dh_free_data(&dh_inputs);
+out1:
        kdf_dealloc(sdesc);
        return ret;
 }
index 0010955d7876c2302704020af8b2ffb6010f2c0a..bb6324d1ccec32f6dde05f520d8d2ed2e089c785 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/scatterlist.h>
 #include <linux/ctype.h>
 #include <crypto/aes.h>
+#include <crypto/algapi.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <crypto/skcipher.h>
@@ -54,13 +55,7 @@ static int blksize;
 #define MAX_DATA_SIZE 4096
 #define MIN_DATA_SIZE  20
 
-struct sdesc {
-       struct shash_desc shash;
-       char ctx[];
-};
-
-static struct crypto_shash *hashalg;
-static struct crypto_shash *hmacalg;
+static struct crypto_shash *hash_tfm;
 
 enum {
        Opt_err = -1, Opt_new, Opt_load, Opt_update
@@ -141,23 +136,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc)
  */
 static int valid_master_desc(const char *new_desc, const char *orig_desc)
 {
-       if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) {
-               if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN)
-                       goto out;
-               if (orig_desc)
-                       if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN))
-                               goto out;
-       } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) {
-               if (strlen(new_desc) == KEY_USER_PREFIX_LEN)
-                       goto out;
-               if (orig_desc)
-                       if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN))
-                               goto out;
-       } else
-               goto out;
+       int prefix_len;
+
+       if (!strncmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN))
+               prefix_len = KEY_TRUSTED_PREFIX_LEN;
+       else if (!strncmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN))
+               prefix_len = KEY_USER_PREFIX_LEN;
+       else
+               return -EINVAL;
+
+       if (!new_desc[prefix_len])
+               return -EINVAL;
+
+       if (orig_desc && strncmp(new_desc, orig_desc, prefix_len))
+               return -EINVAL;
+
        return 0;
-out:
-       return -EINVAL;
 }
 
 /*
@@ -321,53 +315,38 @@ error:
        return ukey;
 }
 
-static struct sdesc *alloc_sdesc(struct crypto_shash *alg)
-{
-       struct sdesc *sdesc;
-       int size;
-
-       size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
-       sdesc = kmalloc(size, GFP_KERNEL);
-       if (!sdesc)
-               return ERR_PTR(-ENOMEM);
-       sdesc->shash.tfm = alg;
-       sdesc->shash.flags = 0x0;
-       return sdesc;
-}
-
-static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
+static int calc_hash(struct crypto_shash *tfm, u8 *digest,
                     const u8 *buf, unsigned int buflen)
 {
-       struct sdesc *sdesc;
-       int ret;
+       SHASH_DESC_ON_STACK(desc, tfm);
+       int err;
 
-       sdesc = alloc_sdesc(hmacalg);
-       if (IS_ERR(sdesc)) {
-               pr_info("encrypted_key: can't alloc %s\n", hmac_alg);
-               return PTR_ERR(sdesc);
-       }
+       desc->tfm = tfm;
+       desc->flags = 0;
 
-       ret = crypto_shash_setkey(hmacalg, key, keylen);
-       if (!ret)
-               ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest);
-       kfree(sdesc);
-       return ret;
+       err = crypto_shash_digest(desc, buf, buflen, digest);
+       shash_desc_zero(desc);
+       return err;
 }
 
-static int calc_hash(u8 *digest, const u8 *buf, unsigned int buflen)
+static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen,
+                    const u8 *buf, unsigned int buflen)
 {
-       struct sdesc *sdesc;
-       int ret;
+       struct crypto_shash *tfm;
+       int err;
 
-       sdesc = alloc_sdesc(hashalg);
-       if (IS_ERR(sdesc)) {
-               pr_info("encrypted_key: can't alloc %s\n", hash_alg);
-               return PTR_ERR(sdesc);
+       tfm = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(tfm)) {
+               pr_err("encrypted_key: can't alloc %s transform: %ld\n",
+                      hmac_alg, PTR_ERR(tfm));
+               return PTR_ERR(tfm);
        }
 
-       ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest);
-       kfree(sdesc);
-       return ret;
+       err = crypto_shash_setkey(tfm, key, keylen);
+       if (!err)
+               err = calc_hash(tfm, digest, buf, buflen);
+       crypto_free_shash(tfm);
+       return err;
 }
 
 enum derived_key_type { ENC_KEY, AUTH_KEY };
@@ -385,10 +364,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
                derived_buf_len = HASH_SIZE;
 
        derived_buf = kzalloc(derived_buf_len, GFP_KERNEL);
-       if (!derived_buf) {
-               pr_err("encrypted_key: out of memory\n");
+       if (!derived_buf)
                return -ENOMEM;
-       }
+
        if (key_type)
                strcpy(derived_buf, "AUTH_KEY");
        else
@@ -396,8 +374,8 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
 
        memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
               master_keylen);
-       ret = calc_hash(derived_key, derived_buf, derived_buf_len);
-       kfree(derived_buf);
+       ret = calc_hash(hash_tfm, derived_key, derived_buf, derived_buf_len);
+       kzfree(derived_buf);
        return ret;
 }
 
@@ -480,12 +458,9 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
        struct skcipher_request *req;
        unsigned int encrypted_datalen;
        u8 iv[AES_BLOCK_SIZE];
-       unsigned int padlen;
-       char pad[16];
        int ret;
 
        encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
-       padlen = encrypted_datalen - epayload->decrypted_datalen;
 
        req = init_skcipher_req(derived_key, derived_keylen);
        ret = PTR_ERR(req);
@@ -493,11 +468,10 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
                goto out;
        dump_decrypted_data(epayload);
 
-       memset(pad, 0, sizeof pad);
        sg_init_table(sg_in, 2);
        sg_set_buf(&sg_in[0], epayload->decrypted_data,
                   epayload->decrypted_datalen);
-       sg_set_buf(&sg_in[1], pad, padlen);
+       sg_set_page(&sg_in[1], ZERO_PAGE(0), AES_BLOCK_SIZE, 0);
 
        sg_init_table(sg_out, 1);
        sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
@@ -533,6 +507,7 @@ static int datablob_hmac_append(struct encrypted_key_payload *epayload,
        if (!ret)
                dump_hmac(NULL, digest, HASH_SIZE);
 out:
+       memzero_explicit(derived_key, sizeof(derived_key));
        return ret;
 }
 
@@ -561,8 +536,8 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
        ret = calc_hmac(digest, derived_key, sizeof derived_key, p, len);
        if (ret < 0)
                goto out;
-       ret = memcmp(digest, epayload->format + epayload->datablob_len,
-                    sizeof digest);
+       ret = crypto_memneq(digest, epayload->format + epayload->datablob_len,
+                           sizeof(digest));
        if (ret) {
                ret = -EINVAL;
                dump_hmac("datablob",
@@ -571,6 +546,7 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload,
                dump_hmac("calc", digest, HASH_SIZE);
        }
 out:
+       memzero_explicit(derived_key, sizeof(derived_key));
        return ret;
 }
 
@@ -584,9 +560,14 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
        struct skcipher_request *req;
        unsigned int encrypted_datalen;
        u8 iv[AES_BLOCK_SIZE];
-       char pad[16];
+       u8 *pad;
        int ret;
 
+       /* Throwaway buffer to hold the unused zero padding at the end */
+       pad = kmalloc(AES_BLOCK_SIZE, GFP_KERNEL);
+       if (!pad)
+               return -ENOMEM;
+
        encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
        req = init_skcipher_req(derived_key, derived_keylen);
        ret = PTR_ERR(req);
@@ -594,13 +575,12 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
                goto out;
        dump_encrypted_data(epayload, encrypted_datalen);
 
-       memset(pad, 0, sizeof pad);
        sg_init_table(sg_in, 1);
        sg_init_table(sg_out, 2);
        sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen);
        sg_set_buf(&sg_out[0], epayload->decrypted_data,
                   epayload->decrypted_datalen);
-       sg_set_buf(&sg_out[1], pad, sizeof pad);
+       sg_set_buf(&sg_out[1], pad, AES_BLOCK_SIZE);
 
        memcpy(iv, epayload->iv, sizeof(iv));
        skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv);
@@ -612,6 +592,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
                goto out;
        dump_decrypted_data(epayload);
 out:
+       kfree(pad);
        return ret;
 }
 
@@ -722,6 +703,7 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
 out:
        up_read(&mkey->sem);
        key_put(mkey);
+       memzero_explicit(derived_key, sizeof(derived_key));
        return ret;
 }
 
@@ -828,13 +810,13 @@ static int encrypted_instantiate(struct key *key,
        ret = encrypted_init(epayload, key->description, format, master_desc,
                             decrypted_datalen, hex_encoded_iv);
        if (ret < 0) {
-               kfree(epayload);
+               kzfree(epayload);
                goto out;
        }
 
        rcu_assign_keypointer(key, epayload);
 out:
-       kfree(datablob);
+       kzfree(datablob);
        return ret;
 }
 
@@ -843,8 +825,7 @@ static void encrypted_rcu_free(struct rcu_head *rcu)
        struct encrypted_key_payload *epayload;
 
        epayload = container_of(rcu, struct encrypted_key_payload, rcu);
-       memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
-       kfree(epayload);
+       kzfree(epayload);
 }
 
 /*
@@ -902,7 +883,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
        rcu_assign_keypointer(key, new_epayload);
        call_rcu(&epayload->rcu, encrypted_rcu_free);
 out:
-       kfree(buf);
+       kzfree(buf);
        return ret;
 }
 
@@ -960,33 +941,26 @@ static long encrypted_read(const struct key *key, char __user *buffer,
 
        up_read(&mkey->sem);
        key_put(mkey);
+       memzero_explicit(derived_key, sizeof(derived_key));
 
        if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0)
                ret = -EFAULT;
-       kfree(ascii_buf);
+       kzfree(ascii_buf);
 
        return asciiblob_len;
 out:
        up_read(&mkey->sem);
        key_put(mkey);
+       memzero_explicit(derived_key, sizeof(derived_key));
        return ret;
 }
 
 /*
- * encrypted_destroy - before freeing the key, clear the decrypted data
- *
- * Before freeing the key, clear the memory containing the decrypted
- * key data.
+ * encrypted_destroy - clear and free the key's payload
  */
 static void encrypted_destroy(struct key *key)
 {
-       struct encrypted_key_payload *epayload = key->payload.data[0];
-
-       if (!epayload)
-               return;
-
-       memzero_explicit(epayload->decrypted_data, epayload->decrypted_datalen);
-       kfree(key->payload.data[0]);
+       kzfree(key->payload.data[0]);
 }
 
 struct key_type key_type_encrypted = {
@@ -999,47 +973,17 @@ struct key_type key_type_encrypted = {
 };
 EXPORT_SYMBOL_GPL(key_type_encrypted);
 
-static void encrypted_shash_release(void)
-{
-       if (hashalg)
-               crypto_free_shash(hashalg);
-       if (hmacalg)
-               crypto_free_shash(hmacalg);
-}
-
-static int __init encrypted_shash_alloc(void)
+static int __init init_encrypted(void)
 {
        int ret;
 
-       hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hmacalg)) {
-               pr_info("encrypted_key: could not allocate crypto %s\n",
-                       hmac_alg);
-               return PTR_ERR(hmacalg);
-       }
-
-       hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(hashalg)) {
-               pr_info("encrypted_key: could not allocate crypto %s\n",
-                       hash_alg);
-               ret = PTR_ERR(hashalg);
-               goto hashalg_fail;
+       hash_tfm = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(hash_tfm)) {
+               pr_err("encrypted_key: can't allocate %s transform: %ld\n",
+                      hash_alg, PTR_ERR(hash_tfm));
+               return PTR_ERR(hash_tfm);
        }
 
-       return 0;
-
-hashalg_fail:
-       crypto_free_shash(hmacalg);
-       return ret;
-}
-
-static int __init init_encrypted(void)
-{
-       int ret;
-
-       ret = encrypted_shash_alloc();
-       if (ret < 0)
-               return ret;
        ret = aes_get_sizes();
        if (ret < 0)
                goto out;
@@ -1048,14 +992,14 @@ static int __init init_encrypted(void)
                goto out;
        return 0;
 out:
-       encrypted_shash_release();
+       crypto_free_shash(hash_tfm);
        return ret;
 
 }
 
 static void __exit cleanup_encrypted(void)
 {
-       encrypted_shash_release();
+       crypto_free_shash(hash_tfm);
        unregister_key_type(&key_type_encrypted);
 }
 
index 595becc6d0d259a017be1305842f6208562324bb..87cb260e4890f3ac464e8d3f3244077653510b74 100644 (file)
@@ -158,9 +158,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
 
                kfree(key->description);
 
-#ifdef KEY_DEBUGGING
-               key->magic = KEY_DEBUG_MAGIC_X;
-#endif
+               memzero_explicit(key, sizeof(*key));
                kmem_cache_free(key_jar, key);
        }
 }
index 455c04d80bbbf27a7b20433708f35fde1ad26ffb..83da68d98b40b452a1c8b37121a6ca270387d4f6 100644 (file)
@@ -660,14 +660,11 @@ not_found:
        goto error;
 
 found:
-       /* pretend it doesn't exist if it is awaiting deletion */
-       if (refcount_read(&key->usage) == 0)
-               goto not_found;
-
-       /* this races with key_put(), but that doesn't matter since key_put()
-        * doesn't actually change the key
+       /* A key is allowed to be looked up only if someone still owns a
+        * reference to it - otherwise it's awaiting the gc.
         */
-       __key_get(key);
+       if (!refcount_inc_not_zero(&key->usage))
+               goto not_found;
 
 error:
        spin_unlock(&key_serial_lock);
@@ -966,12 +963,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
        /* the key must be writable */
        ret = key_permission(key_ref, KEY_NEED_WRITE);
        if (ret < 0)
-               goto error;
+               return ret;
 
        /* attempt to update it if supported */
-       ret = -EOPNOTSUPP;
        if (!key->type->update)
-               goto error;
+               return -EOPNOTSUPP;
 
        memset(&prep, 0, sizeof(prep));
        prep.data = payload;
index 447a7d5cee0f56ebcb1847d9442f6407e259be98..ab0b337c84b4c02e4856719398edb94d1caf101a 100644 (file)
@@ -99,7 +99,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
        /* pull the payload in if one was supplied */
        payload = NULL;
 
-       if (_payload) {
+       if (plen) {
                ret = -ENOMEM;
                payload = kvmalloc(plen, GFP_KERNEL);
                if (!payload)
@@ -132,7 +132,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
 
        key_ref_put(keyring_ref);
  error3:
-       kvfree(payload);
+       if (payload) {
+               memzero_explicit(payload, plen);
+               kvfree(payload);
+       }
  error2:
        kfree(description);
  error:
@@ -324,7 +327,7 @@ long keyctl_update_key(key_serial_t id,
 
        /* pull the payload in if one was supplied */
        payload = NULL;
-       if (_payload) {
+       if (plen) {
                ret = -ENOMEM;
                payload = kmalloc(plen, GFP_KERNEL);
                if (!payload)
@@ -347,7 +350,7 @@ long keyctl_update_key(key_serial_t id,
 
        key_ref_put(key_ref);
 error2:
-       kfree(payload);
+       kzfree(payload);
 error:
        return ret;
 }
@@ -1093,7 +1096,10 @@ long keyctl_instantiate_key_common(key_serial_t id,
                keyctl_change_reqkey_auth(NULL);
 
 error2:
-       kvfree(payload);
+       if (payload) {
+               memzero_explicit(payload, plen);
+               kvfree(payload);
+       }
 error:
        return ret;
 }
index 4d1678e4586f6ae29610bfb818c33000413947bf..de81793f9920787101dec77eca28ddfbe91ebbc7 100644 (file)
@@ -706,7 +706,7 @@ descend_to_keyring:
         * Non-keyrings avoid the leftmost branch of the root entirely (root
         * slots 1-15).
         */
-       ptr = ACCESS_ONCE(keyring->keys.root);
+       ptr = READ_ONCE(keyring->keys.root);
        if (!ptr)
                goto not_this_keyring;
 
@@ -720,7 +720,7 @@ descend_to_keyring:
                if ((shortcut->index_key[0] & ASSOC_ARRAY_FAN_MASK) != 0)
                        goto not_this_keyring;
 
-               ptr = ACCESS_ONCE(shortcut->next_node);
+               ptr = READ_ONCE(shortcut->next_node);
                node = assoc_array_ptr_to_node(ptr);
                goto begin_node;
        }
@@ -740,7 +740,7 @@ descend_to_node:
        if (assoc_array_ptr_is_shortcut(ptr)) {
                shortcut = assoc_array_ptr_to_shortcut(ptr);
                smp_read_barrier_depends();
-               ptr = ACCESS_ONCE(shortcut->next_node);
+               ptr = READ_ONCE(shortcut->next_node);
                BUG_ON(!assoc_array_ptr_is_node(ptr));
        }
        node = assoc_array_ptr_to_node(ptr);
@@ -752,7 +752,7 @@ begin_node:
 ascend_to_node:
        /* Go through the slots in a node */
        for (; slot < ASSOC_ARRAY_FAN_OUT; slot++) {
-               ptr = ACCESS_ONCE(node->slots[slot]);
+               ptr = READ_ONCE(node->slots[slot]);
 
                if (assoc_array_ptr_is_meta(ptr) && node->back_pointer)
                        goto descend_to_node;
@@ -790,13 +790,13 @@ ascend_to_node:
        /* We've dealt with all the slots in the current node, so now we need
         * to ascend to the parent and continue processing there.
         */
-       ptr = ACCESS_ONCE(node->back_pointer);
+       ptr = READ_ONCE(node->back_pointer);
        slot = node->parent_slot;
 
        if (ptr && assoc_array_ptr_is_shortcut(ptr)) {
                shortcut = assoc_array_ptr_to_shortcut(ptr);
                smp_read_barrier_depends();
-               ptr = ACCESS_ONCE(shortcut->back_pointer);
+               ptr = READ_ONCE(shortcut->back_pointer);
                slot = shortcut->parent_slot;
        }
        if (!ptr)
index 2217dfec7996159797abce9d2480fa249691cf28..86bced9fdbdf22eb60170584d87730e1179a2744 100644 (file)
@@ -809,15 +809,14 @@ long join_session_keyring(const char *name)
                ret = PTR_ERR(keyring);
                goto error2;
        } else if (keyring == new->session_keyring) {
-               key_put(keyring);
                ret = 0;
-               goto error2;
+               goto error3;
        }
 
        /* we've got a keyring - now to install it */
        ret = install_session_keyring_to_cred(new, keyring);
        if (ret < 0)
-               goto error2;
+               goto error3;
 
        commit_creds(new);
        mutex_unlock(&key_session_mutex);
@@ -827,6 +826,8 @@ long join_session_keyring(const char *name)
 okay:
        return ret;
 
+error3:
+       key_put(keyring);
 error2:
        mutex_unlock(&key_session_mutex);
 error:
index 2ae31c5a87de9e9084de7e5f9350678da81b49a4..435e86e1387944d723cc569f228239f94c800a81 100644 (file)
@@ -70,7 +70,7 @@ static int TSS_sha1(const unsigned char *data, unsigned int datalen,
        }
 
        ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
-       kfree(sdesc);
+       kzfree(sdesc);
        return ret;
 }
 
@@ -114,7 +114,7 @@ static int TSS_rawhmac(unsigned char *digest, const unsigned char *key,
        if (!ret)
                ret = crypto_shash_final(&sdesc->shash, digest);
 out:
-       kfree(sdesc);
+       kzfree(sdesc);
        return ret;
 }
 
@@ -165,7 +165,7 @@ static int TSS_authhmac(unsigned char *digest, const unsigned char *key,
                                  paramdigest, TPM_NONCE_SIZE, h1,
                                  TPM_NONCE_SIZE, h2, 1, &c, 0, 0);
 out:
-       kfree(sdesc);
+       kzfree(sdesc);
        return ret;
 }
 
@@ -246,7 +246,7 @@ static int TSS_checkhmac1(unsigned char *buffer,
        if (memcmp(testhmac, authdata, SHA1_DIGEST_SIZE))
                ret = -EINVAL;
 out:
-       kfree(sdesc);
+       kzfree(sdesc);
        return ret;
 }
 
@@ -347,7 +347,7 @@ static int TSS_checkhmac2(unsigned char *buffer,
        if (memcmp(testhmac2, authdata2, SHA1_DIGEST_SIZE))
                ret = -EINVAL;
 out:
-       kfree(sdesc);
+       kzfree(sdesc);
        return ret;
 }
 
@@ -564,7 +564,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
                *bloblen = storedsize;
        }
 out:
-       kfree(td);
+       kzfree(td);
        return ret;
 }
 
@@ -678,7 +678,7 @@ static int key_seal(struct trusted_key_payload *p,
        if (ret < 0)
                pr_info("trusted_key: srkseal failed (%d)\n", ret);
 
-       kfree(tb);
+       kzfree(tb);
        return ret;
 }
 
@@ -703,7 +703,7 @@ static int key_unseal(struct trusted_key_payload *p,
                /* pull migratable flag out of sealed key */
                p->migratable = p->key[--p->key_len];
 
-       kfree(tb);
+       kzfree(tb);
        return ret;
 }
 
@@ -1037,12 +1037,12 @@ static int trusted_instantiate(struct key *key,
        if (!ret && options->pcrlock)
                ret = pcrlock(options->pcrlock);
 out:
-       kfree(datablob);
-       kfree(options);
+       kzfree(datablob);
+       kzfree(options);
        if (!ret)
                rcu_assign_keypointer(key, payload);
        else
-               kfree(payload);
+               kzfree(payload);
        return ret;
 }
 
@@ -1051,8 +1051,7 @@ static void trusted_rcu_free(struct rcu_head *rcu)
        struct trusted_key_payload *p;
 
        p = container_of(rcu, struct trusted_key_payload, rcu);
-       memset(p->key, 0, p->key_len);
-       kfree(p);
+       kzfree(p);
 }
 
 /*
@@ -1094,13 +1093,13 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
        ret = datablob_parse(datablob, new_p, new_o);
        if (ret != Opt_update) {
                ret = -EINVAL;
-               kfree(new_p);
+               kzfree(new_p);
                goto out;
        }
 
        if (!new_o->keyhandle) {
                ret = -EINVAL;
-               kfree(new_p);
+               kzfree(new_p);
                goto out;
        }
 
@@ -1114,22 +1113,22 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
        ret = key_seal(new_p, new_o);
        if (ret < 0) {
                pr_info("trusted_key: key_seal failed (%d)\n", ret);
-               kfree(new_p);
+               kzfree(new_p);
                goto out;
        }
        if (new_o->pcrlock) {
                ret = pcrlock(new_o->pcrlock);
                if (ret < 0) {
                        pr_info("trusted_key: pcrlock failed (%d)\n", ret);
-                       kfree(new_p);
+                       kzfree(new_p);
                        goto out;
                }
        }
        rcu_assign_keypointer(key, new_p);
        call_rcu(&p->rcu, trusted_rcu_free);
 out:
-       kfree(datablob);
-       kfree(new_o);
+       kzfree(datablob);
+       kzfree(new_o);
        return ret;
 }
 
@@ -1158,24 +1157,19 @@ static long trusted_read(const struct key *key, char __user *buffer,
        for (i = 0; i < p->blob_len; i++)
                bufp = hex_byte_pack(bufp, p->blob[i]);
        if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) {
-               kfree(ascii_buf);
+               kzfree(ascii_buf);
                return -EFAULT;
        }
-       kfree(ascii_buf);
+       kzfree(ascii_buf);
        return 2 * p->blob_len;
 }
 
 /*
- * trusted_destroy - before freeing the key, clear the decrypted data
+ * trusted_destroy - clear and free the key's payload
  */
 static void trusted_destroy(struct key *key)
 {
-       struct trusted_key_payload *p = key->payload.data[0];
-
-       if (!p)
-               return;
-       memset(p->key, 0, p->key_len);
-       kfree(key->payload.data[0]);
+       kzfree(key->payload.data[0]);
 }
 
 struct key_type key_type_trusted = {
index 26605134f17a8a3cf7c7a5c0a0c14fd5a3052fcb..3d8c68eba5160286fa7af79c8da1ead6e6b05236 100644 (file)
@@ -86,10 +86,18 @@ EXPORT_SYMBOL_GPL(user_preparse);
  */
 void user_free_preparse(struct key_preparsed_payload *prep)
 {
-       kfree(prep->payload.data[0]);
+       kzfree(prep->payload.data[0]);
 }
 EXPORT_SYMBOL_GPL(user_free_preparse);
 
+static void user_free_payload_rcu(struct rcu_head *head)
+{
+       struct user_key_payload *payload;
+
+       payload = container_of(head, struct user_key_payload, rcu);
+       kzfree(payload);
+}
+
 /*
  * update a user defined key
  * - the key's semaphore is write-locked
@@ -112,7 +120,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep)
        prep->payload.data[0] = NULL;
 
        if (zap)
-               kfree_rcu(zap, rcu);
+               call_rcu(&zap->rcu, user_free_payload_rcu);
        return ret;
 }
 EXPORT_SYMBOL_GPL(user_update);
@@ -130,7 +138,7 @@ void user_revoke(struct key *key)
 
        if (upayload) {
                rcu_assign_keypointer(key, NULL);
-               kfree_rcu(upayload, rcu);
+               call_rcu(&upayload->rcu, user_free_payload_rcu);
        }
 }
 
@@ -143,7 +151,7 @@ void user_destroy(struct key *key)
 {
        struct user_key_payload *upayload = key->payload.data[0];
 
-       kfree(upayload);
+       kzfree(upayload);
 }
 
 EXPORT_SYMBOL_GPL(user_destroy);
index e67a526d1f301e4b9f27cc1685875aef85e6e9c3..819fd6858b499dca6ad37e04d11230c4daad6ff5 100644 (file)
@@ -1106,10 +1106,8 @@ static int selinux_parse_opts_str(char *options,
 
        opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int),
                                       GFP_KERNEL);
-       if (!opts->mnt_opts_flags) {
-               kfree(opts->mnt_opts);
+       if (!opts->mnt_opts_flags)
                goto out_err;
-       }
 
        if (fscontext) {
                opts->mnt_opts[num_mnt_opts] = fscontext;
@@ -1132,6 +1130,7 @@ static int selinux_parse_opts_str(char *options,
        return 0;
 
 out_err:
+       security_free_mnt_opts(opts);
        kfree(context);
        kfree(defcontext);
        kfree(fscontext);
index 5088d4b8db2222e28a71baaa4db7c70a30997e48..009e6c98754e484e489ebcdde361e200ee0d6205 100644 (file)
@@ -2492,7 +2492,7 @@ static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
        struct snd_pcm_substream *substream;
        const struct snd_pcm_chmap_elem *map;
 
-       if (snd_BUG_ON(!info->chmap))
+       if (!info->chmap)
                return -EINVAL;
        substream = snd_pcm_chmap_substream(info, idx);
        if (!substream)
@@ -2524,7 +2524,7 @@ static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        unsigned int __user *dst;
        int c, count = 0;
 
-       if (snd_BUG_ON(!info->chmap))
+       if (!info->chmap)
                return -EINVAL;
        if (size < 8)
                return -ENOMEM;
index 2f836ca09860e83995630de7be6546731523489a..cd67d1c12cf1ca9a32daa4de797dc0a5ec7bbb86 100644 (file)
@@ -1618,6 +1618,7 @@ static int snd_timer_user_tselect(struct file *file,
        if (err < 0)
                goto __err;
 
+       tu->qhead = tu->qtail = tu->qused = 0;
        kfree(tu->queue);
        tu->queue = NULL;
        kfree(tu->tqueue);
@@ -1959,6 +1960,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 
        tu = file->private_data;
        unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
+       mutex_lock(&tu->ioctl_lock);
        spin_lock_irq(&tu->qlock);
        while ((long)count - result >= unit) {
                while (!tu->qused) {
@@ -1974,7 +1976,9 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
                        add_wait_queue(&tu->qchange_sleep, &wait);
 
                        spin_unlock_irq(&tu->qlock);
+                       mutex_unlock(&tu->ioctl_lock);
                        schedule();
+                       mutex_lock(&tu->ioctl_lock);
                        spin_lock_irq(&tu->qlock);
 
                        remove_wait_queue(&tu->qchange_sleep, &wait);
@@ -1994,7 +1998,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
                tu->qused--;
                spin_unlock_irq(&tu->qlock);
 
-               mutex_lock(&tu->ioctl_lock);
                if (tu->tread) {
                        if (copy_to_user(buffer, &tu->tqueue[qhead],
                                         sizeof(struct snd_timer_tread)))
@@ -2004,7 +2007,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
                                         sizeof(struct snd_timer_read)))
                                err = -EFAULT;
                }
-               mutex_unlock(&tu->ioctl_lock);
 
                spin_lock_irq(&tu->qlock);
                if (err < 0)
@@ -2014,6 +2016,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
        }
  _error:
        spin_unlock_irq(&tu->qlock);
+       mutex_unlock(&tu->ioctl_lock);
        return result > 0 ? result : err;
 }
 
index 9e6f54f8c45d2330ee339a7f4c7d1ac86c8e4774..1e26854b3425e23bd9d2942194f3665fa37e06cf 100644 (file)
@@ -682,7 +682,9 @@ static void out_stream_callback(struct fw_iso_context *context, u32 tstamp,
                cycle = increment_cycle_count(cycle, 1);
                if (s->handle_packet(s, 0, cycle, i) < 0) {
                        s->packet_index = -1;
-                       amdtp_stream_pcm_abort(s);
+                       if (in_interrupt())
+                               amdtp_stream_pcm_abort(s);
+                       WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
                        return;
                }
        }
@@ -734,7 +736,9 @@ static void in_stream_callback(struct fw_iso_context *context, u32 tstamp,
        /* Queueing error or detecting invalid payload. */
        if (i < packets) {
                s->packet_index = -1;
-               amdtp_stream_pcm_abort(s);
+               if (in_interrupt())
+                       amdtp_stream_pcm_abort(s);
+               WRITE_ONCE(s->pcm_buffer_pointer, SNDRV_PCM_POS_XRUN);
                return;
        }
 
index 7e88317228212a63ad38e6e9880655f6ea567c85..ea1a91e99875e1f06933142d607a8b9880d210b1 100644 (file)
@@ -135,7 +135,7 @@ struct amdtp_stream {
        /* For a PCM substream processing. */
        struct snd_pcm_substream *pcm;
        struct tasklet_struct period_tasklet;
-       unsigned int pcm_buffer_pointer;
+       snd_pcm_uframes_t pcm_buffer_pointer;
        unsigned int pcm_period_pointer;
 
        /* To wait for first packet. */
index d6fb2d5d01a70ef21eb533f1b86cb9c9c8f2be84..60ce1cfc300f9cb419acbc67425076c120829f13 100644 (file)
@@ -295,6 +295,8 @@ struct hda_codec {
 
 #define list_for_each_codec(c, bus) \
        list_for_each_entry(c, &(bus)->core.codec_list, core.list)
+#define list_for_each_codec_safe(c, n, bus)                            \
+       list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list)
 
 /* snd_hda_codec_read/write optional flags */
 #define HDA_RW_NO_RESPONSE_FALLBACK    (1 << 0)
index 3715a5725613bd8b8bdbcafc79b380044cacb491..1c60beb5b70a63a0ab25a828392a3cb175a4da8b 100644 (file)
@@ -1337,8 +1337,12 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs);
 /* configure each codec instance */
 int azx_codec_configure(struct azx *chip)
 {
-       struct hda_codec *codec;
-       list_for_each_codec(codec, &chip->bus) {
+       struct hda_codec *codec, *next;
+
+       /* use _safe version here since snd_hda_codec_configure() deregisters
+        * the device upon error and deletes itself from the bus list.
+        */
+       list_for_each_codec_safe(codec, next, &chip->bus) {
                snd_hda_codec_configure(codec);
        }
        return 0;
index 2842c82363c0435f90edfe06793df254c36d43ef..71545b56b4c82bf3cca37e3d99474c8cad78971f 100644 (file)
@@ -3174,6 +3174,7 @@ static int check_dyn_adc_switch(struct hda_codec *codec)
                                                spec->input_paths[i][nums]);
                                        spec->input_paths[i][nums] =
                                                spec->input_paths[i][n];
+                                       spec->input_paths[i][n] = 0;
                                }
                        }
                        nums++;
index 1770f085c2a694a398e2b30312cb79d6c3fd617a..01eb1dc7b5b3b5cf3c070a7656b81452890781e0 100644 (file)
@@ -370,10 +370,12 @@ enum {
 #define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
 #define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_BXT_T(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x1a98)
 #define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
-                       IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci)  || \
-                       IS_GLK(pci)
+#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348)
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci) || \
+                         IS_BXT_T(pci) || IS_KBL(pci) || IS_KBL_LP(pci) || \
+                         IS_KBL_H(pci) || IS_GLK(pci) || IS_CFL(pci))
 
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
@@ -2378,6 +2380,9 @@ static const struct pci_device_id azx_ids[] = {
        /* Kabylake-H */
        { PCI_DEVICE(0x8086, 0xa2f0),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+       /* Coffelake */
+       { PCI_DEVICE(0x8086, 0xa348),
+         .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 58df440013c54c00da464166f1905bfd4edfbd36..cbeebc0a9711e8283090762450525a84022db600 100644 (file)
@@ -2324,10 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
 
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
-       SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
-       SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
+       SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -2342,6 +2343,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = {
        {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
        {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
        {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
+       {.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
        {}
 };
 
@@ -5852,7 +5854,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC),
@@ -5860,13 +5866,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
+       SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
        SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
@@ -6014,6 +6017,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
        {.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
        {.id = ALC292_FIXUP_TPT460, .name = "tpt460"},
+       {.id = ALC233_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
        {}
 };
 #define ALC225_STANDARD_PINS \
@@ -6465,8 +6469,11 @@ static int patch_alc269(struct hda_codec *codec)
                break;
        case 0x10ec0225:
        case 0x10ec0295:
+               spec->codec_variant = ALC269_TYPE_ALC225;
+               break;
        case 0x10ec0299:
                spec->codec_variant = ALC269_TYPE_ALC225;
+               spec->gen.mixer_nid = 0; /* no loopback on ALC299 */
                break;
        case 0x10ec0234:
        case 0x10ec0274:
@@ -7338,6 +7345,7 @@ static const struct hda_model_fixup alc662_fixup_models[] = {
        {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
        {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
        {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
+       {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
        {}
 };
 
index faa3d38bac0b7e51ab206440e8d17f4f6d751530..6cefdf6c0b758770e2615126285d7cd83d736d64 100644 (file)
@@ -1559,6 +1559,8 @@ static const struct snd_pci_quirk stac9200_fixup_tbl[] = {
                      "Dell Inspiron 1501", STAC_9200_DELL_M26),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6,
                      "unknown Dell", STAC_9200_DELL_M26),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0201,
+                     "Dell Latitude D430", STAC_9200_DELL_M22),
        /* Panasonic */
        SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC),
        /* Gateway machines needs EAPD to be set on resume */
index 7ae46c2647d453bcad1176b6877fcbbae110416b..b7ef8c59b49a2bdb2895f2203e0c207170227c6f 100644 (file)
@@ -301,6 +301,14 @@ static int atmel_classd_codec_probe(struct snd_soc_codec *codec)
        return 0;
 }
 
+static int atmel_classd_codec_resume(struct snd_soc_codec *codec)
+{
+       struct snd_soc_card *card = snd_soc_codec_get_drvdata(codec);
+       struct atmel_classd *dd = snd_soc_card_get_drvdata(card);
+
+       return regcache_sync(dd->regmap);
+}
+
 static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
 {
        return dev_get_regmap(dev, NULL);
@@ -308,6 +316,7 @@ static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
 
 static struct snd_soc_codec_driver soc_codec_dev_classd = {
        .probe          = atmel_classd_codec_probe,
+       .resume         = atmel_classd_codec_resume,
        .get_regmap     = atmel_classd_codec_get_remap,
        .component_driver = {
                .controls               = atmel_classd_snd_controls,
index 6dd7578f0bb8da118adfdb6da76e3247289bfc32..024d83fa6a7f78b81da8b55c8dbdec977871ef46 100644 (file)
@@ -772,7 +772,7 @@ static int da7213_dai_event(struct snd_soc_dapm_widget *w,
                                ++i;
                                msleep(50);
                        }
-               } while ((i < DA7213_SRM_CHECK_RETRIES) & (!srm_lock));
+               } while ((i < DA7213_SRM_CHECK_RETRIES) && (!srm_lock));
 
                if (!srm_lock)
                        dev_warn(codec->dev, "SRM failed to lock\n");
index 9c365a7f758dbb9f1227c726f148b19672402f7c..7899a2cdeb42f46c5d76cd051319a4b547b1ed04 100644 (file)
@@ -1108,6 +1108,13 @@ static const struct dmi_system_id force_combo_jack_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform")
                }
        },
+       {
+               .ident = "Thinkpad Helix 2nd",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix 2nd")
+               }
+       },
 
        { }
 };
index 2c9dedab5184ff74909caf163f7d0697d8b67949..bc136d2bd7cdeb68b5ca7a24db94a193ede323b3 100644 (file)
@@ -202,7 +202,7 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
        if (ret < 0)
                return ret;
 
-       ret = asoc_simple_card_init_mic(rtd->card, &priv->hp_jack, PREFIX);
+       ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX);
        if (ret < 0)
                return ret;
 
index 58c525096a7cbcd6ea4fd833d06e03a0127201fe..498b15345b1a657d608a3fcff773dae206e819b0 100644 (file)
@@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
        u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
        u64 *ipc_header = (u64 *)(&header);
        struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
+       unsigned long flags;
 
+       spin_lock_irqsave(&ipc->dsp->spinlock, flags);
        msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
+       spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
        if (msg == NULL) {
                dev_dbg(ipc->dev, "ipc: rx list is empty\n");
                return;
@@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
                }
        }
 
+       spin_lock_irqsave(&ipc->dsp->spinlock, flags);
        list_del(&msg->list);
        sst_ipc_tx_msg_reply_complete(ipc, msg);
+       spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
 }
 
 irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
index 3a99712e44a80df81f7ad27d52e69501f617e948..64a0f8ed33e135eb5c0af683624afa3ebdb616b9 100644 (file)
@@ -2502,7 +2502,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
 
                        if (ret < 0)
                                return ret;
-                       tkn_count += ret;
+                       tkn_count = ret;
 
                        tuple_size += tkn_count *
                                sizeof(struct snd_soc_tplg_vendor_string_elem);
index 6df3b317a4768e008b539f0a619308e9545a3992..4c9b5781282bb149e8d749b32f2a1bd5c2987338 100644 (file)
@@ -410,7 +410,7 @@ static int skl_free(struct hdac_ext_bus *ebus)
        struct skl *skl  = ebus_to_skl(ebus);
        struct hdac_bus *bus = ebus_to_hbus(ebus);
 
-       skl->init_failed = 1; /* to be sure */
+       skl->init_done = 0; /* to be sure */
 
        snd_hdac_ext_stop_streams(ebus);
 
@@ -428,8 +428,10 @@ static int skl_free(struct hdac_ext_bus *ebus)
 
        snd_hdac_ext_bus_exit(ebus);
 
+       cancel_work_sync(&skl->probe_work);
        if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
                snd_hdac_i915_exit(&ebus->bus);
+
        return 0;
 }
 
@@ -566,6 +568,84 @@ static const struct hdac_bus_ops bus_core_ops = {
        .get_response = snd_hdac_bus_get_response,
 };
 
+static int skl_i915_init(struct hdac_bus *bus)
+{
+       int err;
+
+       /*
+        * The HDMI codec is in GPU so we need to ensure that it is powered
+        * up and ready for probe
+        */
+       err = snd_hdac_i915_init(bus);
+       if (err < 0)
+               return err;
+
+       err = snd_hdac_display_power(bus, true);
+       if (err < 0)
+               dev_err(bus->dev, "Cannot turn on display power on i915\n");
+
+       return err;
+}
+
+static void skl_probe_work(struct work_struct *work)
+{
+       struct skl *skl = container_of(work, struct skl, probe_work);
+       struct hdac_ext_bus *ebus = &skl->ebus;
+       struct hdac_bus *bus = ebus_to_hbus(ebus);
+       struct hdac_ext_link *hlink = NULL;
+       int err;
+
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = skl_i915_init(bus);
+               if (err < 0)
+                       return;
+       }
+
+       err = skl_init_chip(bus, true);
+       if (err < 0) {
+               dev_err(bus->dev, "Init chip failed with err: %d\n", err);
+               goto out_err;
+       }
+
+       /* codec detection */
+       if (!bus->codec_mask)
+               dev_info(bus->dev, "no hda codecs found!\n");
+
+       /* create codec instances */
+       err = skl_codec_create(ebus);
+       if (err < 0)
+               goto out_err;
+
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               err = snd_hdac_display_power(bus, false);
+               if (err < 0) {
+                       dev_err(bus->dev, "Cannot turn off display power on i915\n");
+                       return;
+               }
+       }
+
+       /* register platform dai and controls */
+       err = skl_platform_register(bus->dev);
+       if (err < 0)
+               return;
+       /*
+        * we are done probing so decrement link counts
+        */
+       list_for_each_entry(hlink, &ebus->hlink_list, list)
+               snd_hdac_ext_bus_link_put(ebus, hlink);
+
+       /* configure PM */
+       pm_runtime_put_noidle(bus->dev);
+       pm_runtime_allow(bus->dev);
+       skl->init_done = 1;
+
+       return;
+
+out_err:
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+               err = snd_hdac_display_power(bus, false);
+}
+
 /*
  * constructor
  */
@@ -593,6 +673,7 @@ static int skl_create(struct pci_dev *pci,
        snd_hdac_ext_bus_init(ebus, &pci->dev, &bus_core_ops, io_ops);
        ebus->bus.use_posbuf = 1;
        skl->pci = pci;
+       INIT_WORK(&skl->probe_work, skl_probe_work);
 
        ebus->bus.bdl_pos_adj = 0;
 
@@ -601,27 +682,6 @@ static int skl_create(struct pci_dev *pci,
        return 0;
 }
 
-static int skl_i915_init(struct hdac_bus *bus)
-{
-       int err;
-
-       /*
-        * The HDMI codec is in GPU so we need to ensure that it is powered
-        * up and ready for probe
-        */
-       err = snd_hdac_i915_init(bus);
-       if (err < 0)
-               return err;
-
-       err = snd_hdac_display_power(bus, true);
-       if (err < 0) {
-               dev_err(bus->dev, "Cannot turn on display power on i915\n");
-               return err;
-       }
-
-       return err;
-}
-
 static int skl_first_init(struct hdac_ext_bus *ebus)
 {
        struct skl *skl = ebus_to_skl(ebus);
@@ -684,20 +744,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
        /* initialize chip */
        skl_init_pci(skl);
 
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-               err = skl_i915_init(bus);
-               if (err < 0)
-                       return err;
-       }
-
-       skl_init_chip(bus, true);
-
-       /* codec detection */
-       if (!bus->codec_mask) {
-               dev_info(bus->dev, "no hda codecs found!\n");
-       }
-
-       return 0;
+       return skl_init_chip(bus, true);
 }
 
 static int skl_probe(struct pci_dev *pci,
@@ -706,7 +753,6 @@ static int skl_probe(struct pci_dev *pci,
        struct skl *skl;
        struct hdac_ext_bus *ebus = NULL;
        struct hdac_bus *bus = NULL;
-       struct hdac_ext_link *hlink = NULL;
        int err;
 
        /* we use ext core ops, so provide NULL for ops here */
@@ -729,7 +775,7 @@ static int skl_probe(struct pci_dev *pci,
 
        if (skl->nhlt == NULL) {
                err = -ENODEV;
-               goto out_display_power_off;
+               goto out_free;
        }
 
        err = skl_nhlt_create_sysfs(skl);
@@ -760,56 +806,24 @@ static int skl_probe(struct pci_dev *pci,
        if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(ebus);
 
+       snd_hdac_bus_stop_chip(bus);
+
        /* create device for soc dmic */
        err = skl_dmic_device_register(skl);
        if (err < 0)
                goto out_dsp_free;
 
-       /* register platform dai and controls */
-       err = skl_platform_register(bus->dev);
-       if (err < 0)
-               goto out_dmic_free;
-
-       /* create codec instances */
-       err = skl_codec_create(ebus);
-       if (err < 0)
-               goto out_unregister;
-
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
-               err = snd_hdac_display_power(bus, false);
-               if (err < 0) {
-                       dev_err(bus->dev, "Cannot turn off display power on i915\n");
-                       return err;
-               }
-       }
-
-       /*
-        * we are done probling so decrement link counts
-        */
-       list_for_each_entry(hlink, &ebus->hlink_list, list)
-               snd_hdac_ext_bus_link_put(ebus, hlink);
-
-       /* configure PM */
-       pm_runtime_put_noidle(bus->dev);
-       pm_runtime_allow(bus->dev);
+       schedule_work(&skl->probe_work);
 
        return 0;
 
-out_unregister:
-       skl_platform_unregister(bus->dev);
-out_dmic_free:
-       skl_dmic_device_unregister(skl);
 out_dsp_free:
        skl_free_dsp(skl);
 out_mach_free:
        skl_machine_device_unregister(skl);
 out_nhlt_free:
        skl_nhlt_free(skl->nhlt);
-out_display_power_off:
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, false);
 out_free:
-       skl->init_failed = 1;
        skl_free(ebus);
 
        return err;
@@ -828,7 +842,7 @@ static void skl_shutdown(struct pci_dev *pci)
 
        skl = ebus_to_skl(ebus);
 
-       if (skl->init_failed)
+       if (!skl->init_done)
                return;
 
        snd_hdac_ext_stop_streams(ebus);
index a454f6035f3e64b3be01ea4c53153c141e3a9561..2a630fcb7f088c1d548f06de31933ca662eafca2 100644 (file)
@@ -46,7 +46,7 @@ struct skl {
        struct hdac_ext_bus ebus;
        struct pci_dev *pci;
 
-       unsigned int init_failed:1; /* delayed init failed */
+       unsigned int init_done:1; /* delayed init status */
        struct platform_device *dmic_dev;
        struct platform_device *i2s_dev;
        struct snd_soc_platform *platform;
@@ -64,6 +64,8 @@ struct skl {
        const struct firmware *tplg;
 
        int supend_active;
+
+       struct work_struct probe_work;
 };
 
 #define skl_to_ebus(s) (&(s)->ebus)
index 66203d107a11e5ff17e150adb145b15a0d27934e..d3b0dc145a560c8a35ddc4320810039f481db5aa 100644 (file)
@@ -507,7 +507,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
                                rbga = rbgx;
                                adg->rbga_rate_for_441khz = rate / div;
                                ckr |= brg_table[i] << 20;
-                               if (req_441kHz_rate)
+                               if (req_441kHz_rate &&
+                                   !(adg_mode_flags(adg) & AUDIO_OUT_48))
                                        parent_clk_name = __clk_get_name(clk);
                        }
                }
@@ -522,7 +523,8 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv,
                                rbgb = rbgx;
                                adg->rbgb_rate_for_48khz = rate / div;
                                ckr |= brg_table[i] << 16;
-                               if (req_48kHz_rate)
+                               if (req_48kHz_rate &&
+                                   (adg_mode_flags(adg) & AUDIO_OUT_48))
                                        parent_clk_name = __clk_get_name(clk);
                        }
                }
index 7d92a24b7cfa558afbb8331401c974c59d5f1ae5..d879c010cf03c4607ebdab3c854a582d816ddf62 100644 (file)
@@ -89,6 +89,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod,
        dev_dbg(dev, "ctu/mix path = 0x%08x", data);
 
        rsnd_mod_write(mod, CMD_ROUTE_SLCT, data);
+       rsnd_mod_write(mod, CMD_BUSIF_MODE, rsnd_get_busif_shift(io, mod) | 1);
        rsnd_mod_write(mod, CMD_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
 
        rsnd_adg_set_cmd_timsel_gen2(mod, io);
index 1744015408c38f2ad530fbcbae9a22027f5f0828..8c1f4e2e0c4fb8c3ac09a641b4b8a928defb871c 100644 (file)
@@ -343,6 +343,57 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
                return 0x76543210;
 }
 
+u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod)
+{
+       enum rsnd_mod_type playback_mods[] = {
+               RSND_MOD_SRC,
+               RSND_MOD_CMD,
+               RSND_MOD_SSIU,
+       };
+       enum rsnd_mod_type capture_mods[] = {
+               RSND_MOD_CMD,
+               RSND_MOD_SRC,
+               RSND_MOD_SSIU,
+       };
+       struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+       struct rsnd_mod *tmod = NULL;
+       enum rsnd_mod_type *mods =
+               rsnd_io_is_play(io) ?
+               playback_mods : capture_mods;
+       int i;
+
+       /*
+        * This is needed for 24bit data
+        * We need to shift 8bit
+        *
+        * Linux 24bit data is located as 0x00******
+        * HW    24bit data is located as 0x******00
+        *
+        */
+       switch (runtime->sample_bits) {
+       case 16:
+               return 0;
+       case 32:
+               break;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(playback_mods); i++) {
+               tmod = rsnd_io_to_mod(io, mods[i]);
+               if (tmod)
+                       break;
+       }
+
+       if (tmod != mod)
+               return 0;
+
+       if (rsnd_io_is_play(io))
+               return  (0 << 20) | /* shift to Left */
+                       (8 << 16);  /* 8bit */
+       else
+               return  (1 << 20) | /* shift to Right */
+                       (8 << 16);  /* 8bit */
+}
+
 /*
  *     rsnd_dai functions
  */
index 63b6d3c28021024b1f06278c5c4f217a394faf8c..4b0980728e13ec75f18ac07135ab4971290b5310 100644 (file)
@@ -236,6 +236,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
                RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc,    0x20),
                RSND_GEN_M_REG(SRC_CTRL,        0x10,   0x20),
                RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18,   0x20),
+               RSND_GEN_M_REG(CMD_BUSIF_MODE,  0x184,  0x20),
                RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188,  0x20),
                RSND_GEN_M_REG(CMD_ROUTE_SLCT,  0x18c,  0x20),
                RSND_GEN_M_REG(CMD_CTRL,        0x190,  0x20),
index dbf4163427e808d62dbc37aa62f64b482e65e7c4..323af41ecfcb8ffea222f25fbe6c524968f29fd5 100644 (file)
@@ -73,6 +73,7 @@ enum rsnd_reg {
        RSND_REG_SCU_SYS_INT_EN0,
        RSND_REG_SCU_SYS_INT_EN1,
        RSND_REG_CMD_CTRL,
+       RSND_REG_CMD_BUSIF_MODE,
        RSND_REG_CMD_BUSIF_DALIGN,
        RSND_REG_CMD_ROUTE_SLCT,
        RSND_REG_CMDOUT_TIMSEL,
@@ -204,6 +205,7 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
                    u32 mask, u32 data);
 u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
 u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
+u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
 
 /*
  *     R-Car DMA
index 20b5b2ec625ea7b1e1812ea83d07d35b48b948ea..76a477a3ccb5d88e18fd8398d9ad2b2616a99f48 100644 (file)
@@ -190,11 +190,13 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
        struct device *dev = rsnd_priv_to_dev(priv);
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+       int is_play = rsnd_io_is_play(io);
        int use_src = 0;
        u32 fin, fout;
        u32 ifscr, fsrate, adinr;
        u32 cr, route;
        u32 bsdsr, bsisr;
+       u32 i_busif, o_busif, tmp;
        uint ratio;
 
        if (!runtime)
@@ -270,6 +272,11 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
                break;
        }
 
+       /* BUSIF_MODE */
+       tmp = rsnd_get_busif_shift(io, mod);
+       i_busif = ( is_play ? tmp : 0) | 1;
+       o_busif = (!is_play ? tmp : 0) | 1;
+
        rsnd_mod_write(mod, SRC_ROUTE_MODE0, route);
 
        rsnd_mod_write(mod, SRC_SRCIR, 1);      /* initialize */
@@ -281,8 +288,9 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
        rsnd_mod_write(mod, SRC_BSISR, bsisr);
        rsnd_mod_write(mod, SRC_SRCIR, 0);      /* cancel initialize */
 
-       rsnd_mod_write(mod, SRC_I_BUSIF_MODE, 1);
-       rsnd_mod_write(mod, SRC_O_BUSIF_MODE, 1);
+       rsnd_mod_write(mod, SRC_I_BUSIF_MODE, i_busif);
+       rsnd_mod_write(mod, SRC_O_BUSIF_MODE, o_busif);
+
        rsnd_mod_write(mod, SRC_BUSIF_DALIGN, rsnd_get_dalign(mod, io));
 
        rsnd_adg_set_src_timesel_gen2(mod, io, fin, fout);
index 135c5669f7963bd228c9a1187bc6f5dfd13bc04e..91e5c07911b4a5b14364becf64c568d7a61cc1c4 100644 (file)
@@ -302,7 +302,7 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod,
         * always use 32bit system word.
         * see also rsnd_ssi_master_clk_enable()
         */
-       cr_own = FORCE | SWL_32 | PDTA;
+       cr_own = FORCE | SWL_32;
 
        if (rdai->bit_clk_inv)
                cr_own |= SCKP;
@@ -550,6 +550,13 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
                struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
                u32 *buf = (u32 *)(runtime->dma_area +
                                   rsnd_dai_pointer_offset(io, 0));
+               int shift = 0;
+
+               switch (runtime->sample_bits) {
+               case 32:
+                       shift = 8;
+                       break;
+               }
 
                /*
                 * 8/16/32 data can be assesse to TDR/RDR register
@@ -557,9 +564,9 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
                 * see rsnd_ssi_init()
                 */
                if (rsnd_io_is_play(io))
-                       rsnd_mod_write(mod, SSITDR, *buf);
+                       rsnd_mod_write(mod, SSITDR, (*buf) << shift);
                else
-                       *buf = rsnd_mod_read(mod, SSIRDR);
+                       *buf = (rsnd_mod_read(mod, SSIRDR) >> shift);
 
                elapsed = rsnd_dai_pointer_update(io, sizeof(*buf));
        }
@@ -709,6 +716,11 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
                               struct rsnd_priv *priv)
 {
        struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
+       struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io);
+
+       /* Do nothing for SSI parent mod */
+       if (ssi_parent_mod == mod)
+               return 0;
 
        /* PIO will request IRQ again */
        free_irq(ssi->irq, mod);
index 14fafdaf1395f9737191df18599ee58fc4f858fd..512d238b79e2895f13a4b1b7be3e145859a65280 100644 (file)
@@ -144,7 +144,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
                               (rsnd_io_is_play(io) ?
                                rsnd_runtime_channel_after_ctu(io) :
                                rsnd_runtime_channel_original(io)));
-               rsnd_mod_write(mod, SSI_BUSIF_MODE,  1);
+               rsnd_mod_write(mod, SSI_BUSIF_MODE,
+                              rsnd_get_busif_shift(io, mod) | 1);
                rsnd_mod_write(mod, SSI_BUSIF_DALIGN,
                               rsnd_get_dalign(mod, io));
        }
index aae099c0e50280d67f153d6769ac4237d531e169..754e3ef8d7ae1b8b188c3e52986f2c306fb7b763 100644 (file)
@@ -2286,6 +2286,9 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
        list_for_each_entry(rtd, &card->rtd_list, list)
                flush_delayed_work(&rtd->delayed_work);
 
+       /* free the ALSA card at first; this syncs with pending operations */
+       snd_card_free(card->snd_card);
+
        /* remove and free each DAI */
        soc_remove_dai_links(card);
        soc_remove_pcm_runtimes(card);
@@ -2300,9 +2303,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
        if (card->remove)
                card->remove(card);
 
-       snd_card_free(card->snd_card);
        return 0;
-
 }
 
 /* removes a socdev */
index dc48eedea92e7aaaba64f4db4053fea1b73d0b77..26ed23b18b7774fd495f7ce90e51ec6dc8022e2d 100644 (file)
@@ -698,16 +698,18 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
        struct snd_usb_audio *chip = elem->head.mixer->chip;
        struct snd_us16x08_meter_store *store = elem->private_data;
        u8 meter_urb[64];
-       char tmp[sizeof(mix_init_msg2)] = {0};
 
        switch (kcontrol->private_value) {
-       case 0:
-               snd_us16x08_send_urb(chip, (char *)mix_init_msg1,
-                                    sizeof(mix_init_msg1));
+       case 0: {
+               char tmp[sizeof(mix_init_msg1)];
+
+               memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1));
+               snd_us16x08_send_urb(chip, tmp, 4);
                snd_us16x08_recv_urb(chip, meter_urb,
                        sizeof(meter_urb));
                kcontrol->private_value++;
                break;
+       }
        case 1:
                snd_us16x08_recv_urb(chip, meter_urb,
                        sizeof(meter_urb));
@@ -718,15 +720,18 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
                        sizeof(meter_urb));
                kcontrol->private_value++;
                break;
-       case 3:
+       case 3: {
+               char tmp[sizeof(mix_init_msg2)];
+
                memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2));
                tmp[2] = snd_get_meter_comp_index(store);
-               snd_us16x08_send_urb(chip, tmp, sizeof(mix_init_msg2));
+               snd_us16x08_send_urb(chip, tmp, 10);
                snd_us16x08_recv_urb(chip, meter_urb,
                        sizeof(meter_urb));
                kcontrol->private_value = 0;
                break;
        }
+       }
 
        for (set = 0; set < 6; set++)
                get_meter_levels_from_urb(set, store, meter_urb);
@@ -1135,7 +1140,7 @@ static const struct snd_us16x08_control_params eq_controls[] = {
                .control_id = SND_US16X08_ID_EQLOWMIDWIDTH,
                .type = USB_MIXER_U8,
                .num_channels = 16,
-               .name = "EQ MidQLow Q",
+               .name = "EQ MidLow Q",
        },
        { /* EQ mid high gain */
                .kcontrol_new = &snd_us16x08_eq_gain_ctl,
index 01eff6ce6401a3f8c6c8b51da93524f635bba86a..d7b0b0a3a2db55617a908e2fe4a8a2af90082e02 100644 (file)
@@ -1364,7 +1364,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        /* Amanero Combo384 USB interface with native DSD support */
        case USB_ID(0x16d0, 0x071a):
                if (fp->altsetting == 2) {
-                       switch (chip->dev->descriptor.bcdDevice) {
+                       switch (le16_to_cpu(chip->dev->descriptor.bcdDevice)) {
                        case 0x199:
                                return SNDRV_PCM_FMTBIT_DSD_U32_LE;
                        case 0x19b:
index 664b7fe206d65457cf3e7b1486a05b7e92493cb8..b11d3920b9a521b95142481106d420ac75643b26 100644 (file)
@@ -1809,10 +1809,6 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        pdata->notify_pending = false;
        spin_unlock_irq(&pdata->lpe_audio_slock);
 
-       /* runtime PM isn't enabled as default, since it won't save much on
-        * BYT/CHT devices; user who want the runtime PM should adjust the
-        * power/ontrol and power/autosuspend_delay_ms sysfs entries instead
-        */
        pm_runtime_use_autosuspend(&pdev->dev);
        pm_runtime_mark_last_busy(&pdev->dev);
        pm_runtime_set_active(&pdev->dev);
index 6ebd3e6a1fd12d3202067020b48446fd9bdcff98..5e3c673fa3f4435b027fbc634815be10c26cf39f 100644 (file)
@@ -27,6 +27,8 @@
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
 
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+
 #define KVM_REG_SIZE(id)                                               \
        (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
 
@@ -114,6 +116,8 @@ struct kvm_debug_exit_arch {
 };
 
 struct kvm_sync_regs {
+       /* Used with KVM_CAP_ARM_USER_IRQ */
+       __u64 device_irq_level;
 };
 
 struct kvm_arch_memory_slot {
@@ -192,13 +196,17 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS  8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
                        (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
 #define VGIC_LEVEL_INFO_LINE_LEVEL     0
 
-#define   KVM_DEV_ARM_VGIC_CTRL_INIT    0
+#define   KVM_DEV_ARM_VGIC_CTRL_INIT           0
+#define   KVM_DEV_ARM_ITS_SAVE_TABLES          1
+#define   KVM_DEV_ARM_ITS_RESTORE_TABLES       2
+#define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
 
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_TYPE_SHIFT         24
index c2860358ae3e0c3271d9ca4b944351986276e397..70eea2ecc6631cab3d718c3958cd0513a7f7e6a3 100644 (file)
@@ -39,6 +39,8 @@
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
 
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+
 #define KVM_REG_SIZE(id)                                               \
        (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
 
@@ -143,6 +145,8 @@ struct kvm_debug_exit_arch {
 #define KVM_GUESTDBG_USE_HW            (1 << 17)
 
 struct kvm_sync_regs {
+       /* Used with KVM_CAP_ARM_USER_IRQ */
+       __u64 device_irq_level;
 };
 
 struct kvm_arch_memory_slot {
@@ -212,13 +216,17 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
                        (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
 #define VGIC_LEVEL_INFO_LINE_LEVEL     0
 
-#define   KVM_DEV_ARM_VGIC_CTRL_INIT   0
+#define   KVM_DEV_ARM_VGIC_CTRL_INIT           0
+#define   KVM_DEV_ARM_ITS_SAVE_TABLES           1
+#define   KVM_DEV_ARM_ITS_RESTORE_TABLES        2
+#define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
 
 /* Device Control API on vcpu fd */
 #define KVM_ARM_VCPU_PMU_V3_CTRL       0
index 4edbe4bb0e8b0cdd2553c74df9988823990833d9..07fbeb927834f3a96278414aedaa59ea580ae8de 100644 (file)
@@ -29,6 +29,9 @@
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_GUEST_DEBUG
 
+/* Not always available, but if it is, this is the correct offset.  */
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+
 struct kvm_regs {
        __u64 pc;
        __u64 cr;
index 7f4fd65e9208514b99112c51f0e018f3f441712f..3dd2a1d308dd0b92c36c3c5ca5276fd19838f252 100644 (file)
@@ -26,6 +26,8 @@
 #define KVM_DEV_FLIC_ADAPTER_REGISTER  6
 #define KVM_DEV_FLIC_ADAPTER_MODIFY    7
 #define KVM_DEV_FLIC_CLEAR_IO_IRQ      8
+#define KVM_DEV_FLIC_AISM              9
+#define KVM_DEV_FLIC_AIRQ_INJECT       10
 /*
  * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
  * as well as up  to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
@@ -41,7 +43,14 @@ struct kvm_s390_io_adapter {
        __u8 isc;
        __u8 maskable;
        __u8 swap;
-       __u8 pad;
+       __u8 flags;
+};
+
+#define KVM_S390_ADAPTER_SUPPRESSIBLE 0x01
+
+struct kvm_s390_ais_req {
+       __u8 isc;
+       __u16 mode;
 };
 
 #define KVM_S390_IO_ADAPTER_MASK 1
@@ -110,6 +119,7 @@ struct kvm_s390_vm_cpu_machine {
 #define KVM_S390_VM_CPU_FEAT_CMMA      10
 #define KVM_S390_VM_CPU_FEAT_PFMFI     11
 #define KVM_S390_VM_CPU_FEAT_SIGPIF    12
+#define KVM_S390_VM_CPU_FEAT_KSS       13
 struct kvm_s390_vm_cpu_feat {
        __u64 feat[16];
 };
@@ -198,6 +208,10 @@ struct kvm_guest_debug_arch {
 #define KVM_SYNC_VRS    (1UL << 6)
 #define KVM_SYNC_RICCB  (1UL << 7)
 #define KVM_SYNC_FPRS   (1UL << 8)
+#define KVM_SYNC_GSCB   (1UL << 9)
+/* length and alignment of the sdnx as a power of two */
+#define SDNXC 8
+#define SDNXL (1UL << SDNXC)
 /* definition of registers in kvm_run */
 struct kvm_sync_regs {
        __u64 prefix;   /* prefix register */
@@ -218,8 +232,16 @@ struct kvm_sync_regs {
        };
        __u8  reserved[512];    /* for future vector expansion */
        __u32 fpc;              /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
-       __u8 padding[52];       /* riccb needs to be 64byte aligned */
+       __u8 padding1[52];      /* riccb needs to be 64byte aligned */
        __u8 riccb[64];         /* runtime instrumentation controls block */
+       __u8 padding2[192];     /* sdnx needs to be 256byte aligned */
+       union {
+               __u8 sdnx[SDNXL];  /* state description annex */
+               struct {
+                       __u64 reserved1[2];
+                       __u64 gscb[4];
+               };
+       };
 };
 
 #define KVM_REG_S390_TODPR     (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
index 0fe00446f9cac8c16e1ae3fcabc4a469b772597b..2701e5f8145bd250c3a35dc12cab5839e16ff30d 100644 (file)
 #define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
 #define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
 
+#define X86_FEATURE_MBA         ( 7*32+18) /* Memory Bandwidth Allocation */
+
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
 #define X86_FEATURE_VNMI        ( 8*32+ 1) /* Intel Virtual NMI */
index 85599ad4d0247863cef655d02b9a4b3f83c77fb7..5dff775af7cd6456f7177d9ce5888ae78dc6bc10 100644 (file)
 # define DISABLE_OSPKE         (1<<(X86_FEATURE_OSPKE & 31))
 #endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
 
+#ifdef CONFIG_X86_5LEVEL
+# define DISABLE_LA57  0
+#else
+# define DISABLE_LA57  (1<<(X86_FEATURE_LA57 & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
@@ -55,7 +61,7 @@
 #define DISABLED_MASK13        0
 #define DISABLED_MASK14        0
 #define DISABLED_MASK15        0
-#define DISABLED_MASK16        (DISABLE_PKU|DISABLE_OSPKE)
+#define DISABLED_MASK16        (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57)
 #define DISABLED_MASK17        0
 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
 
index fac9a5c0abe94b233b72b35bca8c7a665847b694..d91ba04dd00709b7e549ced791759c12cf70d5d0 100644 (file)
 # define NEED_MOVBE    0
 #endif
 
+#ifdef CONFIG_X86_5LEVEL
+# define NEED_LA57     (1<<(X86_FEATURE_LA57 & 31))
+#else
+# define NEED_LA57     0
+#endif
+
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_PARAVIRT
 /* Paravirtualized systems may not have PSE or PGE available */
 #define REQUIRED_MASK13        0
 #define REQUIRED_MASK14        0
 #define REQUIRED_MASK15        0
-#define REQUIRED_MASK16        0
+#define REQUIRED_MASK16        (NEED_LA57)
 #define REQUIRED_MASK17        0
 #define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
 
index 739c0c5940226d7af38d2ab4bc068f7772f1a8c7..c2824d02ba3762553b62a07709058102050e34da 100644 (file)
@@ -9,6 +9,9 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
+#define KVM_PIO_PAGE_OFFSET 1
+#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
+
 #define DE_VECTOR 0
 #define DB_VECTOR 1
 #define BP_VECTOR 3
index 14458658e988bb6c9333e73701ea55e7b6525a92..690a2dcf407860cf54793f03e69d8761b06f068d 100644 (file)
 #define EXIT_REASON_WBINVD              54
 #define EXIT_REASON_XSETBV              55
 #define EXIT_REASON_APIC_WRITE          56
+#define EXIT_REASON_RDRAND              57
 #define EXIT_REASON_INVPCID             58
+#define EXIT_REASON_VMFUNC              59
+#define EXIT_REASON_ENCLS               60
+#define EXIT_REASON_RDSEED              61
 #define EXIT_REASON_PML_FULL            62
 #define EXIT_REASON_XSAVES              63
 #define EXIT_REASON_XRSTORS             64
@@ -90,6 +94,7 @@
        { EXIT_REASON_TASK_SWITCH,           "TASK_SWITCH" }, \
        { EXIT_REASON_CPUID,                 "CPUID" }, \
        { EXIT_REASON_HLT,                   "HLT" }, \
+       { EXIT_REASON_INVD,                  "INVD" }, \
        { EXIT_REASON_INVLPG,                "INVLPG" }, \
        { EXIT_REASON_RDPMC,                 "RDPMC" }, \
        { EXIT_REASON_RDTSC,                 "RDTSC" }, \
        { EXIT_REASON_IO_INSTRUCTION,        "IO_INSTRUCTION" }, \
        { EXIT_REASON_MSR_READ,              "MSR_READ" }, \
        { EXIT_REASON_MSR_WRITE,             "MSR_WRITE" }, \
+       { EXIT_REASON_INVALID_STATE,         "INVALID_STATE" }, \
+       { EXIT_REASON_MSR_LOAD_FAIL,         "MSR_LOAD_FAIL" }, \
        { EXIT_REASON_MWAIT_INSTRUCTION,     "MWAIT_INSTRUCTION" }, \
        { EXIT_REASON_MONITOR_TRAP_FLAG,     "MONITOR_TRAP_FLAG" }, \
        { EXIT_REASON_MONITOR_INSTRUCTION,   "MONITOR_INSTRUCTION" }, \
        { EXIT_REASON_MCE_DURING_VMENTRY,    "MCE_DURING_VMENTRY" }, \
        { EXIT_REASON_TPR_BELOW_THRESHOLD,   "TPR_BELOW_THRESHOLD" }, \
        { EXIT_REASON_APIC_ACCESS,           "APIC_ACCESS" }, \
-       { EXIT_REASON_GDTR_IDTR,             "GDTR_IDTR" }, \
-       { EXIT_REASON_LDTR_TR,               "LDTR_TR" }, \
+       { EXIT_REASON_EOI_INDUCED,           "EOI_INDUCED" }, \
+       { EXIT_REASON_GDTR_IDTR,             "GDTR_IDTR" }, \
+       { EXIT_REASON_LDTR_TR,               "LDTR_TR" }, \
        { EXIT_REASON_EPT_VIOLATION,         "EPT_VIOLATION" }, \
        { EXIT_REASON_EPT_MISCONFIG,         "EPT_MISCONFIG" }, \
        { EXIT_REASON_INVEPT,                "INVEPT" }, \
+       { EXIT_REASON_RDTSCP,                "RDTSCP" }, \
        { EXIT_REASON_PREEMPTION_TIMER,      "PREEMPTION_TIMER" }, \
+       { EXIT_REASON_INVVPID,               "INVVPID" }, \
        { EXIT_REASON_WBINVD,                "WBINVD" }, \
+       { EXIT_REASON_XSETBV,                "XSETBV" }, \
        { EXIT_REASON_APIC_WRITE,            "APIC_WRITE" }, \
-       { EXIT_REASON_EOI_INDUCED,           "EOI_INDUCED" }, \
-       { EXIT_REASON_INVALID_STATE,         "INVALID_STATE" }, \
-       { EXIT_REASON_MSR_LOAD_FAIL,         "MSR_LOAD_FAIL" }, \
-       { EXIT_REASON_INVD,                  "INVD" }, \
-       { EXIT_REASON_INVVPID,               "INVVPID" }, \
+       { EXIT_REASON_RDRAND,                "RDRAND" }, \
        { EXIT_REASON_INVPCID,               "INVPCID" }, \
+       { EXIT_REASON_VMFUNC,                "VMFUNC" }, \
+       { EXIT_REASON_ENCLS,                 "ENCLS" }, \
+       { EXIT_REASON_RDSEED,                "RDSEED" }, \
+       { EXIT_REASON_PML_FULL,              "PML_FULL" }, \
        { EXIT_REASON_XSAVES,                "XSAVES" }, \
        { EXIT_REASON_XRSTORS,               "XRSTORS" }
 
index ebc6dceddb58c00e4253e4fc3b37eda7a17b62be..7598361ef1f10898ea73d944ae0b0c02c4725d99 100644 (file)
@@ -29,6 +29,7 @@ int main(void)
        attr.log_size = 0;
        attr.log_level = 0;
        attr.kern_version = 0;
+       attr.prog_flags = 0;
 
        /*
         * Test existence of __NR_bpf and BPF_PROG_LOAD.
index 390d7c9685fd6107c83be2296ead9cb198b571a3..4ce25d43e8e305df8afcfc6fb1747a58fad20c1b 100644 (file)
                .off   = OFF,                                   \
                .imm   = IMM })
 
+/* Unconditional jumps, goto pc + off16 */
+
+#define BPF_JMP_A(OFF)                                         \
+       ((struct bpf_insn) {                                    \
+               .code  = BPF_JMP | BPF_JA,                      \
+               .dst_reg = 0,                                   \
+               .src_reg = 0,                                   \
+               .off   = OFF,                                   \
+               .imm   = 0 })
+
 /* Function call */
 
 #define BPF_EMIT_CALL(FUNC)                                    \
index e553529929f683c4c39ae336d10c6f670e589b54..94dfa9def355f7f52805bba5ade3a32c304f989a 100644 (file)
@@ -132,6 +132,13 @@ enum bpf_attach_type {
  */
 #define BPF_F_ALLOW_OVERRIDE   (1U << 0)
 
+/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+ * verifier will perform strict alignment checking as if the kernel
+ * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
+ * and NET_IP_ALIGN defined to 2.
+ */
+#define BPF_F_STRICT_ALIGNMENT (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
+               __u32           prog_flags;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -481,8 +489,7 @@ union bpf_attr {
  * u32 bpf_get_socket_uid(skb)
  *     Get the owner uid of the socket stored inside sk_buff.
  *     @skb: pointer to skb
- *     Return: uid of the socket owner on success or 0 if the socket pointer
- *     inside sk_buff is NULL
+ *     Return: uid of the socket owner on success or overflowuid if failed.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
index d538897b8e08bb4358c56148c189fc7b8128a9da..17b10304c393355da9ed2da743107a5c59748290 100644 (file)
  * tv_sec holds the number of seconds before (negative) or after (positive)
  * 00:00:00 1st January 1970 UTC.
  *
- * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is
- * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time.
- *
- * Note that if both tv_sec and tv_nsec are non-zero, then the two values must
- * either be both positive or both negative.
+ * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
  *
  * __reserved is held in case we need a yet finer resolution.
  */
 struct statx_timestamp {
        __s64   tv_sec;
-       __s32   tv_nsec;
+       __u32   tv_nsec;
        __s32   __reserved;
 };
 
index 4fe444b8092e2d6dc8aea6b7ce8349a64e439c44..6e178987af8e3f45d63da349e38c39b4e4cd6d84 100644 (file)
@@ -117,6 +117,28 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
        return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 }
 
+int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                      size_t insns_cnt, int strict_alignment,
+                      const char *license, __u32 kern_version,
+                      char *log_buf, size_t log_buf_sz)
+{
+       union bpf_attr attr;
+
+       bzero(&attr, sizeof(attr));
+       attr.prog_type = type;
+       attr.insn_cnt = (__u32)insns_cnt;
+       attr.insns = ptr_to_u64(insns);
+       attr.license = ptr_to_u64(license);
+       attr.log_buf = ptr_to_u64(log_buf);
+       attr.log_size = log_buf_sz;
+       attr.log_level = 2;
+       log_buf[0] = 0;
+       attr.kern_version = kern_version;
+       attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
+
+       return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+}
+
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags)
 {
index edb4daeff7a52c44f6bc366c265a7f5a3aadfc10..972bd8333eb72e982420abeac9f8ceff5a4ed1a3 100644 (file)
@@ -35,6 +35,10 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
                     size_t insns_cnt, const char *license,
                     __u32 kern_version, char *log_buf,
                     size_t log_buf_sz);
+int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                      size_t insns_cnt, int strict_alignment,
+                      const char *license, __u32 kern_version,
+                      char *log_buf, size_t log_buf_sz);
 
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags);
index 282a60368b14df9e88b304d7e60aac77fd8e6bc0..5f66697fe1e09a81b9fa8c5cb37c54331cf5888e 100644 (file)
@@ -192,7 +192,8 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
                "complete_and_exit",
                "kvm_spurious_fault",
                "__reiserfs_panic",
-               "lbug_with_loc"
+               "lbug_with_loc",
+               "fortify_panic",
        };
 
        if (func->bind == STB_WEAK)
index e6c9902c6d82b0e2535059c1a915356e84856589..165c2b1d43177b7df8870d85d7911a1a615ce7e7 100644 (file)
@@ -240,9 +240,13 @@ Add a probe on schedule() function 12th line with recording cpu local variable:
  or
  ./perf probe --add='schedule:12 cpu'
 
- this will add one or more probes which has the name start with "schedule".
+Add one or more probes which has the name start with "schedule".
 
- Add probes on lines in schedule() function which calls update_rq_clock().
+ ./perf probe schedule*
+ or
+ ./perf probe --add='schedule*'
+
+Add probes on lines in schedule() function which calls update_rq_clock().
 
  ./perf probe 'schedule;update_rq_clock*'
  or
index dfbb506d2c349744399637c78148fe6446b124bc..142606c0ec9c1dcbb9329f23cb9b9bc65085c419 100644 (file)
@@ -39,7 +39,7 @@ EVENT HANDLERS
 When perf script is invoked using a trace script, a user-defined
 'handler function' is called for each event in the trace.  If there's
 no handler function defined for a given event type, the event is
-ignored (or passed to a 'trace_handled' function, see below) and the
+ignored (or passed to a 'trace_unhandled' function, see below) and the
 next event is processed.
 
 Most of the event's field values are passed as arguments to the
index 54acba22155865a8fafc7629b9e3987c061fed47..51ec2d20068ad5df7b0a00a0983b5ec08d49979a 100644 (file)
@@ -149,10 +149,8 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
                print "id=%d, args=%s\n" % \
                (id, args),
 
-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
-               common_pid, common_comm):
-               print_header(event_name, common_cpu, common_secs, common_nsecs,
-               common_pid, common_comm)
+def trace_unhandled(event_name, context, event_fields_dict):
+               print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
 
 def print_header(event_name, cpu, secs, nsecs, pid, comm):
        print "%-20s %5u %05u.%09u %8u %-20s " % \
@@ -321,7 +319,7 @@ So those are the essential steps in writing and running a script.  The
 process can be generalized to any tracepoint or set of tracepoints
 you're interested in - basically find the tracepoint(s) you're
 interested in by looking at the list of available events shown by
-'perf list' and/or look in /sys/kernel/debug/tracing events for
+'perf list' and/or look in /sys/kernel/debug/tracing/events/ for
 detailed event and field info, record the corresponding trace data
 using 'perf record', passing it the list of interesting events,
 generate a skeleton script using 'perf script -g python' and modify the
@@ -334,7 +332,7 @@ right place, you can have your script listed alongside the other
 scripts listed by the 'perf script -l' command e.g.:
 
 ----
-root@tropicana:~# perf script -l
+# perf script -l
 List of available trace scripts:
   wakeup-latency                       system-wide min/max/avg wakeup latency
   rw-by-file <comm>                    r/w activity for a program, by file
@@ -383,8 +381,6 @@ source tree:
 
 ----
 # ls -al kernel-source/tools/perf/scripts/python
-
-root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
 total 32
 drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
 drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
@@ -399,7 +395,7 @@ otherwise your script won't show up at run-time), 'perf script -l'
 should show a new entry for your script:
 
 ----
-root@tropicana:~# perf script -l
+# perf script -l
 List of available trace scripts:
   wakeup-latency                       system-wide min/max/avg wakeup latency
   rw-by-file <comm>                    r/w activity for a program, by file
@@ -437,7 +433,7 @@ EVENT HANDLERS
 When perf script is invoked using a trace script, a user-defined
 'handler function' is called for each event in the trace.  If there's
 no handler function defined for a given event type, the event is
-ignored (or passed to a 'trace_handled' function, see below) and the
+ignored (or passed to a 'trace_unhandled' function, see below) and the
 next event is processed.
 
 Most of the event's field values are passed as arguments to the
@@ -532,7 +528,7 @@ can implement a set of optional functions:
 gives scripts a chance to do setup tasks:
 
 ----
-def trace_begin:
+def trace_begin():
     pass
 ----
 
@@ -541,7 +537,7 @@ def trace_begin:
  as display results:
 
 ----
-def trace_end:
+def trace_end():
     pass
 ----
 
@@ -550,8 +546,7 @@ def trace_end:
  of common arguments are passed into it:
 
 ----
-def trace_unhandled(event_name, context, common_cpu, common_secs,
-        common_nsecs, common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
     pass
 ----
 
index cb0eda3925e6d8562da9d3091147c5fca602ebbf..3517e204a2b30754e430213c41b1d48e51d9b52c 100644 (file)
@@ -311,6 +311,10 @@ include::itrace.txt[]
        Set the maximum number of program blocks to print with brstackasm for
        each sample.
 
+--inline::
+       If a callgraph address belongs to an inlined function, the inline stack
+       will be printed. Each entry has function name and file/line.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
index 8354d04b392fd9e94c0812731b55e7267b41504e..1f4fbc9a3292e06b6ae48c47297e795ccbc45809 100644 (file)
@@ -19,18 +19,18 @@ CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
 
 include $(srctree)/tools/scripts/Makefile.arch
 
-$(call detected_var,ARCH)
+$(call detected_var,SRCARCH)
 
 NO_PERF_REGS := 1
 
 # Additional ARCH settings for ppc
-ifeq ($(ARCH),powerpc)
+ifeq ($(SRCARCH),powerpc)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
 endif
 
 # Additional ARCH settings for x86
-ifeq ($(ARCH),x86)
+ifeq ($(SRCARCH),x86)
   $(call detected,CONFIG_X86)
   ifeq (${IS_64_BIT}, 1)
     CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
@@ -43,12 +43,12 @@ ifeq ($(ARCH),x86)
   NO_PERF_REGS := 0
 endif
 
-ifeq ($(ARCH),arm)
+ifeq ($(SRCARCH),arm)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS = -lunwind -lunwind-arm
 endif
 
-ifeq ($(ARCH),arm64)
+ifeq ($(SRCARCH),arm64)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
 endif
@@ -61,7 +61,7 @@ endif
 # Disable it on all other architectures in case libdw unwind
 # support is detected in system. Add supported architectures
 # to the check.
-ifneq ($(ARCH),$(filter $(ARCH),x86 arm))
+ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm))
   NO_LIBDW_DWARF_UNWIND := 1
 endif
 
@@ -115,9 +115,9 @@ endif
 FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
 
-FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
+FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi -I$(srctree)/tools/include/uapi
 # include ARCH specific config
--include $(src-perf)/arch/$(ARCH)/Makefile
+-include $(src-perf)/arch/$(SRCARCH)/Makefile
 
 ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
   CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
@@ -228,12 +228,12 @@ ifeq ($(DEBUG),0)
 endif
 
 INC_FLAGS += -I$(src-perf)/util/include
-INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
+INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include
 INC_FLAGS += -I$(srctree)/tools/include/uapi
 INC_FLAGS += -I$(srctree)/tools/include/
-INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
-INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
-INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
+INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi
+INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/include/
+INC_FLAGS += -I$(srctree)/tools/arch/$(SRCARCH)/
 
 # $(obj-perf)      for generated common-cmds.h
 # $(obj-perf)/util for generated bison/flex headers
@@ -355,7 +355,7 @@ ifndef NO_LIBELF
 
   ifndef NO_DWARF
     ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
-      msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
+      msg := $(warning DWARF register mappings have not been defined for architecture $(SRCARCH), DWARF support disabled);
       NO_DWARF := 1
     else
       CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
@@ -380,7 +380,7 @@ ifndef NO_LIBELF
         CFLAGS += -DHAVE_BPF_PROLOGUE
         $(call detected,CONFIG_BPF_PROLOGUE)
       else
-        msg := $(warning BPF prologue is not supported by architecture $(ARCH), missing regs_query_register_offset());
+        msg := $(warning BPF prologue is not supported by architecture $(SRCARCH), missing regs_query_register_offset());
       endif
     else
       msg := $(warning DWARF support is off, BPF prologue is disabled);
@@ -406,7 +406,7 @@ ifdef PERF_HAVE_JITDUMP
   endif
 endif
 
-ifeq ($(ARCH),powerpc)
+ifeq ($(SRCARCH),powerpc)
   ifndef NO_DWARF
     CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
   endif
@@ -487,7 +487,7 @@ else
 endif
 
 ifndef NO_LOCAL_LIBUNWIND
-  ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
+  ifeq ($(SRCARCH),$(filter $(SRCARCH),arm arm64))
     $(call feature_check,libunwind-debug-frame)
     ifneq ($(feature-libunwind-debug-frame), 1)
       msg := $(warning No debug_frame support found in libunwind);
@@ -740,7 +740,7 @@ ifeq (${IS_64_BIT}, 1)
       NO_PERF_READ_VDSO32 := 1
     endif
   endif
-  ifneq ($(ARCH), x86)
+  ifneq ($(SRCARCH), x86)
     NO_PERF_READ_VDSOX32 := 1
   endif
   ifndef NO_PERF_READ_VDSOX32
@@ -769,7 +769,7 @@ ifdef LIBBABELTRACE
 endif
 
 ifndef NO_AUXTRACE
-  ifeq ($(ARCH),x86)
+  ifeq ($(SRCARCH),x86)
     ifeq ($(feature-get_cpuid), 0)
       msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
       NO_AUXTRACE := 1
@@ -872,7 +872,7 @@ sysconfdir = $(prefix)/etc
 ETC_PERFCONFIG = etc/perfconfig
 endif
 ifndef lib
-ifeq ($(ARCH)$(IS_64_BIT), x861)
+ifeq ($(SRCARCH)$(IS_64_BIT), x861)
 lib = lib64
 else
 lib = lib
index 79fe31f20a17644e416642bb9d3a213c97286479..5008f51a08a2118ca34723a87373acd231afb7c3 100644 (file)
@@ -226,7 +226,7 @@ endif
 
 ifeq ($(config),0)
 include $(srctree)/tools/scripts/Makefile.arch
--include arch/$(ARCH)/Makefile
+-include arch/$(SRCARCH)/Makefile
 endif
 
 # The FEATURE_DUMP_EXPORT holds location of the actual
index 109eb75cf7de4e97c855fe52c3d6437f454b5c8e..d9b6af837c7d392fce6168d9ce5ebe2b9a6b57d5 100644 (file)
@@ -1,2 +1,2 @@
 libperf-y += common.o
-libperf-y += $(ARCH)/
+libperf-y += $(SRCARCH)/
index 837067f48a4c54a88b883e8de6dc95df0dd5b3d0..6b40e9f017404f87877668645f7afa8f28649788 100644 (file)
@@ -26,6 +26,7 @@ const char *const arm64_triplets[] = {
 
 const char *const powerpc_triplets[] = {
        "powerpc-unknown-linux-gnu-",
+       "powerpc-linux-gnu-",
        "powerpc64-unknown-linux-gnu-",
        "powerpc64-linux-gnu-",
        "powerpc64le-linux-gnu-",
index d05aec491cff22189d7fe763120884a639cd2cfb..4761b0d7fcb5b2586e7fd86c1ed8b219d0cec987 100644 (file)
@@ -2494,6 +2494,8 @@ int cmd_script(int argc, const char **argv)
                        "Enable kernel symbol demangling"),
        OPT_STRING(0, "time", &script.time_str, "str",
                   "Time span of interest (start,stop)"),
+       OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
+                   "Show inline function"),
        OPT_END()
        };
        const char * const script_subcommands[] = { "record", "report", NULL };
index a935b502373253217d6f43680e6b88a6ab143bfe..ad9324d1daf9f29a990a0d8f903563873ac91ef9 100644 (file)
@@ -1578,6 +1578,7 @@ static void print_header(int argc, const char **argv)
 static void print_footer(void)
 {
        FILE *output = stat_config.output;
+       int n;
 
        if (!null_run)
                fprintf(output, "\n");
@@ -1590,7 +1591,9 @@ static void print_footer(void)
        }
        fprintf(output, "\n\n");
 
-       if (print_free_counters_hint)
+       if (print_free_counters_hint &&
+           sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
+           n > 0)
                fprintf(output,
 "Some events weren't counted. Try disabling the NMI watchdog:\n"
 "      echo 0 > /proc/sys/kernel/nmi_watchdog\n"
index d014350adc526722da3a12f29421cd6d3c00f4af..4b2a5d2981970baf86e4e458ef4ced256fc98c0e 100644 (file)
@@ -681,6 +681,10 @@ static struct syscall_fmt {
        { .name     = "mlockall",   .errmsg = true,
          .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
        { .name     = "mmap",       .hexret = true,
+/* The standard mmap maps to old_mmap on s390x */
+#if defined(__s390x__)
+       .alias = "old_mmap",
+#endif
          .arg_scnprintf = { [0] = SCA_HEX,       /* addr */
                             [2] = SCA_MMAP_PROT, /* prot */
                             [3] = SCA_MMAP_FLAGS, /* flags */ }, },
index 9213a1273697a801d6b75f4a8804424e68eb6ab7..999a4e8781621677821440e80ec8491689bbc6e3 100644 (file)
@@ -2,7 +2,7 @@ hostprogs := jevents
 
 jevents-y      += json.o jsmn.o jevents.o
 pmu-events-y   += pmu-events.o
-JDIR           =  pmu-events/arch/$(ARCH)
+JDIR           =  pmu-events/arch/$(SRCARCH)
 JSON           =  $(shell [ -d $(JDIR) ] &&                            \
                        find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
 #
@@ -10,4 +10,4 @@ JSON          =  $(shell [ -d $(JDIR) ] &&                            \
 # directory and create tables in pmu-events.c.
 #
 $(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JEVENTS)
-       $(Q)$(call echo-cmd,gen)$(JEVENTS) $(ARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V)
+       $(Q)$(call echo-cmd,gen)$(JEVENTS) $(SRCARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V)
index af58ebc243ef635ff2ddc6efcd26b377cc24a30b..84222bdb8689203924fc8f6a75f0baac4531d82c 100644 (file)
@@ -75,7 +75,7 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
        $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
        $(Q)echo ';' >> $@
 
-ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64 powerpc))
+ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 endif
 
index e7664fe3bd33739fd92be2579c30102e481e8f03..8ba2c4618fe90231d1157e8218bf10a2cb82f6a0 100644 (file)
@@ -288,3 +288,17 @@ int test__bp_signal(int subtest __maybe_unused)
        return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
                TEST_OK : TEST_FAIL;
 }
+
+bool test__bp_signal_is_supported(void)
+{
+/*
+ * The powerpc so far does not have support to even create
+ * instruction breakpoint using the perf event interface.
+ * Once it's there we can release this.
+ */
+#ifdef __powerpc__
+       return false;
+#else
+       return true;
+#endif
+}
index 9e08d297f1a905f57554bf6fd7b9555e980ad10a..3ccfd58a8c3cf3e8b16cc513a67324b8f11eae7b 100644 (file)
@@ -97,10 +97,12 @@ static struct test generic_tests[] = {
        {
                .desc = "Breakpoint overflow signal handler",
                .func = test__bp_signal,
+               .is_supported = test__bp_signal_is_supported,
        },
        {
                .desc = "Breakpoint overflow sampling",
                .func = test__bp_signal_overflow,
+               .is_supported = test__bp_signal_is_supported,
        },
        {
                .desc = "Number of exit events of a simple workload",
@@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
                if (!perf_test__matches(t, curr, argc, argv))
                        continue;
 
+               if (t->is_supported && !t->is_supported()) {
+                       pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
+                       continue;
+               }
+
                pr_info("%2d: %-*s:", i, width, t->desc);
 
                if (intlist__find(skiplist, i)) {
index 1f14e7612cbb1615e993c73758a3c9ac7024a0e1..94b7c7b02bdefbb33f2987677c11b3577ab062ec 100644 (file)
@@ -229,6 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
        unsigned char buf2[BUFSZ];
        size_t ret_len;
        u64 objdump_addr;
+       const char *objdump_name;
+       char decomp_name[KMOD_DECOMP_LEN];
        int ret;
 
        pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
@@ -289,9 +291,25 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
                state->done[state->done_cnt++] = al.map->start;
        }
 
+       objdump_name = al.map->dso->long_name;
+       if (dso__needs_decompress(al.map->dso)) {
+               if (dso__decompress_kmodule_path(al.map->dso, objdump_name,
+                                                decomp_name,
+                                                sizeof(decomp_name)) < 0) {
+                       pr_debug("decompression failed\n");
+                       return -1;
+               }
+
+               objdump_name = decomp_name;
+       }
+
        /* Read the object code using objdump */
        objdump_addr = map__rip_2objdump(al.map, al.addr);
-       ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len);
+       ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
+
+       if (dso__needs_decompress(al.map->dso))
+               unlink(objdump_name);
+
        if (ret > 0) {
                /*
                 * The kernel maps are inaccurate - assume objdump is right in
index 32873ec91a4e1307b30884c1141fe0e8f1da154e..cf00ebad2ef5ccefabee6324e004fc9b4d2e601b 100644 (file)
@@ -83,7 +83,7 @@ int test__task_exit(int subtest __maybe_unused)
 
        evsel = perf_evlist__first(evlist);
        evsel->attr.task = 1;
-       evsel->attr.sample_freq = 0;
+       evsel->attr.sample_freq = 1;
        evsel->attr.inherit = 0;
        evsel->attr.watermark = 0;
        evsel->attr.wakeup_events = 1;
index 6318596294032602b2858acf42c2aa80993fdac9..577363809c9b1b54731f7e80b291278bf2764e78 100644 (file)
@@ -34,6 +34,7 @@ struct test {
                int (*get_nr)(void);
                const char *(*get_desc)(int subtest);
        } subtest;
+       bool (*is_supported)(void);
 };
 
 /* Tests */
@@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest);
 int test__clang_subtest_get_nr(void);
 int test__unit_number__scnprint(int subtest);
 
+bool test__bp_signal_is_supported(void);
+
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
 struct thread;
index 59addd52d9cd51ab2d8789989a9d377d2ce23eb5..ddb2c6fbdf919e8124ffb40eee47c801b43bd6c6 100644 (file)
@@ -210,6 +210,8 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
                        return 0;
 
                ret = b->callchain->max_depth - a->callchain->max_depth;
+               if (callchain_param.order == ORDER_CALLER)
+                       ret = -ret;
        }
        return ret;
 }
index 683f8340460c1777f82f35860b3bb581a07f222a..ddbd56df91878884a4de5da2a29aae991e0689a0 100644 (file)
@@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
        const char *s = strchr(ops->raw, '+');
        const char *c = strchr(ops->raw, ',');
 
-       if (c++ != NULL)
+       /*
+        * skip over possible up to 2 operands to get to address, e.g.:
+        * tbnz  w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
+        */
+       if (c++ != NULL) {
                ops->target.addr = strtoull(c, NULL, 16);
-       else
+               if (!ops->target.addr) {
+                       c = strchr(c, ',');
+                       if (c++ != NULL)
+                               ops->target.addr = strtoull(c, NULL, 16);
+               }
+       } else {
                ops->target.addr = strtoull(ops->raw, NULL, 16);
+       }
 
        if (s++ != NULL) {
                ops->target.offset = strtoull(s, NULL, 16);
@@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
 static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
                           struct ins_operands *ops)
 {
+       const char *c = strchr(ops->raw, ',');
+
        if (!ops->target.addr || ops->target.offset < 0)
                return ins__raw_scnprintf(ins, bf, size, ops);
 
-       return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
+       if (c != NULL) {
+               const char *c2 = strchr(c + 1, ',');
+
+               /* check for 3-op insn */
+               if (c2 != NULL)
+                       c = c2;
+               c++;
+
+               /* mirror arch objdump's space-after-comma style */
+               if (*c == ' ')
+                       c++;
+       }
+
+       return scnprintf(bf, size, "%-6.6s %.*s%" PRIx64,
+                        ins->name, c ? c - ops->raw : 0, ops->raw,
+                        ops->target.offset);
 }
 
 static struct ins_ops jump_ops = {
@@ -1294,6 +1321,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
        char linkname[PATH_MAX];
        char *build_id_filename;
        char *build_id_path = NULL;
+       char *pos;
 
        if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
            !dso__is_kcore(dso))
@@ -1313,7 +1341,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
        if (!build_id_path)
                return -1;
 
-       dirname(build_id_path);
+       /*
+        * old style build-id cache has name of XX/XXXXXXX.. while
+        * new style has XX/XXXXXXX../{elf,kallsyms,vdso}.
+        * extract the build-id part of dirname in the new style only.
+        */
+       pos = strrchr(build_id_path, '/');
+       if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
+               dirname(build_id_path);
 
        if (dso__is_kcore(dso) ||
            readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
@@ -1396,31 +1431,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
                                sizeof(symfs_filename));
                }
        } else if (dso__needs_decompress(dso)) {
-               char tmp[PATH_MAX];
-               struct kmod_path m;
-               int fd;
-               bool ret;
-
-               if (kmod_path__parse_ext(&m, symfs_filename))
-                       goto out;
-
-               snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
-
-               fd = mkstemp(tmp);
-               if (fd < 0) {
-                       free(m.ext);
-                       goto out;
-               }
-
-               ret = decompress_to_file(m.ext, symfs_filename, fd);
-
-               if (ret)
-                       pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename);
-
-               free(m.ext);
-               close(fd);
+               char tmp[KMOD_DECOMP_LEN];
 
-               if (!ret)
+               if (dso__decompress_kmodule_path(dso, symfs_filename,
+                                                tmp, sizeof(tmp)) < 0)
                        goto out;
 
                strcpy(symfs_filename, tmp);
@@ -1429,7 +1443,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
        snprintf(command, sizeof(command),
                 "%s %s%s --start-address=0x%016" PRIx64
                 " --stop-address=0x%016" PRIx64
-                " -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand",
+                " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
                 objdump_path ? objdump_path : "objdump",
                 disassembler_style ? "-M " : "",
                 disassembler_style ? disassembler_style : "",
index 168cc49654e7a4b18f69d177e29373f8a13e3471..e0148b081bdfbb7cead2c118a51ca81bd238e740 100644 (file)
@@ -278,51 +278,6 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
        return bf;
 }
 
-bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
-{
-       char *id_name = NULL, *ch;
-       struct stat sb;
-       char sbuild_id[SBUILD_ID_SIZE];
-
-       if (!dso->has_build_id)
-               goto err;
-
-       build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
-       id_name = build_id_cache__linkname(sbuild_id, NULL, 0);
-       if (!id_name)
-               goto err;
-       if (access(id_name, F_OK))
-               goto err;
-       if (lstat(id_name, &sb) == -1)
-               goto err;
-       if ((size_t)sb.st_size > size - 1)
-               goto err;
-       if (readlink(id_name, bf, size - 1) < 0)
-               goto err;
-
-       bf[sb.st_size] = '\0';
-
-       /*
-        * link should be:
-        * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92
-        */
-       ch = strrchr(bf, '/');
-       if (!ch)
-               goto err;
-       if (ch - 3 < bf)
-               goto err;
-
-       free(id_name);
-       return strncmp(".ko", ch - 3, 3) == 0;
-err:
-       pr_err("Invalid build id: %s\n", id_name ? :
-                                        dso->long_name ? :
-                                        dso->short_name ? :
-                                        "[unknown]");
-       free(id_name);
-       return false;
-}
-
 #define dsos__for_each_with_build_id(pos, head)        \
        list_for_each_entry(pos, head, node)    \
                if (!pos->has_build_id)         \
index 8a89b195c1fc3a5c36d7ca260dafe9c6b3fa8262..96690a55c62c40394444a8f23df1cd03b840acfe 100644 (file)
@@ -17,7 +17,6 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
                                    size_t size);
 
 char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
-bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
 
 int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
                           struct perf_sample *sample, struct perf_evsel *evsel,
index 81fc29ac798facf789712d81147eacda0c01552d..b4204b43ed58a83c9530ae3b75df4c01004b442e 100644 (file)
@@ -621,14 +621,19 @@ enum match_result {
 static enum match_result match_chain_srcline(struct callchain_cursor_node *node,
                                             struct callchain_list *cnode)
 {
-       char *left = get_srcline(cnode->ms.map->dso,
+       char *left = NULL;
+       char *right = NULL;
+       enum match_result ret = MATCH_EQ;
+       int cmp;
+
+       if (cnode->ms.map)
+               left = get_srcline(cnode->ms.map->dso,
                                 map__rip_2objdump(cnode->ms.map, cnode->ip),
                                 cnode->ms.sym, true, false);
-       char *right = get_srcline(node->map->dso,
+       if (node->map)
+               right = get_srcline(node->map->dso,
                                  map__rip_2objdump(node->map, node->ip),
                                  node->sym, true, false);
-       enum match_result ret = MATCH_EQ;
-       int cmp;
 
        if (left && right)
                cmp = strcmp(left, right);
index a96a99d2369f800634025bcdfa9838d1d6bc9d97..4e7ab611377acd56c1be78cbd983058e5ce5142b 100644 (file)
@@ -248,6 +248,64 @@ bool dso__needs_decompress(struct dso *dso)
                dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
 }
 
+static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf)
+{
+       int fd = -1;
+       struct kmod_path m;
+
+       if (!dso__needs_decompress(dso))
+               return -1;
+
+       if (kmod_path__parse_ext(&m, dso->long_name))
+               return -1;
+
+       if (!m.comp)
+               goto out;
+
+       fd = mkstemp(tmpbuf);
+       if (fd < 0) {
+               dso->load_errno = errno;
+               goto out;
+       }
+
+       if (!decompress_to_file(m.ext, name, fd)) {
+               dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
+               close(fd);
+               fd = -1;
+       }
+
+out:
+       free(m.ext);
+       return fd;
+}
+
+int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
+{
+       char tmpbuf[] = KMOD_DECOMP_NAME;
+       int fd;
+
+       fd = decompress_kmodule(dso, name, tmpbuf);
+       unlink(tmpbuf);
+       return fd;
+}
+
+int dso__decompress_kmodule_path(struct dso *dso, const char *name,
+                                char *pathname, size_t len)
+{
+       char tmpbuf[] = KMOD_DECOMP_NAME;
+       int fd;
+
+       fd = decompress_kmodule(dso, name, tmpbuf);
+       if (fd < 0) {
+               unlink(tmpbuf);
+               return -1;
+       }
+
+       strncpy(pathname, tmpbuf, len);
+       close(fd);
+       return 0;
+}
+
 /*
  * Parses kernel module specified in @path and updates
  * @m argument like:
@@ -335,6 +393,21 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
        return 0;
 }
 
+void dso__set_module_info(struct dso *dso, struct kmod_path *m,
+                         struct machine *machine)
+{
+       if (machine__is_host(machine))
+               dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
+       else
+               dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
+
+       /* _KMODULE_COMP should be next to _KMODULE */
+       if (m->kmod && m->comp)
+               dso->symtab_type++;
+
+       dso__set_short_name(dso, strdup(m->name), true);
+}
+
 /*
  * Global list of open DSOs and the counter.
  */
@@ -381,7 +454,7 @@ static int do_open(char *name)
 
 static int __open_dso(struct dso *dso, struct machine *machine)
 {
-       int fd;
+       int fd = -EINVAL;
        char *root_dir = (char *)"";
        char *name = malloc(PATH_MAX);
 
@@ -392,15 +465,30 @@ static int __open_dso(struct dso *dso, struct machine *machine)
                root_dir = machine->root_dir;
 
        if (dso__read_binary_type_filename(dso, dso->binary_type,
-                                           root_dir, name, PATH_MAX)) {
-               free(name);
-               return -EINVAL;
-       }
+                                           root_dir, name, PATH_MAX))
+               goto out;
 
        if (!is_regular_file(name))
-               return -EINVAL;
+               goto out;
+
+       if (dso__needs_decompress(dso)) {
+               char newpath[KMOD_DECOMP_LEN];
+               size_t len = sizeof(newpath);
+
+               if (dso__decompress_kmodule_path(dso, name, newpath, len) < 0) {
+                       fd = -dso->load_errno;
+                       goto out;
+               }
+
+               strcpy(name, newpath);
+       }
 
        fd = do_open(name);
+
+       if (dso__needs_decompress(dso))
+               unlink(name);
+
+out:
        free(name);
        return fd;
 }
index 12350b17172730adf0dffdf324cb9e0b4a4be2ba..bd061ba7b47cc8eab2ff05e4027dc22990d7c7ef 100644 (file)
@@ -244,6 +244,12 @@ bool is_supported_compression(const char *ext);
 bool is_kernel_module(const char *pathname, int cpumode);
 bool decompress_to_file(const char *ext, const char *filename, int output_fd);
 bool dso__needs_decompress(struct dso *dso);
+int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
+int dso__decompress_kmodule_path(struct dso *dso, const char *name,
+                                char *pathname, size_t len);
+
+#define KMOD_DECOMP_NAME  "/tmp/perf-kmod-XXXXXX"
+#define KMOD_DECOMP_LEN   sizeof(KMOD_DECOMP_NAME)
 
 struct kmod_path {
        char *name;
@@ -259,6 +265,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
 #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
 #define kmod_path__parse_ext(__m, __p)  __kmod_path__parse(__m, __p, false, true)
 
+void dso__set_module_info(struct dso *dso, struct kmod_path *m,
+                         struct machine *machine);
+
 /*
  * The dso__data_* external interface provides following functions:
  *   dso__data_get_fd
index e4f7902d5afa62f0aecab1103bc05ca4bcb226e9..cda44b0e821c63baea1f9da52123184768fdd2f4 100644 (file)
@@ -273,8 +273,20 @@ struct perf_evsel *perf_evsel__new_cycles(void)
        struct perf_evsel *evsel;
 
        event_attr_init(&attr);
+       /*
+        * Unnamed union member, not supported as struct member named
+        * initializer in older compilers such as gcc 4.4.7
+        *
+        * Just for probing the precise_ip:
+        */
+       attr.sample_period = 1;
 
        perf_event_attr__set_max_precise_ip(&attr);
+       /*
+        * Now let the usual logic to set up the perf_event_attr defaults
+        * to kick in when we return and before perf_evsel__open() is called.
+        */
+       attr.sample_period = 0;
 
        evsel = perf_evsel__new(&attr);
        if (evsel == NULL)
index e415aee6a24520f3c88e9ce70d621b39109896b6..583f3a602506f29f198d7153b8ad8ee8073a6fd9 100644 (file)
@@ -7,6 +7,7 @@
 #include "map.h"
 #include "strlist.h"
 #include "symbol.h"
+#include "srcline.h"
 
 static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
 {
@@ -168,6 +169,38 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
                        if (!print_oneline)
                                printed += fprintf(fp, "\n");
 
+                       if (symbol_conf.inline_name && node->map) {
+                               struct inline_node *inode;
+
+                               addr = map__rip_2objdump(node->map, node->ip),
+                               inode = dso__parse_addr_inlines(node->map->dso, addr);
+
+                               if (inode) {
+                                       struct inline_list *ilist;
+
+                                       list_for_each_entry(ilist, &inode->val, list) {
+                                               if (print_arrow)
+                                                       printed += fprintf(fp, " <-");
+
+                                               /* IP is same, just skip it */
+                                               if (print_ip)
+                                                       printed += fprintf(fp, "%c%16s",
+                                                                          s, "");
+                                               if (print_sym)
+                                                       printed += fprintf(fp, " %s",
+                                                                          ilist->funcname);
+                                               if (print_srcline)
+                                                       printed += fprintf(fp, "\n  %s:%d",
+                                                                          ilist->filename,
+                                                                          ilist->line_nr);
+                                               if (!print_oneline)
+                                                       printed += fprintf(fp, "\n");
+                                       }
+
+                                       inline_node__delete(inode);
+                               }
+                       }
+
                        if (symbol_conf.bt_stop_list &&
                            node->sym &&
                            strlist__has_entry(symbol_conf.bt_stop_list,
index 314a07151fb772377752dae62658b79ffdc87cd6..b5baff3007bbd477551cc2e62770e534d0919f33 100644 (file)
@@ -841,7 +841,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
 
 /*
  * default get_cpuid(): nothing gets recorded
- * actual implementation must be in arch/$(ARCH)/util/header.c
+ * actual implementation must be in arch/$(SRCARCH)/util/header.c
  */
 int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
 {
@@ -1469,8 +1469,16 @@ static int __event_process_build_id(struct build_id_event *bev,
 
                dso__set_build_id(dso, &bev->build_id);
 
-               if (!is_kernel_module(filename, cpumode))
-                       dso->kernel = dso_type;
+               if (dso_type != DSO_TYPE_USER) {
+                       struct kmod_path m = { .name = NULL, };
+
+                       if (!kmod_path__parse_name(&m, filename) && m.kmod)
+                               dso__set_module_info(dso, &m, machine);
+                       else
+                               dso->kernel = dso_type;
+
+                       free(m.name);
+               }
 
                build_id__sprintf(dso->build_id, sizeof(dso->build_id),
                                  sbuild_id);
index d97e014c3df395e51e61da31f9624e12927a43b2..5de2b86b9880c88a7570674688cfaba50744b5ed 100644 (file)
@@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
                if (dso == NULL)
                        goto out_unlock;
 
-               if (machine__is_host(machine))
-                       dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
-               else
-                       dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
-
-               /* _KMODULE_COMP should be next to _KMODULE */
-               if (m->kmod && m->comp)
-                       dso->symtab_type++;
-
-               dso__set_short_name(dso, strdup(m->name), true);
+               dso__set_module_info(dso, m, machine);
                dso__set_long_name(dso, strdup(filename), true);
        }
 
@@ -1218,10 +1209,12 @@ int machine__create_kernel_maps(struct machine *machine)
         */
        map_groups__fixup_end(&machine->kmaps);
 
-       if (machine__get_running_kernel_start(machine, &name, &addr)) {
-       } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
-               machine__destroy_kernel_maps(machine);
-               return -1;
+       if (!machine__get_running_kernel_start(machine, &name, &addr)) {
+               if (name &&
+                   maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
+                       machine__destroy_kernel_maps(machine);
+                       return -1;
+               }
        }
 
        return 0;
index 84e7e698411e6a80a39050514227cbb90556ca13..a2670e9d652dfa09eebb7e53a8ed2b63a7cea152 100644 (file)
@@ -619,7 +619,7 @@ static int post_process_probe_trace_point(struct probe_trace_point *tp,
                                           struct map *map, unsigned long offs)
 {
        struct symbol *sym;
-       u64 addr = tp->address + tp->offset - offs;
+       u64 addr = tp->address - offs;
 
        sym = map__find_symbol(map, addr);
        if (!sym)
index 9d92af7d07182e662b1a6d7ad5e66c0147a78234..40de3cb40d2100fe918f26795ae29ae702d62665 100644 (file)
@@ -1219,7 +1219,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
        fprintf(ofp, "# be retrieved using Python functions of the form "
                "common_*(context).\n");
 
-       fprintf(ofp, "# See the perf-trace-python Documentation for the list "
+       fprintf(ofp, "# See the perf-script-python Documentation for the list "
                "of available functions.\n\n");
 
        fprintf(ofp, "import os\n");
index df051a52393c1de8e85f46d43f567755888133e7..ebc88a74e67b7129cbbd6790c34f50dcefec0de1 100644 (file)
@@ -56,7 +56,10 @@ static int inline_list__append(char *filename, char *funcname, int line_nr,
                }
        }
 
-       list_add_tail(&ilist->list, &node->val);
+       if (callchain_param.order == ORDER_CALLEE)
+               list_add_tail(&ilist->list, &node->val);
+       else
+               list_add(&ilist->list, &node->val);
 
        return 0;
 }
@@ -200,12 +203,14 @@ static void addr2line_cleanup(struct a2l_data *a2l)
 
 #define MAX_INLINE_NEST 1024
 
-static void inline_list__reverse(struct inline_node *node)
+static int inline_list__append_dso_a2l(struct dso *dso,
+                                      struct inline_node *node)
 {
-       struct inline_list *ilist, *n;
+       struct a2l_data *a2l = dso->a2l;
+       char *funcname = a2l->funcname ? strdup(a2l->funcname) : NULL;
+       char *filename = a2l->filename ? strdup(a2l->filename) : NULL;
 
-       list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
-               list_move_tail(&ilist->list, &node->val);
+       return inline_list__append(filename, funcname, a2l->line, node, dso);
 }
 
 static int addr2line(const char *dso_name, u64 addr,
@@ -230,36 +235,36 @@ static int addr2line(const char *dso_name, u64 addr,
 
        bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
 
-       if (a2l->found && unwind_inlines) {
+       if (!a2l->found)
+               return 0;
+
+       if (unwind_inlines) {
                int cnt = 0;
 
+               if (node && inline_list__append_dso_a2l(dso, node))
+                       return 0;
+
                while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
                                             &a2l->funcname, &a2l->line) &&
                       cnt++ < MAX_INLINE_NEST) {
 
                        if (node != NULL) {
-                               if (inline_list__append(strdup(a2l->filename),
-                                                       strdup(a2l->funcname),
-                                                       a2l->line, node,
-                                                       dso) != 0)
+                               if (inline_list__append_dso_a2l(dso, node))
                                        return 0;
+                               // found at least one inline frame
+                               ret = 1;
                        }
                }
+       }
 
-               if ((node != NULL) &&
-                   (callchain_param.order != ORDER_CALLEE)) {
-                       inline_list__reverse(node);
-               }
+       if (file) {
+               *file = a2l->filename ? strdup(a2l->filename) : NULL;
+               ret = *file ? 1 : 0;
        }
 
-       if (a2l->found && a2l->filename) {
-               *file = strdup(a2l->filename);
+       if (line)
                *line = a2l->line;
 
-               if (*file)
-                       ret = 1;
-       }
-
        return ret;
 }
 
@@ -278,8 +283,6 @@ void dso__free_a2l(struct dso *dso)
 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
        struct dso *dso)
 {
-       char *file = NULL;
-       unsigned int line = 0;
        struct inline_node *node;
 
        node = zalloc(sizeof(*node));
@@ -291,7 +294,7 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
        INIT_LIST_HEAD(&node->val);
        node->addr = addr;
 
-       if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
+       if (!addr2line(dso_name, addr, NULL, NULL, dso, TRUE, node))
                goto out_free_inline_node;
 
        if (list_empty(&node->val))
index e7ee47f7377ab17bbb414be4240cf01565ae863a..502505cf236af30226b22ff82878098060f19862 100644 (file)
@@ -637,43 +637,6 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
        return 0;
 }
 
-static int decompress_kmodule(struct dso *dso, const char *name,
-                             enum dso_binary_type type)
-{
-       int fd = -1;
-       char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
-       struct kmod_path m;
-
-       if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
-           type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
-           type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
-               return -1;
-
-       if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
-               name = dso->long_name;
-
-       if (kmod_path__parse_ext(&m, name) || !m.comp)
-               return -1;
-
-       fd = mkstemp(tmpbuf);
-       if (fd < 0) {
-               dso->load_errno = errno;
-               goto out;
-       }
-
-       if (!decompress_to_file(m.ext, name, fd)) {
-               dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
-               close(fd);
-               fd = -1;
-       }
-
-       unlink(tmpbuf);
-
-out:
-       free(m.ext);
-       return fd;
-}
-
 bool symsrc__possibly_runtime(struct symsrc *ss)
 {
        return ss->dynsym || ss->opdsec;
@@ -705,9 +668,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
        int fd;
 
        if (dso__needs_decompress(dso)) {
-               fd = decompress_kmodule(dso, name, type);
+               fd = dso__decompress_kmodule_fd(dso, name);
                if (fd < 0)
                        return -1;
+
+               type = dso->symtab_type;
        } else {
                fd = open(name, O_RDONLY);
                if (fd < 0) {
index 8f2b068ff7564900c989d1cdec96757c1b3ab45b..e7a98dbd2aed9133d99f38b71b3cac9fb297e0d6 100644 (file)
@@ -1562,10 +1562,6 @@ int dso__load(struct dso *dso, struct map *map)
        if (!runtime_ss && syms_ss)
                runtime_ss = syms_ss;
 
-       if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
-               if (dso__build_id_is_kmod(dso, name, PATH_MAX))
-                       kmod = true;
-
        if (syms_ss)
                ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
        else
index f90e11a555b208302f9dd2a4163d73051e0d2f47..7755a5e0fe5eb290c41502bf22725cce8a0b6935 100644 (file)
@@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip,
                return 0;
 
        mod = dwfl_addrmodule(ui->dwfl, ip);
+       if (mod) {
+               Dwarf_Addr s;
+
+               dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL);
+               if (s != al->map->start)
+                       mod = 0;
+       }
+
        if (!mod)
                mod = dwfl_report_elf(ui->dwfl, dso->short_name,
                                      dso->long_name, -1, al->map->start,
@@ -168,12 +176,24 @@ frame_callback(Dwfl_Frame *state, void *arg)
 {
        struct unwind_info *ui = arg;
        Dwarf_Addr pc;
+       bool isactivation;
 
        if (!dwfl_frame_pc(state, &pc, NULL)) {
                pr_err("%s", dwfl_errmsg(-1));
                return DWARF_CB_ABORT;
        }
 
+       // report the module before we query for isactivation
+       report_module(pc, ui);
+
+       if (!dwfl_frame_pc(state, &pc, &isactivation)) {
+               pr_err("%s", dwfl_errmsg(-1));
+               return DWARF_CB_ABORT;
+       }
+
+       if (!isactivation)
+               --pc;
+
        return entry(pc, ui) || !(--ui->max_stack) ?
               DWARF_CB_ABORT : DWARF_CB_OK;
 }
@@ -220,7 +240,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 
        err = dwfl_getthread_frames(ui->dwfl, thread->tid, frame_callback, ui);
 
-       if (err && !ui->max_stack)
+       if (err && ui->max_stack != max_stack)
                err = 0;
 
        /*
index f8455bed6e653705183b878c40d294991edf4e92..672c2ada9357a25054b4b1ba7eeec643505984e2 100644 (file)
@@ -692,6 +692,17 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
 
                while (!ret && (unw_step(&c) > 0) && i < max_stack) {
                        unw_get_reg(&c, UNW_REG_IP, &ips[i]);
+
+                       /*
+                        * Decrement the IP for any non-activation frames.
+                        * this is required to properly find the srcline
+                        * for caller frames.
+                        * See also the documentation for dwfl_frame_pc(),
+                        * which this code tries to replicate.
+                        */
+                       if (unw_is_signal_frame(&c) <= 0)
+                               --ips[i];
+
                        ++i;
                }
 
diff --git a/tools/power/acpi/.gitignore b/tools/power/acpi/.gitignore
new file mode 100644 (file)
index 0000000..cba3d99
--- /dev/null
@@ -0,0 +1,4 @@
+acpidbg
+acpidump
+ec
+include
index 91edd056623789fb5585bd774b6d98eb5dba1cc2..f389b02d43a004e90aed9acd68148875af3beba2 100644 (file)
@@ -11,7 +11,8 @@ endif
 CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
 LDLIBS += -lcap -lelf
 
-TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs
+TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
+       test_align
 
 TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o
 
@@ -34,6 +35,7 @@ $(BPFOBJ): force
 CLANG ?= clang
 
 %.o: %.c
-       $(CLANG) -I. -I../../../include/uapi -I../../../../samples/bpf/ \
+       $(CLANG) -I. -I./include/uapi -I../../../include/uapi \
+               -I../../../../samples/bpf/ \
                -Wno-compare-distinct-pointer-types \
                -O2 -target bpf -c $< -o $@
index 19d0604f86946824b04138e8bcaf29f3628ab808..487cbfb89beb5012816c7e4989b3f9ff4261995d 100644 (file)
@@ -1,23 +1,42 @@
 #ifndef __BPF_ENDIAN__
 #define __BPF_ENDIAN__
 
-#include <asm/byteorder.h>
+#include <linux/swab.h>
 
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-# define __bpf_ntohs(x)                __builtin_bswap16(x)
-# define __bpf_htons(x)                __builtin_bswap16(x)
-#elif __BYTE_ORDER == __BIG_ENDIAN
-# define __bpf_ntohs(x)                (x)
-# define __bpf_htons(x)                (x)
+/* LLVM's BPF target selects the endianness of the CPU
+ * it compiles on, or the user specifies (bpfel/bpfeb),
+ * respectively. The used __BYTE_ORDER__ is defined by
+ * the compiler, we cannot rely on __BYTE_ORDER from
+ * libc headers, since it doesn't reflect the actual
+ * requested byte order.
+ *
+ * Note, LLVM's BPF target has different __builtin_bswapX()
+ * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
+ * in bpfel and bpfeb case, which means below, that we map
+ * to cpu_to_be16(). We could use it unconditionally in BPF
+ * case, but better not rely on it, so that this header here
+ * can be used from application and BPF program side, which
+ * use different targets.
+ */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define __bpf_ntohs(x)                        __builtin_bswap16(x)
+# define __bpf_htons(x)                        __builtin_bswap16(x)
+# define __bpf_constant_ntohs(x)       ___constant_swab16(x)
+# define __bpf_constant_htons(x)       ___constant_swab16(x)
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define __bpf_ntohs(x)                        (x)
+# define __bpf_htons(x)                        (x)
+# define __bpf_constant_ntohs(x)       (x)
+# define __bpf_constant_htons(x)       (x)
 #else
-# error "Fix your __BYTE_ORDER?!"
+# error "Fix your compiler's __BYTE_ORDER__?!"
 #endif
 
 #define bpf_htons(x)                           \
        (__builtin_constant_p(x) ?              \
-        __constant_htons(x) : __bpf_htons(x))
+        __bpf_constant_htons(x) : __bpf_htons(x))
 #define bpf_ntohs(x)                           \
        (__builtin_constant_p(x) ?              \
-        __constant_ntohs(x) : __bpf_ntohs(x))
+        __bpf_constant_ntohs(x) : __bpf_ntohs(x))
 
-#endif
+#endif /* __BPF_ENDIAN__ */
diff --git a/tools/testing/selftests/bpf/include/uapi/linux/types.h b/tools/testing/selftests/bpf/include/uapi/linux/types.h
new file mode 100644 (file)
index 0000000..5184184
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _UAPI_LINUX_TYPES_H
+#define _UAPI_LINUX_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+/* copied from linux:include/uapi/linux/types.h */
+#define __bitwise
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
+#endif /* _UAPI_LINUX_TYPES_H */
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
new file mode 100644 (file)
index 0000000..9644d4e
--- /dev/null
@@ -0,0 +1,453 @@
+#include <asm/types.h>
+#include <linux/types.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <linux/unistd.h>
+#include <linux/filter.h>
+#include <linux/bpf_perf_event.h>
+#include <linux/bpf.h>
+
+#include <bpf/bpf.h>
+
+#include "../../../include/linux/filter.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#define MAX_INSNS      512
+#define MAX_MATCHES    16
+
+struct bpf_align_test {
+       const char *descr;
+       struct bpf_insn insns[MAX_INSNS];
+       enum {
+               UNDEF,
+               ACCEPT,
+               REJECT
+       } result;
+       enum bpf_prog_type prog_type;
+       const char *matches[MAX_MATCHES];
+};
+
+static struct bpf_align_test tests[] = {
+       {
+               .descr = "mov",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 2),
+                       BPF_MOV64_IMM(BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_3, 8),
+                       BPF_MOV64_IMM(BPF_REG_3, 16),
+                       BPF_MOV64_IMM(BPF_REG_3, 32),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+                       "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
+               },
+       },
+       {
+               .descr = "shift",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_4, 32),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
+                       "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+                       "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
+                       "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
+                       "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "addsub",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
+                       BPF_MOV64_IMM(BPF_REG_4, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp",
+                       "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp",
+                       "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp",
+                       "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "mul",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 7),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
+                       "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
+                       "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
+                       "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp",
+               },
+       },
+
+#define PREP_PKT_POINTERS \
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
+                   offsetof(struct __sk_buff, data)), \
+       BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
+                   offsetof(struct __sk_buff, data_end))
+
+#define LOAD_UNKNOWN(DST_REG) \
+       PREP_PKT_POINTERS, \
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
+       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
+       BPF_EXIT_INSN(), \
+       BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
+
+       {
+               .descr = "unknown shift",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       LOAD_UNKNOWN(BPF_REG_4),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp",
+                       "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp",
+                       "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp",
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp",
+                       "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp",
+                       "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp",
+                       "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp",
+                       "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp",
+                       "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp",
+                       "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "unknown mul",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp",
+                       "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp",
+                       "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp",
+                       "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp",
+                       "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp"
+               },
+       },
+       {
+               .descr = "packet const offset",
+               .insns = {
+                       PREP_PKT_POINTERS,
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+
+                       /* Skip over ethernet header.  */
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
+                       BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
+                       BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp",
+                       "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp",
+                       "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp",
+                       "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp",
+                       "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
+                       "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
+               },
+       },
+       {
+               .descr = "packet variable offset",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
+
+                       /* First, add a constant to the R5 packet pointer,
+                        * then a variable with a known alignment.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       /* Now, test in the other direction.  Adding first
+                        * the variable offset to R5, then the constant.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       /* Test multiple accumulations of unknown values
+                        * into a packet pointer.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       /* Calculated offset in R6 has unknown value, but known
+                        * alignment of 4.
+                        */
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp",
+
+                       /* Offset is added to packet pointer R5, resulting in known
+                        * auxiliary alignment and offset.
+                        */
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (0) +
+                        * reg->aux_off (14) which is 16.  Then the variable
+                        * offset is considered using reg->aux_off_align which
+                        * is 4 and meets the load's requirements.
+                        */
+                       "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+
+                       /* Variable offset is added to R5 packet pointer,
+                        * resulting in auxiliary alignment of 4.
+                        */
+                       "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* Constant offset is added to R5, resulting in
+                        * reg->off of 14.
+                        */
+                       "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (14) which
+                        * is 16.  Then the variable offset is considered using
+                        * reg->aux_off_align which is 4 and meets the load's
+                        * requirements.
+                        */
+                       "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* Constant offset is added to R5 packet pointer,
+                        * resulting in reg->off value of 14.
+                        */
+                       "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp",
+                       /* Variable offset is added to R5, resulting in an
+                        * auxiliary offset of 14, and an auxiliary alignment of 4.
+                        */
+                       "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* Constant is added to R5 again, setting reg->off to 4. */
+                       "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* And once more we add a variable, which causes an accumulation
+                        * of reg->off into reg->aux_off_align, with resulting value of
+                        * 18.  The auxiliary alignment stays at 4.
+                        */
+                       "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (0) +
+                        * reg->aux_off (18) which is 20.  Then the variable offset
+                        * is considered using reg->aux_off_align which is 4 and meets
+                        * the load's requirements.
+                        */
+                       "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+               },
+       },
+};
+
+static int probe_filter_length(const struct bpf_insn *fp)
+{
+       int len;
+
+       for (len = MAX_INSNS - 1; len > 0; --len)
+               if (fp[len].code != 0 || fp[len].imm != 0)
+                       break;
+       return len + 1;
+}
+
+static char bpf_vlog[32768];
+
+static int do_test_single(struct bpf_align_test *test)
+{
+       struct bpf_insn *prog = test->insns;
+       int prog_type = test->prog_type;
+       int prog_len, i;
+       int fd_prog;
+       int ret;
+
+       prog_len = probe_filter_length(prog);
+       fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+                                    prog, prog_len, 1, "GPL", 0,
+                                    bpf_vlog, sizeof(bpf_vlog));
+       if (fd_prog < 0) {
+               printf("Failed to load program.\n");
+               printf("%s", bpf_vlog);
+               ret = 1;
+       } else {
+               ret = 0;
+               for (i = 0; i < MAX_MATCHES; i++) {
+                       const char *t, *m = test->matches[i];
+
+                       if (!m)
+                               break;
+                       t = strstr(bpf_vlog, m);
+                       if (!t) {
+                               printf("Failed to find match: %s\n", m);
+                               ret = 1;
+                               printf("%s", bpf_vlog);
+                               break;
+                       }
+               }
+               close(fd_prog);
+       }
+       return ret;
+}
+
+static int do_test(unsigned int from, unsigned int to)
+{
+       int all_pass = 0;
+       int all_fail = 0;
+       unsigned int i;
+
+       for (i = from; i < to; i++) {
+               struct bpf_align_test *test = &tests[i];
+               int fail;
+
+               printf("Test %3d: %s ... ",
+                      i, test->descr);
+               fail = do_test_single(test);
+               if (fail) {
+                       all_fail++;
+                       printf("FAIL\n");
+               } else {
+                       all_pass++;
+                       printf("PASS\n");
+               }
+       }
+       printf("Results: %d pass %d fail\n",
+              all_pass, all_fail);
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       unsigned int from = 0, to = ARRAY_SIZE(tests);
+
+       if (argc == 3) {
+               unsigned int l = atoi(argv[argc - 2]);
+               unsigned int u = atoi(argv[argc - 1]);
+
+               if (l < to && u < to) {
+                       from = l;
+                       to   = u + 1;
+               }
+       } else if (argc == 2) {
+               unsigned int t = atoi(argv[argc - 1]);
+
+               if (t < to) {
+                       from = t;
+                       to   = t + 1;
+               }
+       }
+       return do_test(from, to);
+}
index 39387bb7e08ca79be1ebd94452c0c126abd2316c..6e11ba11709e5cfcba232be08e706622515cdcef 100644 (file)
@@ -5,6 +5,7 @@
  * License as published by the Free Software Foundation.
  */
 #include <stddef.h>
+#include <string.h>
 #include <linux/bpf.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
index 3773562056da267aee91878ed8088b3c577a997e..0ff8c55c0464a62bddd2bf6bd99ffc5041798ac3 100644 (file)
@@ -49,6 +49,7 @@
 #define MAX_NR_MAPS    4
 
 #define F_NEEDS_EFFICIENT_UNALIGNED_ACCESS     (1 << 0)
+#define F_LOAD_WITH_STRICT_ALIGNMENT           (1 << 1)
 
 struct bpf_test {
        const char *descr;
@@ -2614,6 +2615,30 @@ static struct bpf_test tests[] = {
                .result = REJECT,
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        },
+       {
+               "direct packet access: test17 (pruning, alignment)",
+               .insns = {
+                       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+                                   offsetof(struct __sk_buff, data)),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
+                                   offsetof(struct __sk_buff, data_end)),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
+                                   offsetof(struct __sk_buff, mark)),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 14),
+                       BPF_JMP_IMM(BPF_JGT, BPF_REG_7, 1, 4),
+                       BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 1),
+                       BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, -4),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
+                       BPF_JMP_A(-6),
+               },
+               .errstr = "misaligned packet access off 2+15+-4 size 4",
+               .result = REJECT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .flags = F_LOAD_WITH_STRICT_ALIGNMENT,
+       },
        {
                "helper access to packet: test1, valid packet_ptr range",
                .insns = {
@@ -3340,6 +3365,70 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .prog_type = BPF_PROG_TYPE_SCHED_CLS
        },
+       {
+               "alu ops on ptr_to_map_value_or_null, 1",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_1, 10),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
+               .errstr = "R4 invalid mem access",
+               .result = REJECT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS
+       },
+       {
+               "alu ops on ptr_to_map_value_or_null, 2",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_1, 10),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_4, -1),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
+               .errstr = "R4 invalid mem access",
+               .result = REJECT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS
+       },
+       {
+               "alu ops on ptr_to_map_value_or_null, 3",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_1, 10),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_1, -8),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 1),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
+               .errstr = "R4 invalid mem access",
+               .result = REJECT,
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS
+       },
        {
                "invalid memory access with multiple map_lookup_elem calls",
                .insns = {
@@ -3659,6 +3748,72 @@ static struct bpf_test tests[] = {
                .result = REJECT,
                .errstr = "invalid bpf_context access",
        },
+       {
+               "leak pointer into ctx 1",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
+                                   offsetof(struct __sk_buff, cb[0])),
+                       BPF_LD_MAP_FD(BPF_REG_2, 0),
+                       BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_2,
+                                     offsetof(struct __sk_buff, cb[0])),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 2 },
+               .errstr_unpriv = "R2 leaks addr into mem",
+               .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
+       {
+               "leak pointer into ctx 2",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
+                                   offsetof(struct __sk_buff, cb[0])),
+                       BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_10,
+                                     offsetof(struct __sk_buff, cb[0])),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr_unpriv = "R10 leaks addr into mem",
+               .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
+       {
+               "leak pointer into ctx 3",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_LD_MAP_FD(BPF_REG_2, 0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2,
+                                     offsetof(struct __sk_buff, cb[0])),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 1 },
+               .errstr_unpriv = "R2 leaks addr into ctx",
+               .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
+       {
+               "leak pointer into map val",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
+                       BPF_LD_MAP_FD(BPF_REG_1, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0),
+                       BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map1 = { 4 },
+               .errstr_unpriv = "R6 leaks addr into mem",
+               .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
        {
                "helper access to map: full range",
                .insns = {
@@ -4937,7 +5092,149 @@ static struct bpf_test tests[] = {
                .fixup_map_in_map = { 3 },
                .errstr = "R1 type=map_value_or_null expected=map_ptr",
                .result = REJECT,
-       }
+       },
+       {
+               "ld_abs: check calling conv, r1",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_1, 0),
+                       BPF_LD_ABS(BPF_W, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R1 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_abs: check calling conv, r2",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_LD_ABS(BPF_W, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R2 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_abs: check calling conv, r3",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       BPF_LD_ABS(BPF_W, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R3 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_abs: check calling conv, r4",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_4, 0),
+                       BPF_LD_ABS(BPF_W, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R4 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_abs: check calling conv, r5",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_5, 0),
+                       BPF_LD_ABS(BPF_W, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_5),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R5 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_abs: check calling conv, r7",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_7, 0),
+                       BPF_LD_ABS(BPF_W, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
+       {
+               "ld_ind: check calling conv, r1",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_1, 1),
+                       BPF_LD_IND(BPF_W, BPF_REG_1, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R1 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_ind: check calling conv, r2",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_2, 1),
+                       BPF_LD_IND(BPF_W, BPF_REG_2, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R2 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_ind: check calling conv, r3",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_3, 1),
+                       BPF_LD_IND(BPF_W, BPF_REG_3, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R3 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_ind: check calling conv, r4",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_4, 1),
+                       BPF_LD_IND(BPF_W, BPF_REG_4, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_4),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R4 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_ind: check calling conv, r5",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_5, 1),
+                       BPF_LD_IND(BPF_W, BPF_REG_5, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_5),
+                       BPF_EXIT_INSN(),
+               },
+               .errstr = "R5 !read_ok",
+               .result = REJECT,
+       },
+       {
+               "ld_ind: check calling conv, r7",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_MOV64_IMM(BPF_REG_7, 1),
+                       BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
+                       BPF_EXIT_INSN(),
+               },
+               .result = ACCEPT,
+       },
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)
@@ -5059,9 +5356,9 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
 
        do_test_fixup(test, prog, map_fds);
 
-       fd_prog = bpf_load_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
-                                  prog, prog_len, "GPL", 0, bpf_vlog,
-                                  sizeof(bpf_vlog));
+       fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+                                    prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT,
+                                    "GPL", 0, bpf_vlog, sizeof(bpf_vlog));
 
        expected_ret = unpriv && test->result_unpriv != UNDEF ?
                       test->result_unpriv : test->result;
index 32e6211e1c6e81f44028f9d3b0f78fb8f8c0eb0d..717581145cfcf9dbf8ec129c81c26ce81d4d9ddf 100755 (executable)
@@ -58,7 +58,7 @@ parse_opts() { # opts
     ;;
     --verbose|-v|-vv)
       VERBOSE=$((VERBOSE + 1))
-      [ $1 == '-vv' ] && VERBOSE=$((VERBOSE + 1))
+      [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
       shift 1
     ;;
     --debug|-d)
index 07bb3e5930b459b6ad52765ff92fb0fa416e603d..aa31368851c952e2f6e9dc78dd4a4915a36450fc 100644 (file)
@@ -48,7 +48,7 @@ test_event_enabled() {
     e=`cat $EVENT_ENABLE`
     if [ "$e" != $val ]; then
        echo "Expected $val but found $e"
-       exit -1
+       exit 1
     fi
 }
 
index 9aec6fcb7729ff0e7ec600ae91b80a24236b7bf6..f2019b37370d310cd845b6a42101d77cad77bc6b 100644 (file)
@@ -34,10 +34,10 @@ reset_ftrace_filter() { # reset all triggers in set_ftrace_filter
     echo > set_ftrace_filter
     grep -v '^#' set_ftrace_filter | while read t; do
        tr=`echo $t | cut -d: -f2`
-       if [ "$tr" == "" ]; then
+       if [ "$tr" = "" ]; then
            continue
        fi
-       if [ $tr == "enable_event" -o $tr == "disable_event" ]; then
+       if [ $tr = "enable_event" -o $tr = "disable_event" ]; then
            tr=`echo $t | cut -d: -f1-4`
            limit=`echo $t | cut -d: -f5`
        else
index 4c5a061a5b4e6d522396714de21f64b871e23ab4..c73db7863adbf41b51bd6b88ca79881801d59943 100644 (file)
@@ -75,9 +75,13 @@ rmdir foo
 if [ -d foo ]; then
         fail "foo still exists"
 fi
-exit 0
-
 
+mkdir foo
+echo "schedule:enable_event:sched:sched_switch" > foo/set_ftrace_filter
+rmdir foo
+if [ -d foo ]; then
+        fail "foo still exists"
+fi
 
 
 instance_slam() {
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
new file mode 100644 (file)
index 0000000..f4d1ff7
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+# description: Register/unregister many kprobe events
+
+# ftrace fentry skip size depends on the machine architecture.
+# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc
+case `uname -m` in
+  x86_64|i[3456]86) OFFS=5;;
+  ppc*) OFFS=4;;
+  *) OFFS=0;;
+esac
+
+echo "Setup up to 256 kprobes"
+grep t /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \
+head -n 256 | while read i; do echo p ${i}+${OFFS} ; done > kprobe_events ||:
+
+echo 1 > events/kprobes/enable
+echo 0 > events/kprobes/enable
+echo > kprobe_events
+echo "Waiting for unoptimizing & freeing"
+sleep 5
+echo "Done"
index a676d3eefefbdd4b239d394a9b057f15c6a2cd7f..13f5198ba0ee737819b24cbc3538cc4b97e8d2f2 100755 (executable)
@@ -305,7 +305,7 @@ function perf_test()
        echo "Running remote perf test $WITH DMA"
        write_file "" $REMOTE_PERF/run
        echo -n "  "
-       read_file $LOCAL_PERF/run
+       read_file $REMOTE_PERF/run
        echo "  Passed"
 
        _modprobe -r ntb_perf
index 427621792229e68c7fcdaff89f28782bda14c1da..2f1f7b013293491b2845f68fa03dbc591c8d5412 100644 (file)
@@ -11,3 +11,4 @@ tm-signal-context-chk-fpu
 tm-signal-context-chk-gpr
 tm-signal-context-chk-vmx
 tm-signal-context-chk-vsx
+tm-vmx-unavail
index 5576ee6a51f21bb32a0ede4337d9da049e37fd42..958c11c14acd017a6c3afe79f02d9c6e8fad2240 100644 (file)
@@ -2,7 +2,8 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu
        tm-signal-context-chk-vmx tm-signal-context-chk-vsx
 
 TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
-       tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
+       tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail \
+       $(SIGNAL_CONTEXT_CHK_TESTS)
 
 include ../../lib.mk
 
@@ -13,6 +14,7 @@ CFLAGS += -mhtm
 $(OUTPUT)/tm-syscall: tm-syscall-asm.S
 $(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
 $(OUTPUT)/tm-tmspr: CFLAGS += -pthread
+$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
 
 SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
 $(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
index d9c49f41515e704994ed1669dbe0a859a6dadd79..e79ccd6aada1a9acf10bb2860e76ddb444415d52 100644 (file)
@@ -42,12 +42,12 @@ int test_body(void)
        printf("Check DSCR TM context switch: ");
        fflush(stdout);
        for (;;) {
-               rv = 1;
                asm __volatile__ (
                        /* set a known value into the DSCR */
                        "ld      3, %[dscr1];"
                        "mtspr   %[sprn_dscr], 3;"
 
+                       "li      %[rv], 1;"
                        /* start and suspend a transaction */
                        "tbegin.;"
                        "beq     1f;"
diff --git a/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c b/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
new file mode 100644 (file)
index 0000000..137185b
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2017, Michael Neuling, IBM Corp.
+ * Licensed under GPLv2.
+ * Original: Breno Leitao <brenohl@br.ibm.com> &
+ *           Gustavo Bueno Romero <gromero@br.ibm.com>
+ * Edited: Michael Neuling
+ *
+ * Force VMX unavailable during a transaction and see if it corrupts
+ * the checkpointed VMX register state after the abort.
+ */
+
+#include <inttypes.h>
+#include <htmintrin.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "tm.h"
+#include "utils.h"
+
+int passed;
+
+void *worker(void *unused)
+{
+       __int128 vmx0;
+       uint64_t texasr;
+
+       asm goto (
+               "li       3, 1;"  /* Stick non-zero value in VMX0 */
+               "std      3, 0(%[vmx0_ptr]);"
+               "lvx      0, 0, %[vmx0_ptr];"
+
+               /* Wait here a bit so we get scheduled out 255 times */
+               "lis      3, 0x3fff;"
+               "1: ;"
+               "addi     3, 3, -1;"
+               "cmpdi    3, 0;"
+               "bne      1b;"
+
+               /* Kernel will hopefully turn VMX off now */
+
+               "tbegin. ;"
+               "beq      failure;"
+
+               /* Cause VMX unavail. Any VMX instruction */
+               "vaddcuw  0,0,0;"
+
+               "tend. ;"
+               "b        %l[success];"
+
+               /* Check VMX0 sanity after abort */
+               "failure: ;"
+               "lvx       1,  0, %[vmx0_ptr];"
+               "vcmpequb. 2,  0, 1;"
+               "bc        4, 24, %l[value_mismatch];"
+               "b        %l[value_match];"
+               :
+               : [vmx0_ptr] "r"(&vmx0)
+               : "r3"
+               : success, value_match, value_mismatch
+               );
+
+       /* HTM aborted and VMX0 is corrupted */
+value_mismatch:
+       texasr = __builtin_get_texasr();
+
+       printf("\n\n==============\n\n");
+       printf("Failure with error: %lx\n",   _TEXASR_FAILURE_CODE(texasr));
+       printf("Summary error     : %lx\n",   _TEXASR_FAILURE_SUMMARY(texasr));
+       printf("TFIAR exact       : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr));
+
+       passed = 0;
+       return NULL;
+
+       /* HTM aborted but VMX0 is correct */
+value_match:
+//     printf("!");
+       return NULL;
+
+success:
+//     printf(".");
+       return NULL;
+}
+
+int tm_vmx_unavail_test()
+{
+       int threads;
+       pthread_t *thread;
+
+       SKIP_IF(!have_htm());
+
+       passed = 1;
+
+       threads = sysconf(_SC_NPROCESSORS_ONLN) * 4;
+       thread = malloc(sizeof(pthread_t)*threads);
+       if (!thread)
+               return EXIT_FAILURE;
+
+       for (uint64_t i = 0; i < threads; i++)
+               pthread_create(&thread[i], NULL, &worker, NULL);
+
+       for (uint64_t i = 0; i < threads; i++)
+               pthread_join(thread[i], NULL);
+
+       free(thread);
+
+       return passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+
+int main(int argc, char **argv)
+{
+       return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test");
+}
index c0c48507e44e2992b3624b2374cd08769a8bb607..ad0543e21760562d94bc0a44676700b1179c1787 100644 (file)
@@ -220,6 +220,7 @@ config INITRAMFS_COMPRESSION_LZ4
 endchoice
 
 config INITRAMFS_COMPRESSION
+       depends on INITRAMFS_SOURCE!=""
        string
        default ""      if INITRAMFS_COMPRESSION_NONE
        default ".gz"   if INITRAMFS_COMPRESSION_GZIP
index bce6037cf01d31a73178e44b911dc25c2b6d5929..87940364570bcbff87cfa4447cb555e96612355b 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)           ((v) & 0xf)
-#define vtr_to_nr_pri_bits(v)          (((u32)(v) >> 29) + 1)
+#define vtr_to_nr_pre_bits(v)          ((((u32)(v) >> 26) & 7) + 1)
 
 static u64 __hyp_text __gic_v3_get_lr(unsigned int lr)
 {
@@ -135,13 +135,13 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
        if (used_lrs) {
                int i;
-               u32 nr_pri_bits;
+               u32 nr_pre_bits;
 
                cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2);
 
                write_gicreg(0, ICH_HCR_EL2);
                val = read_gicreg(ICH_VTR_EL2);
-               nr_pri_bits = vtr_to_nr_pri_bits(val);
+               nr_pre_bits = vtr_to_nr_pre_bits(val);
 
                for (i = 0; i < used_lrs; i++) {
                        if (cpu_if->vgic_elrsr & (1 << i))
@@ -152,7 +152,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
                        __gic_v3_set_lr(0, i);
                }
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
                        cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
@@ -162,7 +162,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
                        cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
                }
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
                        cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
@@ -198,7 +198,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
        u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
        u64 val;
-       u32 nr_pri_bits;
+       u32 nr_pre_bits;
        int i;
 
        /*
@@ -217,12 +217,12 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        }
 
        val = read_gicreg(ICH_VTR_EL2);
-       nr_pri_bits = vtr_to_nr_pri_bits(val);
+       nr_pre_bits = vtr_to_nr_pre_bits(val);
 
        if (used_lrs) {
                write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
                        write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
@@ -232,7 +232,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
                        write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
                }
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
                        write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
index 313ee646480f4d88264664d7393fcb39969609ba..e2e5effba2a999577edb338fdc0c2cf5c9a1e63f 100644 (file)
@@ -295,6 +295,13 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
        assert_spin_locked(&kvm->mmu_lock);
        pgd = kvm->arch.pgd + stage2_pgd_index(addr);
        do {
+               /*
+                * Make sure the page table is still active, as another thread
+                * could have possibly freed the page table, while we released
+                * the lock.
+                */
+               if (!READ_ONCE(kvm->arch.pgd))
+                       break;
                next = stage2_pgd_addr_end(addr, end);
                if (!stage2_pgd_none(*pgd))
                        unmap_stage2_puds(kvm, pgd, addr, next);
@@ -829,22 +836,22 @@ void stage2_unmap_vm(struct kvm *kvm)
  * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all
  * underlying level-2 and level-3 tables before freeing the actual level-1 table
  * and setting the struct pointer to NULL.
- *
- * Note we don't need locking here as this is only called when the VM is
- * destroyed, which can only be done once.
  */
 void kvm_free_stage2_pgd(struct kvm *kvm)
 {
-       if (kvm->arch.pgd == NULL)
-               return;
+       void *pgd = NULL;
 
        spin_lock(&kvm->mmu_lock);
-       unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+       if (kvm->arch.pgd) {
+               unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+               pgd = READ_ONCE(kvm->arch.pgd);
+               kvm->arch.pgd = NULL;
+       }
        spin_unlock(&kvm->mmu_lock);
 
        /* Free the HW pgd, one page at a time */
-       free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
-       kvm->arch.pgd = NULL;
+       if (pgd)
+               free_pages_exact(pgd, S2_PGD_SIZE);
 }
 
 static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
@@ -872,6 +879,9 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
        pmd_t *pmd;
 
        pud = stage2_get_pud(kvm, cache, addr);
+       if (!pud)
+               return NULL;
+
        if (stage2_pud_none(*pud)) {
                if (!cache)
                        return NULL;
@@ -1170,11 +1180,13 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
                 * large. Otherwise, we may see kernel panics with
                 * CONFIG_DETECT_HUNG_TASK, CONFIG_LOCKUP_DETECTOR,
                 * CONFIG_LOCKDEP. Additionally, holding the lock too long
-                * will also starve other vCPUs.
+                * will also starve other vCPUs. We have to also make sure
+                * that the page tables are not freed while we released
+                * the lock.
                 */
-               if (need_resched() || spin_needbreak(&kvm->mmu_lock))
-                       cond_resched_lock(&kvm->mmu_lock);
-
+               cond_resched_lock(&kvm->mmu_lock);
+               if (!READ_ONCE(kvm->arch.pgd))
+                       break;
                next = stage2_pgd_addr_end(addr, end);
                if (stage2_pgd_present(*pgd))
                        stage2_wp_puds(pgd, addr, next);
index dc68e2e424abf301151f4a610d412ea4b9109831..3a0b8999f011c6e3e1ff6ea7699577879a651fd3 100644 (file)
@@ -242,8 +242,11 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
         * If we are creating a VCPU with a GICv3 we must also register the
         * KVM io device for the redistributor that belongs to this VCPU.
         */
-       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+               mutex_lock(&vcpu->kvm->lock);
                ret = vgic_register_redist_iodev(vcpu);
+               mutex_unlock(&vcpu->kvm->lock);
+       }
        return ret;
 }
 
index 0a4283ed9aa735e55e476bdea0a19ed159952646..63e0bbdcddcc3e5e59163c08a5691dd36c416564 100644 (file)
@@ -226,7 +226,13 @@ static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
 
        switch (addr & 0xff) {
        case GIC_CPU_CTRL:
-               val = vmcr.ctlr;
+               val = vmcr.grpen0 << GIC_CPU_CTRL_EnableGrp0_SHIFT;
+               val |= vmcr.grpen1 << GIC_CPU_CTRL_EnableGrp1_SHIFT;
+               val |= vmcr.ackctl << GIC_CPU_CTRL_AckCtl_SHIFT;
+               val |= vmcr.fiqen << GIC_CPU_CTRL_FIQEn_SHIFT;
+               val |= vmcr.cbpr << GIC_CPU_CTRL_CBPR_SHIFT;
+               val |= vmcr.eoim << GIC_CPU_CTRL_EOImodeNS_SHIFT;
+
                break;
        case GIC_CPU_PRIMASK:
                /*
@@ -267,7 +273,13 @@ static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
 
        switch (addr & 0xff) {
        case GIC_CPU_CTRL:
-               vmcr.ctlr = val;
+               vmcr.grpen0 = !!(val & GIC_CPU_CTRL_EnableGrp0);
+               vmcr.grpen1 = !!(val & GIC_CPU_CTRL_EnableGrp1);
+               vmcr.ackctl = !!(val & GIC_CPU_CTRL_AckCtl);
+               vmcr.fiqen = !!(val & GIC_CPU_CTRL_FIQEn);
+               vmcr.cbpr = !!(val & GIC_CPU_CTRL_CBPR);
+               vmcr.eoim = !!(val & GIC_CPU_CTRL_EOImodeNS);
+
                break;
        case GIC_CPU_PRIMASK:
                /*
index 99da1a207c19b0563030bf4ad842d8d805b1b153..201d5e2e973dd4504c1f41747b2f07bb797ade11 100644 (file)
@@ -586,7 +586,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
        if (!vgic_v3_check_base(kvm))
                return -EINVAL;
 
-       rd_base = vgic->vgic_redist_base + kvm_vcpu_get_idx(vcpu) * SZ_64K * 2;
+       rd_base = vgic->vgic_redist_base + vgic->vgic_redist_free_offset;
        sgi_base = rd_base + SZ_64K;
 
        kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
@@ -614,11 +614,15 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
        mutex_lock(&kvm->slots_lock);
        ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
                                      SZ_64K, &sgi_dev->dev);
-       mutex_unlock(&kvm->slots_lock);
-       if (ret)
+       if (ret) {
                kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
                                          &rd_dev->dev);
+               goto out;
+       }
 
+       vgic->vgic_redist_free_offset += 2 * SZ_64K;
+out:
+       mutex_unlock(&kvm->slots_lock);
        return ret;
 }
 
@@ -644,10 +648,12 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
 
        if (ret) {
                /* The current c failed, so we start with the previous one. */
+               mutex_lock(&kvm->slots_lock);
                for (c--; c >= 0; c--) {
                        vcpu = kvm_get_vcpu(kvm, c);
                        vgic_unregister_redist_iodev(vcpu);
                }
+               mutex_unlock(&kvm->slots_lock);
        }
 
        return ret;
index a65757aab6d32cef8fff2306e80fb6df0486bbc7..e4187e52bb26e65c87743c760fb5c651eedb5ea7 100644 (file)
@@ -149,6 +149,13 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (irq->hw) {
                val |= GICH_LR_HW;
                val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+               /*
+                * Never set pending+active on a HW interrupt, as the
+                * pending state is kept at the physical distributor
+                * level.
+                */
+               if (irq->active && irq_is_pending(irq))
+                       val &= ~GICH_LR_PENDING_BIT;
        } else {
                if (irq->config == VGIC_CONFIG_LEVEL)
                        val |= GICH_LR_EOI;
@@ -170,7 +177,18 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
        struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
        u32 vmcr;
 
-       vmcr  = (vmcrp->ctlr << GICH_VMCR_CTRL_SHIFT) & GICH_VMCR_CTRL_MASK;
+       vmcr = (vmcrp->grpen0 << GICH_VMCR_ENABLE_GRP0_SHIFT) &
+               GICH_VMCR_ENABLE_GRP0_MASK;
+       vmcr |= (vmcrp->grpen1 << GICH_VMCR_ENABLE_GRP1_SHIFT) &
+               GICH_VMCR_ENABLE_GRP1_MASK;
+       vmcr |= (vmcrp->ackctl << GICH_VMCR_ACK_CTL_SHIFT) &
+               GICH_VMCR_ACK_CTL_MASK;
+       vmcr |= (vmcrp->fiqen << GICH_VMCR_FIQ_EN_SHIFT) &
+               GICH_VMCR_FIQ_EN_MASK;
+       vmcr |= (vmcrp->cbpr << GICH_VMCR_CBPR_SHIFT) &
+               GICH_VMCR_CBPR_MASK;
+       vmcr |= (vmcrp->eoim << GICH_VMCR_EOI_MODE_SHIFT) &
+               GICH_VMCR_EOI_MODE_MASK;
        vmcr |= (vmcrp->abpr << GICH_VMCR_ALIAS_BINPOINT_SHIFT) &
                GICH_VMCR_ALIAS_BINPOINT_MASK;
        vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) &
@@ -188,8 +206,19 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 
        vmcr = cpu_if->vgic_vmcr;
 
-       vmcrp->ctlr = (vmcr & GICH_VMCR_CTRL_MASK) >>
-                       GICH_VMCR_CTRL_SHIFT;
+       vmcrp->grpen0 = (vmcr & GICH_VMCR_ENABLE_GRP0_MASK) >>
+               GICH_VMCR_ENABLE_GRP0_SHIFT;
+       vmcrp->grpen1 = (vmcr & GICH_VMCR_ENABLE_GRP1_MASK) >>
+               GICH_VMCR_ENABLE_GRP1_SHIFT;
+       vmcrp->ackctl = (vmcr & GICH_VMCR_ACK_CTL_MASK) >>
+               GICH_VMCR_ACK_CTL_SHIFT;
+       vmcrp->fiqen = (vmcr & GICH_VMCR_FIQ_EN_MASK) >>
+               GICH_VMCR_FIQ_EN_SHIFT;
+       vmcrp->cbpr = (vmcr & GICH_VMCR_CBPR_MASK) >>
+               GICH_VMCR_CBPR_SHIFT;
+       vmcrp->eoim = (vmcr & GICH_VMCR_EOI_MODE_MASK) >>
+               GICH_VMCR_EOI_MODE_SHIFT;
+
        vmcrp->abpr = (vmcr & GICH_VMCR_ALIAS_BINPOINT_MASK) >>
                        GICH_VMCR_ALIAS_BINPOINT_SHIFT;
        vmcrp->bpr  = (vmcr & GICH_VMCR_BINPOINT_MASK) >>
index 8fa737edde6f2f9458fc0a6a33faa4c8c9fa810e..030248e669f65acd5e0155fbbef189d96e7cf7e3 100644 (file)
@@ -127,6 +127,13 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (irq->hw) {
                val |= ICH_LR_HW;
                val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+               /*
+                * Never set pending+active on a HW interrupt, as the
+                * pending state is kept at the physical distributor
+                * level.
+                */
+               if (irq->active && irq_is_pending(irq))
+                       val &= ~ICH_LR_PENDING_BIT;
        } else {
                if (irq->config == VGIC_CONFIG_LEVEL)
                        val |= ICH_LR_EOI;
@@ -152,15 +159,24 @@ void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr)
 void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
+       u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u32 vmcr;
 
-       /*
-        * Ignore the FIQen bit, because GIC emulation always implies
-        * SRE=1 which means the vFIQEn bit is also RES1.
-        */
-       vmcr = ((vmcrp->ctlr >> ICC_CTLR_EL1_EOImode_SHIFT) <<
-                ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;
-       vmcr |= (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
+       if (model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+               vmcr = (vmcrp->ackctl << ICH_VMCR_ACK_CTL_SHIFT) &
+                       ICH_VMCR_ACK_CTL_MASK;
+               vmcr |= (vmcrp->fiqen << ICH_VMCR_FIQ_EN_SHIFT) &
+                       ICH_VMCR_FIQ_EN_MASK;
+       } else {
+               /*
+                * When emulating GICv3 on GICv3 with SRE=1 on the
+                * VFIQEn bit is RES1 and the VAckCtl bit is RES0.
+                */
+               vmcr = ICH_VMCR_FIQ_EN_MASK;
+       }
+
+       vmcr |= (vmcrp->cbpr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
+       vmcr |= (vmcrp->eoim << ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;
        vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
        vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
        vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
@@ -173,17 +189,27 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
+       u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u32 vmcr;
 
        vmcr = cpu_if->vgic_vmcr;
 
-       /*
-        * Ignore the FIQen bit, because GIC emulation always implies
-        * SRE=1 which means the vFIQEn bit is also RES1.
-        */
-       vmcrp->ctlr = ((vmcr >> ICH_VMCR_EOIM_SHIFT) <<
-                       ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK;
-       vmcrp->ctlr |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+       if (model == KVM_DEV_TYPE_ARM_VGIC_V2) {
+               vmcrp->ackctl = (vmcr & ICH_VMCR_ACK_CTL_MASK) >>
+                       ICH_VMCR_ACK_CTL_SHIFT;
+               vmcrp->fiqen = (vmcr & ICH_VMCR_FIQ_EN_MASK) >>
+                       ICH_VMCR_FIQ_EN_SHIFT;
+       } else {
+               /*
+                * When emulating GICv3 on GICv3 with SRE=1 on the
+                * VFIQEn bit is RES1 and the VAckCtl bit is RES0.
+                */
+               vmcrp->fiqen = 1;
+               vmcrp->ackctl = 0;
+       }
+
+       vmcrp->cbpr = (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+       vmcrp->eoim = (vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT;
        vmcrp->abpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
        vmcrp->bpr  = (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
        vmcrp->pmr  = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
index da83e4caa272f2621b840123e79dfbc3e5ceaead..bba7fa22a7f7c41a5d1fa88c02fb15c158992ccd 100644 (file)
@@ -111,14 +111,18 @@ static inline bool irq_is_pending(struct vgic_irq *irq)
  * registers regardless of the hardware backed GIC used.
  */
 struct vgic_vmcr {
-       u32     ctlr;
+       u32     grpen0;
+       u32     grpen1;
+
+       u32     ackctl;
+       u32     fiqen;
+       u32     cbpr;
+       u32     eoim;
+
        u32     abpr;
        u32     bpr;
        u32     pmr;  /* Priority mask field in the GICC_PMR and
                       * ICC_PMR_EL1 priority field format */
-       /* Below member variable are valid only for GICv3 */
-       u32     grpen0;
-       u32     grpen1;
 };
 
 struct vgic_reg_attr {