]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge back earlier cpufreq material for v5.1.
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sun, 24 Feb 2019 20:18:05 +0000 (21:18 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sun, 24 Feb 2019 20:18:05 +0000 (21:18 +0100)
1421 files changed:
.clang-format
Documentation/ABI/stable/sysfs-driver-mlxreg-io
Documentation/admin-guide/kernel-parameters.txt
Documentation/bpf/bpf_design_QA.rst
Documentation/core-api/xarray.rst
Documentation/devicetree/bindings/Makefile
Documentation/devicetree/bindings/arm/cpu-capacity.txt
Documentation/devicetree/bindings/arm/idle-states.txt
Documentation/devicetree/bindings/arm/sp810.txt
Documentation/devicetree/bindings/arm/topology.txt
Documentation/devicetree/bindings/clock/marvell,mmp2.txt
Documentation/devicetree/bindings/display/arm,pl11x.txt
Documentation/devicetree/bindings/display/msm/gpu.txt
Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
Documentation/devicetree/bindings/serio/olpc,ap-sp.txt
Documentation/devicetree/bindings/soc/qcom/qcom,glink.txt
Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt
Documentation/fb/fbcon.txt
Documentation/networking/index.rst
Documentation/networking/operstates.txt
Documentation/networking/rxrpc.txt
Documentation/networking/snmp_counter.rst
Documentation/networking/timestamping.txt
Documentation/sysctl/fs.txt
Documentation/x86/resctrl_ui.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/irq.h
arch/alpha/mm/fault.c
arch/arc/include/asm/Kbuild
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/bitops.h
arch/arc/include/asm/perf_event.h
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/troubleshoot.c
arch/arc/lib/memset-archs.S
arch/arc/mm/fault.c
arch/arc/mm/init.c
arch/arm/boot/dts/am335x-shc.dts
arch/arm/boot/dts/da850.dtsi
arch/arm/boot/dts/imx6q-pistachio.dts
arch/arm/boot/dts/imx6sll-evk.dts
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/meson8b-ec100.dts
arch/arm/boot/dts/meson8b-odroidc1.dts
arch/arm/boot/dts/meson8m2-mxiii-plus.dts
arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
arch/arm/boot/dts/omap3-gta04.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap4-droid4-xt894.dts
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/omap5-cm-t54.dts
arch/arm/boot/dts/omap5-l4.dtsi
arch/arm/boot/dts/r8a7743.dtsi
arch/arm/boot/dts/rk3188.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
arch/arm/boot/dts/vf610-bk4.dts
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/stage2_pgtable.h
arch/arm/include/asm/xen/page-coherent.h
arch/arm/kvm/coproc.c
arch/arm/kvm/reset.c
arch/arm/mach-cns3xxx/pcie.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-tango/pm.c
arch/arm/mach-tango/pm.h [new file with mode: 0644]
arch/arm/mach-tango/setup.c
arch/arm/plat-pxa/ssp.c
arch/arm/xen/mm.c
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts
arch/arm64/boot/dts/freescale/imx8mq-evk.dts
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/renesas/r8a774a1.dtsi
arch/arm64/boot/dts/renesas/r8a7796.dtsi
arch/arm64/boot/dts/renesas/r8a77965.dtsi
arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/device.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/mmu.h
arch/arm64/include/asm/xen/page-coherent.h
arch/arm64/kernel/hibernate.c
arch/arm64/kernel/hyp-stub.S
arch/arm64/kernel/kaslr.c
arch/arm64/kernel/machine_kexec_file.c
arch/arm64/kernel/probes/kprobes.c
arch/arm64/kernel/setup.c
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/sysreg-sr.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/dump.c
arch/arm64/mm/flush.c
arch/c6x/include/asm/Kbuild
arch/c6x/include/uapi/asm/Kbuild
arch/csky/include/asm/pgtable.h
arch/csky/include/asm/processor.h
arch/csky/kernel/dumpstack.c
arch/csky/kernel/ptrace.c
arch/csky/kernel/smp.c
arch/csky/mm/ioremap.c
arch/h8300/Makefile
arch/h8300/include/asm/Kbuild
arch/h8300/include/uapi/asm/Kbuild
arch/hexagon/include/asm/Kbuild
arch/hexagon/include/uapi/asm/Kbuild
arch/ia64/Makefile
arch/m68k/emu/nfblock.c
arch/m68k/include/asm/Kbuild
arch/m68k/include/uapi/asm/Kbuild
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/uapi/asm/Kbuild
arch/mips/Kconfig
arch/mips/bcm47xx/setup.c
arch/mips/boot/dts/ingenic/ci20.dts
arch/mips/boot/dts/ingenic/jz4740.dtsi
arch/mips/boot/dts/xilfpga/nexys4ddr.dts
arch/mips/cavium-octeon/setup.c
arch/mips/configs/ath79_defconfig
arch/mips/include/asm/atomic.h
arch/mips/include/asm/barrier.h
arch/mips/include/asm/bitops.h
arch/mips/include/asm/futex.h
arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
arch/mips/include/asm/pgtable.h
arch/mips/jazz/jazzdma.c
arch/mips/kernel/mips-cm.c
arch/mips/kernel/process.c
arch/mips/lantiq/irq.c
arch/mips/loongson64/Platform
arch/mips/loongson64/common/reset.c
arch/mips/mm/tlbex.c
arch/mips/pci/msi-octeon.c
arch/mips/pci/pci-octeon.c
arch/mips/vdso/Makefile
arch/nds32/Makefile
arch/openrisc/Makefile
arch/openrisc/include/asm/Kbuild
arch/openrisc/include/uapi/asm/Kbuild
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/uapi/asm/perf_regs.h
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/perf/perf_regs.c
arch/powerpc/platforms/4xx/ocm.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/powernv/npu-dma.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/platforms/pseries/pci.c
arch/riscv/Kconfig
arch/riscv/configs/defconfig
arch/riscv/include/asm/page.h
arch/riscv/include/asm/pgtable-bits.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/processor.h
arch/riscv/kernel/asm-offsets.c
arch/riscv/kernel/entry.S
arch/riscv/kernel/setup.c
arch/riscv/kernel/smpboot.c
arch/riscv/kernel/vmlinux.lds.S
arch/riscv/mm/init.c
arch/s390/include/asm/mmu_context.h
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/swsusp.S
arch/s390/kernel/vdso.c
arch/s390/pci/pci.c
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/uapi/asm/Kbuild
arch/x86/Kconfig
arch/x86/boot/compressed/head_64.S
arch/x86/boot/compressed/pgtable.h
arch/x86/entry/entry_64_compat.S
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/events/perf_event.h
arch/x86/ia32/ia32_aout.c
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/resctrl_sched.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uv/bios.h
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/resctrl/Makefile
arch/x86/kernel/crash.c
arch/x86/kernel/hpet.c
arch/x86/kernel/kexec-bzimage64.c
arch/x86/kernel/kvm.c
arch/x86/kernel/tsc.c
arch/x86/kvm/Makefile
arch/x86/kvm/hyperv.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx/evmcs.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
arch/x86/lib/iomem.c
arch/x86/lib/kaslr.c
arch/x86/mm/fault.c
arch/x86/mm/mem_encrypt_identity.c
arch/x86/mm/pageattr.c
arch/x86/platform/uv/bios_uv.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/time.c
arch/xtensa/Kconfig
arch/xtensa/boot/dts/Makefile
arch/xtensa/configs/audio_kc705_defconfig
arch/xtensa/configs/cadence_csp_defconfig
arch/xtensa/configs/generic_kc705_defconfig
arch/xtensa/configs/nommu_kc705_defconfig
arch/xtensa/configs/smp_lx200_defconfig
arch/xtensa/kernel/head.S
arch/xtensa/kernel/smp.c
arch/xtensa/kernel/time.c
block/bfq-wf2q.c
block/blk-core.c
block/blk-flush.c
block/blk-iolatency.c
block/blk-mq-debugfs-zoned.c
block/blk-mq-debugfs.c
block/blk-mq.c
block/blk-mq.h
block/blk-wbt.c
crypto/adiantum.c
crypto/authenc.c
crypto/authencesn.c
crypto/sm3_generic.c
drivers/acpi/Makefile
drivers/acpi/bus.c
drivers/acpi/internal.h
drivers/acpi/nfit/core.c
drivers/acpi/nfit/intel.c
drivers/android/binder.c
drivers/android/binder_internal.h
drivers/android/binderfs.c
drivers/ata/Kconfig
drivers/ata/libata-core.c
drivers/ata/pata_macio.c
drivers/ata/sata_inic162x.c
drivers/atm/he.c
drivers/auxdisplay/ht16k33.c
drivers/base/cacheinfo.c
drivers/base/power/runtime.c
drivers/base/regmap/regmap-irq.c
drivers/block/floppy.c
drivers/block/nbd.c
drivers/bus/ti-sysc.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_ssif.c
drivers/char/mwave/mwavedd.c
drivers/clk/Kconfig
drivers/clk/clk-versaclock5.c
drivers/clk/clk.c
drivers/clk/imx/clk-frac-pll.c
drivers/clk/imx/clk-imx8qxp-lpcg.c
drivers/clk/mmp/clk-of-mmp2.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/gcc-sdm845.c
drivers/clk/socfpga/clk-pll-s10.c
drivers/clk/socfpga/clk-s10.c
drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
drivers/clk/ti/divider.c
drivers/clk/zynqmp/clkc.c
drivers/clocksource/timer-ti-dm.c
drivers/cpufreq/scmi-cpufreq.c
drivers/cpuidle/poll_state.c
drivers/crypto/Kconfig
drivers/crypto/bcm/cipher.c
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamhash.c
drivers/crypto/caam/desc.h
drivers/crypto/caam/error.h
drivers/crypto/cavium/nitrox/nitrox_reqmgr.c
drivers/crypto/ccree/cc_aead.c
drivers/crypto/ccree/cc_driver.c
drivers/crypto/ccree/cc_pm.c
drivers/crypto/ccree/cc_pm.h
drivers/crypto/talitos.c
drivers/dma/at_xdmac.c
drivers/dma/bcm2835-dma.c
drivers/dma/dmatest.c
drivers/dma/imx-dma.c
drivers/edac/altera_edac.h
drivers/firewire/sbp2.c
drivers/firmware/arm_scmi/bus.c
drivers/firmware/efi/arm-runtime.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/runtime-wrappers.c
drivers/fpga/stratix10-soc.c
drivers/gpio/gpio-altera-a10sr.c
drivers/gpio/gpio-eic-sprd.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-pcf857x.c
drivers/gpio/gpio-vf610.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c
drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdkfd/Kconfig
drivers/gpu/drm/amd/amdkfd/kfd_crat.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
drivers/gpu/drm/drm_lease.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_vma.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/qxl/qxl_drv.c
drivers/gpu/drm/qxl/qxl_prime.c
drivers/gpu/drm/radeon/ci_dpm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/rockchip/rockchip_rgb.c
drivers/gpu/drm/rockchip/rockchip_rgb.h
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_prime.c
drivers/gpu/drm/vkms/vkms_crc.c
drivers/gpu/drm/vkms/vkms_crtc.c
drivers/gpu/drm/vkms/vkms_drv.c
drivers/gpu/drm/vkms/vkms_drv.h
drivers/gpu/drm/vkms/vkms_gem.c
drivers/gpu/drm/vkms/vkms_output.c
drivers/gpu/drm/vkms/vkms_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/ipu-v3/ipu-common.c
drivers/gpu/ipu-v3/ipu-pre.c
drivers/gpu/vga/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-ids.h
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hv/channel.c
drivers/hv/hv_balloon.c
drivers/hv/ring_buffer.c
drivers/hv/vmbus_drv.c
drivers/hwmon/lm80.c
drivers/hwmon/nct6775.c
drivers/hwmon/occ/common.c
drivers/hwmon/tmp421.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-omap.c
drivers/i3c/master.c
drivers/i3c/master/dw-i3c-master.c
drivers/i3c/master/i3c-master-cdns.c
drivers/ide/ide-atapi.c
drivers/ide/ide-io.c
drivers/ide/ide-park.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/iio/adc/axp288_adc.c
drivers/iio/adc/ti-ads8688.c
drivers/iio/adc/ti_am335x_adc.c
drivers/iio/chemical/atlas-ph-sensor.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/core_priv.h
drivers/infiniband/core/device.c
drivers/infiniband/core/nldev.c
drivers/infiniband/core/rdma_core.h
drivers/infiniband/core/umem_odp.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_ioctl.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/core/uverbs_std_types_device.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/ud.c
drivers/infiniband/hw/hns/hns_roce_srq.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx5/flow.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/qib/qib_ud.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/cap11xx.c
drivers/input/keyboard/matrix_keypad.c
drivers/input/keyboard/qt2160.c
drivers/input/keyboard/st-keyscan.c
drivers/input/misc/apanel.c
drivers/input/misc/bma150.c
drivers/input/misc/pwm-vibra.c
drivers/input/misc/uinput.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elantech.c
drivers/input/serio/olpc_apsp.c
drivers/input/serio/ps2-gpio.c
drivers/input/touchscreen/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/mtk_iommu_v1.c
drivers/iommu/of_iommu.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3-mbi.c
drivers/irqchip/irq-madera.c
drivers/irqchip/irq-mmp.c
drivers/irqchip/irq-stm32-exti.c
drivers/irqchip/irq-xtensa-mx.c
drivers/irqchip/irq-xtensa-pic.c
drivers/isdn/hardware/avm/b1.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/mISDN/timerdev.c
drivers/leds/leds-lp5523.c
drivers/md/dm-crypt.c
drivers/md/dm-rq.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid5-cache.c
drivers/md/raid5.c
drivers/media/platform/vim2m.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-core.c
drivers/mfd/axp20x.c
drivers/mfd/bd9571mwv.c
drivers/mfd/cros_ec_dev.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/exynos-lpass.c
drivers/mfd/madera-core.c
drivers/mfd/max77620.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/mt6397-core.c
drivers/mfd/qcom_rpm.c
drivers/mfd/rave-sp.c
drivers/mfd/stmpe.c
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/tps65218.c
drivers/mfd/tps6586x.c
drivers/mfd/twl-core.c
drivers/mfd/wm5110-tables.c
drivers/misc/ibmvmc.c
drivers/misc/mei/client.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hw-me-regs.h
drivers/misc/mei/pci-me.c
drivers/misc/mic/vop/vop_main.c
drivers/misc/pvpanic.c
drivers/mmc/core/block.c
drivers/mmc/core/host.c
drivers/mmc/host/Kconfig
drivers/mmc/host/bcm2835.c
drivers/mmc/host/dw_mmc-bluefield.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/sdhci-iproc.c
drivers/mmc/host/sunxi-mmc.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/raw/denali.c
drivers/mtd/nand/raw/fsmc_nand.c
drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/raw/jz4740_nand.c
drivers/mtd/nand/raw/nand_base.c
drivers/mtd/nand/raw/nand_bbt.c
drivers/mtd/nand/spi/core.c
drivers/net/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/caif/caif_serial.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/dsa/b53/b53_srab.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/global1_atu.c
drivers/net/dsa/mv88e6xxx/port.h
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/dsa/realtek-smi.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/altera/altera_msgdma.c
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amazon/ena/ena_netdev.h
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/xgbe/xgbe-common.h
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/apple/bmac.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bcmsysport.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/Kconfig
drivers/net/ethernet/chelsio/cxgb3/sge.c
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa2/Kconfig
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/hisilicon/hns_mdio.c
drivers/net/ethernet/i825xx/82596.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/marvell/octeontx2/af/cgx.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/icm.c
drivers/net/ethernet/mellanox/mlx4/icm.h
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/events.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/lag.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/qp.c
drivers/net/ethernet/mellanox/mlxsw/Kconfig
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_ctcam.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/qlogic/qed/qed.h
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_l2.h
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_sp.h
drivers/net/ethernet/qlogic/qed/qed_sp_commands.c
drivers/net/ethernet/qlogic/qed/qed_spq.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qed/qed_vf.c
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_fp.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/cassini.h
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/fddi/defxx.c
drivers/net/geneve.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/mcr20a.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macvlan.c
drivers/net/phy/asix.c
drivers/net/phy/bcm87xx.c
drivers/net/phy/cortina.c
drivers/net/phy/dp83640.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-hisi-femac.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/meson-gxl.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/phy/rockchip.c
drivers/net/phy/sfp-bus.c
drivers/net/phy/sfp.c
drivers/net/phy/sfp.h
drivers/net/phy/teranetics.c
drivers/net/ppp/pppoe.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/aqc111.c
drivers/net/usb/asix_devices.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
drivers/net/virtio_net.c
drivers/net/vxlan.c
drivers/net/wan/dscc4.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/intel/iwlwifi/Kconfig
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/virt_wifi.c
drivers/nvdimm/dimm.c
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/nd-core.h
drivers/nvdimm/nd.h
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/host/tcp.c
drivers/nvme/target/rdma.c
drivers/nvme/target/tcp.c
drivers/of/dynamic.c
drivers/of/fdt.c
drivers/of/overlay.c
drivers/of/pdt.c
drivers/of/property.c
drivers/pci/Kconfig
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pcie-armada8k.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/phy/qualcomm/phy-ath79-usb.c
drivers/phy/ti/Kconfig
drivers/phy/ti/phy-gmii-sel.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/mediatek/Kconfig
drivers/pinctrl/pinctrl-mcp23s08.c
drivers/pinctrl/sunxi/pinctrl-sun50i-h6.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/sunxi/pinctrl-sunxi.h
drivers/platform/x86/Kconfig
drivers/ptp/ptp_chardev.c
drivers/remoteproc/remoteproc_virtio.c
drivers/s390/block/dasd_eckd.c
drivers/s390/char/sclp_config.c
drivers/s390/crypto/ap_bus.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/53c700.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aic94xx/aic94xx_init.c
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/csiostor/csio_attr.c
drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/cxgbi/libcxgbi.h
drivers/scsi/cxlflash/main.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/scsi/isci/init.c
drivers/scsi/libfc/fc_lport.c
drivers/scsi/libfc/fc_rport.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/lpfc/lpfc_nvme.h
drivers/scsi/lpfc/lpfc_nvmet.c
drivers/scsi/lpfc/lpfc_nvmet.h
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/qedi/qedi_iscsi.c
drivers/scsi/qedi/qedi_iscsi.h
drivers/scsi/qla1280.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_pm.c
drivers/scsi/sd.c
drivers/scsi/sd_zbc.c
drivers/scsi/smartpqi/smartpqi_init.c
drivers/scsi/ufs/ufs.h
drivers/scsi/ufs/ufshcd.c
drivers/soc/fsl/qbman/qman.c
drivers/soc/fsl/qe/qe_tdm.c
drivers/staging/android/ion/ion.c
drivers/staging/octeon/ethernet-mdio.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8723bs/include/ieee80211.h
drivers/staging/speakup/spk_ttyio.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
drivers/staging/wilc1000/host_interface.c
drivers/staging/wilc1000/wilc_wlan.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_configfs.c
drivers/target/target_core_user.c
drivers/thermal/cpu_cooling.c
drivers/thermal/intel/int340x_thermal/Kconfig
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/thermal/of-thermal.c
drivers/tty/n_hdlc.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/earlycon-riscv-sbi.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sh-sci.c
drivers/tty/tty_io.c
drivers/tty/vt/vt.c
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/core/ledtrig-usbport.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/udc/net2272.c
drivers/usb/host/ehci-mv.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musbhsdma.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-am335x.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/keyspan_usa26msg.h
drivers/usb/serial/keyspan_usa28msg.h
drivers/usb/serial/keyspan_usa49msg.h
drivers/usb/serial/keyspan_usa67msg.h
drivers/usb/serial/keyspan_usa90msg.h
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/usb-serial-simple.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/usbip/README [deleted file]
drivers/vfio/pci/trace.h
drivers/vfio/pci/vfio_pci_nvlink2.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/vhost/vsock.c
drivers/video/backlight/88pm860x_bl.c
drivers/video/backlight/pwm_bl.c
drivers/video/console/vgacon.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/offb.c
drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c
drivers/video/logo/Kconfig
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_ring.c
drivers/watchdog/mt7621_wdt.c
drivers/watchdog/rt2880_wdt.c
drivers/watchdog/tqmx86_wdt.c
drivers/xen/events/events_base.c
drivers/xen/pvcalls-back.c
drivers/xen/pvcalls-front.c
drivers/xen/swiotlb-xen.c
fs/afs/flock.c
fs/afs/inode.c
fs/afs/protocol_yfs.h
fs/afs/rxrpc.c
fs/afs/server_list.c
fs/afs/yfsclient.c
fs/aio.c
fs/autofs/expire.c
fs/autofs/inode.c
fs/binfmt_script.c
fs/block_dev.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/inode.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/buffer.c
fs/ceph/caps.c
fs/ceph/quota.c
fs/cifs/cifs_debug.c
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/smb2inode.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/trace.c
fs/cifs/trace.h
fs/cifs/transport.c
fs/dcache.c
fs/debugfs/inode.c
fs/direct-io.c
fs/drop_caches.c
fs/ext4/fsync.c
fs/fs-writeback.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/inode.c
fs/gfs2/glops.c
fs/gfs2/log.c
fs/gfs2/lops.c
fs/gfs2/lops.h
fs/gfs2/ops_fstype.c
fs/gfs2/recovery.c
fs/gfs2/recovery.h
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/inode.c
fs/iomap.c
fs/nfs/nfs4file.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/nfsctl.c
fs/nfsd/vfs.c
fs/notify/inotify/inotify_user.c
fs/proc/generic.c
fs/proc/internal.h
fs/proc/proc_net.c
fs/proc/task_mmu.c
fs/pstore/ram.c
fs/xfs/scrub/repair.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_buf.c
include/asm-generic/shmparam.h [moved from include/uapi/asm-generic/shmparam.h with 100% similarity]
include/dt-bindings/clock/imx8mq-clock.h
include/dt-bindings/clock/marvell,mmp2.h
include/dt-bindings/reset/amlogic,meson-axg-reset.h
include/kvm/arm_vgic.h
include/linux/backing-dev-defs.h
include/linux/bcma/bcma_soc.h
include/linux/blk_types.h
include/linux/blktrace_api.h
include/linux/bpf_verifier.h
include/linux/bpfilter.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/compiler-intel.h
include/linux/compiler.h
include/linux/compiler_attributes.h
include/linux/cpu.h
include/linux/dcache.h
include/linux/efi.h
include/linux/fb.h
include/linux/filter.h
include/linux/fs.h
include/linux/hid-debug.h
include/linux/hid.h
include/linux/hyperv.h
include/linux/ide.h
include/linux/if_arp.h
include/linux/interrupt.h
include/linux/irqchip/arm-gic-v3.h
include/linux/libnvdimm.h
include/linux/memblock.h
include/linux/memory_hotplug.h
include/linux/mfd/cros_ec_commands.h
include/linux/mfd/ingenic-tcu.h
include/linux/mfd/madera/core.h
include/linux/mfd/ti_am335x_tscadc.h
include/linux/mfd/tmio.h
include/linux/mmc/card.h
include/linux/module.h
include/linux/netdevice.h
include/linux/of.h
include/linux/perf_event.h
include/linux/phy.h
include/linux/pm_runtime.h
include/linux/qed/qed_chain.h
include/linux/sched.h
include/linux/sched/coredump.h
include/linux/sched/wake_q.h
include/linux/signal.h
include/linux/skbuff.h
include/linux/stmmac.h
include/linux/umh.h
include/linux/virtio_config.h
include/linux/xarray.h
include/net/af_rxrpc.h
include/net/ax25.h
include/net/inetpeer.h
include/net/ip_fib.h
include/net/l3mdev.h
include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_tables.h
include/net/sock.h
include/net/tls.h
include/rdma/ib_verbs.h
include/sound/compress_driver.h
include/sound/hda_codec.h
include/sound/soc.h
include/trace/events/afs.h
include/uapi/linux/android/binderfs.h [moved from include/uapi/linux/android/binder_ctl.h with 83% similarity]
include/uapi/linux/blkzoned.h
include/uapi/linux/in.h
include/uapi/linux/inet_diag.h
include/uapi/linux/input.h
include/uapi/linux/ptp_clock.h
include/uapi/linux/virtio_config.h
include/uapi/linux/virtio_ring.h
include/uapi/rdma/hns-abi.h
include/uapi/rdma/vmw_pvrdma-abi.h
include/xen/arm/page-coherent.h
init/Kconfig
init/main.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/hashtab.c
kernel/bpf/map_in_map.c
kernel/bpf/percpu_freelist.c
kernel/bpf/percpu_freelist.h
kernel/bpf/stackmap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cpu.c
kernel/dma/swiotlb.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/exit.c
kernel/futex.c
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/locking/rtmutex.c
kernel/locking/rwsem-xadd.c
kernel/relay.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/seccomp.c
kernel/signal.c
kernel/smp.c
kernel/time/posix-cpu-timers.c
kernel/trace/bpf_trace.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe_tmpl.h
kernel/trace/trace_uprobe.c
kernel/umh.c
kernel/workqueue.c
kernel/workqueue_internal.h
lib/crc32.c
lib/int_sqrt.c
lib/sbitmap.c
lib/test_kmod.c
lib/test_rhashtable.c
lib/test_xarray.c
lib/xarray.c
mm/backing-dev.c
mm/gup.c
mm/hugetlb.c
mm/kasan/Makefile
mm/memblock.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/migrate.c
mm/mincore.c
mm/oom_kill.c
mm/page_alloc.c
mm/page_ext.c
mm/vmscan.c
net/ax25/ax25_ip.c
net/ax25/ax25_route.c
net/batman-adv/bat_v_elp.c
net/batman-adv/hard-interface.c
net/batman-adv/soft-interface.c
net/bpfilter/bpfilter_kern.c
net/bpfilter/bpfilter_umh_blob.S
net/bridge/br_fdb.c
net/bridge/br_forward.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_netfilter_ipv6.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/bridge/netfilter/ebtables.c
net/bridge/netfilter/nft_reject_bridge.c
net/can/bcm.c
net/can/gw.c
net/ceph/messenger.c
net/core/dev.c
net/core/filter.c
net/core/lwt_bpf.c
net/core/neighbour.c
net/core/skbuff.c
net/core/skmsg.c
net/core/sock.c
net/dccp/ccid.h
net/decnet/dn_dev.c
net/dsa/master.c
net/dsa/slave.c
net/ipv4/bpfilter/sockopt.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_trie.c
net/ipv4/fou.c
net/ipv4/gre_demux.c
net/ipv4/inet_diag.c
net/ipv4/inetpeer.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
net/ipv4/netfilter/nf_nat_snmp_basic_main.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv4/udp_impl.h
net/ipv4/udplite.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/datagram.c
net/ipv6/fou6.c
net/ipv6/icmp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6mr.c
net/ipv6/netfilter.c
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
net/ipv6/route.c
net/ipv6/seg6.c
net/ipv6/seg6_iptunnel.c
net/ipv6/sit.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udplite.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/ipvs/Kconfig
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_osf.c
net/netfilter/nft_compat.c
net/netfilter/nft_dynset.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_immediate.c
net/netfilter/nft_lookup.c
net/netfilter/nft_objref.c
net/netfilter/x_tables.c
net/netrom/nr_timer.c
net/openvswitch/flow.c
net/openvswitch/flow_netlink.c
net/packet/af_packet.c
net/rds/bind.c
net/rds/ib_send.c
net/rds/message.c
net/rds/rds.h
net/rds/send.c
net/rose/rose_route.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_object.c
net/rxrpc/conn_client.c
net/rxrpc/recvmsg.c
net/rxrpc/sendmsg.c
net/sched/act_tunnel_key.c
net/sched/cls_api.c
net/sched/cls_flower.c
net/sched/cls_tcindex.c
net/sched/sch_cake.c
net/sched/sch_cbs.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_tbf.c
net/sctp/diag.c
net/sctp/ipv6.c
net/sctp/offload.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/sctp/stream.c
net/smc/af_smc.c
net/smc/smc_cdc.c
net/smc/smc_cdc.h
net/smc/smc_clc.c
net/smc/smc_close.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/smc/smc_llc.c
net/smc/smc_pnet.c
net/smc/smc_tx.c
net/smc/smc_wr.c
net/smc/smc_wr.h
net/socket.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_seqnum.c
net/sunrpc/clnt.c
net/sunrpc/debugfs.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtsock.c
net/tipc/link.c
net/tipc/msg.h
net/tipc/netlink_compat.c
net/tipc/node.c
net/tipc/topsrv.c
net/tls/tls_sw.c
net/vmw_vsock/virtio_transport.c
net/vmw_vsock/vmci_transport.c
net/wireless/ap.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/pmsr.c
net/wireless/reg.c
net/wireless/sme.c
net/wireless/util.c
net/x25/af_x25.c
net/xdp/xdp_umem.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
samples/bpf/Makefile
samples/bpf/asm_goto_workaround.h [new file with mode: 0644]
samples/bpf/test_cgrp2_attach2.c
samples/bpf/test_current_task_under_cgroup_user.c
samples/bpf/xdp1_user.c
samples/mei/mei-amt-version.c
scripts/Kbuild.include
scripts/gcc-plugins/arm_ssp_per_task_plugin.c
scripts/kconfig/Makefile
security/apparmor/domain.c
security/apparmor/lsm.c
security/security.c
security/selinux/ss/policydb.c
security/yama/yama_lsm.c
sound/core/compress_offload.c
sound/core/pcm_lib.c
sound/pci/hda/hda_bind.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/pcm512x.c
sound/soc/codecs/rt274.c
sound/soc/codecs/rt5514-spi.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/rt5682.h
sound/soc/codecs/tlv320aic32x4.c
sound/soc/fsl/imx-audmux.c
sound/soc/intel/Kconfig
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/broadwell.c
sound/soc/intel/boards/glk_rt5682_max98357a.c
sound/soc/intel/boards/haswell.c
sound/soc/intel/skylake/skl.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/qcom/sdm845.c
sound/soc/samsung/i2s.c
sound/soc/sh/dma-sh7760.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-topology.c
sound/soc/ti/davinci-mcasp.c
sound/soc/xilinx/Kconfig
sound/soc/xilinx/xlnx_i2s.c
sound/usb/pcm.c
sound/usb/quirks.c
tools/arch/powerpc/include/uapi/asm/perf_regs.h
tools/bpf/bpftool/Makefile
tools/bpf/bpftool/btf_dumper.c
tools/bpf/bpftool/common.c
tools/bpf/bpftool/json_writer.c
tools/bpf/bpftool/json_writer.h
tools/bpf/bpftool/map.c
tools/bpf/bpftool/prog.c
tools/iio/iio_generic_buffer.c
tools/include/uapi/asm/bitsperlong.h
tools/include/uapi/linux/in.h
tools/include/uapi/linux/pkt_sched.h [new file with mode: 0644]
tools/lib/bpf/.gitignore
tools/lib/bpf/README.rst
tools/lib/bpf/bpf.c
tools/perf/Documentation/perf-c2c.txt
tools/perf/Documentation/perf-mem.txt
tools/perf/arch/powerpc/include/perf_regs.h
tools/perf/arch/powerpc/util/Build
tools/perf/arch/powerpc/util/mem-events.c [new file with mode: 0644]
tools/perf/arch/powerpc/util/perf_regs.c
tools/perf/builtin-script.c
tools/perf/builtin-trace.c
tools/perf/tests/attr.py
tools/perf/tests/evsel-tp-sched.c
tools/perf/ui/browsers/annotate.c
tools/perf/util/c++/clang.cpp
tools/perf/util/cpumap.c
tools/perf/util/mem-events.c
tools/perf/util/ordered-events.c
tools/perf/util/setup.py
tools/perf/util/symbol-elf.c
tools/testing/nvdimm/dimm_devs.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/.gitignore
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/bpf_util.h
tools/testing/selftests/bpf/cgroup_helpers.c
tools/testing/selftests/bpf/test_btf.c
tools/testing/selftests/bpf/test_cgroup_storage.c
tools/testing/selftests/bpf/test_dev_cgroup.c
tools/testing/selftests/bpf/test_netcnt.c
tools/testing/selftests/bpf/test_progs.c
tools/testing/selftests/bpf/test_skb_cgroup_id_user.c
tools/testing/selftests/bpf/test_sock.c
tools/testing/selftests/bpf/test_sock_addr.c
tools/testing/selftests/bpf/test_socket_cookie.c
tools/testing/selftests/bpf/test_tcpbpf_user.c
tools/testing/selftests/bpf/test_tcpnotify_user.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh
tools/testing/selftests/drivers/net/mlxsw/rtnetlink.sh
tools/testing/selftests/drivers/net/mlxsw/vxlan.sh
tools/testing/selftests/filesystems/binderfs/.gitignore [new file with mode: 0644]
tools/testing/selftests/filesystems/binderfs/Makefile [new file with mode: 0644]
tools/testing/selftests/filesystems/binderfs/binderfs_test.c [new file with mode: 0644]
tools/testing/selftests/filesystems/binderfs/config [new file with mode: 0644]
tools/testing/selftests/gpio/gpio-mockup-chardev.c
tools/testing/selftests/ir/Makefile
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/x86_64/evmcs_test.c
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/forwarding/bridge_vlan_aware.sh
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh
tools/testing/selftests/net/ip_defrag.c
tools/testing/selftests/net/ip_defrag.sh
tools/testing/selftests/net/xfrm_policy.sh
tools/testing/selftests/netfilter/Makefile
tools/testing/selftests/netfilter/config
tools/testing/selftests/netfilter/nft_nat.sh [new file with mode: 0755]
tools/testing/selftests/networking/timestamping/Makefile
tools/testing/selftests/networking/timestamping/txtimestamp.c
tools/testing/selftests/proc/.gitignore
tools/testing/selftests/proc/Makefile
tools/testing/selftests/proc/setns-dcache.c [new file with mode: 0644]
tools/testing/selftests/rtc/rtctest.c
tools/testing/selftests/seccomp/Makefile
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
tools/testing/selftests/tc-testing/tc-tests/actions/tunnel_key.json
tools/testing/selftests/timers/Makefile
tools/testing/selftests/vm/gup_benchmark.c
tools/testing/selftests/x86/mpx-mini-test.c
tools/testing/selftests/x86/protection_keys.c
tools/testing/selftests/x86/unwind_vdso.c
virt/kvm/arm/arm.c
virt/kvm/arm/mmu.c
virt/kvm/arm/psci.c
virt/kvm/arm/vgic/vgic-debug.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic-mmio-v2.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/kvm_main.c

index e6080f5834a3566830478dfe7c08622dfaca7939..bc2ffb2a0b5366b2d31bc533486ec30e33f3d057 100644 (file)
@@ -72,6 +72,10 @@ ForEachMacros:
   - 'apei_estatus_for_each_section'
   - 'ata_for_each_dev'
   - 'ata_for_each_link'
+  - '__ata_qc_for_each'
+  - 'ata_qc_for_each'
+  - 'ata_qc_for_each_raw'
+  - 'ata_qc_for_each_with_internal'
   - 'ax25_for_each'
   - 'ax25_uid_for_each'
   - 'bio_for_each_integrity_vec'
@@ -85,6 +89,7 @@ ForEachMacros:
   - 'blk_queue_for_each_rl'
   - 'bond_for_each_slave'
   - 'bond_for_each_slave_rcu'
+  - 'bpf_for_each_spilled_reg'
   - 'btree_for_each_safe128'
   - 'btree_for_each_safe32'
   - 'btree_for_each_safe64'
@@ -103,6 +108,8 @@ ForEachMacros:
   - 'drm_atomic_crtc_for_each_plane'
   - 'drm_atomic_crtc_state_for_each_plane'
   - 'drm_atomic_crtc_state_for_each_plane_state'
+  - 'drm_atomic_for_each_plane_damage'
+  - 'drm_connector_for_each_possible_encoder'
   - 'drm_for_each_connector_iter'
   - 'drm_for_each_crtc'
   - 'drm_for_each_encoder'
@@ -121,11 +128,21 @@ ForEachMacros:
   - 'for_each_bio'
   - 'for_each_board_func_rsrc'
   - 'for_each_bvec'
+  - 'for_each_card_components'
+  - 'for_each_card_links'
+  - 'for_each_card_links_safe'
+  - 'for_each_card_prelinks'
+  - 'for_each_card_rtds'
+  - 'for_each_card_rtds_safe'
+  - 'for_each_cgroup_storage_type'
   - 'for_each_child_of_node'
   - 'for_each_clear_bit'
   - 'for_each_clear_bit_from'
   - 'for_each_cmsghdr'
   - 'for_each_compatible_node'
+  - 'for_each_component_dais'
+  - 'for_each_component_dais_safe'
+  - 'for_each_comp_order'
   - 'for_each_console'
   - 'for_each_cpu'
   - 'for_each_cpu_and'
@@ -133,6 +150,10 @@ ForEachMacros:
   - 'for_each_cpu_wrap'
   - 'for_each_dev_addr'
   - 'for_each_dma_cap_mask'
+  - 'for_each_dpcm_be'
+  - 'for_each_dpcm_be_rollback'
+  - 'for_each_dpcm_be_safe'
+  - 'for_each_dpcm_fe'
   - 'for_each_drhd_unit'
   - 'for_each_dss_dev'
   - 'for_each_efi_memory_desc'
@@ -149,6 +170,7 @@ ForEachMacros:
   - 'for_each_iommu'
   - 'for_each_ip_tunnel_rcu'
   - 'for_each_irq_nr'
+  - 'for_each_link_codecs'
   - 'for_each_lru'
   - 'for_each_matching_node'
   - 'for_each_matching_node_and_match'
@@ -160,6 +182,7 @@ ForEachMacros:
   - 'for_each_mem_range_rev'
   - 'for_each_migratetype_order'
   - 'for_each_msi_entry'
+  - 'for_each_msi_entry_safe'
   - 'for_each_net'
   - 'for_each_netdev'
   - 'for_each_netdev_continue'
@@ -183,12 +206,14 @@ ForEachMacros:
   - 'for_each_node_with_property'
   - 'for_each_of_allnodes'
   - 'for_each_of_allnodes_from'
+  - 'for_each_of_cpu_node'
   - 'for_each_of_pci_range'
   - 'for_each_old_connector_in_state'
   - 'for_each_old_crtc_in_state'
   - 'for_each_oldnew_connector_in_state'
   - 'for_each_oldnew_crtc_in_state'
   - 'for_each_oldnew_plane_in_state'
+  - 'for_each_oldnew_plane_in_state_reverse'
   - 'for_each_oldnew_private_obj_in_state'
   - 'for_each_old_plane_in_state'
   - 'for_each_old_private_obj_in_state'
@@ -206,14 +231,17 @@ ForEachMacros:
   - 'for_each_process'
   - 'for_each_process_thread'
   - 'for_each_property_of_node'
+  - 'for_each_registered_fb'
   - 'for_each_reserved_mem_region'
-  - 'for_each_resv_unavail_range'
+  - 'for_each_rtd_codec_dai'
+  - 'for_each_rtd_codec_dai_rollback'
   - 'for_each_rtdcom'
   - 'for_each_rtdcom_safe'
   - 'for_each_set_bit'
   - 'for_each_set_bit_from'
   - 'for_each_sg'
   - 'for_each_sg_page'
+  - 'for_each_sibling_event'
   - '__for_each_thread'
   - 'for_each_thread'
   - 'for_each_zone'
@@ -251,6 +279,8 @@ ForEachMacros:
   - 'hlist_nulls_for_each_entry_from'
   - 'hlist_nulls_for_each_entry_rcu'
   - 'hlist_nulls_for_each_entry_safe'
+  - 'i3c_bus_for_each_i2cdev'
+  - 'i3c_bus_for_each_i3cdev'
   - 'ide_host_for_each_port'
   - 'ide_port_for_each_dev'
   - 'ide_port_for_each_present_dev'
@@ -267,11 +297,14 @@ ForEachMacros:
   - 'kvm_for_each_memslot'
   - 'kvm_for_each_vcpu'
   - 'list_for_each'
+  - 'list_for_each_codec'
+  - 'list_for_each_codec_safe'
   - 'list_for_each_entry'
   - 'list_for_each_entry_continue'
   - 'list_for_each_entry_continue_rcu'
   - 'list_for_each_entry_continue_reverse'
   - 'list_for_each_entry_from'
+  - 'list_for_each_entry_from_rcu'
   - 'list_for_each_entry_from_reverse'
   - 'list_for_each_entry_lockless'
   - 'list_for_each_entry_rcu'
@@ -291,6 +324,7 @@ ForEachMacros:
   - 'media_device_for_each_intf'
   - 'media_device_for_each_link'
   - 'media_device_for_each_pad'
+  - 'nanddev_io_for_each_page'
   - 'netdev_for_each_lower_dev'
   - 'netdev_for_each_lower_private'
   - 'netdev_for_each_lower_private_rcu'
@@ -357,12 +391,14 @@ ForEachMacros:
   - 'sk_nulls_for_each'
   - 'sk_nulls_for_each_from'
   - 'sk_nulls_for_each_rcu'
+  - 'snd_array_for_each'
   - 'snd_pcm_group_for_each_entry'
   - 'snd_soc_dapm_widget_for_each_path'
   - 'snd_soc_dapm_widget_for_each_path_safe'
   - 'snd_soc_dapm_widget_for_each_sink_path'
   - 'snd_soc_dapm_widget_for_each_source_path'
   - 'tb_property_for_each'
+  - 'tcf_exts_for_each_action'
   - 'udp_portaddr_for_each_entry'
   - 'udp_portaddr_for_each_entry_rcu'
   - 'usb_hub_for_each_child'
@@ -371,6 +407,11 @@ ForEachMacros:
   - 'v4l2_m2m_for_each_dst_buf_safe'
   - 'v4l2_m2m_for_each_src_buf'
   - 'v4l2_m2m_for_each_src_buf_safe'
+  - 'virtio_device_for_each_vq'
+  - 'xa_for_each'
+  - 'xas_for_each'
+  - 'xas_for_each_conflict'
+  - 'xas_for_each_marked'
   - 'zorro_for_each_dev'
 
 #IncludeBlocks: Preserve # Unknown to clang-format-5.0
index 9b642669cb160c6e1535022c31628818faa37fdb..169fe08a649baff3bb1643c6c74150ea1ce87807 100644 (file)
@@ -24,7 +24,7 @@ What:         /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                        cpld3_version
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show with which CPLD versions have been burned
                on LED board.
@@ -35,7 +35,7 @@ What:         /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                        jtag_enable
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files enable and disable the access to the JTAG domain.
                By default access to the JTAG domain is disabled.
@@ -105,7 +105,7 @@ What:               /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                reset_voltmon_upgrade_fail
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show the system reset cause, as following: ComEx
                power fail, reset from ComEx, system platform reset, reset
index b799bcf67d7b5ae080694467442b113b49c92567..858b6c0b9a15ae71853645013c718dc0398804d4 100644 (file)
                        By default, super page will be supported if Intel IOMMU
                        has the capability. With this option, super page will
                        not be supported.
-               sm_off [Default Off]
-                       By default, scalable mode will be supported if the
+               sm_on [Default Off]
+                       By default, scalable mode will be disabled even if the
                        hardware advertises that it has support for the scalable
                        mode translation. With this option set, scalable mode
-                       will not be used even on hardware which claims to support
-                       it.
+                       will be used on hardware which claims to support it.
                tboot_noforce [Default Off]
                        Do not force the Intel IOMMU enabled under tboot.
                        By default, tboot will force Intel IOMMU on, which
index 6780a6d8174580ea1caeac4a13fb4f8dae6bd91b..7cc9e368c1e9b48244c97bce151561dca3c634e7 100644 (file)
@@ -157,12 +157,11 @@ Q: Does BPF have a stable ABI?
 ------------------------------
 A: YES. BPF instructions, arguments to BPF programs, set of helper
 functions and their arguments, recognized return codes are all part
-of ABI. However when tracing programs are using bpf_probe_read() helper
-to walk kernel internal datastructures and compile with kernel
-internal headers these accesses can and will break with newer
-kernels. The union bpf_attr -> kern_version is checked at load time
-to prevent accidentally loading kprobe-based bpf programs written
-for a different kernel. Networking programs don't do kern_version check.
+of ABI. However there is one specific exception to tracing programs
+which are using helpers like bpf_probe_read() to walk kernel internal
+data structures and compile with kernel internal headers. Both of these
+kernel internals are subject to change and can break with newer kernels
+such that the program needs to be adapted accordingly.
 
 Q: How much stack space a BPF program uses?
 -------------------------------------------
index 6a6d67acaf690abfadc40c05e97a4557060dc188..5d54b27c6ebab15a41e53bb6f9529af128be8092 100644 (file)
@@ -108,12 +108,13 @@ some, but not all of the other indices changing.
 
 Sometimes you need to ensure that a subsequent call to :c:func:`xa_store`
 will not need to allocate memory.  The :c:func:`xa_reserve` function
-will store a reserved entry at the indicated index.  Users of the normal
-API will see this entry as containing ``NULL``.  If you do not need to
-use the reserved entry, you can call :c:func:`xa_release` to remove the
-unused entry.  If another user has stored to the entry in the meantime,
-:c:func:`xa_release` will do nothing; if instead you want the entry to
-become ``NULL``, you should use :c:func:`xa_erase`.
+will store a reserved entry at the indicated index.  Users of the
+normal API will see this entry as containing ``NULL``.  If you do
+not need to use the reserved entry, you can call :c:func:`xa_release`
+to remove the unused entry.  If another user has stored to the entry
+in the meantime, :c:func:`xa_release` will do nothing; if instead you
+want the entry to become ``NULL``, you should use :c:func:`xa_erase`.
+Using :c:func:`xa_insert` on a reserved entry will fail.
 
 If all entries in the array are ``NULL``, the :c:func:`xa_empty` function
 will return ``true``.
@@ -183,6 +184,8 @@ Takes xa_lock internally:
  * :c:func:`xa_store_bh`
  * :c:func:`xa_store_irq`
  * :c:func:`xa_insert`
+ * :c:func:`xa_insert_bh`
+ * :c:func:`xa_insert_irq`
  * :c:func:`xa_erase`
  * :c:func:`xa_erase_bh`
  * :c:func:`xa_erase_irq`
index 6e5cef0ed6fb1895681baee8524f5ce7eda66f81..50daa0b3b032fb90001c42025865a5cd48999b65 100644 (file)
@@ -17,7 +17,11 @@ extra-y += $(DT_TMP_SCHEMA)
 quiet_cmd_mk_schema = SCHEMA  $@
       cmd_mk_schema = $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) -o $@ $(filter-out FORCE, $^)
 
-DT_DOCS = $(shell cd $(srctree)/$(src) && find * -name '*.yaml')
+DT_DOCS = $(shell \
+       cd $(srctree)/$(src) && \
+       find * \( -name '*.yaml' ! -name $(DT_TMP_SCHEMA) \) \
+       )
+
 DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
 
 extra-y += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES))
index 84262cdb8d29ae3f95ef94f6e7b9900897774c17..96fa46cb133c1f9186c662ba1980a215df109687 100644 (file)
@@ -235,4 +235,4 @@ cpus {
 ===========================================
 
 [1] ARM Linux Kernel documentation - CPUs bindings
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
index 8f0937db55c5c92d97ebf7fe3da404e749e24ff8..45730ba60af5411f1f0c13a8d3078d37a9b94c25 100644 (file)
@@ -684,7 +684,7 @@ cpus {
 ===========================================
 
 [1] ARM Linux Kernel documentation - CPUs bindings
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
 
 [2] ARM Linux Kernel documentation - PSCI bindings
     Documentation/devicetree/bindings/arm/psci.txt
index 1b2ab1ff5587f0f01c6755238802cff157f4881c..46652bf651478c86ec1eba9b7219fb36381fb389 100644 (file)
@@ -4,7 +4,7 @@ SP810 System Controller
 Required properties:
 
 - compatible:  standard compatible string for a Primecell peripheral,
-               see Documentation/devicetree/bindings/arm/primecell.txt
+               see Documentation/devicetree/bindings/arm/primecell.yaml
                for more details
                should be: "arm,sp810", "arm,primecell"
 
index de9eb0486630dd1b0e7b4418494f11a9ecc3a1bb..b0d80c0fb2653bb9abc17bcfd8b22e89a8196c0d 100644 (file)
@@ -472,4 +472,4 @@ cpus {
 
 ===============================================================================
 [1] ARM Linux kernel documentation
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
index af376a01f2b7236a67ca69af2d2b84cdc5e09b3b..23b52dc02266a4901b41efe0e22d8fa813c60c28 100644 (file)
@@ -18,4 +18,4 @@ Required Properties:
 Each clock is assigned an identifier and client nodes use this identifier
 to specify the clock which they consume.
 
-All these identifier could be found in <dt-bindings/clock/marvell-mmp2.h>.
+All these identifiers could be found in <dt-bindings/clock/marvell,mmp2.h>.
index ef89ab46b2c933945b86197aa1031ecbbfc3b6c4..572fa2773ec43850d6c45f32aab8bac8a223f0b8 100644 (file)
@@ -1,6 +1,6 @@
 * ARM PrimeCell Color LCD Controller PL110/PL111
 
-See also Documentation/devicetree/bindings/arm/primecell.txt
+See also Documentation/devicetree/bindings/arm/primecell.yaml
 
 Required properties:
 
index ac8df3b871f900a0672f266a5b05635a7aca01cf..f8759145ce1a08e57046f4aa63198e642887b4e8 100644 (file)
@@ -27,7 +27,6 @@ Example:
                reg = <0x04300000 0x20000>;
                reg-names = "kgsl_3d0_reg_memory";
                interrupts = <GIC_SPI 80 0>;
-               interrupt-names = "kgsl_3d0_irq";
                clock-names =
                    "core",
                    "iface",
index 38ca2201e8ae1f99f83eb6c8e10fca42955c1eed..2e097b57f170e749a5c1733bff3c9b5eab717d49 100644 (file)
@@ -14,8 +14,6 @@ Required properties:
 
     "marvell,armada-8k-gpio" should be used for the Armada 7K and 8K
     SoCs (either from AP or CP), see
-    Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
-    and
     Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
     for specific details about the offset property.
 
index b83bb8249074f08870662162465e9dca442164e3..a3be5298a5eb524e748a5be131dc494ab61920c4 100644 (file)
@@ -78,7 +78,7 @@ Sub-nodes:
 PPI affinity can be expressed as a single "ppi-partitions" node,
 containing a set of sub-nodes, each with the following property:
 - affinity: Should be a list of phandles to CPU nodes (as described in
-Documentation/devicetree/bindings/arm/cpus.txt).
+  Documentation/devicetree/bindings/arm/cpus.yaml).
 
 GICv3 has one or more Interrupt Translation Services (ITS) that are
 used to route Message Signalled Interrupts (MSI) to the CPUs.
index 36603419d6f8e7858692af125f51726db85c5905..0e72183f52bc9dc5926b34f414941780e70847cc 100644 (file)
@@ -4,14 +4,10 @@ Required properties:
 - compatible : "olpc,ap-sp"
 - reg : base address and length of SoC's WTM registers
 - interrupts : SP-AP interrupt
-- clocks : phandle + clock-specifier for the clock that drives the WTM
-- clock-names:  should be "sp"
 
 Example:
        ap-sp@d4290000 {
                compatible = "olpc,ap-sp";
                reg = <0xd4290000 0x1000>;
                interrupts = <40>;
-               clocks = <&soc_clocks MMP2_CLK_SP>;
-               clock-names = "sp";
        }
index 0b8cc533ca83f6eddfd10f2f84e0abae20ca9204..cf759e5f9b108450a80a71ea4bcc282d1abba388 100644 (file)
@@ -55,7 +55,7 @@ of these nodes are defined by the individual bindings for the specific function
 = EXAMPLE
 The following example represents the GLINK RPM node on a MSM8996 device, with
 the function for the "rpm_request" channel defined, which is used for
-regualtors and root clocks.
+regulators and root clocks.
 
        apcs_glb: mailbox@9820000 {
                compatible = "qcom,msm8996-apcs-hmss-global";
index a35af2dafdad6a78b989f7a519f4887203a50735..49e1d72d3648b2aebac0410a7f0ceb2c94c90f69 100644 (file)
@@ -41,12 +41,12 @@ processor ID) and a string identifier.
 - qcom,local-pid:
        Usage: required
        Value type: <u32>
-       Definition: specifies the identfier of the local endpoint of this edge
+       Definition: specifies the identifier of the local endpoint of this edge
 
 - qcom,remote-pid:
        Usage: required
        Value type: <u32>
-       Definition: specifies the identfier of the remote endpoint of this edge
+       Definition: specifies the identifier of the remote endpoint of this edge
 
 = SUBNODES
 Each SMP2P pair contain a set of inbound and outbound entries, these are
index 62af30511a95247549b7334093122e35884cbab8..60a5ec04e8f05884ce48a83796662745ef552975 100644 (file)
@@ -163,6 +163,14 @@ C. Boot options
        be preserved until there actually is some text is output to the console.
        This option causes fbcon to bind immediately to the fbdev device.
 
+7. fbcon=logo-pos:<location>
+
+       The only possible 'location' is 'center' (without quotes), and when
+       given, the bootup logo is moved from the default top-left corner
+       location to the center of the framebuffer. If more than one logo is
+       displayed due to multiple CPUs, the collected line of logos is moved
+       as a whole.
+
 C. Attaching, Detaching and Unloading
 
 Before going on to how to attach, detach and unload the framebuffer console, an
index 6a47629ef8ed219acd1e44cc6e86431f4baba6b4..59e86de662cd1db363f794dac7d69f4185610bf6 100644 (file)
@@ -11,19 +11,19 @@ Contents:
    batman-adv
    can
    can_ucan_protocol
-   dpaa2/index
-   e100
-   e1000
-   e1000e
-   fm10k
-   igb
-   igbvf
-   ixgb
-   ixgbe
-   ixgbevf
-   i40e
-   iavf
-   ice
+   device_drivers/freescale/dpaa2/index
+   device_drivers/intel/e100
+   device_drivers/intel/e1000
+   device_drivers/intel/e1000e
+   device_drivers/intel/fm10k
+   device_drivers/intel/igb
+   device_drivers/intel/igbvf
+   device_drivers/intel/ixgb
+   device_drivers/intel/ixgbe
+   device_drivers/intel/ixgbevf
+   device_drivers/intel/i40e
+   device_drivers/intel/iavf
+   device_drivers/intel/ice
    kapi
    z8530book
    msg_zerocopy
index 355c6d8ef8ad7bff92071f45ebfbf085f9115df9..b203d13348224e982bcd7c76dc7476342bda2449 100644 (file)
@@ -22,8 +22,9 @@ and changeable from userspace under certain rules.
 2. Querying from userspace
 
 Both admin and operational state can be queried via the netlink
-operation RTM_GETLINK. It is also possible to subscribe to RTMGRP_LINK
-to be notified of updates. This is important for setting from userspace.
+operation RTM_GETLINK. It is also possible to subscribe to RTNLGRP_LINK
+to be notified of updates while the interface is admin up. This is
+important for setting from userspace.
 
 These values contain interface state:
 
@@ -101,8 +102,9 @@ because some driver controlled protocol establishment has to
 complete. Corresponding functions are netif_dormant_on() to set the
 flag, netif_dormant_off() to clear it and netif_dormant() to query.
 
-On device allocation, networking core sets the flags equivalent to
-netif_carrier_ok() and !netif_dormant().
+On device allocation, both flags __LINK_STATE_NOCARRIER and
+__LINK_STATE_DORMANT are cleared, so the effective state is equivalent
+to netif_carrier_ok() and !netif_dormant().
 
 
 Whenever the driver CHANGES one of these flags, a workqueue event is
@@ -133,11 +135,11 @@ netif_carrier_ok() && !netif_dormant() is set by the
 driver. Afterwards, the userspace application can set IFLA_OPERSTATE
 to IF_OPER_DORMANT or IF_OPER_UP as long as the driver does not set
 netif_carrier_off() or netif_dormant_on(). Changes made by userspace
-are multicasted on the netlink group RTMGRP_LINK.
+are multicasted on the netlink group RTNLGRP_LINK.
 
 So basically a 802.1X supplicant interacts with the kernel like this:
 
--subscribe to RTMGRP_LINK
+-subscribe to RTNLGRP_LINK
 -set IFLA_LINKMODE to 1 via RTM_SETLINK
 -query RTM_GETLINK once to get initial state
 -if initial flags are not (IFF_LOWER_UP && !IFF_DORMANT), wait until
index c9d052e0cf5136774c1f9a77de8f5bae7d7ad423..2df5894353d6954f5c0dd26d2c149c6e9ee6ee4c 100644 (file)
@@ -1000,51 +1000,6 @@ The kernel interface functions are as follows:
      size should be set when the call is begun.  tx_total_len may not be less
      than zero.
 
- (*) Check to see the completion state of a call so that the caller can assess
-     whether it needs to be retried.
-
-       enum rxrpc_call_completion {
-               RXRPC_CALL_SUCCEEDED,
-               RXRPC_CALL_REMOTELY_ABORTED,
-               RXRPC_CALL_LOCALLY_ABORTED,
-               RXRPC_CALL_LOCAL_ERROR,
-               RXRPC_CALL_NETWORK_ERROR,
-       };
-
-       int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
-                                   enum rxrpc_call_completion *_compl,
-                                   u32 *_abort_code);
-
-     On return, -EINPROGRESS will be returned if the call is still ongoing; if
-     it is finished, *_compl will be set to indicate the manner of completion,
-     *_abort_code will be set to any abort code that occurred.  0 will be
-     returned on a successful completion, -ECONNABORTED will be returned if the
-     client failed due to a remote abort and anything else will return an
-     appropriate error code.
-
-     The caller should look at this information to decide if it's worth
-     retrying the call.
-
- (*) Retry a client call.
-
-       int rxrpc_kernel_retry_call(struct socket *sock,
-                                   struct rxrpc_call *call,
-                                   struct sockaddr_rxrpc *srx,
-                                   struct key *key);
-
-     This attempts to partially reinitialise a call and submit it again while
-     reusing the original call's Tx queue to avoid the need to repackage and
-     re-encrypt the data to be sent.  call indicates the call to retry, srx the
-     new address to send it to and key the encryption key to use for signing or
-     encrypting the packets.
-
-     For this to work, the first Tx data packet must still be in the transmit
-     queue, and currently this is only permitted for local and network errors
-     and the call must not have been aborted.  Any partially constructed Tx
-     packet is left as is and can continue being filled afterwards.
-
-     It returns 0 if the call was requeued and an error otherwise.
-
  (*) Get call RTT.
 
        u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);
index b0dfdaaca512b38bc1b5a940ce52d55011618279..fe8f741193becacc2ee94632c36fc5ea22fbc722 100644 (file)
@@ -336,7 +336,26 @@ time client replies ACK, this socket will get another chance to move
 to the accept queue.
 
 
-TCP Fast Open
+* TcpEstabResets
+Defined in `RFC1213 tcpEstabResets`_.
+
+.. _RFC1213 tcpEstabResets: https://tools.ietf.org/html/rfc1213#page-48
+
+* TcpAttemptFails
+Defined in `RFC1213 tcpAttemptFails`_.
+
+.. _RFC1213 tcpAttemptFails: https://tools.ietf.org/html/rfc1213#page-48
+
+* TcpOutRsts
+Defined in `RFC1213 tcpOutRsts`_. The RFC says this counter indicates
+the 'segments sent containing the RST flag', but in linux kernel, this
+couner indicates the segments kerenl tried to send. The sending
+process might be failed due to some errors (e.g. memory alloc failed).
+
+.. _RFC1213 tcpOutRsts: https://tools.ietf.org/html/rfc1213#page-52
+
+
+TCP Fast Path
 ============
 When kernel receives a TCP packet, it has two paths to handler the
 packet, one is fast path, another is slow path. The comment in kernel
@@ -383,8 +402,6 @@ increase 1.
 
 TCP abort
 ========
-
-
 * TcpExtTCPAbortOnData
 It means TCP layer has data in flight, but need to close the
 connection. So TCP layer sends a RST to the other side, indicate the
@@ -545,7 +562,6 @@ packet yet, the sender would know packet 4 is out of order. The TCP
 stack of kernel will increase TcpExtTCPSACKReorder for both of the
 above scenarios.
 
-
 DSACK
 =====
 The DSACK is defined in `RFC2883`_. The receiver uses DSACK to report
@@ -566,13 +582,63 @@ The TCP stack receives an out of order duplicate packet, so it sends a
 DSACK to the sender.
 
 * TcpExtTCPDSACKRecv
-The TCP stack receives a DSACK, which indicate an acknowledged
+The TCP stack receives a DSACK, which indicates an acknowledged
 duplicate packet is received.
 
 * TcpExtTCPDSACKOfoRecv
 The TCP stack receives a DSACK, which indicate an out of order
 duplicate packet is received.
 
+invalid SACK and DSACK
+====================
+When a SACK (or DSACK) block is invalid, a corresponding counter would
+be updated. The validation method is base on the start/end sequence
+number of the SACK block. For more details, please refer the comment
+of the function tcp_is_sackblock_valid in the kernel source code. A
+SACK option could have up to 4 blocks, they are checked
+individually. E.g., if 3 blocks of a SACk is invalid, the
+corresponding counter would be updated 3 times. The comment of the
+`Add counters for discarded SACK blocks`_ patch has additional
+explaination:
+
+.. _Add counters for discarded SACK blocks: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18f02545a9a16c9a89778b91a162ad16d510bb32
+
+* TcpExtTCPSACKDiscard
+This counter indicates how many SACK blocks are invalid. If the invalid
+SACK block is caused by ACK recording, the TCP stack will only ignore
+it and won't update this counter.
+
+* TcpExtTCPDSACKIgnoredOld and TcpExtTCPDSACKIgnoredNoUndo
+When a DSACK block is invalid, one of these two counters would be
+updated. Which counter will be updated depends on the undo_marker flag
+of the TCP socket. If the undo_marker is not set, the TCP stack isn't
+likely to re-transmit any packets, and we still receive an invalid
+DSACK block, the reason might be that the packet is duplicated in the
+middle of the network. In such scenario, TcpExtTCPDSACKIgnoredNoUndo
+will be updated. If the undo_marker is set, TcpExtTCPDSACKIgnoredOld
+will be updated. As implied in its name, it might be an old packet.
+
+SACK shift
+=========
+The linux networking stack stores data in sk_buff struct (skb for
+short). If a SACK block acrosses multiple skb, the TCP stack will try
+to re-arrange data in these skb. E.g. if a SACK block acknowledges seq
+10 to 15, skb1 has seq 10 to 13, skb2 has seq 14 to 20. The seq 14 and
+15 in skb2 would be moved to skb1. This operation is 'shift'. If a
+SACK block acknowledges seq 10 to 20, skb1 has seq 10 to 13, skb2 has
+seq 14 to 20. All data in skb2 will be moved to skb1, and skb2 will be
+discard, this operation is 'merge'.
+
+* TcpExtTCPSackShifted
+A skb is shifted
+
+* TcpExtTCPSackMerged
+A skb is merged
+
+* TcpExtTCPSackShiftFallback
+A skb should be shifted or merged, but the TCP stack doesn't do it for
+some reasons.
+
 TCP out of order
 ===============
 * TcpExtTCPOFOQueue
@@ -662,6 +728,60 @@ unacknowledged number (more strict than `RFC 5961 section 5.2`_).
 .. _RFC 5961 section 4.2: https://tools.ietf.org/html/rfc5961#page-9
 .. _RFC 5961 section 5.2: https://tools.ietf.org/html/rfc5961#page-11
 
+TCP receive window
+=================
+* TcpExtTCPWantZeroWindowAdv
+Depending on current memory usage, the TCP stack tries to set receive
+window to zero. But the receive window might still be a no-zero
+value. For example, if the previous window size is 10, and the TCP
+stack receives 3 bytes, the current window size would be 7 even if the
+window size calculated by the memory usage is zero.
+
+* TcpExtTCPToZeroWindowAdv
+The TCP receive window is set to zero from a no-zero value.
+
+* TcpExtTCPFromZeroWindowAdv
+The TCP receive window is set to no-zero value from zero.
+
+
+Delayed ACK
+==========
+The TCP Delayed ACK is a technique which is used for reducing the
+packet count in the network. For more details, please refer the
+`Delayed ACK wiki`_
+
+.. _Delayed ACK wiki: https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment
+
+* TcpExtDelayedACKs
+A delayed ACK timer expires. The TCP stack will send a pure ACK packet
+and exit the delayed ACK mode.
+
+* TcpExtDelayedACKLocked
+A delayed ACK timer expires, but the TCP stack can't send an ACK
+immediately due to the socket is locked by a userspace program. The
+TCP stack will send a pure ACK later (after the userspace program
+unlock the socket). When the TCP stack sends the pure ACK later, the
+TCP stack will also update TcpExtDelayedACKs and exit the delayed ACK
+mode.
+
+* TcpExtDelayedACKLost
+It will be updated when the TCP stack receives a packet which has been
+ACKed. A Delayed ACK loss might cause this issue, but it would also be
+triggered by other reasons, such as a packet is duplicated in the
+network.
+
+Tail Loss Probe (TLP)
+===================
+TLP is an algorithm which is used to detect TCP packet loss. For more
+details, please refer the `TLP paper`_.
+
+.. _TLP paper: https://tools.ietf.org/html/draft-dukkipati-tcpm-tcp-loss-probe-01
+
+* TcpExtTCPLossProbes
+A TLP probe packet is sent.
+
+* TcpExtTCPLossProbeRecovery
+A packet loss is detected and recovered by TLP.
 
 examples
 =======
index 1be0b6f9e0cb223a6e781d119b236896f186499d..9d1432e0aaa89e1de3cfbc7185525059aed79e42 100644 (file)
@@ -417,7 +417,7 @@ is again deprecated and ts[2] holds a hardware timestamp if set.
 
 Hardware time stamping must also be initialized for each device driver
 that is expected to do hardware time stamping. The parameter is defined in
-/include/linux/net_tstamp.h as:
+include/uapi/linux/net_tstamp.h as:
 
 struct hwtstamp_config {
        int flags;      /* no flags defined right now, must be zero */
@@ -487,7 +487,7 @@ enum {
        HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
 
        /* for the complete list of values, please check
-        * the include file /include/linux/net_tstamp.h
+        * the include file include/uapi/linux/net_tstamp.h
         */
 };
 
index 819caf8ca05f8b4b16226c0f5d6f76068de09131..ebc679bcb2dca6a4110eb359fffc0248ff11d236 100644 (file)
@@ -56,26 +56,34 @@ of any kernel data structures.
 
 dentry-state:
 
-From linux/fs/dentry.c:
+From linux/include/linux/dcache.h:
 --------------------------------------------------------------
-struct {
+struct dentry_stat_t dentry_stat {
         int nr_dentry;
         int nr_unused;
         int age_limit;         /* age in seconds */
         int want_pages;        /* pages requested by system */
-        int dummy[2];
-} dentry_stat = {0, 0, 45, 0,};
--------------------------------------------------------------- 
-
-Dentries are dynamically allocated and deallocated, and
-nr_dentry seems to be 0 all the time. Hence it's safe to
-assume that only nr_unused, age_limit and want_pages are
-used. Nr_unused seems to be exactly what its name says.
+        int nr_negative;       /* # of unused negative dentries */
+        int dummy;             /* Reserved for future use */
+};
+--------------------------------------------------------------
+
+Dentries are dynamically allocated and deallocated.
+
+nr_dentry shows the total number of dentries allocated (active
++ unused). nr_unused shows the number of dentries that are not
+actively used, but are saved in the LRU list for future reuse.
+
 Age_limit is the age in seconds after which dcache entries
 can be reclaimed when memory is short and want_pages is
 nonzero when shrink_dcache_pages() has been called and the
 dcache isn't pruned yet.
 
+nr_negative shows the number of unused dentries that are also
+negative dentries which do not map to any files. Instead,
+they help speeding up rejection of non-existing files provided
+by the users.
+
 ==============================================================
 
 dquot-max & dquot-nr:
index e8e8d14d3c4e8d114f65e5258fdb8a15ba015f49..c1f95b59e14d9b73ab9ab9f8702fa2b85a170694 100644 (file)
@@ -9,7 +9,7 @@ Fenghua Yu <fenghua.yu@intel.com>
 Tony Luck <tony.luck@intel.com>
 Vikas Shivappa <vikas.shivappa@intel.com>
 
-This feature is enabled by the CONFIG_X86_RESCTRL and the x86 /proc/cpuinfo
+This feature is enabled by the CONFIG_X86_CPU_RESCTRL and the x86 /proc/cpuinfo
 flag bits:
 RDT (Resource Director Technology) Allocation - "rdt_a"
 CAT (Cache Allocation Technology) - "cat_l3", "cat_l2"
index b34df5d57cde67dcbbc452e23f586ab931bbb70d..3f2c6d697cab9f305f7b9fb00ae76485f336dafb 100644 (file)
@@ -2849,6 +2849,9 @@ F:        include/uapi/linux/if_bonding.h
 BPF (Safe dynamic programs and tools)
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+R:     Martin KaFai Lau <kafai@fb.com>
+R:     Song Liu <songliubraving@fb.com>
+R:     Yonghong Song <yhs@fb.com>
 L:     netdev@vger.kernel.org
 L:     linux-kernel@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
@@ -2874,6 +2877,8 @@ F:        samples/bpf/
 F:     tools/bpf/
 F:     tools/lib/bpf/
 F:     tools/testing/selftests/bpf/
+K:     bpf
+N:     bpf
 
 BPF JIT for ARM
 M:     Shubham Bansal <illusionist.neo@gmail.com>
@@ -3053,8 +3058,8 @@ F:        include/linux/bcm963xx_nvram.h
 F:     include/linux/bcm963xx_tag.h
 
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Rasesh Mody <rmody@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2.*
@@ -3073,9 +3078,9 @@ S:        Supported
 F:     drivers/scsi/bnx2i/
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Ariel Elior <ariel.elior@cavium.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
-M:     everest-linux-l2@cavium.com
+M:     Ariel Elior <aelior@marvell.com>
+M:     Sudarsana Kalluru <skalluru@marvell.com>
+M:     GR-everest-linux-l2@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
@@ -3250,9 +3255,9 @@ S:        Supported
 F:     drivers/scsi/bfa/
 
 BROCADE BNA 10 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@cavium.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Rasesh Mody <rmody@marvell.com>
+M:     Sudarsana Kalluru <skalluru@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/brocade/bna/
@@ -3472,10 +3477,9 @@ F:       drivers/i2c/busses/i2c-octeon*
 F:     drivers/i2c/busses/i2c-thunderx*
 
 CAVIUM LIQUIDIO NETWORK DRIVER
-M:     Derek Chickles <derek.chickles@caviumnetworks.com>
-M:     Satanand Burla <satananda.burla@caviumnetworks.com>
-M:     Felix Manlunas <felix.manlunas@caviumnetworks.com>
-M:     Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
+M:     Derek Chickles <dchickles@marvell.com>
+M:     Satanand Burla <sburla@marvell.com>
+M:     Felix Manlunas <fmanlunas@marvell.com>
 L:     netdev@vger.kernel.org
 W:     http://www.cavium.com
 S:     Supported
@@ -3980,6 +3984,7 @@ F:        drivers/cpufreq/arm_big_little.c
 CPU POWER MONITORING SUBSYSTEM
 M:     Thomas Renninger <trenn@suse.com>
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 F:     tools/power/cpupower/
@@ -5182,7 +5187,7 @@ DRM DRIVERS FOR XEN
 M:     Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 L:     dri-devel@lists.freedesktop.org
-L:     xen-devel@lists.xen.org
+L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/gpu/drm/xen/
 F:     Documentation/gpu/xen-front.rst
@@ -6147,7 +6152,7 @@ FREESCALE SOC SOUND DRIVERS
 M:     Timur Tabi <timur@kernel.org>
 M:     Nicolin Chen <nicoleotsuka@gmail.com>
 M:     Xiubo Li <Xiubo.Lee@gmail.com>
-R:     Fabio Estevam <fabio.estevam@nxp.com>
+R:     Fabio Estevam <festevam@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Maintained
@@ -8260,6 +8265,7 @@ F:        include/uapi/linux/sunrpc/
 
 KERNEL SELFTEST FRAMEWORK
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-kselftest@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
 Q:     https://patchwork.kernel.org/project/linux-kselftest/list/
@@ -10690,9 +10696,9 @@ S:      Maintained
 F:     drivers/net/netdevsim/*
 
 NETXEN (1/10) GbE SUPPORT
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Rahul Verma <rahul.verma@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Manish Chopra <manishc@marvell.com>
+M:     Rahul Verma <rahulv@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/netxen/
@@ -10893,7 +10899,7 @@ F:      include/linux/nvmem-consumer.h
 F:     include/linux/nvmem-provider.h
 
 NXP SGTL5000 DRIVER
-M:     Fabio Estevam <fabio.estevam@nxp.com>
+M:     Fabio Estevam <festevam@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/sound/sgtl5000.txt
@@ -11307,10 +11313,12 @@ F:    include/dt-bindings/
 
 OPENCORES I2C BUS DRIVER
 M:     Peter Korsgaard <peter@korsgaard.com>
+M:     Andrew Lunn <andrew@lunn.ch>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-ocores
 F:     drivers/i2c/busses/i2c-ocores.c
+F:     include/linux/platform_data/i2c-ocores.h
 
 OPENRISC ARCHITECTURE
 M:     Jonas Bonn <jonas@southpole.se>
@@ -12476,8 +12484,8 @@ S:      Supported
 F:     drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Ariel Elior <Ariel.Elior@cavium.com>
-M:     everest-linux-l2@cavium.com
+M:     Ariel Elior <aelior@marvell.com>
+M:     GR-everest-linux-l2@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qed/
@@ -12485,8 +12493,8 @@ F:      include/linux/qed/
 F:     drivers/net/ethernet/qlogic/qede/
 
 QLOGIC QL4xxx RDMA DRIVER
-M:     Michal Kalderon <Michal.Kalderon@cavium.com>
-M:     Ariel Elior <Ariel.Elior@cavium.com>
+M:     Michal Kalderon <mkalderon@marvell.com>
+M:     Ariel Elior <aelior@marvell.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 F:     drivers/infiniband/hw/qedr/
@@ -12506,7 +12514,7 @@ F:      Documentation/scsi/LICENSE.qla2xxx
 F:     drivers/scsi/qla2xxx/
 
 QLOGIC QLA3XXX NETWORK DRIVER
-M:     Dept-GELinuxNICDev@cavium.com
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/device_drivers/qlogic/LICENSE.qla3xxx
@@ -12520,16 +12528,16 @@ F:    Documentation/scsi/LICENSE.qla4xxx
 F:     drivers/scsi/qla4xxx/
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Shahed Shaikh <Shahed.Shaikh@cavium.com>
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Shahed Shaikh <shshaikh@marvell.com>
+M:     Manish Chopra <manishc@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Manish Chopra <manishc@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlge/
@@ -12868,6 +12876,13 @@ F:     Documentation/devicetree/bindings/net/dsa/realtek-smi.txt
 F:     drivers/net/dsa/realtek-smi*
 F:     drivers/net/dsa/rtl83*
 
+REDPINE WIRELESS DRIVER
+M:     Amitkumar Karwar <amitkarwar@gmail.com>
+M:     Siva Rebbagondla <siva8118@gmail.com>
+L:     linux-wireless@vger.kernel.org
+S:     Maintained
+F:     drivers/net/wireless/rsi/
+
 REGISTER MAP ABSTRACTION
 M:     Mark Brown <broonie@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -13696,6 +13711,15 @@ L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/sfc/
 
+SFF/SFP/SFP+ MODULE SUPPORT
+M:     Russell King <linux@armlinux.org.uk>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/phy/phylink.c
+F:     drivers/net/phy/sfp*
+F:     include/linux/phylink.h
+F:     include/linux/sfp.h
+
 SGI GRU DRIVER
 M:     Dimitri Sivanich <sivanich@sgi.com>
 S:     Maintained
@@ -15843,6 +15867,7 @@ F:      drivers/usb/common/usb-otg-fsm.c
 USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/usbip_protocol.txt
@@ -16640,6 +16665,15 @@ S:     Maintained
 F:     drivers/platform/x86/
 F:     drivers/platform/olpc/
 
+X86 PLATFORM DRIVERS - ARCH
+R:     Darren Hart <dvhart@infradead.org>
+R:     Andy Shevchenko <andy@infradead.org>
+L:     platform-driver-x86@vger.kernel.org
+L:     x86@kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
+S:     Maintained
+F:     arch/x86/platform
+
 X86 VDSO
 M:     Andy Lutomirski <luto@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -16672,6 +16706,24 @@ T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/tuners/tuner-xc2028.*
 
+XDP (eXpress Data Path)
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     David S. Miller <davem@davemloft.net>
+M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jesper Dangaard Brouer <hawk@kernel.org>
+M:     John Fastabend <john.fastabend@gmail.com>
+L:     netdev@vger.kernel.org
+L:     xdp-newbies@vger.kernel.org
+S:     Supported
+F:     net/core/xdp.c
+F:     include/net/xdp.h
+F:     kernel/bpf/devmap.c
+F:     kernel/bpf/cpumap.c
+F:     include/trace/events/xdp.h
+K:     xdp
+N:     xdp
+
 XDP SOCKETS (AF_XDP)
 M:     Björn Töpel <bjorn.topel@intel.com>
 M:     Magnus Karlsson <magnus.karlsson@intel.com>
index 499b9681099543269ce97aa6935f7acc3ac98ab2..96c5335e7ee4c06512c0d295facc12377bedd16a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc7
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
@@ -955,6 +955,7 @@ ifdef CONFIG_STACK_VALIDATION
   endif
 endif
 
+PHONY += prepare0
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
@@ -1061,8 +1062,7 @@ scripts: scripts_basic scripts_dtc
 # archprepare is used in arch Makefiles and when processed asm symlink,
 # version.h and scripts_basic is processed / created.
 
-# Listed in dependency order
-PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
+PHONY += prepare archprepare prepare1 prepare2 prepare3
 
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
@@ -1360,11 +1360,11 @@ mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
 mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
 mrproper-dirs      := $(addprefix _mrproper_,scripts)
 
-PHONY += $(mrproper-dirs) mrproper archmrproper
+PHONY += $(mrproper-dirs) mrproper
 $(mrproper-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
 
-mrproper: clean archmrproper $(mrproper-dirs)
+mrproper: clean $(mrproper-dirs)
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
 
index 4d17cacd146222c7c099eb1af0611eb68ec59c91..432402c8e47f5b8e1126fae0e2971d74d9d95f76 100644 (file)
 
 #elif defined(CONFIG_ALPHA_DP264) || \
       defined(CONFIG_ALPHA_LYNX)  || \
-      defined(CONFIG_ALPHA_SHARK) || \
-      defined(CONFIG_ALPHA_EIGER)
+      defined(CONFIG_ALPHA_SHARK)
 # define NR_IRQS       64
 
 #elif defined(CONFIG_ALPHA_TITAN)
 #define NR_IRQS                80
 
 #elif defined(CONFIG_ALPHA_RAWHIDE) || \
-       defined(CONFIG_ALPHA_TAKARA)
+      defined(CONFIG_ALPHA_TAKARA) || \
+      defined(CONFIG_ALPHA_EIGER)
 # define NR_IRQS       128
 
 #elif defined(CONFIG_ALPHA_WILDFIRE)
index d73dc473fbb9432f61d6f1383224a6aff1f67249..188fc9256baf16824431cb273f588daa219b2521 100644 (file)
@@ -78,7 +78,7 @@ __load_new_mm_context(struct mm_struct *next_mm)
 /* Macro for exception fixup code to access integer registers.  */
 #define dpf_reg(r)                                                     \
        (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 :  \
-                                (r) <= 18 ? (r)+8 : (r)-10])
+                                (r) <= 18 ? (r)+10 : (r)-10])
 
 asmlinkage void
 do_page_fault(unsigned long address, unsigned long mmcsr,
index feed50ce89fadfc1291080dffb16b969370553d8..caa270261521d45e46759592e9a3007c15fdd80f 100644 (file)
@@ -3,23 +3,19 @@ generic-y += bugs.h
 generic-y += compat.h
 generic-y += device.h
 generic-y += div64.h
-generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += extable.h
-generic-y += fb.h
 generic-y += ftrace.h
 generic-y += hardirq.h
 generic-y += hw_irq.h
 generic-y += irq_regs.h
 generic-y += irq_work.h
-generic-y += kmap_types.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += msi.h
 generic-y += parport.h
-generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += topology.h
index 49bfbd879caa6ffa08553e9b0f49b542739bb95b..f1b86cef09057ace18085cb1cb3f18b3be274852 100644 (file)
@@ -216,6 +216,14 @@ struct bcr_fp_arcv2 {
 #endif
 };
 
+struct bcr_actionpoint {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:21, min:1, num:2, ver:8;
+#else
+       unsigned int ver:8, num:2, min:1, pad:21;
+#endif
+};
+
 #include <soc/arc/timers.h>
 
 struct bcr_bpu_arcompact {
@@ -283,7 +291,7 @@ struct cpuinfo_arc_cache {
 };
 
 struct cpuinfo_arc_bpu {
-       unsigned int ver, full, num_cache, num_pred;
+       unsigned int ver, full, num_cache, num_pred, ret_stk;
 };
 
 struct cpuinfo_arc_ccm {
@@ -302,7 +310,7 @@ struct cpuinfo_arc {
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
                             fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4,
-                            debug:1, ap:1, smart:1, rtt:1, pad3:4,
+                            ap_num:4, ap_full:1, smart:1, rtt:1, pad3:1,
                             timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
        } extn;
        struct bcr_mpy extn_mpy;
index ee9246184033b3138f8d09878fc7763502b11e5c..202b74c339f0b43c6ca31a9ab0f76ae2240f0934 100644 (file)
@@ -340,7 +340,7 @@ static inline __attribute__ ((const)) int __fls(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long word)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
 {
        if (!word)
                return word;
@@ -400,9 +400,9 @@ static inline __attribute__ ((const)) int ffs(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long x)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
 {
-       int n;
+       unsigned long n;
 
        asm volatile(
        "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
index 9185541035cc3a716b59eb12a159850b18c5a7ea..6958545390f0f847ed3a7745b7325964d7f23f17 100644 (file)
@@ -103,7 +103,8 @@ static const char * const arc_pmu_ev_hw_map[] = {
 
        /* counts condition */
        [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", /* Excludes ZOL jumps */
+       /* All jump instructions that are taken */
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmptak",
        [PERF_COUNT_ARC_BPOK]         = "bpok",   /* NP-NT, PT-T, PNT-NT */
 #ifdef CONFIG_ISA_ARCV2
        [PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
index 8aec462d90fbe8f0aa88847272d02004a863f2db..861a8aea51f9fe0c086665dd84677f7ee80ea838 100644 (file)
@@ -1,15 +1,10 @@
-/*
- * Linux performance counter support for ARC700 series
- *
- * Copyright (C) 2013-2015 Synopsys, Inc. (www.synopsys.com)
- *
- * This code is inspired by the perf support of various other architectures.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Linux performance counter support for ARC CPUs.
+// This code is inspired by the perf support of various other architectures.
+//
+// Copyright (C) 2013-2018 Synopsys, Inc. (www.synopsys.com)
+
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <asm/arcregs.h>
 #include <asm/stacktrace.h>
 
+/* HW holds 8 symbols + one for null terminator */
+#define ARCPMU_EVENT_NAME_LEN  9
+
+enum arc_pmu_attr_groups {
+       ARCPMU_ATTR_GR_EVENTS,
+       ARCPMU_ATTR_GR_FORMATS,
+       ARCPMU_NR_ATTR_GR
+};
+
+struct arc_pmu_raw_event_entry {
+       char name[ARCPMU_EVENT_NAME_LEN];
+};
+
 struct arc_pmu {
        struct pmu      pmu;
        unsigned int    irq;
        int             n_counters;
+       int             n_events;
        u64             max_period;
        int             ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
+
+       struct arc_pmu_raw_event_entry  *raw_entry;
+       struct attribute                **attrs;
+       struct perf_pmu_events_attr     *attr;
+       const struct attribute_group    *attr_groups[ARCPMU_NR_ATTR_GR + 1];
 };
 
 struct arc_pmu_cpu {
@@ -49,6 +63,7 @@ static int callchain_trace(unsigned int addr, void *data)
 {
        struct arc_callchain_trace *ctrl = data;
        struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff;
+
        perf_callchain_store(entry, addr);
 
        if (ctrl->depth++ < 3)
@@ -57,8 +72,8 @@ static int callchain_trace(unsigned int addr, void *data)
        return -1;
 }
 
-void
-perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
+                          struct pt_regs *regs)
 {
        struct arc_callchain_trace ctrl = {
                .depth = 0,
@@ -68,8 +83,8 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
        arc_unwind_core(NULL, regs, callchain_trace, &ctrl);
 }
 
-void
-perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+                        struct pt_regs *regs)
 {
        /*
         * User stack can't be unwound trivially with kernel dwarf unwinder
@@ -82,10 +97,10 @@ static struct arc_pmu *arc_pmu;
 static DEFINE_PER_CPU(struct arc_pmu_cpu, arc_pmu_cpu);
 
 /* read counter #idx; note that counter# != event# on ARC! */
-static uint64_t arc_pmu_read_counter(int idx)
+static u64 arc_pmu_read_counter(int idx)
 {
-       uint32_t tmp;
-       uint64_t result;
+       u32 tmp;
+       u64 result;
 
        /*
         * ARC supports making 'snapshots' of the counters, so we don't
@@ -94,7 +109,7 @@ static uint64_t arc_pmu_read_counter(int idx)
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN);
-       result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
+       result = (u64) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
        result |= read_aux_reg(ARC_REG_PCT_SNAPL);
 
        return result;
@@ -103,9 +118,9 @@ static uint64_t arc_pmu_read_counter(int idx)
 static void arc_perf_event_update(struct perf_event *event,
                                  struct hw_perf_event *hwc, int idx)
 {
-       uint64_t prev_raw_count = local64_read(&hwc->prev_count);
-       uint64_t new_raw_count = arc_pmu_read_counter(idx);
-       int64_t delta = new_raw_count - prev_raw_count;
+       u64 prev_raw_count = local64_read(&hwc->prev_count);
+       u64 new_raw_count = arc_pmu_read_counter(idx);
+       s64 delta = new_raw_count - prev_raw_count;
 
        /*
         * We aren't afraid of hwc->prev_count changing beneath our feet
@@ -155,7 +170,7 @@ static int arc_pmu_event_init(struct perf_event *event)
        int ret;
 
        if (!is_sampling_event(event)) {
-               hwc->sample_period  = arc_pmu->max_period;
+               hwc->sample_period = arc_pmu->max_period;
                hwc->last_period = hwc->sample_period;
                local64_set(&hwc->period_left, hwc->sample_period);
        }
@@ -192,6 +207,18 @@ static int arc_pmu_event_init(struct perf_event *event)
                pr_debug("init cache event with h/w %08x \'%s\'\n",
                         (int)hwc->config, arc_pmu_ev_hw_map[ret]);
                return 0;
+
+       case PERF_TYPE_RAW:
+               if (event->attr.config >= arc_pmu->n_events)
+                       return -ENOENT;
+
+               hwc->config |= event->attr.config;
+               pr_debug("init raw event with idx %lld \'%s\'\n",
+                        event->attr.config,
+                        arc_pmu->raw_entry[event->attr.config].name);
+
+               return 0;
+
        default:
                return -ENOENT;
        }
@@ -200,7 +227,7 @@ static int arc_pmu_event_init(struct perf_event *event)
 /* starts all counters */
 static void arc_pmu_enable(struct pmu *pmu)
 {
-       uint32_t tmp;
+       u32 tmp;
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1);
 }
@@ -208,7 +235,7 @@ static void arc_pmu_enable(struct pmu *pmu)
 /* stops all counters */
 static void arc_pmu_disable(struct pmu *pmu)
 {
-       uint32_t tmp;
+       u32 tmp;
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
 }
@@ -228,7 +255,7 @@ static int arc_pmu_event_set_period(struct perf_event *event)
                local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                overflow = 1;
-       } else  if (unlikely(left <= 0)) {
+       } else if (unlikely(left <= 0)) {
                /* left underflowed by less than period. */
                left += period;
                local64_set(&hwc->period_left, left);
@@ -246,8 +273,8 @@ static int arc_pmu_event_set_period(struct perf_event *event)
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
 
        /* Write value */
-       write_aux_reg(ARC_REG_PCT_COUNTL, (u32)value);
-       write_aux_reg(ARC_REG_PCT_COUNTH, (value >> 32));
+       write_aux_reg(ARC_REG_PCT_COUNTL, lower_32_bits(value));
+       write_aux_reg(ARC_REG_PCT_COUNTH, upper_32_bits(value));
 
        perf_event_update_userpage(event);
 
@@ -277,7 +304,7 @@ static void arc_pmu_start(struct perf_event *event, int flags)
        /* Enable interrupt for this counter */
        if (is_sampling_event(event))
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                             read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+                             read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
 
        /* enable ARC pmu here */
        write_aux_reg(ARC_REG_PCT_INDEX, idx);          /* counter # */
@@ -295,9 +322,9 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
                 * Reset interrupt flag by writing of 1. This is required
                 * to make sure pending interrupt was not left.
                 */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+               write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                             read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx));
+                             read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~BIT(idx));
        }
 
        if (!(event->hw.state & PERF_HES_STOPPED)) {
@@ -349,9 +376,10 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 
        if (is_sampling_event(event)) {
                /* Mimic full counter overflow as other arches do */
-               write_aux_reg(ARC_REG_PCT_INT_CNTL, (u32)arc_pmu->max_period);
+               write_aux_reg(ARC_REG_PCT_INT_CNTL,
+                             lower_32_bits(arc_pmu->max_period));
                write_aux_reg(ARC_REG_PCT_INT_CNTH,
-                             (arc_pmu->max_period >> 32));
+                             upper_32_bits(arc_pmu->max_period));
        }
 
        write_aux_reg(ARC_REG_PCT_CONFIG, 0);
@@ -392,7 +420,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                idx = __ffs(active_ints);
 
                /* Reset interrupt flag by writing of 1 */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+               write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
 
                /*
                 * On reset of "interrupt active" bit corresponding
@@ -400,7 +428,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                 * Now we need to re-enable interrupt for the counter.
                 */
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                       read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+                       read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
 
                event = pmu_cpu->act_counter[idx];
                hwc = &event->hw;
@@ -414,7 +442,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                                arc_pmu_stop(event, 0);
                }
 
-               active_ints &= ~(1U << idx);
+               active_ints &= ~BIT(idx);
        } while (active_ints);
 
 done:
@@ -441,19 +469,108 @@ static void arc_cpu_pmu_irq_init(void *data)
        write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
 }
 
+/* Event field occupies the bottom 15 bits of our config field */
+PMU_FORMAT_ATTR(event, "config:0-14");
+static struct attribute *arc_pmu_format_attrs[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group arc_pmu_format_attr_gr = {
+       .name = "format",
+       .attrs = arc_pmu_format_attrs,
+};
+
+static ssize_t arc_pmu_events_sysfs_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr;
+
+       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+       return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
+}
+
+/*
+ * We don't add attrs here as we don't have pre-defined list of perf events.
+ * We will generate and add attrs dynamically in probe() after we read HW
+ * configuration.
+ */
+static struct attribute_group arc_pmu_events_attr_gr = {
+       .name = "events",
+};
+
+static void arc_pmu_add_raw_event_attr(int j, char *str)
+{
+       memmove(arc_pmu->raw_entry[j].name, str, ARCPMU_EVENT_NAME_LEN - 1);
+       arc_pmu->attr[j].attr.attr.name = arc_pmu->raw_entry[j].name;
+       arc_pmu->attr[j].attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0444);
+       arc_pmu->attr[j].attr.show = arc_pmu_events_sysfs_show;
+       arc_pmu->attr[j].id = j;
+       arc_pmu->attrs[j] = &(arc_pmu->attr[j].attr.attr);
+}
+
+static int arc_pmu_raw_alloc(struct device *dev)
+{
+       arc_pmu->attr = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
+               sizeof(*arc_pmu->attr), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->attr)
+               return -ENOMEM;
+
+       arc_pmu->attrs = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
+               sizeof(*arc_pmu->attrs), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->attrs)
+               return -ENOMEM;
+
+       arc_pmu->raw_entry = devm_kmalloc_array(dev, arc_pmu->n_events,
+               sizeof(*arc_pmu->raw_entry), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->raw_entry)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static inline bool event_in_hw_event_map(int i, char *name)
+{
+       if (!arc_pmu_ev_hw_map[i])
+               return false;
+
+       if (!strlen(arc_pmu_ev_hw_map[i]))
+               return false;
+
+       if (strcmp(arc_pmu_ev_hw_map[i], name))
+               return false;
+
+       return true;
+}
+
+static void arc_pmu_map_hw_event(int j, char *str)
+{
+       int i;
+
+       /* See if HW condition has been mapped to a perf event_id */
+       for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
+               if (event_in_hw_event_map(i, str)) {
+                       pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
+                                i, str, j);
+                       arc_pmu->ev_hw_idx[i] = j;
+               }
+       }
+}
+
 static int arc_pmu_device_probe(struct platform_device *pdev)
 {
        struct arc_reg_pct_build pct_bcr;
        struct arc_reg_cc_build cc_bcr;
-       int i, j, has_interrupts;
+       int i, has_interrupts;
        int counter_size;       /* in bits */
 
        union cc_name {
                struct {
-                       uint32_t word0, word1;
+                       u32 word0, word1;
                        char sentinel;
                } indiv;
-               char str[9];
+               char str[ARCPMU_EVENT_NAME_LEN];
        } cc_name;
 
 
@@ -463,15 +580,22 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                return -ENODEV;
        }
        BUILD_BUG_ON(ARC_PERF_MAX_COUNTERS > 32);
-       BUG_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS);
+       if (WARN_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS))
+               return -EINVAL;
 
        READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-       BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */
+       if (WARN(!cc_bcr.v, "Counters exist but No countable conditions?"))
+               return -EINVAL;
 
        arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
        if (!arc_pmu)
                return -ENOMEM;
 
+       arc_pmu->n_events = cc_bcr.c;
+
+       if (arc_pmu_raw_alloc(&pdev->dev))
+               return -ENOMEM;
+
        has_interrupts = is_isa_arcv2() ? pct_bcr.i : 0;
 
        arc_pmu->n_counters = pct_bcr.c;
@@ -481,30 +605,26 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
        pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n",
                arc_pmu->n_counters, counter_size, cc_bcr.c,
-               has_interrupts ? ", [overflow IRQ support]":"");
+               has_interrupts ? ", [overflow IRQ support]" : "");
 
-       cc_name.str[8] = 0;
+       cc_name.str[ARCPMU_EVENT_NAME_LEN - 1] = 0;
        for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++)
                arc_pmu->ev_hw_idx[i] = -1;
 
        /* loop thru all available h/w condition indexes */
-       for (j = 0; j < cc_bcr.c; j++) {
-               write_aux_reg(ARC_REG_CC_INDEX, j);
+       for (i = 0; i < cc_bcr.c; i++) {
+               write_aux_reg(ARC_REG_CC_INDEX, i);
                cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
                cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
 
-               /* See if it has been mapped to a perf event_id */
-               for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
-                       if (arc_pmu_ev_hw_map[i] &&
-                           !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
-                           strlen(arc_pmu_ev_hw_map[i])) {
-                               pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
-                                        i, cc_name.str, j);
-                               arc_pmu->ev_hw_idx[i] = j;
-                       }
-               }
+               arc_pmu_map_hw_event(i, cc_name.str);
+               arc_pmu_add_raw_event_attr(i, cc_name.str);
        }
 
+       arc_pmu_events_attr_gr.attrs = arc_pmu->attrs;
+       arc_pmu->attr_groups[ARCPMU_ATTR_GR_EVENTS] = &arc_pmu_events_attr_gr;
+       arc_pmu->attr_groups[ARCPMU_ATTR_GR_FORMATS] = &arc_pmu_format_attr_gr;
+
        arc_pmu->pmu = (struct pmu) {
                .pmu_enable     = arc_pmu_enable,
                .pmu_disable    = arc_pmu_disable,
@@ -514,6 +634,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                .start          = arc_pmu_start,
                .stop           = arc_pmu_stop,
                .read           = arc_pmu_read,
+               .attr_groups    = arc_pmu->attr_groups,
        };
 
        if (has_interrupts) {
@@ -535,17 +656,19 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
        } else
                arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-       return perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
+       /*
+        * perf parser doesn't really like '-' symbol in events name, so let's
+        * use '_' in arc pct name as it goes to kernel PMU event prefix.
+        */
+       return perf_pmu_register(&arc_pmu->pmu, "arc_pct", PERF_TYPE_RAW);
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id arc_pmu_match[] = {
        { .compatible = "snps,arc700-pct" },
        { .compatible = "snps,archs-pct" },
        {},
 };
 MODULE_DEVICE_TABLE(of, arc_pmu_match);
-#endif
 
 static struct platform_driver arc_pmu_driver = {
        .driver = {
index 2e018b8c2e19ce368c43d8eec102fe5334627da7..feb90093e6b1354eaf60064d7d961c736ded3108 100644 (file)
@@ -123,6 +123,7 @@ static void read_arc_build_cfg_regs(void)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        const struct id_to_str *tbl;
        struct bcr_isa_arcv2 isa;
+       struct bcr_actionpoint ap;
 
        FIX_PTR(cpu);
 
@@ -195,6 +196,7 @@ static void read_arc_build_cfg_regs(void)
                cpu->bpu.full = bpu.ft;
                cpu->bpu.num_cache = 256 << bpu.bce;
                cpu->bpu.num_pred = 2048 << bpu.pte;
+               cpu->bpu.ret_stk = 4 << bpu.rse;
 
                if (cpu->core.family >= 0x54) {
                        unsigned int exec_ctrl;
@@ -207,8 +209,11 @@ static void read_arc_build_cfg_regs(void)
                }
        }
 
-       READ_BCR(ARC_REG_AP_BCR, bcr);
-       cpu->extn.ap = bcr.ver ? 1 : 0;
+       READ_BCR(ARC_REG_AP_BCR, ap);
+       if (ap.ver) {
+               cpu->extn.ap_num = 2 << ap.num;
+               cpu->extn.ap_full = !!ap.min;
+       }
 
        READ_BCR(ARC_REG_SMART_BCR, bcr);
        cpu->extn.smart = bcr.ver ? 1 : 0;
@@ -216,8 +221,6 @@ static void read_arc_build_cfg_regs(void)
        READ_BCR(ARC_REG_RTT_BCR, bcr);
        cpu->extn.rtt = bcr.ver ? 1 : 0;
 
-       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
-
        READ_BCR(ARC_REG_ISA_CFG_BCR, isa);
 
        /* some hacks for lack of feature BCR info in old ARC700 cores */
@@ -299,10 +302,10 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
        if (cpu->bpu.ver)
                n += scnprintf(buf + n, len - n,
-                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d",
+                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d",
                              IS_AVAIL1(cpu->bpu.full, "full"),
                              IS_AVAIL1(!cpu->bpu.full, "partial"),
-                             cpu->bpu.num_cache, cpu->bpu.num_pred);
+                             cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk);
 
        if (is_isa_arcv2()) {
                struct bcr_lpb lpb;
@@ -336,11 +339,17 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
                               IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
                               IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
 
-       if (cpu->extn.debug)
-               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
-                              IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
+       if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) {
+               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s",
                               IS_AVAIL1(cpu->extn.smart, "smaRT "),
                               IS_AVAIL1(cpu->extn.rtt, "RTT "));
+               if (cpu->extn.ap_num) {
+                       n += scnprintf(buf + n, len - n, "ActionPoint %d/%s",
+                                      cpu->extn.ap_num,
+                                      cpu->extn.ap_full ? "full":"min");
+               }
+               n += scnprintf(buf + n, len - n, "\n");
+       }
 
        if (cpu->dccm.sz || cpu->iccm.sz)
                n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
index e8d9fb4523462a9807358fea19c4e7668cc1126d..215f515442e03d53ee3a18ade4c62e2a06987b3b 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/arcregs.h>
 #include <asm/irqflags.h>
 
+#define ARC_PATH_MAX   256
+
 /*
  * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
  *   -Prints 3 regs per line and a CR.
@@ -58,11 +60,12 @@ static void show_callee_regs(struct callee_regs *cregs)
        print_reg_file(&(cregs->r13), 13);
 }
 
-static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
+static void print_task_path_n_nm(struct task_struct *tsk)
 {
        char *path_nm = NULL;
        struct mm_struct *mm;
        struct file *exe_file;
+       char buf[ARC_PATH_MAX];
 
        mm = get_task_mm(tsk);
        if (!mm)
@@ -72,7 +75,7 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
        mmput(mm);
 
        if (exe_file) {
-               path_nm = file_path(exe_file, buf, 255);
+               path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
                fput(exe_file);
        }
 
@@ -80,10 +83,9 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
        pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
 }
 
-static void show_faulting_vma(unsigned long address, char *buf)
+static void show_faulting_vma(unsigned long address)
 {
        struct vm_area_struct *vma;
-       char *nm = buf;
        struct mm_struct *active_mm = current->active_mm;
 
        /* can't use print_vma_addr() yet as it doesn't check for
@@ -96,8 +98,11 @@ static void show_faulting_vma(unsigned long address, char *buf)
         * if the container VMA is not found
         */
        if (vma && (vma->vm_start <= address)) {
+               char buf[ARC_PATH_MAX];
+               char *nm = "?";
+
                if (vma->vm_file) {
-                       nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1);
+                       nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
                        if (IS_ERR(nm))
                                nm = "?";
                }
@@ -173,13 +178,14 @@ void show_regs(struct pt_regs *regs)
 {
        struct task_struct *tsk = current;
        struct callee_regs *cregs;
-       char *buf;
 
-       buf = (char *)__get_free_page(GFP_KERNEL);
-       if (!buf)
-               return;
+       /*
+        * generic code calls us with preemption disabled, but some calls
+        * here could sleep, so re-enable to avoid lockdep splat
+        */
+       preempt_enable();
 
-       print_task_path_n_nm(tsk, buf);
+       print_task_path_n_nm(tsk);
        show_regs_print_info(KERN_INFO);
 
        show_ecr_verbose(regs);
@@ -189,7 +195,7 @@ void show_regs(struct pt_regs *regs)
                (void *)regs->blink, (void *)regs->ret);
 
        if (user_mode(regs))
-               show_faulting_vma(regs->ret, buf); /* faulting code, not data */
+               show_faulting_vma(regs->ret); /* faulting code, not data */
 
        pr_info("[STAT32]: 0x%08lx", regs->status32);
 
@@ -222,7 +228,7 @@ void show_regs(struct pt_regs *regs)
        if (cregs)
                show_callee_regs(cregs);
 
-       free_page((unsigned long)buf);
+       preempt_disable();
 }
 
 void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
index 62ad4bcb841aa70811a637c3621d80190ed0c352..f230bb7092fdb3d7d98883ab7310db1b4bc56654 100644 (file)
@@ -7,11 +7,39 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/cache.h>
 
-#undef PREALLOC_NOT_AVAIL
+/*
+ * The memset implementation below is optimized to use prefetchw and prealloc
+ * instruction in case of CPU with 64B L1 data cache line (L1_CACHE_SHIFT == 6)
+ * If you want to implement optimized memset for other possible L1 data cache
+ * line lengths (32B and 128B) you should rewrite code carefully checking
+ * we don't call any prefetchw/prealloc instruction for L1 cache lines which
+ * don't belongs to memset area.
+ */
+
+#if L1_CACHE_SHIFT == 6
+
+.macro PREALLOC_INSTR  reg, off
+       prealloc        [\reg, \off]
+.endm
+
+.macro PREFETCHW_INSTR reg, off
+       prefetchw       [\reg, \off]
+.endm
+
+#else
+
+.macro PREALLOC_INSTR
+.endm
+
+.macro PREFETCHW_INSTR
+.endm
+
+#endif
 
 ENTRY_CFI(memset)
-       prefetchw [r0]          ; Prefetch the write location
+       PREFETCHW_INSTR r0, 0   ; Prefetch the first write location
        mov.f   0, r2
 ;;; if size is zero
        jz.d    [blink]
@@ -48,11 +76,8 @@ ENTRY_CFI(memset)
 
        lpnz    @.Lset64bytes
        ;; LOOP START
-#ifdef PREALLOC_NOT_AVAIL
-       prefetchw [r3, 64]      ;Prefetch the next write location
-#else
-       prealloc  [r3, 64]
-#endif
+       PREALLOC_INSTR  r3, 64  ; alloc next line w/o fetching
+
 #ifdef CONFIG_ARC_HAS_LL64
        std.ab  r4, [r3, 8]
        std.ab  r4, [r3, 8]
@@ -85,7 +110,6 @@ ENTRY_CFI(memset)
        lsr.f   lp_count, r2, 5 ;Last remaining  max 124 bytes
        lpnz    .Lset32bytes
        ;; LOOP START
-       prefetchw   [r3, 32]    ;Prefetch the next write location
 #ifdef CONFIG_ARC_HAS_LL64
        std.ab  r4, [r3, 8]
        std.ab  r4, [r3, 8]
index a1d7231970848dbc6f1f097fd7536153d63cf38d..8df1638259f3f2daa6b7d3cd3f70f54c3094017a 100644 (file)
@@ -141,12 +141,17 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       /* If Pagefault was interrupted by SIGKILL, exit page fault "early" */
        if (fatal_signal_pending(current)) {
-               if ((fault & VM_FAULT_ERROR) && !(fault & VM_FAULT_RETRY))
-                       up_read(&mm->mmap_sem);
-               if (user_mode(regs))
+
+               /*
+                * if fault retry, mmap_sem already relinquished by core mm
+                * so OK to return to user mode (with signal handled first)
+                */
+               if (fault & VM_FAULT_RETRY) {
+                       if (!user_mode(regs))
+                               goto no_context;
                        return;
+               }
        }
 
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
index 43bf4c3a1290d818578bfdcda5fefaf76df27810..e1ab2d7f1d646510ab17a4be31b675e88027745b 100644 (file)
@@ -119,7 +119,8 @@ void __init setup_arch_memory(void)
         */
 
        memblock_add_node(low_mem_start, low_mem_sz, 0);
-       memblock_reserve(low_mem_start, __pa(_end) - low_mem_start);
+       memblock_reserve(CONFIG_LINUX_LINK_BASE,
+                        __pa(_end) - CONFIG_LINUX_LINK_BASE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        if (phys_initrd_size) {
index d0fd68873689cfc8b37344a077ade06ae2d09851..5b250060f6ddc2366a556f9ac394b01cbfa43003 100644 (file)
@@ -215,7 +215,7 @@ &mmc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        bus-width = <0x4>;
-       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
        cd-inverted;
        max-frequency = <26000000>;
        vmmc-supply = <&vmmcsd_fixed>;
index 47aa53ba6b92236d4616992aeea113a81bfb8c97..559659b399d04d6d9642d673d335772bc8274b5f 100644 (file)
@@ -476,7 +476,7 @@ i2c1: i2c@228000 {
                clocksource: timer@20000 {
                        compatible = "ti,da830-timer";
                        reg = <0x20000 0x1000>;
-                       interrupts = <12>, <13>;
+                       interrupts = <21>, <22>;
                        interrupt-names = "tint12", "tint34";
                        clocks = <&pll0_auxclk>;
                };
index 5edf858c8b860e840c8515d094a1b13fe8f7ef91..a31b17eaf51c2cfc7ff00420848af6506d74f52b 100644 (file)
@@ -103,7 +103,7 @@ gpio-keys {
                power {
                        label = "Power Button";
                        gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                        linux,code = <KEY_POWER>;
                };
        };
index d8163705363ec3580c8068e66ad881f23efb5aa8..4a31a415f88e295fa37881b2991f4edaed04024f 100644 (file)
@@ -309,7 +309,7 @@ &usdhc3 {
        pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
        cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
        keep-power-in-suspend;
-       enable-sdio-wakeup;
+       wakeup-source;
        vmmc-supply = <&reg_sd3_vmmc>;
        status = "okay";
 };
index 272ff6133ec1803b8f23d8eaa5d26f2d35d3d341..d1375d3650fdc38ca313977fe788bee4de1bbbb6 100644 (file)
@@ -467,7 +467,7 @@ flexcan2: can@2094000 {
                        };
 
                        gpt: gpt@2098000 {
-                               compatible = "fsl,imx6sx-gpt", "fsl,imx31-gpt";
+                               compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
                                reg = <0x02098000 0x4000>;
                                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_GPT_BUS>,
index e4645f61271244fedeb0d128a6ad4535b452b6b2..2ab74860d962212f6377ee50de34b67fd0a01fe8 100644 (file)
@@ -274,7 +274,7 @@ ethmac: ethernet@c9410000 {
                        compatible = "amlogic,meson6-dwmac", "snps,dwmac";
                        reg = <0xc9410000 0x10000
                               0xc1108108 0x4>;
-                       interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
+                       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "macirq";
                        status = "disabled";
                };
index 0872f6e3abf56f02c1f4d3f7423a3a6d17bda1a4..d50fc2f60fa31fc24e296de7f3ed2af3e4834321 100644 (file)
@@ -205,8 +205,7 @@ sd_card_slot: slot@1 {
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&vcc_3v3>;
        };
index 58669abda2594d4979086695db3af0aee095983b..0f0a46ddf3ff2e9d3fa8148803d01d5b28897e1b 100644 (file)
@@ -221,7 +221,6 @@ mdio {
                /* Realtek RTL8211F (0x001cc916) */
                eth_phy: ethernet-phy@0 {
                        reg = <0>;
-                       eee-broken-1000t;
                        interrupt-parent = <&gpio_intc>;
                        /* GPIOH_3 */
                        interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
@@ -273,8 +272,7 @@ sd_card_slot: slot@1 {
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&tflash_vdd>;
                vqmmc-supply = <&tf_io>;
index f5853610b20b804170e941c5b24d2b50b94a1d62..6ac02beb5fa724c34706dcbf522312eedf09d618 100644 (file)
@@ -206,8 +206,7 @@ sd_card_slot: slot@1 {
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&vcc_3v3>;
        };
index ddc7a7bb33c0de974a74ecf754f0a4644c5fc46b..f57acf8f66b95d1a2f1e17899e97b61a433c43da 100644 (file)
@@ -105,7 +105,7 @@ cpcap_usb2_phy: phy {
                        interrupts-extended = <
                                &cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
                                &cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
-                               &cpcap 48 1
+                               &cpcap 48 0
                        >;
                        interrupt-names =
                                "id_ground", "id_float", "se0conn", "vbusvld",
index e53d326913080f34e180996bfbed8e8a6320ad69..93b420934e8ee96115b41b80c9f78b842cae0d8b 100644 (file)
@@ -714,11 +714,7 @@ &venc {
 
        vdda-supply = <&vdac>;
 
-       #address-cells = <1>;
-       #size-cells = <0>;
-
        port {
-               reg = <0>;
                venc_out: endpoint {
                        remote-endpoint = <&opa_in>;
                        ti,channels = <1>;
index 182a53991c901a387317db9710bceb9d0d1d5bb6..826920e6b8787ee10e06753795d7224f84e84158 100644 (file)
@@ -814,7 +814,7 @@ &mmc1 {
        /* For debugging, it is often good idea to remove this GPIO.
           It means you can remove back cover (to reboot by removing
           battery) and still use the MMC card. */
-       cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
+       cd-gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
 };
 
 /* most boards use vaux3, only some old versions use vmmc2 instead */
index 0d9b85317529b317ce9b8788c8cdbde14c7c53c7..e142e6c70a59fa7deb3ffee947b212ec50ba0fac 100644 (file)
@@ -370,6 +370,19 @@ onenand@0,0 {
                compatible = "ti,omap2-onenand";
                reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
 
+               /*
+                * These timings are based on CONFIG_OMAP_GPMC_DEBUG=y reported
+                * bootloader set values when booted with v4.19 using both N950
+                * and N9 devices (OneNAND Manufacturer: Samsung):
+                *
+                *   gpmc cs0 before gpmc_cs_program_settings:
+                *   cs0 GPMC_CS_CONFIG1: 0xfd001202
+                *   cs0 GPMC_CS_CONFIG2: 0x00181800
+                *   cs0 GPMC_CS_CONFIG3: 0x00030300
+                *   cs0 GPMC_CS_CONFIG4: 0x18001804
+                *   cs0 GPMC_CS_CONFIG5: 0x03171d1d
+                *   cs0 GPMC_CS_CONFIG6: 0x97080000
+                */
                gpmc,sync-read;
                gpmc,sync-write;
                gpmc,burst-length = <16>;
@@ -379,26 +392,27 @@ onenand@0,0 {
                gpmc,device-width = <2>;
                gpmc,mux-add-data = <2>;
                gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <87>;
-               gpmc,cs-wr-off-ns = <87>;
+               gpmc,cs-rd-off-ns = <122>;
+               gpmc,cs-wr-off-ns = <122>;
                gpmc,adv-on-ns = <0>;
-               gpmc,adv-rd-off-ns = <10>;
-               gpmc,adv-wr-off-ns = <10>;
-               gpmc,oe-on-ns = <15>;
-               gpmc,oe-off-ns = <87>;
+               gpmc,adv-rd-off-ns = <15>;
+               gpmc,adv-wr-off-ns = <15>;
+               gpmc,oe-on-ns = <20>;
+               gpmc,oe-off-ns = <122>;
                gpmc,we-on-ns = <0>;
-               gpmc,we-off-ns = <87>;
-               gpmc,rd-cycle-ns = <112>;
-               gpmc,wr-cycle-ns = <112>;
-               gpmc,access-ns = <81>;
+               gpmc,we-off-ns = <122>;
+               gpmc,rd-cycle-ns = <148>;
+               gpmc,wr-cycle-ns = <148>;
+               gpmc,access-ns = <117>;
                gpmc,page-burst-access-ns = <15>;
                gpmc,bus-turnaround-ns = <0>;
                gpmc,cycle2cycle-delay-ns = <0>;
                gpmc,wait-monitoring-ns = <0>;
-               gpmc,clk-activation-ns = <5>;
-               gpmc,wr-data-mux-bus-ns = <30>;
-               gpmc,wr-access-ns = <81>;
-               gpmc,sync-clk-ps = <15000>;
+               gpmc,clk-activation-ns = <10>;
+               gpmc,wr-data-mux-bus-ns = <40>;
+               gpmc,wr-access-ns = <117>;
+
+               gpmc,sync-clk-ps = <15000>; /* TBC; Where this value came? */
 
                /*
                 * MTD partition table corresponding to Nokia's MeeGo 1.2
index 04758a2a87f031eb42df555cc85a85bd0bf63816..67d77eee9433c655e0bd8f0c1dbf7c25aba3ecce 100644 (file)
@@ -644,6 +644,17 @@ OMAP4_IOPAD(0x040, PIN_OUTPUT_PULLDOWN | MUX_MODE3)
        };
 };
 
+/* Configure pwm clock source for timers 8 & 9 */
+&timer8 {
+       assigned-clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>;
+       assigned-clock-parents = <&sys_clkin_ck>;
+};
+
+&timer9 {
+       assigned-clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>;
+       assigned-clock-parents = <&sys_clkin_ck>;
+};
+
 /*
  * As uart1 is wired to mdm6600 with rts and cts, we can use the cts pin for
  * uart1 wakeirq.
index bc853ebeda221f43dfeeb78a64c60f10578eb3e6..61a06f6add3ca52a9d7c4851080c53d0a5d18ac9 100644 (file)
@@ -317,7 +317,8 @@ &usbhost_wkup_pins
 
        palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
                pinctrl-single,pins = <
-                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq1 */
+                       /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */
+                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0)
                >;
        };
 
@@ -385,7 +386,8 @@ &i2c1 {
 
        palmas: palmas@48 {
                compatible = "ti,palmas";
-               interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
@@ -651,7 +653,8 @@ twl6040: twl@4b {
                pinctrl-names = "default";
                pinctrl-0 = <&twl6040_pins>;
 
-               interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_LOW>;
 
                /* audpwron gpio defined in the board specific dts */
 
index 5e21fb430a65daa8e29a1ca90a404389d9dc99a9..e78d3718f145d544dee0625ada9c3bfe7ca9327b 100644 (file)
@@ -181,6 +181,13 @@ ads7846_pins: pinmux_ads7846_pins {
                        OMAP5_IOPAD(0x0042, PIN_INPUT_PULLDOWN | MUX_MODE6)  /* llib_wakereqin.gpio1_wk15 */
                >;
        };
+
+       palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
+               pinctrl-single,pins = <
+                       /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */
+                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0)
+               >;
+       };
 };
 
 &omap5_pmx_core {
@@ -414,8 +421,11 @@ at24@50 {
 
        palmas: palmas@48 {
                compatible = "ti,palmas";
-               interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
                reg = <0x48>;
+               pinctrl-0 = <&palmas_sys_nirq_pins>;
+               pinctrl-names = "default";
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>;
                interrupt-controller;
                #interrupt-cells = <2>;
                ti,system-power-controller;
index 9c7e309d9c2cc20e8db86a1ef51bdf20c18995d2..0960348002ad85fca5326dc55caab39b7bcaeffa 100644 (file)
@@ -1046,8 +1046,6 @@ SYSC_OMAP2_SOFTRESET |
                                        <SYSC_IDLE_SMART>,
                                        <SYSC_IDLE_SMART_WKUP>;
                        ti,syss-mask = <1>;
-                       ti,no-reset-on-init;
-                       ti,no-idle-on-init;
                        /* Domains (V, P, C): core, core_pwrdm, l4per_clkdm */
                        clocks = <&l4per_clkctrl OMAP5_UART3_CLKCTRL 0>;
                        clock-names = "fck";
index 3cc33f7ff7febae7e8eebb586f180d0c07c02b3c..3adc158a40bb34f0d8954163595333293ce21653 100644 (file)
@@ -1681,15 +1681,12 @@ vsp@fe938000 {
 
                du: display@feb00000 {
                        compatible = "renesas,du-r8a7743";
-                       reg = <0 0xfeb00000 0 0x40000>,
-                             <0 0xfeb90000 0 0x1c>;
-                       reg-names = "du", "lvds.0";
+                       reg = <0 0xfeb00000 0 0x40000>;
                        interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 724>,
-                                <&cpg CPG_MOD 723>,
-                                <&cpg CPG_MOD 726>;
-                       clock-names = "du.0", "du.1", "lvds.0";
+                                <&cpg CPG_MOD 723>;
+                       clock-names = "du.0", "du.1";
                        status = "disabled";
 
                        ports {
@@ -1704,6 +1701,33 @@ du_out_rgb: endpoint {
                                port@1 {
                                        reg = <1>;
                                        du_out_lvds0: endpoint {
+                                               remote-endpoint = <&lvds0_in>;
+                                       };
+                               };
+                       };
+               };
+
+               lvds0: lvds@feb90000 {
+                       compatible = "renesas,r8a7743-lvds";
+                       reg = <0 0xfeb90000 0 0x1c>;
+                       clocks = <&cpg CPG_MOD 726>;
+                       power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 726>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       lvds0_in: endpoint {
+                                               remote-endpoint = <&du_out_lvds0>;
+                                       };
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       lvds0_out: endpoint {
                                        };
                                };
                        };
index 4acb501dd3f8ef31355f2ae2adb9d6a60a386d40..3ed49898f4b2edab7e6a5efbf68ea081cfa64734 100644 (file)
@@ -719,7 +719,6 @@ pd_vio@RK3188_PD_VIO {
                        pm_qos = <&qos_lcdc0>,
                                 <&qos_lcdc1>,
                                 <&qos_cif0>,
-                                <&qos_cif1>,
                                 <&qos_ipp>,
                                 <&qos_rga>;
                };
index 353d90f99b406e9e267e56bd84e082968ae433e2..13304b8c51390de7c31f67b1850ed5aca931a29f 100644 (file)
@@ -216,6 +216,7 @@ osc24M: clk-24M {
                        #clock-cells = <0>;
                        compatible = "fixed-clock";
                        clock-frequency = <24000000>;
+                       clock-output-names = "osc24M";
                };
 
                osc32k: clk-32k {
index 5d23667dc2d2e72f3fc557c0fa387c69b45ac3a2..25540b7694d590dea1c3c54c5453d4a7217d9f37 100644 (file)
@@ -53,7 +53,7 @@ / {
 
        aliases {
                serial0 = &uart0;
-               /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+               ethernet0 = &emac;
                ethernet1 = &sdiowifi;
        };
 
index 689c8930dce35ceb9b54f94d796ce3283e4be482..b08d561d6748ed1b1d4cfb99890748834672198c 100644 (file)
@@ -110,11 +110,11 @@ &dspi3 {
        bus-num = <3>;
        status = "okay";
        spi-slave;
+       #address-cells = <0>;
 
-       slave@0 {
+       slave {
                compatible = "lwn,bk4";
                spi-max-frequency = <30000000>;
-               reg = <0>;
        };
 };
 
index ca56537b61bc87473bf9df15d5169cca22c4390f..50e89869178a9725f0bb6c8bb2082bc186fcbab7 100644 (file)
@@ -48,6 +48,7 @@
 #define KVM_REQ_SLEEP \
        KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
+#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -147,6 +148,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+struct vcpu_reset_state {
+       unsigned long   pc;
+       unsigned long   r0;
+       bool            be;
+       bool            reset;
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -186,6 +194,8 @@ struct kvm_vcpu_arch {
        /* Cache some mmu pages needed inside spinlock regions */
        struct kvm_mmu_memory_cache mmu_page_cache;
 
+       struct vcpu_reset_state reset_state;
+
        /* Detect first run of a vcpu */
        bool has_run_once;
 };
index c4b1d4fb17972ed3d638e187663607fe42bc9f0e..de2089501b8b5705a29bcb80b7007d630cfabc60 100644 (file)
@@ -76,4 +76,9 @@ static inline bool kvm_stage2_has_pud(struct kvm *kvm)
 #define S2_PMD_MASK                            PMD_MASK
 #define S2_PMD_SIZE                            PMD_SIZE
 
+static inline bool kvm_stage2_has_pmd(struct kvm *kvm)
+{
+       return true;
+}
+
 #endif /* __ARM_S2_PGTABLE_H_ */
index b3ef061d8b7417b90279c94a8706995fc116bd21..2c403e7c782d31f83b956dcbcc9a9a9027092ffe 100644 (file)
@@ -1 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
+#define _ASM_ARM_XEN_PAGE_COHERENT_H
+
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <xen/arm/page-coherent.h>
+
+static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev)
+{
+       if (dev && dev->archdata.dev_dma_ops)
+               return dev->archdata.dev_dma_ops;
+       return get_arch_dma_ops(NULL);
+}
+
+static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
+               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
+{
+       return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
+}
+
+static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
+               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
+{
+       xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
+            dma_addr_t dev_addr, unsigned long offset, size_t size,
+            enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can span across
+        * multiple Xen pages, it's not possible for it to contain a
+        * mix of local and foreign Xen pages. So if the first xen_pfn
+        * == mfn the page is local otherwise it's a foreign page
+        * grant-mapped in dom0. If the page is local we can safely
+        * call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (local)
+               xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
+       else
+               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
+}
+
+static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+        * multiple Xen page, it's not possible to have a mix of local and
+        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
+        * foreign mfn will always return false. If the page is local we can
+        * safely call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->unmap_page)
+                       xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
+       } else
+               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
+}
+
+static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->sync_single_for_cpu)
+                       xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
+       } else
+               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->sync_single_for_device)
+                       xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
+       } else
+               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
+}
+
+#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
index 222c1635bc7a1337c80e3af115df5f0696f52a7d..e8bd288fd5be909dad8ec74561330fea3a972ff7 100644 (file)
@@ -1450,6 +1450,6 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
        reset_coproc_regs(vcpu, table, num);
 
        for (num = 1; num < NR_CP15_REGS; num++)
-               if (vcpu_cp15(vcpu, num) == 0x42424242)
-                       panic("Didn't reset vcpu_cp15(vcpu, %zi)", num);
+               WARN(vcpu_cp15(vcpu, num) == 0x42424242,
+                    "Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
index 5ed0c3ee33d66b3c8263d28d28da756693b4c935..e53327912adc67e80a93f6f4130df5b81313f902 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/cputype.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_emulate.h>
 
 #include <kvm/arm_arch_timer.h>
 
@@ -69,6 +70,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset CP15 registers */
        kvm_reset_coprocs(vcpu);
 
+       /*
+        * Additional reset state handling that PSCI may have imposed on us.
+        * Must be done after all the sys_reg reset.
+        */
+       if (READ_ONCE(vcpu->arch.reset_state.reset)) {
+               unsigned long target_pc = vcpu->arch.reset_state.pc;
+
+               /* Gracefully handle Thumb2 entry point */
+               if (target_pc & 1) {
+                       target_pc &= ~1UL;
+                       vcpu_set_thumb(vcpu);
+               }
+
+               /* Propagate caller endianness */
+               if (vcpu->arch.reset_state.be)
+                       kvm_vcpu_set_be(vcpu);
+
+               *vcpu_pc(vcpu) = target_pc;
+               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
+
+               vcpu->arch.reset_state.reset = false;
+       }
+
        /* Reset arch_timer context */
        return kvm_timer_vcpu_reset(vcpu);
 }
index 318394ed5c7a97c2923c8c35134b88cb188ef238..95a11d5b3587fd1ba2accad36460a956c17eb173 100644 (file)
@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
        } else /* remote PCI bus */
                base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
 
-       return base + (where & 0xffc) + (devfn << 12);
+       return base + where + (devfn << 12);
 }
 
 static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -93,7 +93,7 @@ static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        u32 mask = (0x1ull << (size * 8)) - 1;
        int shift = (where % 4) * 8;
 
-       ret = pci_generic_config_read32(bus, devfn, where, size, val);
+       ret = pci_generic_config_read(bus, devfn, where, size, val);
 
        if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn &&
            (where & 0xffc) == PCI_CLASS_REVISION)
index 3b73813c6b0434f93c85bf4256ae70049de8ae2c..23e8c93515d4ec5d0648a5be2f1a900e0f97ca8d 100644 (file)
@@ -75,8 +75,7 @@ void __init n2100_map_io(void)
 /*
  * N2100 PCI.
  */
-static int __init
-n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index a8b291f00109c653c05d47ab49abb7c9c306b238..dae514c8276aac6218fd4a7f5df711769c048769 100644 (file)
@@ -152,6 +152,10 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
                                 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
+       /* Enter broadcast mode for periodic timers */
+       tick_broadcast_enable();
+
+       /* Enter broadcast mode for one-shot timers */
        tick_broadcast_enter();
 
        /*
@@ -218,15 +222,6 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        return index;
 }
 
-/*
- * For each cpu, setup the broadcast timer because local timers
- * stops for the states above C1.
- */
-static void omap_setup_broadcast_timer(void *arg)
-{
-       tick_broadcast_enable();
-}
-
 static struct cpuidle_driver omap4_idle_driver = {
        .name                           = "omap4_idle",
        .owner                          = THIS_MODULE,
@@ -319,8 +314,5 @@ int __init omap4_idle_init(void)
        if (!cpu_clkdm[0] || !cpu_clkdm[1])
                return -ENODEV;
 
-       /* Configure the broadcast timer on each cpu */
-       on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
-
        return cpuidle_register(idle_driver, cpu_online_mask);
 }
index f86b72d1d59e51f4af15319df87ee61141b4fd02..1444b4b4bd9f85e54368c0e18ac31f3f2fc033eb 100644 (file)
@@ -83,6 +83,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
        u32 enable_mask, enable_shift;
        u32 pipd_mask, pipd_shift;
        u32 reg;
+       int ret;
 
        if (dsi_id == 0) {
                enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
@@ -98,7 +99,11 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
                return -ENODEV;
        }
 
-       regmap_read(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, &reg);
+       ret = regmap_read(omap4_dsi_mux_syscon,
+                                         OMAP4_DSIPHY_SYSCON_OFFSET,
+                                         &reg);
+       if (ret)
+               return ret;
 
        reg &= ~enable_mask;
        reg &= ~pipd_mask;
index fc5fb776a7101234bd64da673815d10a0b75f0f2..17558be4bf0a528700939684e4f39c002e0215c7 100644 (file)
@@ -50,6 +50,9 @@
 #define OMAP4_NR_BANKS         4
 #define OMAP4_NR_IRQS          128
 
+#define SYS_NIRQ1_EXT_SYS_IRQ_1        7
+#define SYS_NIRQ2_EXT_SYS_IRQ_2        119
+
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_RAW_SPINLOCK(wakeupgen_lock);
@@ -153,6 +156,37 @@ static void wakeupgen_unmask(struct irq_data *d)
        irq_chip_unmask_parent(d);
 }
 
+/*
+ * The sys_nirq pins bypass peripheral modules and are wired directly
+ * to MPUSS wakeupgen. They get automatically inverted for GIC.
+ */
+static int wakeupgen_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       bool inverted = false;
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_LOW:
+               type &= ~IRQ_TYPE_LEVEL_MASK;
+               type |= IRQ_TYPE_LEVEL_HIGH;
+               inverted = true;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               type &= ~IRQ_TYPE_EDGE_BOTH;
+               type |= IRQ_TYPE_EDGE_RISING;
+               inverted = true;
+               break;
+       default:
+               break;
+       }
+
+       if (inverted && d->hwirq != SYS_NIRQ1_EXT_SYS_IRQ_1 &&
+           d->hwirq != SYS_NIRQ2_EXT_SYS_IRQ_2)
+               pr_warn("wakeupgen: irq%li polarity inverted in dts\n",
+                       d->hwirq);
+
+       return irq_chip_set_type_parent(d, type);
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
 
@@ -446,7 +480,7 @@ static struct irq_chip wakeupgen_chip = {
        .irq_mask               = wakeupgen_mask,
        .irq_unmask             = wakeupgen_unmask,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
-       .irq_set_type           = irq_chip_set_type_parent,
+       .irq_set_type           = wakeupgen_irq_set_type,
        .flags                  = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
index 028e50c6383fa4b1a15b36e23f961161ffb76dbe..a32c3b631484a9f2751fe1750a1750284aa419d4 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/suspend.h>
 #include <asm/suspend.h>
 #include "smc.h"
+#include "pm.h"
 
 static int tango_pm_powerdown(unsigned long arg)
 {
@@ -24,10 +25,7 @@ static const struct platform_suspend_ops tango_pm_ops = {
        .valid = suspend_valid_only_mem,
 };
 
-static int __init tango_pm_init(void)
+void __init tango_pm_init(void)
 {
        suspend_set_ops(&tango_pm_ops);
-       return 0;
 }
-
-late_initcall(tango_pm_init);
diff --git a/arch/arm/mach-tango/pm.h b/arch/arm/mach-tango/pm.h
new file mode 100644 (file)
index 0000000..35ea705
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifdef CONFIG_SUSPEND
+void __init tango_pm_init(void);
+#else
+#define tango_pm_init NULL
+#endif
index 677dd7b5efd9007412a5e7047573f02594337ef4..824f90737b044145378137cbecd795168cc09a4f 100644 (file)
@@ -2,6 +2,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 #include "smc.h"
+#include "pm.h"
 
 static void tango_l2c_write(unsigned long val, unsigned int reg)
 {
@@ -15,4 +16,5 @@ DT_MACHINE_START(TANGO_DT, "Sigma Tango DT")
        .dt_compat      = tango_dt_compat,
        .l2c_aux_mask   = ~0,
        .l2c_write_sec  = tango_l2c_write,
+       .init_late      = tango_pm_init,
 MACHINE_END
index ed36dcab80f1e7fb1a89cb41bc05ed71a1afd66f..f519199741837664df922fc60e31c42de8eab145 100644 (file)
@@ -190,8 +190,6 @@ static int pxa_ssp_remove(struct platform_device *pdev)
        if (ssp == NULL)
                return -ENODEV;
 
-       iounmap(ssp->mmio_base);
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, resource_size(res));
 
@@ -201,7 +199,6 @@ static int pxa_ssp_remove(struct platform_device *pdev)
        list_del(&ssp->node);
        mutex_unlock(&ssp_lock);
 
-       kfree(ssp);
        return 0;
 }
 
index cb44aa290e73c5290586f737fe5ffae2f108bae6..e1d44b903dfc3fd7f9d252ba266cc1e64ab20c61 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 
index b0c64f75792c163bd7d0000ea023541079fbd1be..8974b5a1d3b1ecb2da4c22a0f8c780d6794b33a6 100644 (file)
@@ -188,6 +188,7 @@ axp803: pmic@3a3 {
                reg = <0x3a3>;
                interrupt-parent = <&r_intc>;
                interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */
        };
 };
 
index 837a03dee875c45c3c73663b35bbc78bb0f677cb..2abb335145a68a49d102e9e1e668246e6a21957d 100644 (file)
@@ -390,7 +390,7 @@ tcon1_out_hdmi: endpoint@1 {
                };
 
                video-codec@1c0e000 {
-                       compatible = "allwinner,sun50i-h5-video-engine";
+                       compatible = "allwinner,sun50i-a64-video-engine";
                        reg = <0x01c0e000 0x1000>;
                        clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
                                 <&ccu CLK_DRAM_VE>;
index e14e0ce7e89fed32970003859a30841915fcc9fc..016641a41694a4d0500a8db4f6340f19c4252be1 100644 (file)
@@ -187,8 +187,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 8cd50b75171de6f2d64f9732d36e4b280510b48f..ade2ee09ae9624cb1b89fcc5588649b4233dbc7d 100644 (file)
@@ -305,8 +305,7 @@ &sd_emmc_b {
        max-frequency = <200000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddio_ao3v3>;
        vqmmc-supply = <&vddio_tf>;
index 4cf7f6e80c6a00e4d2838f1552b976d96cf0860b..25105ac96d5596cf2a0abf412cccfa2ebfd7d502 100644 (file)
@@ -238,8 +238,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index 2e1cd5e3a246c48ef27c391497bb30e315f1539d..1cc9dc68ef00be8b30bd45754be1e79123c09963 100644 (file)
@@ -258,8 +258,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&tflash_vdd>;
        vqmmc-supply = <&tf_io>;
index ce862266b9aac89f2895406ad1f3c5ed3e8a4813..0be0f2a5d2fe918e2f1a43b798f2ee4899719bb9 100644 (file)
@@ -196,8 +196,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index 93a4acf2c46c50d9fc5110f0cff639308883a536..ad4d50bd9d7756043757139faa0a74dc9a598c52 100644 (file)
@@ -154,8 +154,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vcc_3v3>;
 };
index ec09bb5792b71078b72d95ac9650a73c2d5f29c4..2d2db783c44c149d7c5bf6b4824da82f885e7261 100644 (file)
@@ -211,8 +211,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vcc_3v3>;
index f1c410e2da2b6f1e71e3ccafdab23548172d1e8e..796baea7a0bfb7f89b083d19bf034214cb7e7ca2 100644 (file)
@@ -131,8 +131,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index db293440e4caedea4e86d5ffc842ada6e42c4050..255cede7b4476ee7ae31007bb5f8fb139fcff05d 100644 (file)
@@ -238,8 +238,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vcc_3v3>;
        vqmmc-supply = <&vcc_card>;
index 6739697be1defd72693e1e867c172a85cfe643ba..9cbdb85fb591735f8c890a9c43d5a5b4e3911205 100644 (file)
@@ -183,8 +183,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index a1b31013ab6e3494d810619fadf81752a67b94f4..bc811a2faf4207dd42da6586cff3e013499f3b5e 100644 (file)
@@ -137,8 +137,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 3c3a667a8df8bf838e5f6b1f28783e275e5917d7..3f086ed7de05525c3bcf11866133c085fb3e7bd4 100644 (file)
@@ -356,8 +356,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index f7a1cffab4a886e48dd35515213a0575419481c6..8acfd40090d2e0b558f5e8bc2f6201ff5dad5560 100644 (file)
@@ -147,8 +147,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 7212dc4531e49ea5db17be7ca4e8252123472544..7fa20a8ede171e745610a3ad21de2b3ff07e24e8 100644 (file)
@@ -170,8 +170,7 @@ &sd_emmc_b {
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 64acccc4bfcb4d1c0cf834e42f031b99a4d8316b..f74b13aa5aa59ac962de33147ac5730d7df4a2cf 100644 (file)
@@ -227,34 +227,34 @@ MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B           0xc1
 
        pinctrl_usdhc1_100mhz: usdhc1-100grp {
                fsl,pins = <
-                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x85
-                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc5
-                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc5
-                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x85
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x8d
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xcd
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xcd
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x8d
                        MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
                >;
        };
 
        pinctrl_usdhc1_200mhz: usdhc1-200grp {
                fsl,pins = <
-                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x87
-                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc7
-                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc7
-                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x87
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x9f
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xdf
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xdf
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x9f
                        MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
                >;
        };
index 8e9d6d5ed7b230656a5b621f855e063aea16dd9b..b6d31499fb431d1fc9a6a35484ad819f71dd134d 100644 (file)
@@ -360,6 +360,8 @@ usdhc1: mmc@30b40000 {
                                         <&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MQ_CLK_USDHC1_ROOT>;
                                clock-names = "ipg", "ahb", "per";
+                               assigned-clocks = <&clk IMX8MQ_CLK_USDHC1>;
+                               assigned-clock-rates = <400000000>;
                                fsl,tuning-start-tap = <20>;
                                fsl,tuning-step = <2>;
                                bus-width = <4>;
index 99b7495455a621742b49523c304b07f8cbf27ca2..838e32cc14c9273db473aa5bcce1f54aeaab676c 100644 (file)
@@ -404,7 +404,7 @@ tcsr: syscon@7a0000 {
                };
 
                intc: interrupt-controller@9bc0000 {
-                       compatible = "arm,gic-v3";
+                       compatible = "qcom,msm8996-gic-v3", "arm,gic-v3";
                        #interrupt-cells = <3>;
                        interrupt-controller;
                        #redistributor-regions = <1>;
index 20745a8528c50c44f35e68d5207121bc9e740c01..719ed9d9067d767e820c778968b9a15b60bce5ab 100644 (file)
@@ -1011,6 +1011,9 @@ scif2: serial@e6e88000 {
                                 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index afedbf5728ec54b5ef9270b2cc78d424f4e08bb6..0648d12778edc09ffe038650b9414cf012b8fe40 100644 (file)
@@ -1262,6 +1262,9 @@ scif2: serial@e6e88000 {
                                 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index 6dc9b1fef83037749f52ba9449691256caff35ba..4b3730f640efa78b6cec3db68973585d6b14ca8e 100644 (file)
@@ -1068,6 +1068,9 @@ scif2: serial@e6e88000 {
                                 <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index bd937d68ca3bdb99e378c069d8a9b388ec46a516..040b36ef0dd2b7e7b3cd1cb280dcc94606b99e0f 100644 (file)
@@ -40,6 +40,7 @@ vcc_host_5v: vcc-host-5v-regulator {
                pinctrl-0 = <&usb30_host_drv>;
                regulator-name = "vcc_host_5v";
                regulator-always-on;
+               regulator-boot-on;
                vin-supply = <&vcc_sys>;
        };
 
@@ -51,6 +52,7 @@ vcc_host1_5v: vcc_otg_5v: vcc-host1-5v-regulator {
                pinctrl-0 = <&usb20_host_drv>;
                regulator-name = "vcc_host1_5v";
                regulator-always-on;
+               regulator-boot-on;
                vin-supply = <&vcc_sys>;
        };
 
index 1ee0dc0d9f10ff9641f02bdad4aae75fc225d078..d1cf404b87084a00b18d55b26d50681b68ce48d5 100644 (file)
@@ -22,7 +22,7 @@ edp_panel: edp-panel {
                backlight = <&backlight>;
                power-supply = <&pp3300_disp>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 81e73103fa788605471679fd1b0868f50822c4f8..15e254a7739120592c1905253ab8ffe4f9c40cc1 100644 (file)
@@ -43,7 +43,7 @@ edp_panel: edp-panel {
                backlight = <&backlight>;
                power-supply = <&pp3300_disp>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 0b8f1edbd746b5ce0359e60f8279ca11b6633322..b48a63c3efc3d4bc2563e05a53c4d87c0d740232 100644 (file)
@@ -91,7 +91,7 @@ edp_panel: edp-panel {
                pinctrl-0 = <&lcd_panel_reset>;
                power-supply = <&vcc3v3_s0>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index eb43e09c1980f6f7e3ab4b4a1d99b411ee635733..926434f413fa2d965e3847d46e8c651505cfb30d 100644 (file)
@@ -60,8 +60,6 @@
 
 #ifdef CONFIG_KASAN_SW_TAGS
 #define ARCH_SLAB_MINALIGN     (1ULL << KASAN_SHADOW_SCALE_SHIFT)
-#else
-#define ARCH_SLAB_MINALIGN     __alignof__(unsigned long long)
 #endif
 
 #ifndef __ASSEMBLY__
index 3dd3d664c5c5dfc3ee759af069d248f09eba4e50..4658c937e17304fcf86212294d3cfc9badb40e37 100644 (file)
@@ -20,9 +20,6 @@ struct dev_archdata {
 #ifdef CONFIG_IOMMU_API
        void *iommu;                    /* private IOMMU data */
 #endif
-#ifdef CONFIG_XEN
-       const struct dma_map_ops *dev_dma_ops;
-#endif
 };
 
 struct pdev_archdata {
index 7732d0ba4e603210fedb645011488ce5ef31a99e..da3fc7324d6826b7b600c4167c77b1f4bd494cf1 100644 (file)
@@ -48,6 +48,7 @@
 #define KVM_REQ_SLEEP \
        KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
+#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -208,6 +209,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+struct vcpu_reset_state {
+       unsigned long   pc;
+       unsigned long   r0;
+       bool            be;
+       bool            reset;
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -297,6 +305,9 @@ struct kvm_vcpu_arch {
        /* Virtual SError ESR to restore when HCR_EL2.VSE is set */
        u64 vsesr_el2;
 
+       /* Additional reset state */
+       struct vcpu_reset_state reset_state;
+
        /* True when deferrable sysregs are loaded on the physical CPU,
         * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
        bool sysregs_loaded_on_cpu;
index e1ec947e7c0cabc08837ef37318bf66db5c05d76..0c656850eeeaa9df40f0e7b3a643228ea33ec9d7 100644 (file)
@@ -332,6 +332,17 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define virt_addr_valid(kaddr)         \
        (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr))
 
+/*
+ * Given that the GIC architecture permits ITS implementations that can only be
+ * configured with a LPI table address once, GICv3 systems with many CPUs may
+ * end up reserving a lot of different regions after a kexec for their LPI
+ * tables (one per CPU), as we are forced to reuse the same memory after kexec
+ * (and thus reserve it persistently with EFI beforehand)
+ */
+#if defined(CONFIG_EFI) && defined(CONFIG_ARM_GIC_V3_ITS)
+# define INIT_MEMBLOCK_RESERVED_REGIONS        (INIT_MEMBLOCK_REGIONS + NR_CPUS + 1)
+#endif
+
 #include <asm-generic/memory_model.h>
 
 #endif
index ac352accb3d98dd00b32f266ae71b3b9b4cb494b..3e8063f4f9d341d127e00fb5e4b86e1322817075 100644 (file)
@@ -60,8 +60,11 @@ static inline bool arm64_kernel_use_ng_mappings(void)
         * later determine that kpti is required, then
         * kpti_install_ng_mappings() will make them non-global.
         */
+       if (arm64_kernel_unmapped_at_el0())
+               return true;
+
        if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
-               return arm64_kernel_unmapped_at_el0();
+               return false;
 
        /*
         * KASLR is enabled so we're going to be enabling kpti on non-broken
index b3ef061d8b7417b90279c94a8706995fc116bd21..d88e56b90b93a55fa972fbf22b518c17bdfba1cb 100644 (file)
@@ -1 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_XEN_PAGE_COHERENT_H
+#define _ASM_ARM64_XEN_PAGE_COHERENT_H
+
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <xen/arm/page-coherent.h>
+
+static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
+               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
+{
+       return dma_direct_alloc(hwdev, size, dma_handle, flags, attrs);
+}
+
+static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
+               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
+{
+       dma_direct_free(hwdev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+
+       if (pfn_valid(pfn))
+               dma_direct_sync_single_for_cpu(hwdev, handle, size, dir);
+       else
+               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn))
+               dma_direct_sync_single_for_device(hwdev, handle, size, dir);
+       else
+               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
+            dma_addr_t dev_addr, unsigned long offset, size_t size,
+            enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
+       if (local)
+               dma_direct_map_page(hwdev, page, offset, size, dir, attrs);
+       else
+               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
+}
+
+static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+        * multiple Xen page, it's not possible to have a mix of local and
+        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
+        * foreign mfn will always return false. If the page is local we can
+        * safely call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (pfn_valid(pfn))
+               dma_direct_unmap_page(hwdev, handle, size, dir, attrs);
+       else
+               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
+}
+
+#endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 29cdc99688f335075dcfa71ed0b387d9ca548538..9859e1178e6bed174835ccb90b355f9f43c0a5f8 100644 (file)
@@ -299,8 +299,10 @@ int swsusp_arch_suspend(void)
                dcache_clean_range(__idmap_text_start, __idmap_text_end);
 
                /* Clean kvm setup code to PoC? */
-               if (el2_reset_needed())
+               if (el2_reset_needed()) {
                        dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end);
+                       dcache_clean_range(__hyp_text_start, __hyp_text_end);
+               }
 
                /* make the crash dump kernel image protected again */
                crash_post_resume();
index e1261fbaa374e02471214664df742cb26c4da1d7..17f325ba831e8299131415390a2b40494412709d 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/virt.h>
 
        .text
+       .pushsection    .hyp.text, "ax"
+
        .align 11
 
 ENTRY(__hyp_stub_vectors)
index f0e6ab8abe9c9657e3103dbc84cf08c0a4242a82..b09b6f75f759183b0aaf3671e631af5942bd6afd 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
+#include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
@@ -43,7 +44,7 @@ static __init u64 get_kaslr_seed(void *fdt)
        return ret;
 }
 
-static __init const u8 *get_cmdline(void *fdt)
+static __init const u8 *kaslr_get_cmdline(void *fdt)
 {
        static __initconst const u8 default_cmdline[] = CONFIG_CMDLINE;
 
@@ -87,6 +88,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * we end up running with module randomization disabled.
         */
        module_alloc_base = (u64)_etext - MODULES_VSIZE;
+       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
 
        /*
         * Try to map the FDT early. If this fails, we simply bail,
@@ -109,7 +111,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * Check if 'nokaslr' appears on the command line, and
         * return 0 if that is the case.
         */
-       cmdline = get_cmdline(fdt);
+       cmdline = kaslr_get_cmdline(fdt);
        str = strstr(cmdline, "nokaslr");
        if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
                return 0;
@@ -169,5 +171,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
        module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
        module_alloc_base &= PAGE_MASK;
 
+       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
+       __flush_dcache_area(&memstart_offset_seed, sizeof(memstart_offset_seed));
+
        return offset;
 }
index f2c211a6229baa3928ba4a652e9c4a947fe27dae..58871333737a4e5458d723dcb0fd6e5e609548da 100644 (file)
@@ -120,10 +120,12 @@ static int create_dtb(struct kimage *image,
 {
        void *buf;
        size_t buf_size;
+       size_t cmdline_len;
        int ret;
 
+       cmdline_len = cmdline ? strlen(cmdline) : 0;
        buf_size = fdt_totalsize(initial_boot_params)
-                       + strlen(cmdline) + DTB_EXTRA_SPACE;
+                       + cmdline_len + DTB_EXTRA_SPACE;
 
        for (;;) {
                buf = vmalloc(buf_size);
index 2a5b338b254240c8af9d552632214df144a1215a..f17afb99890c7241f1c035140d5d24ab10a7c79e 100644 (file)
@@ -478,13 +478,13 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
            addr < (unsigned long)__entry_text_end) ||
            (addr >= (unsigned long)__idmap_text_start &&
            addr < (unsigned long)__idmap_text_end) ||
+           (addr >= (unsigned long)__hyp_text_start &&
+           addr < (unsigned long)__hyp_text_end) ||
            !!search_exception_tables(addr))
                return true;
 
        if (!is_kernel_in_hyp_mode()) {
-               if ((addr >= (unsigned long)__hyp_text_start &&
-                   addr < (unsigned long)__hyp_text_end) ||
-                   (addr >= (unsigned long)__hyp_idmap_text_start &&
+               if ((addr >= (unsigned long)__hyp_idmap_text_start &&
                    addr < (unsigned long)__hyp_idmap_text_end))
                        return true;
        }
index 4b0e1231625cd6bd54fce6a4cd5ec15b98b73953..d09ec76f08cfcee42e9fcc4a12e8a1760e8ac7bb 100644 (file)
@@ -313,7 +313,6 @@ void __init setup_arch(char **cmdline_p)
        arm64_memblock_init();
 
        paging_init();
-       efi_apply_persistent_mem_reservations();
 
        acpi_table_upgrade();
 
index b0b1478094b4c56907dcc1040aac9985f52187e4..421ebf6f708630416a41a975f9b6c2a7d6eff1fe 100644 (file)
@@ -23,6 +23,7 @@
 #include <kvm/arm_psci.h>
 
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_host.h>
@@ -107,6 +108,7 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
 
        write_sysreg(kvm_get_hyp_vector(), vbar_el1);
 }
+NOKPROBE_SYMBOL(activate_traps_vhe);
 
 static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
 {
@@ -154,6 +156,7 @@ static void deactivate_traps_vhe(void)
        write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1);
        write_sysreg(vectors, vbar_el1);
 }
+NOKPROBE_SYMBOL(deactivate_traps_vhe);
 
 static void __hyp_text __deactivate_traps_nvhe(void)
 {
@@ -513,6 +516,7 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
        return exit_code;
 }
+NOKPROBE_SYMBOL(kvm_vcpu_run_vhe);
 
 /* Switch to the guest for legacy non-VHE systems */
 int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
@@ -620,6 +624,7 @@ static void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
              read_sysreg_el2(esr),   read_sysreg_el2(far),
              read_sysreg(hpfar_el2), par, vcpu);
 }
+NOKPROBE_SYMBOL(__hyp_call_panic_vhe);
 
 void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt)
 {
index 68d6f7c3b237dc1713fa36bc55d4a27fef2e5949..b426e2cf973cfe01a90ae40545abb2ee46c66bca 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/compiler.h>
 #include <linux/kvm_host.h>
 
+#include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
@@ -98,12 +99,14 @@ void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_save_common_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_save_host_state_vhe);
 
 void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_save_common_state(ctxt);
        __sysreg_save_el2_return_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
 
 static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
 {
@@ -188,12 +191,14 @@ void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_restore_common_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe);
 
 void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_restore_common_state(ctxt);
        __sysreg_restore_el2_return_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
 
 void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
 {
index b72a3dd562044584355bc94fce99efb95e694484..f16a5f8ff2b41fa4284da58d1d2caf7af7b46e7b 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 
 /* Maximum phys_shift supported for any VM on this host */
@@ -105,16 +106,33 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
  * This function finds the right table above and sets the registers on
  * the virtual CPU struct to their architecturally defined reset
  * values.
+ *
+ * Note: This function can be called from two paths: The KVM_ARM_VCPU_INIT
+ * ioctl or as part of handling a request issued by another VCPU in the PSCI
+ * handling code.  In the first case, the VCPU will not be loaded, and in the
+ * second case the VCPU will be loaded.  Because this function operates purely
+ * on the memory-backed valus of system registers, we want to do a full put if
+ * we were loaded (handling a request) and load the values back at the end of
+ * the function.  Otherwise we leave the state alone.  In both cases, we
+ * disable preemption around the vcpu reset as we would otherwise race with
+ * preempt notifiers which also call put/load.
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
        const struct kvm_regs *cpu_reset;
+       int ret = -EINVAL;
+       bool loaded;
+
+       preempt_disable();
+       loaded = (vcpu->cpu != -1);
+       if (loaded)
+               kvm_arch_vcpu_put(vcpu);
 
        switch (vcpu->arch.target) {
        default:
                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
                        if (!cpu_has_32bit_el1())
-                               return -EINVAL;
+                               goto out;
                        cpu_reset = &default_regs_reset32;
                } else {
                        cpu_reset = &default_regs_reset;
@@ -129,6 +147,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset system registers */
        kvm_reset_sys_regs(vcpu);
 
+       /*
+        * Additional reset state handling that PSCI may have imposed on us.
+        * Must be done after all the sys_reg reset.
+        */
+       if (vcpu->arch.reset_state.reset) {
+               unsigned long target_pc = vcpu->arch.reset_state.pc;
+
+               /* Gracefully handle Thumb2 entry point */
+               if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
+                       target_pc &= ~1UL;
+                       vcpu_set_thumb(vcpu);
+               }
+
+               /* Propagate caller endianness */
+               if (vcpu->arch.reset_state.be)
+                       kvm_vcpu_set_be(vcpu);
+
+               *vcpu_pc(vcpu) = target_pc;
+               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
+
+               vcpu->arch.reset_state.reset = false;
+       }
+
        /* Reset PMU */
        kvm_pmu_vcpu_reset(vcpu);
 
@@ -137,7 +178,12 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
                vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG;
 
        /* Reset timer */
-       return kvm_timer_vcpu_reset(vcpu);
+       ret = kvm_timer_vcpu_reset(vcpu);
+out:
+       if (loaded)
+               kvm_arch_vcpu_load(vcpu, smp_processor_id());
+       preempt_enable();
+       return ret;
 }
 
 void kvm_set_ipa_limit(void)
index e3e37228ae4e86f54e88a9fcbd8c8005636c93f5..c936aa40c3f4a0393d03ee66e4b8316c35fa0566 100644 (file)
@@ -314,12 +314,29 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                return read_zero(vcpu, p);
 }
 
-static bool trap_undef(struct kvm_vcpu *vcpu,
-                      struct sys_reg_params *p,
-                      const struct sys_reg_desc *r)
+/*
+ * ARMv8.1 mandates at least a trivial LORegion implementation, where all the
+ * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0
+ * system, these registers should UNDEF. LORID_EL1 being a RO register, we
+ * treat it separately.
+ */
+static bool trap_loregion(struct kvm_vcpu *vcpu,
+                         struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
 {
-       kvm_inject_undefined(vcpu);
-       return false;
+       u64 val = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
+       u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1,
+                        (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
+
+       if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) {
+               kvm_inject_undefined(vcpu);
+               return false;
+       }
+
+       if (p->is_write && sr == SYS_LORID_EL1)
+               return write_to_read_only(vcpu, p, r);
+
+       return trap_raz_wi(vcpu, p, r);
 }
 
 static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
@@ -1048,11 +1065,6 @@ static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)
                if (val & ptrauth_mask)
                        kvm_debug("ptrauth unsupported for guests, suppressing\n");
                val &= ~ptrauth_mask;
-       } else if (id == SYS_ID_AA64MMFR1_EL1) {
-               if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
-                       kvm_debug("LORegions unsupported for guests, suppressing\n");
-
-               val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT);
        }
 
        return val;
@@ -1338,11 +1350,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
        { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
 
-       { SYS_DESC(SYS_LORSA_EL1), trap_undef },
-       { SYS_DESC(SYS_LOREA_EL1), trap_undef },
-       { SYS_DESC(SYS_LORN_EL1), trap_undef },
-       { SYS_DESC(SYS_LORC_EL1), trap_undef },
-       { SYS_DESC(SYS_LORID_EL1), trap_undef },
+       { SYS_DESC(SYS_LORSA_EL1), trap_loregion },
+       { SYS_DESC(SYS_LOREA_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORN_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORC_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORID_EL1), trap_loregion },
 
        { SYS_DESC(SYS_VBAR_EL1), NULL, reset_val, VBAR_EL1, 0 },
        { SYS_DESC(SYS_DISR_EL1), NULL, reset_val, DISR_EL1, 0 },
@@ -2596,7 +2608,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
        table = get_target_table(vcpu->arch.target, true, &num);
        reset_sys_reg_descs(vcpu, table, num);
 
-       for (num = 1; num < NR_SYS_REGS; num++)
-               if (__vcpu_sys_reg(vcpu, num) == 0x4242424242424242)
-                       panic("Didn't reset __vcpu_sys_reg(%zi)", num);
+       for (num = 1; num < NR_SYS_REGS; num++) {
+               if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
+                        "Didn't reset __vcpu_sys_reg(%zi)\n", num))
+                       break;
+       }
 }
index fb0908456a1f99fcb0479d50c33c48c15d2a90a6..78c0a72f822c0a2b0e05b1394e9ca8b982ceb62b 100644 (file)
@@ -466,9 +466,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
        __iommu_setup_dma_ops(dev, dma_base, size, iommu);
 
 #ifdef CONFIG_XEN
-       if (xen_initial_domain()) {
-               dev->archdata.dev_dma_ops = dev->dma_ops;
+       if (xen_initial_domain())
                dev->dma_ops = xen_dma_ops;
-       }
 #endif
 }
index fcb1f2a6d7c66d779a752a4d926123e7f0822b34..99bb8facb5cbc34e22e2df37fc6267a0e3d2f3f5 100644 (file)
@@ -286,74 +286,73 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 
 }
 
-static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start)
+static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
+                    unsigned long end)
 {
-       pte_t *ptep = pte_offset_kernel(pmdp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long addr = start;
+       pte_t *ptep = pte_offset_kernel(pmdp, start);
 
-       for (i = 0; i < PTRS_PER_PTE; i++, ptep++) {
-               addr = start + i * PAGE_SIZE;
+       do {
                note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
-       }
+       } while (ptep++, addr += PAGE_SIZE, addr != end);
 }
 
-static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start)
+static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
+                    unsigned long end)
 {
-       pmd_t *pmdp = pmd_offset(pudp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long next, addr = start;
+       pmd_t *pmdp = pmd_offset(pudp, start);
 
-       for (i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
+       do {
                pmd_t pmd = READ_ONCE(*pmdp);
+               next = pmd_addr_end(addr, end);
 
-               addr = start + i * PMD_SIZE;
                if (pmd_none(pmd) || pmd_sect(pmd)) {
                        note_page(st, addr, 3, pmd_val(pmd));
                } else {
                        BUG_ON(pmd_bad(pmd));
-                       walk_pte(st, pmdp, addr);
+                       walk_pte(st, pmdp, addr, next);
                }
-       }
+       } while (pmdp++, addr = next, addr != end);
 }
 
-static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start)
+static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
+                    unsigned long end)
 {
-       pud_t *pudp = pud_offset(pgdp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long next, addr = start;
+       pud_t *pudp = pud_offset(pgdp, start);
 
-       for (i = 0; i < PTRS_PER_PUD; i++, pudp++) {
+       do {
                pud_t pud = READ_ONCE(*pudp);
+               next = pud_addr_end(addr, end);
 
-               addr = start + i * PUD_SIZE;
                if (pud_none(pud) || pud_sect(pud)) {
                        note_page(st, addr, 2, pud_val(pud));
                } else {
                        BUG_ON(pud_bad(pud));
-                       walk_pmd(st, pudp, addr);
+                       walk_pmd(st, pudp, addr, next);
                }
-       }
+       } while (pudp++, addr = next, addr != end);
 }
 
 static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
                     unsigned long start)
 {
-       pgd_t *pgdp = pgd_offset(mm, 0UL);
-       unsigned i;
-       unsigned long addr;
+       unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
+       unsigned long next, addr = start;
+       pgd_t *pgdp = pgd_offset(mm, start);
 
-       for (i = 0; i < PTRS_PER_PGD; i++, pgdp++) {
+       do {
                pgd_t pgd = READ_ONCE(*pgdp);
+               next = pgd_addr_end(addr, end);
 
-               addr = start + i * PGDIR_SIZE;
                if (pgd_none(pgd)) {
                        note_page(st, addr, 1, pgd_val(pgd));
                } else {
                        BUG_ON(pgd_bad(pgd));
-                       walk_pud(st, pgdp, addr);
+                       walk_pud(st, pgdp, addr, next);
                }
-       }
+       } while (pgdp++, addr = next, addr != end);
 }
 
 void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
index 30695a8681074402057f1a357870760d321b950b..5c9073bace83a656e0c2b6cb64d3a5bc62b1462a 100644 (file)
@@ -33,7 +33,11 @@ void sync_icache_aliases(void *kaddr, unsigned long len)
                __clean_dcache_area_pou(kaddr, len);
                __flush_icache_all();
        } else {
-               flush_icache_range(addr, addr + len);
+               /*
+                * Don't issue kick_all_cpus_sync() after I-cache invalidation
+                * for user mappings.
+                */
+               __flush_icache_range(addr, addr + len);
        }
 }
 
index 33a2c94fed0dec731da4ee2a182b2acba6dd8d37..63b4a170518220397d22ec86cf9911f470139b97 100644 (file)
@@ -30,6 +30,7 @@ generic-y += pgalloc.h
 generic-y += preempt.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += tlbflush.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 6c6f6301012ef6c1c86f14a5edd26cb01c409455..0febf1a07c30a7df64bd64806151f91de123da45 100644 (file)
@@ -1,5 +1,4 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-generic-y += shmparam.h
 generic-y += ucontext.h
index edfcbb25fd9f6998ae09c53b93b229018de03b89..dcea277c09aea8787325abbe50e18e3c467fc993 100644 (file)
@@ -45,8 +45,8 @@
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset_t(address))
 #define pmd_page(pmd)  (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pte_clear(mm, addr, ptep)      set_pte((ptep), \
-                       (((unsigned int)addr&0x80000000)?__pte(1):__pte(0)))
-#define pte_none(pte)  (!(pte_val(pte)&0xfffffffe))
+       (((unsigned int) addr & PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0)))
+#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
 #define pte_pfn(x)     ((unsigned long)((x).pte_low >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \
@@ -241,6 +241,11 @@ static inline pte_t pte_mkyoung(pte_t pte)
 
 #define pgd_index(address)     ((address) >> PGDIR_SHIFT)
 
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
+
 /*
  * Macro to make mark a page protection value as "uncacheable".  Note
  * that "protection" is really a misnomer here as the protection value
index 8f454810514f21be1356bd9d763f28e68f8d70b5..21e0bd5293dde27b0b21a9168b2dc62a1e7085d1 100644 (file)
@@ -49,7 +49,7 @@ struct thread_struct {
 };
 
 #define INIT_THREAD  { \
-       .ksp = (unsigned long) init_thread_union.stack + THREAD_SIZE, \
+       .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
        .sr = DEFAULT_PSR_VALUE, \
 }
 
@@ -95,7 +95,7 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_ESP(tsk)          (task_pt_regs(tsk)->usp)
 
 #define task_pt_regs(p) \
-       ((struct pt_regs *)(THREAD_SIZE + p->stack) - 1)
+       ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1)
 
 #define cpu_relax() barrier()
 
index 659253e9989cb062e84f38c04ce9d4219ebf1d2e..d67f9777cfd9d7a10ca0b439937fd9784f88f8e6 100644 (file)
@@ -38,7 +38,11 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                if (task)
                        stack = (unsigned long *)thread_saved_fp(task);
                else
+#ifdef CONFIG_STACKTRACE
+                       asm volatile("mov %0, r8\n":"=r"(stack)::"memory");
+#else
                        stack = (unsigned long *)&stack;
+#endif
        }
 
        show_trace(stack);
index 57f1afe19a52cb7896021a47691fc17c37d0b4bb..f2f12fff36f70c90d260c8052e6ba5feb69b306c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/sched.h>
+#include <linux/sched/task_stack.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/uaccess.h>
@@ -159,7 +160,7 @@ static int fpr_set(struct task_struct *target,
 static const struct user_regset csky_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
-               .n = ELF_NGREG,
+               .n = sizeof(struct pt_regs) / sizeof(u32),
                .size = sizeof(u32),
                .align = sizeof(u32),
                .get = &gpr_get,
index ddc4dd79f2826f837b3557a239043f7b0aa1c162..b07a534b30627fa93d39edfed3090e57b29bb04e 100644 (file)
@@ -160,7 +160,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        unsigned long mask = 1 << cpu;
 
-       secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE - 8;
+       secondary_stack =
+               (unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
        secondary_hint = mfcr("cr31");
        secondary_ccr  = mfcr("cr18");
 
index cb7c03e5cd218a4236d1cb686a2cc36f0e4f91ff..8473b6bdf51205b35b761dac33f6456d1216072f 100644 (file)
@@ -46,3 +46,17 @@ void iounmap(void __iomem *addr)
        vunmap((void *)((unsigned long)addr & PAGE_MASK));
 }
 EXPORT_SYMBOL(iounmap);
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                             unsigned long size, pgprot_t vma_prot)
+{
+       if (!pfn_valid(pfn)) {
+               vma_prot.pgprot |= _PAGE_SO;
+               return pgprot_noncached(vma_prot);
+       } else if (file->f_flags & O_SYNC) {
+               return pgprot_noncached(vma_prot);
+       }
+
+       return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
index 4003ddc616e1ecaf089cc04d498ed2891a6acb8a..f801f3708a89e17cd5e933b34d4dcbefd6c1c995 100644 (file)
@@ -37,8 +37,6 @@ libs-y        += arch/$(ARCH)/lib/
 
 boot := arch/h8300/boot
 
-archmrproper:
-
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index cd400d353d182b22a5b32300b4d8e3fc9f628bc7..961c1dc064e167748428ed6b6e95acf97ad66d8f 100644 (file)
@@ -40,6 +40,7 @@ generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += spinlock.h
 generic-y += timex.h
index 6c6f6301012ef6c1c86f14a5edd26cb01c409455..0febf1a07c30a7df64bd64806151f91de123da45 100644 (file)
@@ -1,5 +1,4 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-generic-y += shmparam.h
 generic-y += ucontext.h
index 47c4da3d64a4e1de7f7e2083636336e0813e2c3d..b25fd42aa0f47372162decdff321f3cca2e1a4d8 100644 (file)
@@ -30,6 +30,7 @@ generic-y += rwsem.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 61d955c1747a774eab639928eaae89a2ef7cf385..c1b06dcf6cf8e816552895882094f09e44afc77b 100644 (file)
@@ -1,4 +1,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += shmparam.h
 generic-y += ucontext.h
index 320d86f192ee54b53ea5f7be7c7e1a560b6cc44b..171290f9f1de48a5d0a8eb627c9468d1fafa1b0a 100644 (file)
@@ -16,8 +16,6 @@ KBUILD_DEFCONFIG := generic_defconfig
 NM := $(CROSS_COMPILE)nm -B
 READELF := $(CROSS_COMPILE)readelf
 
-export AWK
-
 CHECKFLAGS     += -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__
 
 OBJCOPYFLAGS   := --strip-all
index 38049357d6d3279ff7b95ff801a01e2cb88d9a4b..40712e49381b216dd0ae4af9438e7023bcbeebe3 100644 (file)
@@ -155,18 +155,22 @@ static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
 static int __init nfhd_init(void)
 {
        u32 blocks, bsize;
+       int ret;
        int i;
 
        nfhd_id = nf_get_id("XHDI");
        if (!nfhd_id)
                return -ENODEV;
 
-       major_num = register_blkdev(major_num, "nfhd");
-       if (major_num <= 0) {
+       ret = register_blkdev(major_num, "nfhd");
+       if (ret < 0) {
                pr_warn("nfhd: unable to get major number\n");
-               return major_num;
+               return ret;
        }
 
+       if (!major_num)
+               major_num = ret;
+
        for (i = NFHD_DEV_OFFSET; i < 24; i++) {
                if (nfhd_get_capacity(i, 0, &blocks, &bsize))
                        continue;
index 9f1dd26903e33bd2aa4b80eba10d34d4df48099a..95f8f631c4df08aebc71b25d878fc29e0f89a1ba 100644 (file)
@@ -20,6 +20,7 @@ generic-y += mm-arch-hooks.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
+generic-y += shmparam.h
 generic-y += spinlock.h
 generic-y += topology.h
 generic-y += trace_clock.h
index b8b3525271fafe272647f0ca12a8e089f0df7b4d..960bf1e4be530b383da54074990d7a05dd9f34e2 100644 (file)
@@ -2,4 +2,3 @@ include include/uapi/asm-generic/Kbuild.asm
 
 generated-y += unistd_32.h
 generic-y += kvm_para.h
-generic-y += shmparam.h
index 9c7d1d25bf3db6e82726d087e72dc3f580fbba01..791cc8d54d0a9eff79b5264a74b507fc3233699c 100644 (file)
@@ -26,6 +26,7 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += syscalls.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 28823e3db8253f631873b98be067fb97602a9682..97823ec46e97c02d45cd30168b930e3a9904d733 100644 (file)
@@ -2,5 +2,4 @@ include include/uapi/asm-generic/Kbuild.asm
 
 generated-y += unistd_32.h
 generic-y += kvm_para.h
-generic-y += shmparam.h
 generic-y += ucontext.h
index 787290781b8c6d52b7b937b222a1d61eec92f97c..a84c24d894aa4341dca03a1320927100ceb4cb96 100644 (file)
@@ -1403,6 +1403,21 @@ config LOONGSON3_ENHANCEMENT
          please say 'N' here. If you want a high-performance kernel to run on
          new Loongson 3 machines only, please say 'Y' here.
 
+config CPU_LOONGSON3_WORKAROUNDS
+       bool "Old Loongson 3 LLSC Workarounds"
+       default y if SMP
+       depends on CPU_LOONGSON3
+       help
+         Loongson 3 processors have the llsc issues which require workarounds.
+         Without workarounds the system may hang unexpectedly.
+
+         Newer Loongson 3 will fix these issues and no workarounds are needed.
+         The workarounds have no significant side effect on them but may
+         decrease the performance of the system so this option should be
+         disabled unless the kernel is intended to be run on old systems.
+
+         If unsure, please say Y.
+
 config CPU_LOONGSON2E
        bool "Loongson 2E"
        depends on SYS_HAS_CPU_LOONGSON2E
@@ -3155,6 +3170,7 @@ config MIPS32_O32
 config MIPS32_N32
        bool "Kernel support for n32 binaries"
        depends on 64BIT
+       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        select COMPAT
        select MIPS32_COMPAT
        select SYSVIPC_COMPAT if SYSVIPC
index 6054d49e608eec038e1bbd49599bc783270aa09a..fe3773539effe61e638ec7e277783ac24b022563 100644 (file)
@@ -173,6 +173,31 @@ void __init plat_mem_setup(void)
        pm_power_off = bcm47xx_machine_halt;
 }
 
+#ifdef CONFIG_BCM47XX_BCMA
+static struct device * __init bcm47xx_setup_device(void)
+{
+       struct device *dev;
+       int err;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+
+       err = dev_set_name(dev, "bcm47xx_soc");
+       if (err) {
+               pr_err("Failed to set SoC device name: %d\n", err);
+               kfree(dev);
+               return NULL;
+       }
+
+       err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (err)
+               pr_err("Failed to set SoC DMA mask: %d\n", err);
+
+       return dev;
+}
+#endif
+
 /*
  * This finishes bus initialization doing things that were not possible without
  * kmalloc. Make sure to call it late enough (after mm_init).
@@ -183,6 +208,10 @@ void __init bcm47xx_bus_setup(void)
        if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
                int err;
 
+               bcm47xx_bus.bcma.dev = bcm47xx_setup_device();
+               if (!bcm47xx_bus.bcma.dev)
+                       panic("Failed to setup SoC device\n");
+
                err = bcma_host_soc_init(&bcm47xx_bus.bcma);
                if (err)
                        panic("Failed to initialize BCMA bus (err %d)", err);
@@ -235,6 +264,8 @@ static int __init bcm47xx_register_bus_complete(void)
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
        case BCM47XX_BUS_TYPE_BCMA:
+               if (device_register(bcm47xx_bus.bcma.dev))
+                       pr_err("Failed to register SoC device\n");
                bcma_bus_register(&bcm47xx_bus.bcma.bus);
                break;
 #endif
index 50cff3cbcc6de6386d11b07cdbe5a10b60ef976f..4f7b1fa31cf53f04517e51a72a9e522487454550 100644 (file)
@@ -76,7 +76,7 @@ &uart3 {
        status = "okay";
 
        pinctrl-names = "default";
-       pinctrl-0 = <&pins_uart2>;
+       pinctrl-0 = <&pins_uart3>;
 };
 
 &uart4 {
@@ -196,9 +196,9 @@ pins_uart1: uart1 {
                bias-disable;
        };
 
-       pins_uart2: uart2 {
-               function = "uart2";
-               groups = "uart2-data", "uart2-hwflow";
+       pins_uart3: uart3 {
+               function = "uart3";
+               groups = "uart3-data", "uart3-hwflow";
                bias-disable;
        };
 
index 6fb16fd240353aa733f2fec5178db98541184bcc..2beb78a62b7dc7e2f6f99c7afc82c788cc8b626e 100644 (file)
@@ -161,7 +161,7 @@ dmac: dma-controller@13020000 {
                #dma-cells = <2>;
 
                interrupt-parent = <&intc>;
-               interrupts = <29>;
+               interrupts = <20>;
 
                clocks = <&cgu JZ4740_CLK_DMA>;
 
index 2152b7ba65fbcdaefc97c8f9fd13cd50568ca15b..cc8dbea0911fcf5a61761a38997ebe1e9f690074 100644 (file)
@@ -90,11 +90,11 @@ axi_uart16550: serial@10400000 {
                interrupts = <0>;
        };
 
-       axi_i2c: i2c@10A00000 {
+       axi_i2c: i2c@10a00000 {
            compatible = "xlnx,xps-iic-2.00.a";
            interrupt-parent = <&axi_intc>;
            interrupts = <4>;
-           reg = < 0x10A00000 0x10000 >;
+           reg = < 0x10a00000 0x10000 >;
            clocks = <&ext>;
            xlnx,clk-freq = <0x5f5e100>;
            xlnx,family = "Artix7";
@@ -106,9 +106,9 @@ axi_i2c: i2c@10A00000 {
            #address-cells = <1>;
            #size-cells = <0>;
 
-           ad7420@4B {
+           ad7420@4b {
                compatible = "adi,adt7420";
-               reg = <0x4B>;
+               reg = <0x4b>;
            };
        } ;
 };
index 2c79ab52977a4ed2d3cd7618988209c50bedd208..8bf43c5a7bc71588d648c58b1d68bb3b82677832 100644 (file)
@@ -98,7 +98,7 @@ static void octeon_kexec_smp_down(void *ignored)
        "       sync                                            \n"
        "       synci   ($0)                                    \n");
 
-       relocated_kexec_smp_wait(NULL);
+       kexec_reboot();
 }
 #endif
 
index 4e4ec779f1820117956845e2cc95b9b12410db44..6f981af67826d4f1b750559dd9af512f66102927 100644 (file)
@@ -66,6 +66,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=1
 CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AR933X=y
 CONFIG_SERIAL_AR933X_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
index 43fcd35e295759d7368268d48bfa6534b074f117..94096299fc569280a6b013a011d22de8c2be6fdd 100644 (file)
@@ -58,6 +58,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)                             \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -85,6 +86,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v)             \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -118,6 +120,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v)            \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -256,6 +259,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)                      \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -283,6 +287,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -316,6 +321,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v)  \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
index a5eb1bb199a7fdf76087bcea1d63b962e2555606..b7f6ac5e513c9a47e0943c768666f2ccab2144e0 100644 (file)
 #define __smp_mb__before_atomic()      __smp_mb__before_llsc()
 #define __smp_mb__after_atomic()       smp_llsc_mb()
 
+/*
+ * Some Loongson 3 CPUs have a bug wherein execution of a memory access (load,
+ * store or pref) in between an ll & sc can cause the sc instruction to
+ * erroneously succeed, breaking atomicity. Whilst it's unusual to write code
+ * containing such sequences, this bug bites harder than we might otherwise
+ * expect due to reordering & speculation:
+ *
+ * 1) A memory access appearing prior to the ll in program order may actually
+ *    be executed after the ll - this is the reordering case.
+ *
+ *    In order to avoid this we need to place a memory barrier (ie. a sync
+ *    instruction) prior to every ll instruction, in between it & any earlier
+ *    memory access instructions. Many of these cases are already covered by
+ *    smp_mb__before_llsc() but for the remaining cases, typically ones in
+ *    which multiple CPUs may operate on a memory location but ordering is not
+ *    usually guaranteed, we use loongson_llsc_mb() below.
+ *
+ *    This reordering case is fixed by 3A R2 CPUs, ie. 3A2000 models and later.
+ *
+ * 2) If a conditional branch exists between an ll & sc with a target outside
+ *    of the ll-sc loop, for example an exit upon value mismatch in cmpxchg()
+ *    or similar, then misprediction of the branch may allow speculative
+ *    execution of memory accesses from outside of the ll-sc loop.
+ *
+ *    In order to avoid this we need a memory barrier (ie. a sync instruction)
+ *    at each affected branch target, for which we also use loongson_llsc_mb()
+ *    defined below.
+ *
+ *    This case affects all current Loongson 3 CPUs.
+ */
+#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS /* Loongson-3's LLSC workaround */
+#define loongson_llsc_mb()     __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
+#else
+#define loongson_llsc_mb()     do { } while (0)
+#endif
+
 #include <asm-generic/barrier.h>
 
 #endif /* __ASM_BARRIER_H */
index c4675957b21bca1e5be2cddd37f8af71a24eb6b9..830c93a010c34926b26d3dea33a9f6ac8049ee59 100644 (file)
@@ -69,6 +69,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                : "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       " __LL "%0, %1          # set_bit       \n"
@@ -79,6 +80,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                } while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
        } else if (kernel_uses_llsc) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
@@ -123,6 +125,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                : "ir" (~(1UL << bit)));
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       " __LL "%0, %1          # clear_bit     \n"
@@ -133,6 +136,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                } while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
        } else if (kernel_uses_llsc) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
@@ -193,6 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp;
 
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
index c14d798f38886c15b0f8d8adfbcf7008ad863d74..b83b0397462d9e74cff12be9ee3897b9cf1e29d8 100644 (file)
@@ -50,6 +50,7 @@
                  "i" (-EFAULT)                                         \
                : "memory");                                            \
        } else if (cpu_has_llsc) {                                      \
+               loongson_llsc_mb();                                     \
                __asm__ __volatile__(                                   \
                "       .set    push                            \n"     \
                "       .set    noat                            \n"     \
@@ -163,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                  "i" (-EFAULT)
                : "memory");
        } else if (cpu_has_llsc) {
+               loongson_llsc_mb();
                __asm__ __volatile__(
                "# futex_atomic_cmpxchg_inatomic                        \n"
                "       .set    push                                    \n"
@@ -192,6 +194,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
                  "i" (-EFAULT)
                : "memory");
+               loongson_llsc_mb();
        } else
                return -ENOSYS;
 
index c6b63a409641627359526356b4fd99e0ea7e23da..6dd8ad2409dc98af9fcf9f4c10eea6f87bbbb542 100644 (file)
@@ -18,8 +18,6 @@
 #define INT_NUM_EXTRA_START            (INT_NUM_IM4_IRL0 + 32)
 #define INT_NUM_IM_OFFSET              (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
 
-#define MIPS_CPU_TIMER_IRQ                     7
-
 #define MAX_IM                 5
 
 #endif /* _FALCON_IRQ__ */
index 141076325307ecfd748d36e76ff008aa76366b5c..0b424214a5e9215affda0000c4395406704d5d69 100644 (file)
@@ -19,8 +19,6 @@
 
 #define LTQ_DMA_CH0_INT                (INT_NUM_IM2_IRL0)
 
-#define MIPS_CPU_TIMER_IRQ     7
-
 #define MAX_IM                 5
 
 #endif
index 57933fc8fd9877d09b4f885a6cb4b4412978e4c2..910851c62db3d3f457d3781175a83a444d3e0b76 100644 (file)
@@ -228,6 +228,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                        : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
                } else if (kernel_uses_llsc) {
+                       loongson_llsc_mb();
                        __asm__ __volatile__ (
                        "       .set    push                            \n"
                        "       .set    "MIPS_ISA_ARCH_LEVEL"           \n"
@@ -242,6 +243,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                        "       .set    pop                             \n"
                        : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
+                       loongson_llsc_mb();
                }
 #else /* !CONFIG_SMP */
                if (pte_none(*buddy))
index 6256d35dbf4dba1425b1b6fc072699c22230f598..bedb5047aff3de0c725b0f2029ed2e177277d727 100644 (file)
@@ -74,14 +74,15 @@ static int __init vdma_init(void)
                                                    get_order(VDMA_PGTBL_SIZE));
        BUG_ON(!pgtbl);
        dma_cache_wback_inv((unsigned long)pgtbl, VDMA_PGTBL_SIZE);
-       pgtbl = (VDMA_PGTBL_ENTRY *)KSEG1ADDR(pgtbl);
+       pgtbl = (VDMA_PGTBL_ENTRY *)CKSEG1ADDR((unsigned long)pgtbl);
 
        /*
         * Clear the R4030 translation table
         */
        vdma_pgtbl_init();
 
-       r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE, CPHYSADDR(pgtbl));
+       r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
+                         CPHYSADDR((unsigned long)pgtbl));
        r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
        r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
 
index 8f5bd04f320a90be3861dd75664fdead350655a3..7f3f136572decc82d666d0fca0515f38d15dd2b3 100644 (file)
@@ -457,5 +457,5 @@ void mips_cm_error_report(void)
        }
 
        /* reprime cause register */
-       write_gcr_error_cause(0);
+       write_gcr_error_cause(cm_error);
 }
index 6829a064aac8f6119da343748f6ccc2e35bde751..339870ed92f79c99e9a0678f9493bbfcaab5787b 100644 (file)
@@ -371,7 +371,7 @@ static inline int is_sp_move_ins(union mips_instruction *ip, int *frame_size)
 static int get_frame_info(struct mips_frame_info *info)
 {
        bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
-       union mips_instruction insn, *ip, *ip_end;
+       union mips_instruction insn, *ip;
        const unsigned int max_insns = 128;
        unsigned int last_insn_size = 0;
        unsigned int i;
@@ -384,10 +384,9 @@ static int get_frame_info(struct mips_frame_info *info)
        if (!ip)
                goto err;
 
-       ip_end = (void *)ip + info->func_size;
-
-       for (i = 0; i < max_insns && ip < ip_end; i++) {
+       for (i = 0; i < max_insns; i++) {
                ip = (void *)ip + last_insn_size;
+
                if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
                        insn.word = ip->halfword[0] << 16;
                        last_insn_size = 2;
index f0bc3312ed1103bea83c69338e1cf4cc010619cf..6549499eb202dd348b4044f9254c744832a5e8dc 100644 (file)
@@ -224,9 +224,11 @@ static struct irq_chip ltq_eiu_type = {
        .irq_set_type = ltq_eiu_settype,
 };
 
-static void ltq_hw_irqdispatch(int module)
+static void ltq_hw_irq_handler(struct irq_desc *desc)
 {
+       int module = irq_desc_get_irq(desc) - 2;
        u32 irq;
+       int hwirq;
 
        irq = ltq_icu_r32(module, LTQ_ICU_IM0_IOSR);
        if (irq == 0)
@@ -237,7 +239,8 @@ static void ltq_hw_irqdispatch(int module)
         * other bits might be bogus
         */
        irq = __fls(irq);
-       do_IRQ((int)irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module));
+       hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
+       generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
 
        /* if this is a EBU irq, we need to ack it or get a deadlock */
        if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
@@ -245,49 +248,6 @@ static void ltq_hw_irqdispatch(int module)
                        LTQ_EBU_PCC_ISTAT);
 }
 
-#define DEFINE_HWx_IRQDISPATCH(x)                                      \
-       static void ltq_hw ## x ## _irqdispatch(void)                   \
-       {                                                               \
-               ltq_hw_irqdispatch(x);                                  \
-       }
-DEFINE_HWx_IRQDISPATCH(0)
-DEFINE_HWx_IRQDISPATCH(1)
-DEFINE_HWx_IRQDISPATCH(2)
-DEFINE_HWx_IRQDISPATCH(3)
-DEFINE_HWx_IRQDISPATCH(4)
-
-#if MIPS_CPU_TIMER_IRQ == 7
-static void ltq_hw5_irqdispatch(void)
-{
-       do_IRQ(MIPS_CPU_TIMER_IRQ);
-}
-#else
-DEFINE_HWx_IRQDISPATCH(5)
-#endif
-
-static void ltq_hw_irq_handler(struct irq_desc *desc)
-{
-       ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-       int irq;
-
-       if (!pending) {
-               spurious_interrupt();
-               return;
-       }
-
-       pending >>= CAUSEB_IP;
-       while (pending) {
-               irq = fls(pending) - 1;
-               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-               pending &= ~BIT(irq);
-       }
-}
-
 static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
        struct irq_chip *chip = &ltq_irq_type;
@@ -343,38 +303,13 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
        for (i = 0; i < MAX_IM; i++)
                irq_set_chained_handler(i + 2, ltq_hw_irq_handler);
 
-       if (cpu_has_vint) {
-               pr_info("Setting up vectored interrupts\n");
-               set_vi_handler(2, ltq_hw0_irqdispatch);
-               set_vi_handler(3, ltq_hw1_irqdispatch);
-               set_vi_handler(4, ltq_hw2_irqdispatch);
-               set_vi_handler(5, ltq_hw3_irqdispatch);
-               set_vi_handler(6, ltq_hw4_irqdispatch);
-               set_vi_handler(7, ltq_hw5_irqdispatch);
-       }
-
        ltq_domain = irq_domain_add_linear(node,
                (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
                &irq_domain_ops, 0);
 
-#ifndef CONFIG_MIPS_MT_SMP
-       set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
-               IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#else
-       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
-               IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#endif
-
        /* tell oprofile which irq to use */
        ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
-       /*
-        * if the timer irq is not one of the mips irqs we need to
-        * create a mapping
-        */
-       if (MIPS_CPU_TIMER_IRQ != 7)
-               irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ);
-
        /* the external interrupts are optional and xway only */
        eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
        if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
@@ -411,7 +346,7 @@ EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
 
 unsigned int get_c0_compare_int(void)
 {
-       return MIPS_CPU_TIMER_IRQ;
+       return CP0_LEGACY_COMPARE_IRQ;
 }
 
 static struct of_device_id __initdata of_irq_ids[] = {
index 0fce4608aa88665febfcad2964690beff5000a0d..c1a4d4dc46655fe914c1927cb8088969e5909318 100644 (file)
@@ -23,6 +23,29 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap
+
+#
+# Some versions of binutils, not currently mainline as of 2019/02/04, support
+# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction
+# to work around a CPU bug (see loongson_llsc_mb() in asm/barrier.h for a
+# description).
+#
+# We disable this in order to prevent the assembler meddling with the
+# instruction that labels refer to, ie. if we label an ll instruction:
+#
+# 1: ll v0, 0(a0)
+#
+# ...then with the assembler fix applied the label may actually point at a sync
+# instruction inserted by the assembler, and if we were using the label in an
+# exception table the table would no longer contain the address of the ll
+# instruction.
+#
+# Avoid this by explicitly disabling that assembler behaviour. If upstream
+# binutils does not merge support for the flag then we can revisit & remove
+# this later - for now it ensures vendor toolchains don't cause problems.
+#
+cflags-$(CONFIG_CPU_LOONGSON3) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,)
+
 #
 # binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
 # as MIPS64 R2; older versions as just R1.  This leaves the possibility open
index a60715e11306b272bc0402a8f8351a2afec5fc48..b26892ce871c87cdf1f8c4e39d5ca81b11bfff31 100644 (file)
@@ -59,7 +59,12 @@ static void loongson_poweroff(void)
 {
 #ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
        mach_prepare_shutdown();
-       unreachable();
+
+       /*
+        * It needs a wait loop here, but mips/kernel/reset.c already calls
+        * a generic delay loop, machine_hang(), so simply return.
+        */
+       return;
 #else
        void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
 
index 37b1cb246332298bd612cd841352093e6323fa49..65b6e85447b1ebc82364c879da5e8561482a0f08 100644 (file)
@@ -932,6 +932,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
                 * to mimic that here by taking a load/istream page
                 * fault.
                 */
+               if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+                       uasm_i_sync(p, 0);
                UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
                uasm_i_jr(p, ptr);
 
@@ -1646,6 +1648,8 @@ static void
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(p, 0);
 # ifdef CONFIG_PHYS_ADDR_T_64BIT
        if (cpu_has_64bits)
                uasm_i_lld(p, pte, 0, ptr);
@@ -2259,6 +2263,8 @@ static void build_r4000_tlb_load_handler(void)
 #endif
 
        uasm_l_nopage_tlbl(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_0 & 1) {
@@ -2313,6 +2319,8 @@ static void build_r4000_tlb_store_handler(void)
 #endif
 
        uasm_l_nopage_tlbs(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_1 & 1) {
@@ -2368,6 +2376,8 @@ static void build_r4000_tlb_modify_handler(void)
 #endif
 
        uasm_l_nopage_tlbm(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_1 & 1) {
index 2a5bb849b10efa742a82f8855708b4afcc8a9c4e..288b58b00dc84537fd1d49f43da0ecd3db02aefd 100644 (file)
@@ -369,7 +369,9 @@ int __init octeon_msi_initialize(void)
        int irq;
        struct irq_chip *msi;
 
-       if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
+       if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_INVALID) {
+               return 0;
+       } else if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
                msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0;
                msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1;
                msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2;
index 5017d5843c5ac4913aa254b2157bd66d86b91bcd..fc29b85cfa926d1b70e69901b2e2c3abc7e46fcc 100644 (file)
@@ -568,6 +568,11 @@ static int __init octeon_pci_setup(void)
        if (octeon_has_feature(OCTEON_FEATURE_PCIE))
                return 0;
 
+       if (!octeon_is_pci_host()) {
+               pr_notice("Not in host mode, PCI Controller not initialized\n");
+               return 0;
+       }
+
        /* Point pcibios_map_irq() to the PCI version of it */
        octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
 
@@ -579,11 +584,6 @@ static int __init octeon_pci_setup(void)
        else
                octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
 
-       if (!octeon_is_pci_host()) {
-               pr_notice("Not in host mode, PCI Controller not initialized\n");
-               return 0;
-       }
-
        /* PCI I/O and PCI MEM values */
        set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
        ioport_resource.start = 0;
index f6fd340e39c2f4bae451f0ecdab0bd929a041eef..0ede4deb8181ce20300f6bc12cfffaf683b99684 100644 (file)
@@ -8,6 +8,7 @@ ccflags-vdso := \
        $(filter -E%,$(KBUILD_CFLAGS)) \
        $(filter -mmicromips,$(KBUILD_CFLAGS)) \
        $(filter -march=%,$(KBUILD_CFLAGS)) \
+       $(filter -m%-float,$(KBUILD_CFLAGS)) \
        -D__VDSO__
 
 ifdef CONFIG_CC_IS_CLANG
@@ -129,7 +130,7 @@ $(obj)/%-o32.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=32
 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
@@ -169,7 +170,7 @@ $(obj)/%-n32.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=n32
 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
index 0a935c136ec24f964e2716203d32f3108d62ad7b..ac3482882cf93e50b165ac3896712fc65ce66e65 100644 (file)
@@ -3,9 +3,6 @@ OBJCOPYFLAGS    := -O binary -R .note -R .note.gnu.build-id -R .comment -S
 
 KBUILD_DEFCONFIG := defconfig
 
-comma = ,
-
-
 ifdef CONFIG_FUNCTION_TRACER
 arch-y += -malways-save-lp -mno-relax
 endif
@@ -54,8 +51,6 @@ endif
 boot := arch/nds32/boot
 core-y += $(boot)/dts/
 
-.PHONY: FORCE
-
 Image: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
@@ -68,9 +63,6 @@ prepare: vdso_prepare
 vdso_prepare: prepare0
        $(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso include/generated/vdso-offsets.h
 
-CLEAN_FILES += include/asm-nds32/constants.h*
-
-# We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index 70e06d34006cb757349f12cf77a710b744b32cfd..bf10141c7426844fe505a0bb8f5da0b73472aaca 100644 (file)
@@ -20,7 +20,6 @@
 KBUILD_DEFCONFIG := or1ksim_defconfig
 
 OBJCOPYFLAGS    := -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux :=
 LIBGCC                 := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
 KBUILD_CFLAGS  += -pipe -ffixed-r10 -D__linux__
@@ -50,5 +49,3 @@ else
 BUILTIN_DTB := n
 endif
 core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
-
-all: vmlinux
index eb87cd8327c89e9b7941617d3df3927c1a2d9da8..1f04844b6b82d2233be080cabfe7ca36db7ea4b8 100644 (file)
@@ -34,6 +34,7 @@ generic-y += qrwlock_types.h
 generic-y += qrwlock.h
 generic-y += sections.h
 generic-y += segment.h
+generic-y += shmparam.h
 generic-y += string.h
 generic-y += switch_to.h
 generic-y += topology.h
index 6c6f6301012ef6c1c86f14a5edd26cb01c409455..0febf1a07c30a7df64bd64806151f91de123da45 100644 (file)
@@ -1,5 +1,4 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-generic-y += shmparam.h
 generic-y += ucontext.h
index 2e6ada28da645fd6a122d153fedfdc2c62b7843e..d8c8d7c9df1510451367dca149df932b30648720 100644 (file)
@@ -904,7 +904,7 @@ static inline int pud_none(pud_t pud)
 
 static inline int pud_present(pud_t pud)
 {
-       return (pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 extern struct page *pud_page(pud_t pud);
@@ -951,7 +951,7 @@ static inline int pgd_none(pgd_t pgd)
 
 static inline int pgd_present(pgd_t pgd)
 {
-       return (pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 static inline pte_t pgd_pte(pgd_t pgd)
@@ -1258,21 +1258,13 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
-static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
-                                        struct spinlock *old_pmd_ptl,
-                                        struct vm_area_struct *vma)
-{
-       if (radix_enabled())
-               return false;
-       /*
-        * Archs like ppc64 use pgtable to store per pmd
-        * specific information. So when we switch the pmd,
-        * we should also withdraw and deposit the pgtable
-        */
-       return true;
-}
-
-
+extern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                                 struct spinlock *old_pmd_ptl,
+                                 struct vm_area_struct *vma);
+/*
+ * Hash translation mode use the deposited table to store hash pte
+ * slot information.
+ */
 #define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
 static inline bool arch_needs_pgtable_deposit(void)
 {
index ff91192407d1b3c027257b5e32ac9b6956f8bb13..f599064dd8dc8431fbe705320d9afc7f862f1207 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index 57deb1e9ffea7a70e4f71c4a2457abb7534147fa..20cc816b3508d3f689a11ebefebaf9fc2a711ae2 100644 (file)
@@ -852,11 +852,12 @@ start_here:
 
        /* set up the PTE pointers for the Abatron bdiGDB.
        */
-       tovirt(r6,r6)
        lis     r5, abatron_pteptrs@h
        ori     r5, r5, abatron_pteptrs@l
        stw     r5, 0xf0(0)     /* Must match your Abatron config file */
        tophys(r5,r5)
+       lis     r6, swapper_pg_dir@h
+       ori     r6, r6, swapper_pg_dir@l
        stw     r6, 0(r5)
 
 /* Now turn on the MMU for real! */
index bd5e6834ca6928c54a627a470dd1932fd4f91497..6794466f64200b4dae247b8997d530e0b2030cdc 100644 (file)
@@ -755,11 +755,12 @@ SYSCALL_DEFINE0(rt_sigreturn)
                if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
                                           &uc_transact->uc_mcontext))
                        goto badframe;
-       }
+       } else
 #endif
-       /* Fall through, for non-TM restore */
-       if (!MSR_TM_ACTIVE(msr)) {
+       {
                /*
+                * Fall through, for non-TM restore
+                *
                 * Unset MSR[TS] on the thread regs since MSR from user
                 * context does not have MSR active, and recheckpoint was
                 * not called since restore_tm_sigcontexts() was not called
index 29746dc28df5286187f97afad9d8c1008663143b..517662a56bdc937e1e7dd98d72ec17404c297565 100644 (file)
@@ -967,13 +967,6 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
-#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
-unsigned long __init arch_syscall_addr(int nr)
-{
-       return sys_call_table[nr*2];
-}
-#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
-
 #ifdef PPC64_ELF_ABI_v1
 char *arch_ftrace_match_adjust(char *str, const char *search)
 {
index f3c31f5e1026fca9f2e01da261e1319dccbceaf0..ecd31569a120a716d30d1f030b6732e0298a172b 100644 (file)
@@ -400,3 +400,25 @@ void arch_report_meminfo(struct seq_file *m)
                   atomic_long_read(&direct_pages_count[MMU_PAGE_1G]) << 20);
 }
 #endif /* CONFIG_PROC_FS */
+
+/*
+ * For hash translation mode, we use the deposited table to store hash slot
+ * information and they are stored at PTRS_PER_PMD offset from related pmd
+ * location. Hence a pmd move requires deposit and withdraw.
+ *
+ * For radix translation with split pmd ptl, we store the deposited table in the
+ * pmd page. Hence if we have different pmd page we need to withdraw during pmd
+ * move.
+ *
+ * With hash we use deposited table always irrespective of anon or not.
+ * With radix we use deposited table only for anonymous mapping.
+ */
+int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                          struct spinlock *old_pmd_ptl,
+                          struct vm_area_struct *vma)
+{
+       if (radix_enabled())
+               return (new_pmd_ptl != old_pmd_ptl) && vma_is_anonymous(vma);
+
+       return true;
+}
index 5c36b3a8d47aba640d5136dcdfca30469375a3a6..3349f3f8fe840ae52de297d59822f103726259ff 100644 (file)
@@ -70,6 +70,7 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
        PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
        PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
        PT_REGS_OFFSET(PERF_REG_POWERPC_SIER, dar),
+       PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr),
 };
 
 u64 perf_reg_value(struct pt_regs *regs, int idx)
@@ -83,6 +84,11 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
            !is_sier_available()))
                return 0;
 
+       if (idx == PERF_REG_POWERPC_MMCRA &&
+          (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
+           IS_ENABLED(CONFIG_PPC32)))
+               return 0;
+
        return regs_get_register(regs, pt_regs_offset[idx]);
 }
 
index a1aaa1569d7ce63793398610b4abdb8a0f38ebe1..f0e488d975678eaca40e7ab8baa4d1a04e41d7f0 100644 (file)
@@ -237,12 +237,12 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                        continue;
 
                seq_printf(m, "PPC4XX OCM   : %d\n", ocm->index);
-               seq_printf(m, "PhysAddr     : %pa[p]\n", &(ocm->phys));
+               seq_printf(m, "PhysAddr     : %pa\n", &(ocm->phys));
                seq_printf(m, "MemTotal     : %d Bytes\n", ocm->memtotal);
                seq_printf(m, "MemTotal(NC) : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "MemTotal(C)  : %d Bytes\n\n", ocm->c.memtotal);
 
-               seq_printf(m, "NC.PhysAddr  : %pa[p]\n", &(ocm->nc.phys));
+               seq_printf(m, "NC.PhysAddr  : %pa\n", &(ocm->nc.phys));
                seq_printf(m, "NC.VirtAddr  : 0x%p\n", ocm->nc.virt);
                seq_printf(m, "NC.MemTotal  : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "NC.MemFree   : %d Bytes\n", ocm->nc.memfree);
@@ -252,7 +252,7 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                                                        blk->size, blk->owner);
                }
 
-               seq_printf(m, "\nC.PhysAddr   : %pa[p]\n", &(ocm->c.phys));
+               seq_printf(m, "\nC.PhysAddr   : %pa\n", &(ocm->c.phys));
                seq_printf(m, "C.VirtAddr   : 0x%p\n", ocm->c.virt);
                seq_printf(m, "C.MemTotal   : %d Bytes\n", ocm->c.memtotal);
                seq_printf(m, "C.MemFree    : %d Bytes\n", ocm->c.memfree);
index e66644e0fb400c6df684423cc6f2f63fa3095abc..9438fa0fc3552bdf6347dba963ece2b049ca2090 100644 (file)
@@ -538,8 +538,7 @@ static void __init chrp_init_IRQ(void)
        /* see if there is a keyboard in the device tree
           with a parent of type "adb" */
        for_each_node_by_name(kbd, "keyboard")
-               if (kbd->parent && kbd->parent->type
-                   && strcmp(kbd->parent->type, "adb") == 0)
+               if (of_node_is_type(kbd->parent, "adb"))
                        break;
        of_node_put(kbd);
        if (kbd)
index d7f742ed48ba4bb3b002f23daf2ffa576f055dfb..3f58c7dbd581e1f018c7e941fc2ea1b649436c07 100644 (file)
@@ -564,7 +564,7 @@ struct iommu_table_group *pnv_try_setup_npu_table_group(struct pnv_ioda_pe *pe)
                }
        } else {
                /* Create a group for 1 GPU and attached NPUs for POWER8 */
-               pe->npucomp = kzalloc(sizeof(pe->npucomp), GFP_KERNEL);
+               pe->npucomp = kzalloc(sizeof(*pe->npucomp), GFP_KERNEL);
                table_group = &pe->npucomp->table_group;
                table_group->ops = &pnv_npu_peers_ops;
                iommu_register_group(table_group, hose->global_number,
index 1d6406a051f1216782094ee5bfcf9a662de9e0f1..7db3119f8a5b33404a5b88d5eb035f9836a94d18 100644 (file)
@@ -2681,7 +2681,8 @@ static void pnv_pci_ioda_setup_iommu_api(void)
        list_for_each_entry(hose, &hose_list, list_node) {
                phb = hose->private_data;
 
-               if (phb->type == PNV_PHB_NPU_NVLINK)
+               if (phb->type == PNV_PHB_NPU_NVLINK ||
+                   phb->type == PNV_PHB_NPU_OCAPI)
                        continue;
 
                list_for_each_entry(pe, &phb->ioda.pe_list, list) {
index 7d6457ab5d3450f0db4d6cc25e2067c80db59f13..bba281b1fe1b0730f8a0d31fc469f324118a8933 100644 (file)
@@ -43,6 +43,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
 {
        unsigned long ret[PLPAR_HCALL_BUFSIZE];
        uint64_t rc, token;
+       uint64_t saved = 0;
 
        /*
         * When the hypervisor cannot map all the requested memory in a single
@@ -56,6 +57,8 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0,
                                p->blocks, BIND_ANY_ADDR, token);
                token = ret[0];
+               if (!saved)
+                       saved = ret[1];
                cond_resched();
        } while (rc == H_BUSY);
 
@@ -64,7 +67,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                return -ENXIO;
        }
 
-       p->bound_addr = ret[1];
+       p->bound_addr = saved;
 
        dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res);
 
index 7725825d887d32903a699fdc2e26134f9b101100..37a77e57893eda7cda4dd58ceefcb837d71bc978 100644 (file)
@@ -264,7 +264,9 @@ void __init pSeries_final_fixup(void)
                        if (!of_device_is_compatible(nvdn->parent,
                                                "ibm,power9-npu"))
                                continue;
+#ifdef CONFIG_PPC_POWERNV
                        WARN_ON_ONCE(pnv_npu2_init(hose));
+#endif
                        break;
                }
        }
index feeeaa60697caae10cbfa1cbcff6b316440a048b..515fc3cc96871ff71d2e2809ca4448821efb071b 100644 (file)
@@ -103,7 +103,7 @@ choice
        prompt "Base ISA"
        default ARCH_RV64I
        help
-         This selects the base ISA that this kernel will traget and must match
+         This selects the base ISA that this kernel will target and must match
          the target platform.
 
 config ARCH_RV32I
index f399659d3b8d8caa07c7f989b01e5cf3cf440e75..2fd3461e50abc9311cfe546de626b3ae58cb7e88 100644 (file)
@@ -13,8 +13,6 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_SMP=y
-CONFIG_PCI=y
-CONFIG_PCIE_XILINX=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
@@ -28,6 +26,10 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETLINK_DIAG=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
@@ -63,7 +65,6 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_SIFIVE_PLIC=y
-CONFIG_RAS=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_AUTOFS4_FS=y
@@ -77,5 +78,6 @@ CONFIG_NFS_V4_1=y
 CONFIG_NFS_V4_2=y
 CONFIG_ROOT_NFS=y
 CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_PRINTK_TIME=y
 # CONFIG_RCU_TRACE is not set
index 06cfbb3aacbb02bba5921091691a274586463c2a..2a546a52f02a08ae0583c4825048a3c39fc26a6f 100644 (file)
@@ -80,7 +80,7 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) })
 #define __pgprot(x)    ((pgprot_t) { (x) })
 
-#ifdef CONFIG_64BITS
+#ifdef CONFIG_64BIT
 #define PTE_FMT "%016lx"
 #else
 #define PTE_FMT "%08lx"
index 2fa2942be221e480088ab1a5681c9240ef3a1e23..470755cb75584ee6e6b8c607070b2e89669ce816 100644 (file)
 #define _PAGE_SPECIAL   _PAGE_SOFT
 #define _PAGE_TABLE     _PAGE_PRESENT
 
+/*
+ * _PAGE_PROT_NONE is set on not-present pages (and ignored by the hardware) to
+ * distinguish them from swapped out pages
+ */
+#define _PAGE_PROT_NONE _PAGE_READ
+
 #define _PAGE_PFN_SHIFT 10
 
 /* Set of bits to preserve across pte_modify() */
index 16301966d65b6fd8a54614d12f0815866d19d948..a8179a8c1491c28a6ad3eeedda34a122bc00a2c3 100644 (file)
@@ -44,7 +44,7 @@
 /* Page protection bits */
 #define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER)
 
-#define PAGE_NONE              __pgprot(0)
+#define PAGE_NONE              __pgprot(_PAGE_PROT_NONE)
 #define PAGE_READ              __pgprot(_PAGE_BASE | _PAGE_READ)
 #define PAGE_WRITE             __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE)
 #define PAGE_EXEC              __pgprot(_PAGE_BASE | _PAGE_EXEC)
@@ -98,7 +98,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 static inline int pmd_present(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _PAGE_PRESENT);
+       return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
 }
 
 static inline int pmd_none(pmd_t pmd)
@@ -178,7 +178,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long addr)
 
 static inline int pte_present(pte_t pte)
 {
-       return (pte_val(pte) & _PAGE_PRESENT);
+       return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
 }
 
 static inline int pte_none(pte_t pte)
@@ -380,7 +380,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
  *
  * Format of swap PTE:
  *     bit            0:       _PAGE_PRESENT (zero)
- *     bit            1:       reserved for future use (zero)
+ *     bit            1:       _PAGE_PROT_NONE (zero)
  *     bits      2 to 6:       swap type
  *     bits 7 to XLEN-1:       swap offset
  */
index 0531f49af5c30e7f5c825c84e3057f160b3a87dd..ce70bceb8872e76e5cfd6c553c28ed1799b2563f 100644 (file)
@@ -22,7 +22,7 @@
  * This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE >> 1)
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE / 3)
 
 #define STACK_TOP              TASK_SIZE
 #define STACK_TOP_MAX          STACK_TOP
index 6a92a2fe198e4e433a4f3e21e21e03e84a1bce76..dac98348c6a34a362ffa92fa34829d37d7ea26c9 100644 (file)
@@ -39,6 +39,7 @@ void asm_offsets(void)
        OFFSET(TASK_STACK, task_struct, stack);
        OFFSET(TASK_TI, task_struct, thread_info);
        OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags);
+       OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
        OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
        OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
        OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
index 355166f57205184ca4bd311477a58a1387a80097..fd9b57c8b4cef412091fddd8326f7d64e35544d4 100644 (file)
@@ -144,6 +144,10 @@ _save_context:
        REG_L x2,  PT_SP(sp)
        .endm
 
+#if !IS_ENABLED(CONFIG_PREEMPT)
+.set resume_kernel, restore_all
+#endif
+
 ENTRY(handle_exception)
        SAVE_ALL
 
@@ -228,7 +232,7 @@ ret_from_exception:
        REG_L s0, PT_SSTATUS(sp)
        csrc sstatus, SR_SIE
        andi s0, s0, SR_SPP
-       bnez s0, restore_all
+       bnez s0, resume_kernel
 
 resume_userspace:
        /* Interrupts must be disabled here so flags are checked atomically */
@@ -250,6 +254,18 @@ restore_all:
        RESTORE_ALL
        sret
 
+#if IS_ENABLED(CONFIG_PREEMPT)
+resume_kernel:
+       REG_L s0, TASK_TI_PREEMPT_COUNT(tp)
+       bnez s0, restore_all
+need_resched:
+       REG_L s0, TASK_TI_FLAGS(tp)
+       andi s0, s0, _TIF_NEED_RESCHED
+       beqz s0, restore_all
+       call preempt_schedule_irq
+       j need_resched
+#endif
+
 work_pending:
        /* Enter slow path for supplementary processing */
        la ra, ret_from_exception
index 6e079e94b6386277ae80e5a542fc70a80a4b3e73..77564310235f4d0a545ddde1478e5adfb7b2d08a 100644 (file)
@@ -181,7 +181,7 @@ static void __init setup_bootmem(void)
        BUG_ON(mem_size == 0);
 
        set_max_mapnr(PFN_DOWN(mem_size));
-       max_low_pfn = memblock_end_of_DRAM();
+       max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
 
 #ifdef CONFIG_BLK_DEV_INITRD
        setup_initrd();
index fc185ecabb0a324c0a4d07c81775d89952a48100..18cda0e8cf9414310e0ec594ee30360f7938808c 100644 (file)
@@ -57,15 +57,12 @@ void __init setup_smp(void)
 
        while ((dn = of_find_node_by_type(dn, "cpu"))) {
                hart = riscv_of_processor_hartid(dn);
-               if (hart < 0) {
-                       of_node_put(dn);
+               if (hart < 0)
                        continue;
-               }
 
                if (hart == cpuid_to_hartid_map(0)) {
                        BUG_ON(found_boot_cpu);
                        found_boot_cpu = 1;
-                       of_node_put(dn);
                        continue;
                }
 
@@ -73,7 +70,6 @@ void __init setup_smp(void)
                set_cpu_possible(cpuid, true);
                set_cpu_present(cpuid, true);
                cpuid++;
-               of_node_put(dn);
        }
 
        BUG_ON(!found_boot_cpu);
index 1e1395d63dabb8ca48a6dbf7cd0e0a44d687cc27..65df1dfdc30385be7a9a149034a0ba66a5bbbd8e 100644 (file)
@@ -18,8 +18,6 @@
 #include <asm/cache.h>
 #include <asm/thread_info.h>
 
-#define MAX_BYTES_PER_LONG     0x10
-
 OUTPUT_ARCH(riscv)
 ENTRY(_start)
 
@@ -76,6 +74,8 @@ SECTIONS
                *(.sbss*)
        }
 
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
+
        EXCEPTION_TABLE(0x10)
        NOTES
 
@@ -83,10 +83,6 @@ SECTIONS
                *(.rel.dyn*)
        }
 
-       BSS_SECTION(MAX_BYTES_PER_LONG,
-                   MAX_BYTES_PER_LONG,
-                   MAX_BYTES_PER_LONG)
-
        _end = .;
 
        STABS_DEBUG
index 1d9bfaff60bca8c703646428af3581f4607fe0ef..658ebf645f42002d536983f01e828312f0dce9fb 100644 (file)
@@ -28,7 +28,8 @@ static void __init zone_sizes_init(void)
        unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
 
 #ifdef CONFIG_ZONE_DMA32
-       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G, max_low_pfn));
+       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G,
+                       (unsigned long) PFN_PHYS(max_low_pfn)));
 #endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
index ccbb53e2202404b85aae86e883d3e64405d2d305..8d04e6f3f79649d460376f09217c9e8fe211a850 100644 (file)
@@ -25,7 +25,7 @@ static inline int init_new_context(struct task_struct *tsk,
        atomic_set(&mm->context.flush_count, 0);
        mm->context.gmap_asce = 0;
        mm->context.flush_mm = 0;
-       mm->context.compat_mm = 0;
+       mm->context.compat_mm = test_thread_flag(TIF_31BIT);
 #ifdef CONFIG_PGSTE
        mm->context.alloc_pgste = page_table_allocate_pgste ||
                test_thread_flag(TIF_PGSTE) ||
@@ -90,8 +90,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
        int cpu = smp_processor_id();
 
-       if (prev == next)
-               return;
        S390_lowcore.user_asce = next->context.asce;
        cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
        /* Clear previous user-ASCE from CR1 and CR7 */
@@ -103,7 +101,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                __ctl_load(S390_lowcore.vdso_asce, 7, 7);
                clear_cpu_flag(CIF_ASCE_SECONDARY);
        }
-       cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
+       if (prev != next)
+               cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
 }
 
 #define finish_arch_post_lock_switch finish_arch_post_lock_switch
index af5c2b3f706567f5f9927686ccfd210b50366221..a8c7789b246b49eb5a546360e4491eaf0f9eac7b 100644 (file)
@@ -63,10 +63,10 @@ static noinline __init void detect_machine_type(void)
        if (stsi(vmms, 3, 2, 2) || !vmms->count)
                return;
 
-       /* Running under KVM? If not we assume z/VM */
+       /* Detect known hypervisors */
        if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
                S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
-       else
+       else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4))
                S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
 }
 
index 72dd23ef771b6bf22f77e71df22a40e05fbee2d5..7ed90a75913572f752652d611a0cd5347279d8e2 100644 (file)
@@ -1006,6 +1006,8 @@ void __init setup_arch(char **cmdline_p)
                pr_info("Linux is running under KVM in 64-bit mode\n");
        else if (MACHINE_IS_LPAR)
                pr_info("Linux is running natively in 64-bit mode\n");
+       else
+               pr_info("Linux is running as a guest in 64-bit mode\n");
 
        /* Have one command line that is parsed and saved in /proc/cmdline */
        /* boot_command_line has been already set up in early.c */
index f82b3d3c36e2d5620e4b8e6b363936bcdf38d673..b198ece2aad63d70f58b2acde1c280ce5534cf7a 100644 (file)
@@ -381,8 +381,13 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
  */
 void smp_call_ipl_cpu(void (*func)(void *), void *data)
 {
+       struct lowcore *lc = pcpu_devices->lowcore;
+
+       if (pcpu_devices[0].address == stap())
+               lc = &S390_lowcore;
+
        pcpu_delegate(&pcpu_devices[0], func, data,
-                     pcpu_devices->lowcore->nodat_stack);
+                     lc->nodat_stack);
 }
 
 int smp_find_processor_id(u16 address)
@@ -1166,7 +1171,11 @@ static ssize_t __ref rescan_store(struct device *dev,
 {
        int rc;
 
+       rc = lock_device_hotplug_sysfs();
+       if (rc)
+               return rc;
        rc = smp_rescan_cpus();
+       unlock_device_hotplug();
        return rc ? rc : count;
 }
 static DEVICE_ATTR_WO(rescan);
index 537f97fde37f977c4d6b3af0d45aab00926644d5..b6796e616812dbe6acdb6c455acff1bb54c20879 100644 (file)
        .section .text
 ENTRY(swsusp_arch_suspend)
        lg      %r1,__LC_NODAT_STACK
-       aghi    %r1,-STACK_FRAME_OVERHEAD
        stmg    %r6,%r15,__SF_GPRS(%r1)
+       aghi    %r1,-STACK_FRAME_OVERHEAD
        stg     %r15,__SF_BACKCHAIN(%r1)
-       lgr     %r1,%r15
+       lgr     %r15,%r1
 
        /* Store FPU registers */
        brasl   %r14,save_fpu_regs
index ebe748a9f472fde63cfccd42921472233f6ea529..4ff354887db412a504bb432956c28b2ba6b8a936 100644 (file)
@@ -224,10 +224,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        vdso_pages = vdso64_pages;
 #ifdef CONFIG_COMPAT
-       if (is_compat_task()) {
+       mm->context.compat_mm = is_compat_task();
+       if (mm->context.compat_mm)
                vdso_pages = vdso32_pages;
-               mm->context.compat_mm = 1;
-       }
 #endif
        /*
         * vDSO has a problem and was disabled, just don't "enable" it for
index a966d7bfac579daa15514983d56993862363c502..4266a4de31601c0164a841532520febe5dc635b9 100644 (file)
@@ -382,7 +382,9 @@ static void zpci_irq_handler(struct airq_struct *airq)
                        if (ai == -1UL)
                                break;
                        inc_irq_stat(IRQIO_MSI);
+                       airq_iv_lock(aibv, ai);
                        generic_handle_irq(airq_iv_get_data(aibv, ai));
+                       airq_iv_unlock(aibv, ai);
                }
        }
 }
@@ -408,7 +410,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        zdev->aisb = aisb;
 
        /* Create adapter interrupt vector */
-       zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA);
+       zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
        if (!zdev->aibv)
                return -ENOMEM;
 
index 1372553dc0a9ad04aacd3c86476c4bd2cfdcf113..1d1544b6ca74ce96e765c68cfa2f1a86a7ef7ac8 100644 (file)
@@ -28,6 +28,7 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += syscalls.h
 generic-y += topology.h
index 6c6f6301012ef6c1c86f14a5edd26cb01c409455..0febf1a07c30a7df64bd64806151f91de123da45 100644 (file)
@@ -1,5 +1,4 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-generic-y += shmparam.h
 generic-y += ucontext.h
index 15af091611e29cf2353befbaa260e40dc8664298..68261430fe6e9ca949a8e3e067b6bc0e496c4734 100644 (file)
@@ -198,7 +198,7 @@ config X86
        select IRQ_FORCED_THREADING
        select NEED_SG_DMA_LENGTH
        select PCI_DOMAINS                      if PCI
-       select PCI_LOCKLESS_CONFIG
+       select PCI_LOCKLESS_CONFIG              if PCI
        select PERF_EVENTS
        select RTC_LIB
        select RTC_MC146818_LIB
@@ -446,12 +446,12 @@ config RETPOLINE
          branches. Requires a compiler with -mindirect-branch=thunk-extern
          support for full protection. The kernel may run slower.
 
-config X86_RESCTRL
-       bool "Resource Control support"
+config X86_CPU_RESCTRL
+       bool "x86 CPU resource control support"
        depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
        select KERNFS
        help
-         Enable Resource Control support.
+         Enable x86 CPU resource control support.
 
          Provide support for the allocation and monitoring of system resources
          usage by the CPU.
@@ -617,7 +617,7 @@ config X86_INTEL_QUARK
 
 config X86_INTEL_LPSS
        bool "Intel Low Power Subsystem Support"
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select COMMON_CLK
        select PINCTRL
        select IOSF_MBI
index 64037895b0859fdb25b8b104a2e5ed5d028baf45..f62e347862ccc61ba417d80dabee304ef28b6ec7 100644 (file)
@@ -600,6 +600,16 @@ ENTRY(trampoline_32bit_src)
        leal    TRAMPOLINE_32BIT_PGTABLE_OFFSET(%ecx), %eax
        movl    %eax, %cr3
 3:
+       /* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
+       pushl   %ecx
+       pushl   %edx
+       movl    $MSR_EFER, %ecx
+       rdmsr
+       btsl    $_EFER_LME, %eax
+       wrmsr
+       popl    %edx
+       popl    %ecx
+
        /* Enable PAE and LA57 (if required) paging modes */
        movl    $X86_CR4_PAE, %eax
        cmpl    $0, %edx
index 91f75638f6e68ef5df8da5f428fe54341bef3813..6ff7e81b5628456b92779ede7a9c941fe7df6a85 100644 (file)
@@ -6,7 +6,7 @@
 #define TRAMPOLINE_32BIT_PGTABLE_OFFSET        0
 
 #define TRAMPOLINE_32BIT_CODE_OFFSET   PAGE_SIZE
-#define TRAMPOLINE_32BIT_CODE_SIZE     0x60
+#define TRAMPOLINE_32BIT_CODE_SIZE     0x70
 
 #define TRAMPOLINE_32BIT_STACK_END     TRAMPOLINE_32BIT_SIZE
 
index 8eaf8952c408cd619124f9696b4888fae2f529ad..39913770a44d5aeed855c51082a6cf55080457f1 100644 (file)
@@ -361,7 +361,8 @@ ENTRY(entry_INT80_compat)
 
        /* Need to switch before accessing the thread stack. */
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
-       movq    %rsp, %rdi
+       /* In the Xen PV case we already run on the thread stack. */
+       ALTERNATIVE "movq %rsp, %rdi", "jmp .Lint80_keep_stack", X86_FEATURE_XENPV
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
        pushq   6*8(%rdi)               /* regs->ss */
@@ -370,8 +371,9 @@ ENTRY(entry_INT80_compat)
        pushq   3*8(%rdi)               /* regs->cs */
        pushq   2*8(%rdi)               /* regs->ip */
        pushq   1*8(%rdi)               /* regs->orig_ax */
-
        pushq   (%rdi)                  /* pt_regs->di */
+.Lint80_keep_stack:
+
        pushq   %rsi                    /* pt_regs->si */
        xorl    %esi, %esi              /* nospec   si */
        pushq   %rdx                    /* pt_regs->dx */
index 374a19712e2009a0cbcb0c3048d4489cf5c2f9d9..b684f0294f35d93bb5e7367a7d7903719c25c6a6 100644 (file)
@@ -2278,6 +2278,19 @@ void perf_check_microcode(void)
                x86_pmu.check_microcode();
 }
 
+static int x86_pmu_check_period(struct perf_event *event, u64 value)
+{
+       if (x86_pmu.check_period && x86_pmu.check_period(event, value))
+               return -EINVAL;
+
+       if (value && x86_pmu.limit_period) {
+               if (x86_pmu.limit_period(event, value) > value)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static struct pmu pmu = {
        .pmu_enable             = x86_pmu_enable,
        .pmu_disable            = x86_pmu_disable,
@@ -2302,6 +2315,7 @@ static struct pmu pmu = {
        .event_idx              = x86_pmu_event_idx,
        .sched_task             = x86_pmu_sched_task,
        .task_ctx_size          = sizeof(struct x86_perf_task_context),
+       .check_period           = x86_pmu_check_period,
 };
 
 void arch_perf_update_userpage(struct perf_event *event,
index 40e12cfc87f62eb5b68490053c0861ac05af18e6..730978dff63f5e577628936e26183b5a36da0cca 100644 (file)
@@ -3558,6 +3558,14 @@ static void free_excl_cntrs(int cpu)
 }
 
 static void intel_pmu_cpu_dying(int cpu)
+{
+       fini_debug_store_on_cpu(cpu);
+
+       if (x86_pmu.counter_freezing)
+               disable_counter_freeze();
+}
+
+static void intel_pmu_cpu_dead(int cpu)
 {
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
        struct intel_shared_regs *pc;
@@ -3570,11 +3578,6 @@ static void intel_pmu_cpu_dying(int cpu)
        }
 
        free_excl_cntrs(cpu);
-
-       fini_debug_store_on_cpu(cpu);
-
-       if (x86_pmu.counter_freezing)
-               disable_counter_freeze();
 }
 
 static void intel_pmu_sched_task(struct perf_event_context *ctx,
@@ -3584,6 +3587,11 @@ static void intel_pmu_sched_task(struct perf_event_context *ctx,
        intel_pmu_lbr_sched_task(ctx, sched_in);
 }
 
+static int intel_pmu_check_period(struct perf_event *event, u64 value)
+{
+       return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
+}
+
 PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
 
 PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3663,6 +3671,9 @@ static __initconst const struct x86_pmu core_pmu = {
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
+       .cpu_dead               = intel_pmu_cpu_dead,
+
+       .check_period           = intel_pmu_check_period,
 };
 
 static struct attribute *intel_pmu_attrs[];
@@ -3703,8 +3714,12 @@ static __initconst const struct x86_pmu intel_pmu = {
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
+       .cpu_dead               = intel_pmu_cpu_dead,
+
        .guest_get_msrs         = intel_guest_get_msrs,
        .sched_task             = intel_pmu_sched_task,
+
+       .check_period           = intel_pmu_check_period,
 };
 
 static __init void intel_clovertown_quirk(void)
index c07bee31abe859c61c53c499e9aabcbe11f1f07b..b10e04387f380342c9b9427012b09b9534a347d1 100644 (file)
@@ -1222,6 +1222,8 @@ static struct pci_driver snbep_uncore_pci_driver = {
        .id_table       = snbep_uncore_pci_ids,
 };
 
+#define NODE_ID_MASK   0x7
+
 /*
  * build pci bus to socket mapping
  */
@@ -1243,7 +1245,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
                err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
                if (err)
                        break;
-               nodeid = config;
+               nodeid = config & NODE_ID_MASK;
                /* get the Node ID mapping */
                err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
                if (err)
index 78d7b7031bfccb8ec2dbcd7de6e54a29fd1365ce..d46fd6754d920b0c5331c2658a55e1685b111957 100644 (file)
@@ -646,6 +646,11 @@ struct x86_pmu {
         * Intel host/guest support (KVM)
         */
        struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+
+       /*
+        * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+        */
+       int (*check_period) (struct perf_event *event, u64 period);
 };
 
 struct x86_perf_task_context {
@@ -857,7 +862,7 @@ static inline int amd_pmu_init(void)
 
 #ifdef CONFIG_CPU_SUP_INTEL
 
-static inline bool intel_pmu_has_bts(struct perf_event *event)
+static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
 {
        struct hw_perf_event *hwc = &event->hw;
        unsigned int hw_event, bts_event;
@@ -868,7 +873,14 @@ static inline bool intel_pmu_has_bts(struct perf_event *event)
        hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
        bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
-       return hw_event == bts_event && hwc->sample_period == 1;
+       return hw_event == bts_event && period == 1;
+}
+
+static inline bool intel_pmu_has_bts(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       return intel_pmu_has_bts_period(event, hwc->sample_period);
 }
 
 int intel_pmu_save_and_restart(struct perf_event *event);
index f65b78d32f5eb7bb0a926c7c4e49b41cb0e66969..7dbbe9ffda173dd25456c1ca70b34a8883a98c60 100644 (file)
@@ -51,7 +51,7 @@ static unsigned long get_dr(int n)
 /*
  * fill in the user structure for a core dump..
  */
-static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
+static void fill_dump(struct pt_regs *regs, struct user32 *dump)
 {
        u32 fs, gs;
        memset(dump, 0, sizeof(*dump));
@@ -157,10 +157,12 @@ static int aout_core_dump(struct coredump_params *cprm)
        fs = get_fs();
        set_fs(KERNEL_DS);
        has_dumped = 1;
+
+       fill_dump(cprm->regs, &dump);
+
        strncpy(dump.u_comm, current->comm, sizeof(current->comm));
        dump.u_ar0 = offsetof(struct user32, regs);
        dump.signal = cprm->siginfo->si_signo;
-       dump_thread32(cprm->regs, &dump);
 
        /*
         * If the size of the dump file exceeds the rlimit, then see
index 0dd6b0f4000e86d80be7b38b29f33bfa9ac61e8f..9f15384c504a407818168966610b36d3798a6683 100644 (file)
@@ -6,7 +6,7 @@
  * "Big Core" Processors (Branded as Core, Xeon, etc...)
  *
  * The "_X" parts are generally the EP and EX Xeons, or the
- * "Extreme" ones, like Broadwell-E.
+ * "Extreme" ones, like Broadwell-E, or Atom microserver.
  *
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
@@ -52,6 +52,8 @@
 
 #define INTEL_FAM6_CANNONLAKE_MOBILE   0x66
 
+#define INTEL_FAM6_ICELAKE_MOBILE      0x7E
+
 /* "Small Core" Processors (Atom) */
 
 #define INTEL_FAM6_ATOM_BONNELL                0x1C /* Diamondville, Pineview */
@@ -71,6 +73,7 @@
 #define INTEL_FAM6_ATOM_GOLDMONT       0x5C /* Apollo Lake */
 #define INTEL_FAM6_ATOM_GOLDMONT_X     0x5F /* Denverton */
 #define INTEL_FAM6_ATOM_GOLDMONT_PLUS  0x7A /* Gemini Lake */
+#define INTEL_FAM6_ATOM_TREMONT_X      0x86 /* Jacobsville */
 
 /* Xeon Phi */
 
index 0ca50611e8cec0b5af0f29947bee90761bc76ef1..19d18fae6ec660e8119f21d2f80cf0ac3552486e 100644 (file)
@@ -178,6 +178,10 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next)
 
 void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk);
 
+/*
+ * Init a new mm.  Used on mm copies, like at fork()
+ * and on mm's that are brand-new, like at execve().
+ */
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
 {
@@ -228,8 +232,22 @@ do {                                               \
 } while (0)
 #endif
 
+static inline void arch_dup_pkeys(struct mm_struct *oldmm,
+                                 struct mm_struct *mm)
+{
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+       if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
+               return;
+
+       /* Duplicate the oldmm pkey state in mm: */
+       mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map;
+       mm->context.execute_only_pkey   = oldmm->context.execute_only_pkey;
+#endif
+}
+
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
+       arch_dup_pkeys(oldmm, mm);
        paravirt_arch_dup_mmap(oldmm, mm);
        return ldt_dup_context(oldmm, mm);
 }
index 8f657286d599a9577dca86b46b8199c9c547a661..0ce558a8150d34fe6c3476274bae038f43a291a0 100644 (file)
@@ -7,7 +7,11 @@
 #endif
 
 #ifdef CONFIG_KASAN
+#ifdef CONFIG_KASAN_EXTRA
+#define KASAN_STACK_ORDER 2
+#else
 #define KASAN_STACK_ORDER 1
+#endif
 #else
 #define KASAN_STACK_ORDER 0
 #endif
index 40616e805292421b8277b5d2abca04ff3279e0e4..2779ace16d23f21d5cb7b65faf87f384b3b05268 100644 (file)
@@ -1065,7 +1065,7 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
 static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                              pmd_t *pmdp, pmd_t pmd)
 {
-       native_set_pmd(pmdp, pmd);
+       set_pmd(pmdp, pmd);
 }
 
 static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
index 40ebddde6ac21205f4622b16edc790c6b323a1b0..f6b7fe2833cc72a78bed2c0cad3b59b8c6eb4f23 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _ASM_X86_RESCTRL_SCHED_H
 #define _ASM_X86_RESCTRL_SCHED_H
 
-#ifdef CONFIG_X86_RESCTRL
+#ifdef CONFIG_X86_CPU_RESCTRL
 
 #include <linux/sched.h>
 #include <linux/jump_label.h>
@@ -88,6 +88,6 @@ static inline void resctrl_sched_in(void)
 
 static inline void resctrl_sched_in(void) {}
 
-#endif /* CONFIG_X86_RESCTRL */
+#endif /* CONFIG_X86_CPU_RESCTRL */
 
 #endif /* _ASM_X86_RESCTRL_SCHED_H */
index a77445d1b0348675b5b750ad6acd617321b49b1b..780f2b42c8efe76b5d78291d4b633dd26b6e5c64 100644 (file)
@@ -711,7 +711,7 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
 {
        if (unlikely(!access_ok(ptr,len)))
                return 0;
-       __uaccess_begin();
+       __uaccess_begin_nospec();
        return 1;
 }
 #define user_access_begin(a,b) user_access_begin(a,b)
index e652a7cc61863667fad8ff2baa0a7242485600df..3f697a9e3f59b37e4fa37cf0f672114a2d84312b 100644 (file)
@@ -48,7 +48,8 @@ enum {
        BIOS_STATUS_SUCCESS             =  0,
        BIOS_STATUS_UNIMPLEMENTED       = -ENOSYS,
        BIOS_STATUS_EINVAL              = -EINVAL,
-       BIOS_STATUS_UNAVAIL             = -EBUSY
+       BIOS_STATUS_UNAVAIL             = -EBUSY,
+       BIOS_STATUS_ABORT               = -EINTR,
 };
 
 /* Address map parameters */
@@ -167,4 +168,9 @@ extern long system_serial_number;
 
 extern struct kobject *sgi_uv_kobj;    /* /sys/firmware/sgi_uv */
 
+/*
+ * EFI runtime lock; cf. firmware/efi/runtime-wrappers.c for details
+ */
+extern struct semaphore __efi_uv_runtime_lock;
+
 #endif /* _ASM_X86_UV_BIOS_H */
index b6fa0869f7aa141bd9cb1af9d328b1340b40c7e5..cfd24f9f761442392c9d42540835c31001bda71f 100644 (file)
@@ -39,7 +39,7 @@ obj-$(CONFIG_CPU_SUP_UMC_32)          += umc.o
 obj-$(CONFIG_X86_MCE)                  += mce/
 obj-$(CONFIG_MTRR)                     += mtrr/
 obj-$(CONFIG_MICROCODE)                        += microcode/
-obj-$(CONFIG_X86_RESCTRL)              += resctrl/
+obj-$(CONFIG_X86_CPU_RESCTRL)          += resctrl/
 
 obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o
 
index 1de0f417017833ec2580e5c95e16870dbcd1c424..01874d54f4fd955d4e16b8fcf0c76d81112eddb7 100644 (file)
@@ -71,7 +71,7 @@ void __init check_bugs(void)
         * identify_boot_cpu() initialized SMT support information, let the
         * core code know.
         */
-       cpu_smt_check_topology_early();
+       cpu_smt_check_topology();
 
        if (!IS_ENABLED(CONFIG_SMP)) {
                pr_info("CPU: ");
index 672c7225cb1b89426b682f40b4a4b33a73803d89..6ce290c506d93e83318f3b13b95d8f5861e02983 100644 (file)
@@ -784,6 +784,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
                        quirk_no_way_out(i, m, regs);
 
                if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
+                       m->bank = i;
                        mce_read_aux(m, i);
                        *msg = tmp;
                        return 1;
index 51adde0a0f1a0cf1686cf8fda386b052f6e1ef9d..e1f3ba19ba54fc062abdb10bbe5b9d81ccfb182b 100644 (file)
@@ -855,7 +855,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
        if (!p) {
                return ret;
        } else {
-               if (boot_cpu_data.microcode == p->patch_id)
+               if (boot_cpu_data.microcode >= p->patch_id)
                        return ret;
 
                ret = UCODE_NEW;
index 1cabe6fd8e115e508b162c9dac910c76c75648c6..4a06c37b9cf11bef1b00b546e3c2344691e6e18a 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_X86_RESCTRL)      += core.o rdtgroup.o monitor.o
-obj-$(CONFIG_X86_RESCTRL)      += ctrlmondata.o pseudo_lock.o
+obj-$(CONFIG_X86_CPU_RESCTRL)  += core.o rdtgroup.o monitor.o
+obj-$(CONFIG_X86_CPU_RESCTRL)  += ctrlmondata.o pseudo_lock.o
 CFLAGS_pseudo_lock.o = -I$(src)
index c8b07d8ea5a2bba61448b169a0cd0ea3daa086ad..17ffc869cab822d03e85baea56bade232a0e4598 100644 (file)
@@ -470,6 +470,7 @@ int crash_load_segments(struct kimage *image)
 
        kbuf.memsz = kbuf.bufsz;
        kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
+       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret) {
                vfree((void *)image->arch.elf_headers);
index b0acb22e5a465096b37f7a67a689852685228087..dfd3aca82c61cbe345f462a62ea6b52fa0b81516 100644 (file)
 
 #define HPET_MASK                      CLOCKSOURCE_MASK(32)
 
-/* FSEC = 10^-15
-   NSEC = 10^-9 */
-#define FSEC_PER_NSEC                  1000000L
-
 #define HPET_DEV_USED_BIT              2
 #define HPET_DEV_USED                  (1 << HPET_DEV_USED_BIT)
 #define HPET_DEV_VALID                 0x8
index 278cd07228dd886778cabf708dd2b1237a318d72..53917a3ebf949632b33617482549265cd08c6ceb 100644 (file)
@@ -167,6 +167,9 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
        struct efi_info *current_ei = &boot_params.efi_info;
        struct efi_info *ei = &params->efi_info;
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES))
+               return 0;
+
        if (!current_ei->efi_memmap_size)
                return 0;
 
@@ -434,6 +437,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
        kbuf.memsz = PAGE_ALIGN(header->init_size);
        kbuf.buf_align = header->kernel_alignment;
        kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret)
                goto out_free_params;
@@ -448,6 +452,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
                kbuf.bufsz = kbuf.memsz = initrd_len;
                kbuf.buf_align = PAGE_SIZE;
                kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
+               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
                ret = kexec_add_buffer(&kbuf);
                if (ret)
                        goto out_free_params;
index ba4bfb7f6a36996a806a634bf3c4a86bd594129f..5c93a65ee1e5c2ec56e83eda147bc1bc31e159cd 100644 (file)
@@ -457,6 +457,7 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
 #else
        u64 ipi_bitmap = 0;
 #endif
+       long ret;
 
        if (cpumask_empty(mask))
                return;
@@ -482,8 +483,9 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
                } else if (apic_id < min + KVM_IPI_CLUSTER_SIZE) {
                        max = apic_id < max ? max : apic_id;
                } else {
-                       kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+                       ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
                                (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr);
+                       WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret);
                        min = max = apic_id;
                        ipi_bitmap = 0;
                }
@@ -491,8 +493,9 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
        }
 
        if (ipi_bitmap) {
-               kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+               ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
                        (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr);
+               WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret);
        }
 
        local_irq_restore(flags);
index e9f777bfed404340a36de19898fffd129610fc3c..3fae238340699376ef2b5f84d4b6d4c7f60c48c5 100644 (file)
@@ -297,15 +297,16 @@ static int __init tsc_setup(char *str)
 
 __setup("tsc=", tsc_setup);
 
-#define MAX_RETRIES     5
-#define SMI_TRESHOLD    50000
+#define MAX_RETRIES            5
+#define TSC_DEFAULT_THRESHOLD  0x20000
 
 /*
- * Read TSC and the reference counters. Take care of SMI disturbance
+ * Read TSC and the reference counters. Take care of any disturbances
  */
 static u64 tsc_read_refs(u64 *p, int hpet)
 {
        u64 t1, t2;
+       u64 thresh = tsc_khz ? tsc_khz >> 5 : TSC_DEFAULT_THRESHOLD;
        int i;
 
        for (i = 0; i < MAX_RETRIES; i++) {
@@ -315,7 +316,7 @@ static u64 tsc_read_refs(u64 *p, int hpet)
                else
                        *p = acpi_pm_read_early();
                t2 = get_cycles();
-               if ((t2 - t1) < SMI_TRESHOLD)
+               if ((t2 - t1) < thresh)
                        return t2;
        }
        return ULLONG_MAX;
@@ -703,15 +704,15 @@ static unsigned long pit_hpet_ptimer_calibrate_cpu(void)
         * zero. In each wait loop iteration we read the TSC and check
         * the delta to the previous read. We keep track of the min
         * and max values of that delta. The delta is mostly defined
-        * by the IO time of the PIT access, so we can detect when a
-        * SMI/SMM disturbance happened between the two reads. If the
+        * by the IO time of the PIT access, so we can detect when
+        * any disturbance happened between the two reads. If the
         * maximum time is significantly larger than the minimum time,
         * then we discard the result and have another try.
         *
         * 2) Reference counter. If available we use the HPET or the
         * PMTIMER as a reference to check the sanity of that value.
         * We use separate TSC readouts and check inside of the
-        * reference read for a SMI/SMM disturbance. We dicard
+        * reference read for any possible disturbance. We dicard
         * disturbed values here as well. We do that around the PIT
         * calibration delay loop as we have to wait for a certain
         * amount of time anyway.
@@ -744,7 +745,7 @@ static unsigned long pit_hpet_ptimer_calibrate_cpu(void)
                if (ref1 == ref2)
                        continue;
 
-               /* Check, whether the sampling was disturbed by an SMI */
+               /* Check, whether the sampling was disturbed */
                if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX)
                        continue;
 
@@ -1268,7 +1269,7 @@ static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
  */
 static void tsc_refine_calibration_work(struct work_struct *work)
 {
-       static u64 tsc_start = -1, ref_start;
+       static u64 tsc_start = ULLONG_MAX, ref_start;
        static int hpet;
        u64 tsc_stop, ref_stop, delta;
        unsigned long freq;
@@ -1283,14 +1284,15 @@ static void tsc_refine_calibration_work(struct work_struct *work)
         * delayed the first time we expire. So set the workqueue
         * again once we know timers are working.
         */
-       if (tsc_start == -1) {
+       if (tsc_start == ULLONG_MAX) {
+restart:
                /*
                 * Only set hpet once, to avoid mixing hardware
                 * if the hpet becomes enabled later.
                 */
                hpet = is_hpet_enabled();
-               schedule_delayed_work(&tsc_irqwork, HZ);
                tsc_start = tsc_read_refs(&ref_start, hpet);
+               schedule_delayed_work(&tsc_irqwork, HZ);
                return;
        }
 
@@ -1300,9 +1302,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
        if (ref_start == ref_stop)
                goto out;
 
-       /* Check, whether the sampling was disturbed by an SMI */
-       if (tsc_start == ULLONG_MAX || tsc_stop == ULLONG_MAX)
-               goto out;
+       /* Check, whether the sampling was disturbed */
+       if (tsc_stop == ULLONG_MAX)
+               goto restart;
 
        delta = tsc_stop - tsc_start;
        delta *= 1000000LL;
index 69b3a7c3001397f65f9cfde541b042347827ee98..31ecf7a76d5a40474e2bc833f9834797e10f295f 100644 (file)
@@ -2,10 +2,6 @@
 
 ccflags-y += -Iarch/x86/kvm
 
-CFLAGS_x86.o := -I.
-CFLAGS_svm.o := -I.
-CFLAGS_vmx.o := -I.
-
 KVM := ../../../virt/kvm
 
 kvm-y                  += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
index c90a5352d158fa29ff72b42cd11efba0163225e2..89d20ed1d2e8bf7abe753adba301ef2b31ae8398 100644 (file)
@@ -1636,7 +1636,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
                ret = kvm_hvcall_signal_event(vcpu, fast, ingpa);
                if (ret != HV_STATUS_INVALID_PORT_ID)
                        break;
-               /* maybe userspace knows this conn_id: fall through */
+               /* fall through - maybe userspace knows this conn_id. */
        case HVCALL_POST_MESSAGE:
                /* don't bother userspace if it has no way to handle it */
                if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) {
@@ -1832,7 +1832,6 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                        ent->eax |= HV_X64_MSR_VP_INDEX_AVAILABLE;
                        ent->eax |= HV_X64_MSR_RESET_AVAILABLE;
                        ent->eax |= HV_MSR_REFERENCE_TSC_AVAILABLE;
-                       ent->eax |= HV_X64_MSR_GUEST_IDLE_AVAILABLE;
                        ent->eax |= HV_X64_ACCESS_FREQUENCY_MSRS;
                        ent->eax |= HV_X64_ACCESS_REENLIGHTENMENT;
 
@@ -1848,11 +1847,11 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                case HYPERV_CPUID_ENLIGHTMENT_INFO:
                        ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED;
                        ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
-                       ent->eax |= HV_X64_SYSTEM_RESET_RECOMMENDED;
                        ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
                        ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED;
                        ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED;
-                       ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
+                       if (evmcs_ver)
+                               ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
 
                        /*
                         * Default number of spinlock retry attempts, matches
index 9f089e2e09d02b7585a9b9c1203549c62576112f..4b6c2da7265c88f8f530eb026ba6b0e950eac51e 100644 (file)
@@ -1035,6 +1035,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
        switch (delivery_mode) {
        case APIC_DM_LOWEST:
                vcpu->arch.apic_arb_prio++;
+               /* fall through */
        case APIC_DM_FIXED:
                if (unlikely(trig_mode && !level))
                        break;
@@ -1874,6 +1875,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
        case APIC_LVT0:
                apic_manage_nmi_watchdog(apic, val);
+               /* fall through */
        case APIC_LVTTHMR:
        case APIC_LVTPC:
        case APIC_LVT1:
index ce770b446238592e985bba826aefdf3bd4e6efcc..da9c42349b1f800ec06ad3441be7ade3f852248f 100644 (file)
@@ -4371,6 +4371,7 @@ __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                        rsvd_bits(maxphyaddr, 51);
                rsvd_check->rsvd_bits_mask[1][4] =
                        rsvd_check->rsvd_bits_mask[0][4];
+               /* fall through */
        case PT64_ROOT_4LEVEL:
                rsvd_check->rsvd_bits_mask[0][3] = exb_bit_rsvd |
                        nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
index a157ca5b686955bbf9942f6a6f3b68247f7bb5cb..f13a3a24d3609e03b2bd849c0058ff41a670f2ca 100644 (file)
@@ -3414,6 +3414,14 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
        kvm_mmu_reset_context(&svm->vcpu);
        kvm_mmu_load(&svm->vcpu);
 
+       /*
+        * Drop what we picked up for L2 via svm_complete_interrupts() so it
+        * doesn't end up in L1.
+        */
+       svm->vcpu.arch.nmi_injected = false;
+       kvm_clear_exception_queue(&svm->vcpu);
+       kvm_clear_interrupt_queue(&svm->vcpu);
+
        return 0;
 }
 
@@ -4395,7 +4403,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
        case MSR_IA32_APICBASE:
                if (kvm_vcpu_apicv_active(vcpu))
                        avic_update_vapic_bar(to_svm(vcpu), data);
-               /* Follow through */
+               /* Fall through */
        default:
                return kvm_set_msr_common(vcpu, msr);
        }
@@ -4504,28 +4512,19 @@ static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
                kvm_lapic_reg_write(apic, APIC_ICR, icrl);
                break;
        case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
-               int i;
-               struct kvm_vcpu *vcpu;
-               struct kvm *kvm = svm->vcpu.kvm;
                struct kvm_lapic *apic = svm->vcpu.arch.apic;
 
                /*
-                * At this point, we expect that the AVIC HW has already
-                * set the appropriate IRR bits on the valid target
-                * vcpus. So, we just need to kick the appropriate vcpu.
+                * Update ICR high and low, then emulate sending IPI,
+                * which is handled when writing APIC_ICR.
                 */
-               kvm_for_each_vcpu(i, vcpu, kvm) {
-                       bool m = kvm_apic_match_dest(vcpu, apic,
-                                                    icrl & KVM_APIC_SHORT_MASK,
-                                                    GET_APIC_DEST_FIELD(icrh),
-                                                    icrl & KVM_APIC_DEST_MASK);
-
-                       if (m && !avic_vcpu_is_running(vcpu))
-                               kvm_vcpu_wake_up(vcpu);
-               }
+               kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
+               kvm_lapic_reg_write(apic, APIC_ICR, icrl);
                break;
        }
        case AVIC_IPI_FAILURE_INVALID_TARGET:
+               WARN_ONCE(1, "Invalid IPI target: index=%u, vcpu=%d, icr=%#0x:%#0x\n",
+                         index, svm->vcpu.vcpu_id, icrh, icrl);
                break;
        case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
                WARN_ONCE(1, "Invalid backing page\n");
index 705f40ae25329ca74fee07191a9104e0945dba92..6432d08c7de79ccbde654b7ab17c9649b75a25c2 100644 (file)
@@ -1465,7 +1465,7 @@ TRACE_EVENT(kvm_hv_send_ipi_ex,
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH arch/x86/kvm
+#define TRACE_INCLUDE_PATH ../../arch/x86/kvm
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 95bc2247478d90bda1d9305f11986f85db908e5b..5466c6d85cf3ef07388e47012b88fb478ac0d5c2 100644 (file)
@@ -332,16 +332,17 @@ int nested_enable_evmcs(struct kvm_vcpu *vcpu,
                        uint16_t *vmcs_version)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
+       bool evmcs_already_enabled = vmx->nested.enlightened_vmcs_enabled;
+
+       vmx->nested.enlightened_vmcs_enabled = true;
 
        if (vmcs_version)
                *vmcs_version = nested_get_evmcs_version(vcpu);
 
        /* We don't support disabling the feature for simplicity. */
-       if (vmx->nested.enlightened_vmcs_enabled)
+       if (evmcs_already_enabled)
                return 0;
 
-       vmx->nested.enlightened_vmcs_enabled = true;
-
        vmx->nested.msrs.pinbased_ctls_high &= ~EVMCS1_UNSUPPORTED_PINCTRL;
        vmx->nested.msrs.entry_ctls_high &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
        vmx->nested.msrs.exit_ctls_high &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
index 2616bd2c7f2c78b25339eff719d37a22b9070404..d737a51a53ca368b3a223e2ed41e397a7abbafbd 100644 (file)
@@ -55,7 +55,7 @@ static u16 shadow_read_write_fields[] = {
 static int max_shadow_read_write_fields =
        ARRAY_SIZE(shadow_read_write_fields);
 
-void init_vmcs_shadow_fields(void)
+static void init_vmcs_shadow_fields(void)
 {
        int i, j;
 
@@ -211,6 +211,7 @@ static void free_nested(struct kvm_vcpu *vcpu)
        if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
                return;
 
+       hrtimer_cancel(&vmx->nested.preemption_timer);
        vmx->nested.vmxon = false;
        vmx->nested.smm.vmxon = false;
        free_vpid(vmx->nested.vpid02);
@@ -2472,6 +2473,10 @@ static int nested_check_vm_execution_controls(struct kvm_vcpu *vcpu,
            (nested_cpu_has_vpid(vmcs12) && !vmcs12->virtual_processor_id))
                return -EINVAL;
 
+       if (!nested_cpu_has_preemption_timer(vmcs12) &&
+           nested_cpu_has_save_preemption_timer(vmcs12))
+               return -EINVAL;
+
        if (nested_cpu_has_ept(vmcs12) &&
            !valid_ept_address(vcpu, vmcs12->ept_pointer))
                return -EINVAL;
@@ -4140,11 +4145,11 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu)
        if (r < 0)
                goto out_vmcs02;
 
-       vmx->nested.cached_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
+       vmx->nested.cached_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
        if (!vmx->nested.cached_vmcs12)
                goto out_cached_vmcs12;
 
-       vmx->nested.cached_shadow_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
+       vmx->nested.cached_shadow_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
        if (!vmx->nested.cached_shadow_vmcs12)
                goto out_cached_shadow_vmcs12;
 
@@ -5263,13 +5268,17 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
                        copy_shadow_to_vmcs12(vmx);
        }
 
-       if (copy_to_user(user_kvm_nested_state->data, vmcs12, sizeof(*vmcs12)))
+       /*
+        * Copy over the full allocated size of vmcs12 rather than just the size
+        * of the struct.
+        */
+       if (copy_to_user(user_kvm_nested_state->data, vmcs12, VMCS12_SIZE))
                return -EFAULT;
 
        if (nested_cpu_has_shadow_vmcs(vmcs12) &&
            vmcs12->vmcs_link_pointer != -1ull) {
                if (copy_to_user(user_kvm_nested_state->data + VMCS12_SIZE,
-                                get_shadow_vmcs12(vcpu), sizeof(*vmcs12)))
+                                get_shadow_vmcs12(vcpu), VMCS12_SIZE))
                        return -EFAULT;
        }
 
@@ -5552,9 +5561,11 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
         * secondary cpu-based controls.  Do not include those that
         * depend on CPUID bits, they are added later by vmx_cpuid_update.
         */
-       rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
-               msrs->secondary_ctls_low,
-               msrs->secondary_ctls_high);
+       if (msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
+               rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
+                     msrs->secondary_ctls_low,
+                     msrs->secondary_ctls_high);
+
        msrs->secondary_ctls_low = 0;
        msrs->secondary_ctls_high &=
                SECONDARY_EXEC_DESC |
index f6915f10e584a5f568e2e6a38123ac70c4d3881c..30a6bcd735ec36e4163b6e9a72ce26ff3f6b356a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
+#include <linux/sched/smt.h>
 #include <linux/slab.h>
 #include <linux/tboot.h>
 #include <linux/trace_events.h>
@@ -423,7 +424,7 @@ static void check_ept_pointer_match(struct kvm *kvm)
        to_kvm_vmx(kvm)->ept_pointers_match = EPT_POINTERS_MATCH;
 }
 
-int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
+static int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
                void *data)
 {
        struct kvm_tlb_range *range = data;
@@ -862,7 +863,8 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
        if (!entry_only)
                j = find_msr(&m->host, msr);
 
-       if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) {
+       if ((i < 0 && m->guest.nr == NR_AUTOLOAD_MSRS) ||
+               (j < 0 &&  m->host.nr == NR_AUTOLOAD_MSRS)) {
                printk_once(KERN_WARNING "Not enough msr switch entries. "
                                "Can't add msr %x\n", msr);
                return;
@@ -1192,21 +1194,6 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
        if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
                return;
 
-       /*
-        * First handle the simple case where no cmpxchg is necessary; just
-        * allow posting non-urgent interrupts.
-        *
-        * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
-        * PI.NDST: pi_post_block will do it for us and the wakeup_handler
-        * expects the VCPU to be on the blocked_vcpu_list that matches
-        * PI.NDST.
-        */
-       if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
-           vcpu->cpu == cpu) {
-               pi_clear_sn(pi_desc);
-               return;
-       }
-
        /* The full case.  */
        do {
                old.control = new.control = pi_desc->control;
@@ -1221,6 +1208,17 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
                new.sn = 0;
        } while (cmpxchg64(&pi_desc->control, old.control,
                           new.control) != old.control);
+
+       /*
+        * Clear SN before reading the bitmap.  The VT-d firmware
+        * writes the bitmap and reads SN atomically (5.2.3 in the
+        * spec), so it doesn't really have a memory barrier that
+        * pairs with this, but we cannot do that and we need one.
+        */
+       smp_mb__after_atomic();
+
+       if (!bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS))
+               pi_set_on(pi_desc);
 }
 
 /*
@@ -1773,7 +1771,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                if (!msr_info->host_initiated &&
                    !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
                        return 1;
-               /* Otherwise falls through */
+               /* Else, falls through */
        default:
                msr = find_msr_entry(vmx, msr_info->index);
                if (msr) {
@@ -2014,7 +2012,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                /* Check reserved bit, higher 32 bits should be zero */
                if ((data >> 32) != 0)
                        return 1;
-               /* Otherwise falls through */
+               /* Else, falls through */
        default:
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
@@ -2344,7 +2342,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                case 37: /* AAT100 */
                case 44: /* BC86,AAY89,BD102 */
                case 46: /* BA97 */
-                       _vmexit_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+                       _vmentry_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
                        _vmexit_control &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
                        pr_warn_once("kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
                                        "does not work properly. Using workaround\n");
@@ -6362,72 +6360,9 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
        vmx->loaded_vmcs->hv_timer_armed = false;
 }
 
-static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+static void __vmx_vcpu_run(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       unsigned long cr3, cr4, evmcs_rsp;
-
-       /* Record the guest's net vcpu time for enforced NMI injections. */
-       if (unlikely(!enable_vnmi &&
-                    vmx->loaded_vmcs->soft_vnmi_blocked))
-               vmx->loaded_vmcs->entry_time = ktime_get();
-
-       /* Don't enter VMX if guest state is invalid, let the exit handler
-          start emulation until we arrive back to a valid state */
-       if (vmx->emulation_required)
-               return;
-
-       if (vmx->ple_window_dirty) {
-               vmx->ple_window_dirty = false;
-               vmcs_write32(PLE_WINDOW, vmx->ple_window);
-       }
-
-       if (vmx->nested.need_vmcs12_sync)
-               nested_sync_from_vmcs12(vcpu);
-
-       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
-               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
-       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
-               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
-
-       cr3 = __get_current_cr3_fast();
-       if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
-               vmcs_writel(HOST_CR3, cr3);
-               vmx->loaded_vmcs->host_state.cr3 = cr3;
-       }
-
-       cr4 = cr4_read_shadow();
-       if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
-               vmcs_writel(HOST_CR4, cr4);
-               vmx->loaded_vmcs->host_state.cr4 = cr4;
-       }
-
-       /* When single-stepping over STI and MOV SS, we must clear the
-        * corresponding interruptibility bits in the guest state. Otherwise
-        * vmentry fails as it then expects bit 14 (BS) in pending debug
-        * exceptions being set, but that's not correct for the guest debugging
-        * case. */
-       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-               vmx_set_interrupt_shadow(vcpu, 0);
-
-       if (static_cpu_has(X86_FEATURE_PKU) &&
-           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
-           vcpu->arch.pkru != vmx->host_pkru)
-               __write_pkru(vcpu->arch.pkru);
-
-       pt_guest_enter(vmx);
-
-       atomic_switch_perf_msrs(vmx);
-
-       vmx_update_hv_timer(vcpu);
-
-       /*
-        * If this vCPU has touched SPEC_CTRL, restore the guest's value if
-        * it's non-zero. Since vmentry is serialising on affected CPUs, there
-        * is no need to worry about the conditional branch over the wrmsr
-        * being speculatively taken.
-        */
-       x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+       unsigned long evmcs_rsp;
 
        vmx->__launched = vmx->loaded_vmcs->launched;
 
@@ -6567,6 +6502,77 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
                , "eax", "ebx", "edi"
 #endif
              );
+}
+STACK_FRAME_NON_STANDARD(__vmx_vcpu_run);
+
+static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       unsigned long cr3, cr4;
+
+       /* Record the guest's net vcpu time for enforced NMI injections. */
+       if (unlikely(!enable_vnmi &&
+                    vmx->loaded_vmcs->soft_vnmi_blocked))
+               vmx->loaded_vmcs->entry_time = ktime_get();
+
+       /* Don't enter VMX if guest state is invalid, let the exit handler
+          start emulation until we arrive back to a valid state */
+       if (vmx->emulation_required)
+               return;
+
+       if (vmx->ple_window_dirty) {
+               vmx->ple_window_dirty = false;
+               vmcs_write32(PLE_WINDOW, vmx->ple_window);
+       }
+
+       if (vmx->nested.need_vmcs12_sync)
+               nested_sync_from_vmcs12(vcpu);
+
+       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
+       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
+
+       cr3 = __get_current_cr3_fast();
+       if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
+               vmcs_writel(HOST_CR3, cr3);
+               vmx->loaded_vmcs->host_state.cr3 = cr3;
+       }
+
+       cr4 = cr4_read_shadow();
+       if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
+               vmcs_writel(HOST_CR4, cr4);
+               vmx->loaded_vmcs->host_state.cr4 = cr4;
+       }
+
+       /* When single-stepping over STI and MOV SS, we must clear the
+        * corresponding interruptibility bits in the guest state. Otherwise
+        * vmentry fails as it then expects bit 14 (BS) in pending debug
+        * exceptions being set, but that's not correct for the guest debugging
+        * case. */
+       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+               vmx_set_interrupt_shadow(vcpu, 0);
+
+       if (static_cpu_has(X86_FEATURE_PKU) &&
+           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
+           vcpu->arch.pkru != vmx->host_pkru)
+               __write_pkru(vcpu->arch.pkru);
+
+       pt_guest_enter(vmx);
+
+       atomic_switch_perf_msrs(vmx);
+
+       vmx_update_hv_timer(vcpu);
+
+       /*
+        * If this vCPU has touched SPEC_CTRL, restore the guest's value if
+        * it's non-zero. Since vmentry is serialising on affected CPUs, there
+        * is no need to worry about the conditional branch over the wrmsr
+        * being speculatively taken.
+        */
+       x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+
+       __vmx_vcpu_run(vcpu, vmx);
 
        /*
         * We do not use IBRS in the kernel. If this vCPU has used the
@@ -6648,7 +6654,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
        vmx_recover_nmi_blocking(vmx);
        vmx_complete_interrupts(vmx);
 }
-STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
 
 static struct kvm *vmx_vm_alloc(void)
 {
@@ -6816,7 +6821,7 @@ static int vmx_vm_init(struct kvm *kvm)
                         * Warn upon starting the first VM in a potentially
                         * insecure environment.
                         */
-                       if (cpu_smt_control == CPU_SMT_ENABLED)
+                       if (sched_smt_active())
                                pr_warn_once(L1TF_MSG_SMT);
                        if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
                                pr_warn_once(L1TF_MSG_L1D);
index 99328954c2fc1c43d8573f727b0e9219a2828065..0ac0a64c7790fb772b31d61179480548e6d06082 100644 (file)
@@ -337,16 +337,16 @@ static inline int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
        return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
 }
 
-static inline void pi_clear_sn(struct pi_desc *pi_desc)
+static inline void pi_set_sn(struct pi_desc *pi_desc)
 {
-       return clear_bit(POSTED_INTR_SN,
+       return set_bit(POSTED_INTR_SN,
                        (unsigned long *)&pi_desc->control);
 }
 
-static inline void pi_set_sn(struct pi_desc *pi_desc)
+static inline void pi_set_on(struct pi_desc *pi_desc)
 {
-       return set_bit(POSTED_INTR_SN,
-                       (unsigned long *)&pi_desc->control);
+       set_bit(POSTED_INTR_ON,
+               (unsigned long *)&pi_desc->control);
 }
 
 static inline void pi_clear_on(struct pi_desc *pi_desc)
index 02c8e095a23907f821f2ae3f1dc958ec66af0a7b..941f932373d03547f606ea6a20fd6161c48c6398 100644 (file)
@@ -3834,6 +3834,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        case KVM_CAP_HYPERV_SYNIC2:
                if (cap->args[0])
                        return -EINVAL;
+               /* fall through */
+
        case KVM_CAP_HYPERV_SYNIC:
                if (!irqchip_in_kernel(vcpu->kvm))
                        return -EINVAL;
@@ -5114,6 +5116,13 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
 {
        u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 
+       /*
+        * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
+        * is returned, but our callers are not ready for that and they blindly
+        * call kvm_inject_page_fault.  Ensure that they at least do not leak
+        * uninitialized kernel stack memory into cr2 and error code.
+        */
+       memset(exception, 0, sizeof(*exception));
        return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
                                          exception);
 }
@@ -6480,8 +6489,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
                toggle_interruptibility(vcpu, ctxt->interruptibility);
                vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
                kvm_rip_write(vcpu, ctxt->eip);
-               if (r == EMULATE_DONE &&
-                   (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
+               if (r == EMULATE_DONE && ctxt->tf)
                        kvm_vcpu_do_singlestep(vcpu, &r);
                if (!ctxt->have_exception ||
                    exception_type(ctxt->exception.vector) == EXCPT_TRAP)
@@ -7093,10 +7101,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        case KVM_HC_CLOCK_PAIRING:
                ret = kvm_pv_clock_pairing(vcpu, a0, a1);
                break;
+#endif
        case KVM_HC_SEND_IPI:
                ret = kvm_pv_send_ipi(vcpu->kvm, a0, a1, a2, a3, op_64_bit);
                break;
-#endif
        default:
                ret = -KVM_ENOSYS;
                break;
@@ -7793,7 +7801,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
         * 1) We should set ->mode before checking ->requests.  Please see
         * the comment in kvm_vcpu_exiting_guest_mode().
         *
-        * 2) For APICv, we should set ->mode before checking PIR.ON.  This
+        * 2) For APICv, we should set ->mode before checking PID.ON. This
         * pairs with the memory barrier implicit in pi_test_and_set_on
         * (see vmx_deliver_posted_interrupt).
         *
@@ -7937,6 +7945,7 @@ static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu)
                vcpu->arch.pv.pv_unhalted = false;
                vcpu->arch.mp_state =
                        KVM_MP_STATE_RUNNABLE;
+               /* fall through */
        case KVM_MP_STATE_RUNNABLE:
                vcpu->arch.apf.halted = false;
                break;
index 66894675f3c8d3ac65c4efdae5039d904110c9b2..df50451d94ef7edf095defd0253aa7bb329123ab 100644 (file)
@@ -2,8 +2,11 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
+#define movs(type,to,from) \
+       asm volatile("movs" type:"=&D" (to), "=&S" (from):"0" (to), "1" (from):"memory")
+
 /* Originally from i386/string.h */
-static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n)
+static __always_inline void rep_movs(void *to, const void *from, size_t n)
 {
        unsigned long d0, d1, d2;
        asm volatile("rep ; movsl\n\t"
@@ -21,13 +24,37 @@ static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n)
 
 void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
 {
-       __iomem_memcpy(to, (const void *)from, n);
+       if (unlikely(!n))
+               return;
+
+       /* Align any unaligned source IO */
+       if (unlikely(1 & (unsigned long)from)) {
+               movs("b", to, from);
+               n--;
+       }
+       if (n > 1 && unlikely(2 & (unsigned long)from)) {
+               movs("w", to, from);
+               n-=2;
+       }
+       rep_movs(to, (const void *)from, n);
 }
 EXPORT_SYMBOL(memcpy_fromio);
 
 void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
 {
-       __iomem_memcpy((void *)to, (const void *) from, n);
+       if (unlikely(!n))
+               return;
+
+       /* Align any unaligned destination IO */
+       if (unlikely(1 & (unsigned long)to)) {
+               movs("b", to, from);
+               n--;
+       }
+       if (n > 1 && unlikely(2 & (unsigned long)to)) {
+               movs("w", to, from);
+               n-=2;
+       }
+       rep_movs((void *)to, (const void *) from, n);
 }
 EXPORT_SYMBOL(memcpy_toio);
 
index 79778ab200e494c16cac7441cdb5da9507940715..a536651164584c96a19b1455f743834291a355c6 100644 (file)
@@ -36,8 +36,8 @@ static inline u16 i8254(void)
        u16 status, timer;
 
        do {
-               outb(I8254_PORT_CONTROL,
-                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+               outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
+                    I8254_PORT_CONTROL);
                status = inb(I8254_PORT_COUNTER0);
                timer  = inb(I8254_PORT_COUNTER0);
                timer |= inb(I8254_PORT_COUNTER0) << 8;
index 2ff25ad33233877760ef1660c6d9503b70c0f312..9d5c75f0229567c49b1237a33b4c27a21cee3d68 100644 (file)
@@ -595,7 +595,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
                return;
        }
 
-       addr = desc.base0 | (desc.base1 << 16) | (desc.base2 << 24);
+       addr = desc.base0 | (desc.base1 << 16) | ((unsigned long)desc.base2 << 24);
 #ifdef CONFIG_X86_64
        addr |= ((u64)desc.base3 << 32);
 #endif
index a19ef1a416ff66f0f1c70928644815dc385aa1e0..4aa9b1480866b70d16dbeafdc711a3479de1d670 100644 (file)
@@ -158,8 +158,8 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
        pmd = pmd_offset(pud, ppd->vaddr);
        if (pmd_none(*pmd)) {
                pte = ppd->pgtable_area;
-               memset(pte, 0, sizeof(pte) * PTRS_PER_PTE);
-               ppd->pgtable_area += sizeof(pte) * PTRS_PER_PTE;
+               memset(pte, 0, sizeof(*pte) * PTRS_PER_PTE);
+               ppd->pgtable_area += sizeof(*pte) * PTRS_PER_PTE;
                set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte)));
        }
 
index 4f8972311a77ef931226996d4c0d86fb7327cd2f..14e6119838a6480d28de8c94f0a4c89273f51e7a 100644 (file)
@@ -230,6 +230,29 @@ static bool __cpa_pfn_in_highmap(unsigned long pfn)
 
 #endif
 
+/*
+ * See set_mce_nospec().
+ *
+ * Machine check recovery code needs to change cache mode of poisoned pages to
+ * UC to avoid speculative access logging another error. But passing the
+ * address of the 1:1 mapping to set_memory_uc() is a fine way to encourage a
+ * speculative access. So we cheat and flip the top bit of the address. This
+ * works fine for the code that updates the page tables. But at the end of the
+ * process we need to flush the TLB and cache and the non-canonical address
+ * causes a #GP fault when used by the INVLPG and CLFLUSH instructions.
+ *
+ * But in the common case we already have a canonical address. This code
+ * will fix the top bit if needed and is a no-op otherwise.
+ */
+static inline unsigned long fix_addr(unsigned long addr)
+{
+#ifdef CONFIG_X86_64
+       return (long)(addr << 1) >> 1;
+#else
+       return addr;
+#endif
+}
+
 static unsigned long __cpa_addr(struct cpa_data *cpa, unsigned long idx)
 {
        if (cpa->flags & CPA_PAGES_ARRAY) {
@@ -313,7 +336,7 @@ void __cpa_flush_tlb(void *data)
        unsigned int i;
 
        for (i = 0; i < cpa->numpages; i++)
-               __flush_tlb_one_kernel(__cpa_addr(cpa, i));
+               __flush_tlb_one_kernel(fix_addr(__cpa_addr(cpa, i)));
 }
 
 static void cpa_flush(struct cpa_data *data, int cache)
@@ -347,7 +370,7 @@ static void cpa_flush(struct cpa_data *data, int cache)
                 * Only flush present addresses:
                 */
                if (pte && (pte_val(*pte) & _PAGE_PRESENT))
-                       clflush_cache_range_opt((void *)addr, PAGE_SIZE);
+                       clflush_cache_range_opt((void *)fix_addr(addr), PAGE_SIZE);
        }
        mb();
 }
@@ -1627,29 +1650,6 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
        return ret;
 }
 
-/*
- * Machine check recovery code needs to change cache mode of poisoned
- * pages to UC to avoid speculative access logging another error. But
- * passing the address of the 1:1 mapping to set_memory_uc() is a fine
- * way to encourage a speculative access. So we cheat and flip the top
- * bit of the address. This works fine for the code that updates the
- * page tables. But at the end of the process we need to flush the cache
- * and the non-canonical address causes a #GP fault when used by the
- * CLFLUSH instruction.
- *
- * But in the common case we already have a canonical address. This code
- * will fix the top bit if needed and is a no-op otherwise.
- */
-static inline unsigned long make_addr_canonical_again(unsigned long addr)
-{
-#ifdef CONFIG_X86_64
-       return (long)(addr << 1) >> 1;
-#else
-       return addr;
-#endif
-}
-
-
 static int change_page_attr_set_clr(unsigned long *addr, int numpages,
                                    pgprot_t mask_set, pgprot_t mask_clr,
                                    int force_split, int in_flag,
index 4a6a5a26c58295e4245b09be21a658c3ddae86a2..eb33432f2f241db7475e32e651ae2bc9ca526361 100644 (file)
@@ -29,7 +29,8 @@
 
 struct uv_systab *uv_systab;
 
-s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
+                       u64 a4, u64 a5)
 {
        struct uv_systab *tab = uv_systab;
        s64 ret;
@@ -51,6 +52,19 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 
        return ret;
 }
+
+s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+{
+       s64 ret;
+
+       if (down_interruptible(&__efi_uv_runtime_lock))
+               return BIOS_STATUS_ABORT;
+
+       ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
+       up(&__efi_uv_runtime_lock);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(uv_bios_call);
 
 s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
@@ -59,10 +73,15 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
        unsigned long bios_flags;
        s64 ret;
 
+       if (down_interruptible(&__efi_uv_runtime_lock))
+               return BIOS_STATUS_ABORT;
+
        local_irq_save(bios_flags);
-       ret = uv_bios_call(which, a1, a2, a3, a4, a5);
+       ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
        local_irq_restore(bios_flags);
 
+       up(&__efi_uv_runtime_lock);
+
        return ret;
 }
 
index 2f6787fc710660aae1598c8e245d04101f77cb18..c54a493e139a78e37eab27cc36556396303a390e 100644 (file)
@@ -898,10 +898,7 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
        val = native_read_msr_safe(msr, err);
        switch (msr) {
        case MSR_IA32_APICBASE:
-#ifdef CONFIG_X86_X2APIC
-               if (!(cpuid_ecx(1) & (1 << (X86_FEATURE_X2APIC & 31))))
-#endif
-                       val &= ~X2APIC_ENABLE;
+               val &= ~X2APIC_ENABLE;
                break;
        }
        return val;
index 72bf446c3fee3456e9961c760a1b3d48520b1b37..6e29794573b72f18d9179a17d78d0981b84c5094 100644 (file)
@@ -361,8 +361,6 @@ void xen_timer_resume(void)
 {
        int cpu;
 
-       pvclock_resume();
-
        if (xen_clockevent != &xen_vcpuop_clockevent)
                return;
 
@@ -379,12 +377,15 @@ static const struct pv_time_ops xen_time_ops __initconst = {
 };
 
 static struct pvclock_vsyscall_time_info *xen_clock __read_mostly;
+static u64 xen_clock_value_saved;
 
 void xen_save_time_memory_area(void)
 {
        struct vcpu_register_time_memory_area t;
        int ret;
 
+       xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset;
+
        if (!xen_clock)
                return;
 
@@ -404,7 +405,7 @@ void xen_restore_time_memory_area(void)
        int ret;
 
        if (!xen_clock)
-               return;
+               goto out;
 
        t.addr.v = &xen_clock->pvti;
 
@@ -421,6 +422,11 @@ void xen_restore_time_memory_area(void)
        if (ret != 0)
                pr_notice("Cannot restore secondary vcpu_time_info (err %d)",
                          ret);
+
+out:
+       /* Need pvclock_resume() before using xen_clocksource_read(). */
+       pvclock_resume();
+       xen_sched_clock_offset = xen_clocksource_read() - xen_clock_value_saved;
 }
 
 static void xen_setup_vsyscall_time_info(void)
index 20a0756f27efffbecc3892cc1dee4c1d983483c7..ce91682770cb91c93749b2f3c1ba9e86a9d86102 100644 (file)
@@ -164,7 +164,7 @@ config XTENSA_FAKE_NMI
          If unsure, say N.
 
 config XTENSA_UNALIGNED_USER
-       bool "Unaligned memory access in use space"
+       bool "Unaligned memory access in user space"
        help
          The Xtensa architecture currently does not handle unaligned
          memory accesses in hardware but through an exception handler.
@@ -451,7 +451,7 @@ config USE_OF
        help
          Include support for flattened device tree machine descriptions.
 
-config BUILTIN_DTB
+config BUILTIN_DTB_SOURCE
        string "DTB to build into the kernel image"
        depends on OF
 
index f8052ba5aea8ca33754b0b4b996b2f3594aa06e1..0b8d00cdae7c26b1b87a8d6ae102128d0679b603 100644 (file)
@@ -7,9 +7,9 @@
 #
 #
 
-BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
-ifneq ($(CONFIG_BUILTIN_DTB),"")
-obj-$(CONFIG_OF) += $(BUILTIN_DTB)
+BUILTIN_DTB_SOURCE := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
+ifneq ($(CONFIG_BUILTIN_DTB_SOURCE),"")
+obj-$(CONFIG_OF) += $(BUILTIN_DTB_SOURCE)
 endif
 
 # for CONFIG_OF_ALL_DTBS test
index 2bf964df37bac3c8e4752c3047da6af10f01129f..f378e56f9ce6dba2cdb9597def885a61fe5e2a70 100644 (file)
@@ -34,7 +34,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705"
+CONFIG_BUILTIN_DTB_SOURCE="kc705"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM=y
index 3221b7053fa3c83dbe07e1c93ca29976ca7c1f3f..62f32a902568a2d6dea192e15201bf77c034e233 100644 (file)
@@ -38,7 +38,7 @@ CONFIG_HIGHMEM=y
 # CONFIG_PCI is not set
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="csp"
+CONFIG_BUILTIN_DTB_SOURCE="csp"
 # CONFIG_COMPACTION is not set
 CONFIG_XTFPGA_LCD=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
index 985fa8546e4e8d19fec0908efec4d6dd48ae44a5..8bebe07f10608f78215b4b39665924b64837564a 100644 (file)
@@ -33,7 +33,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705"
+CONFIG_BUILTIN_DTB_SOURCE="kc705"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
index f3fc4f970ca8e22b0f7c271bced6235640e787af..933ab2adf434e5f5a245d2d22a86140fd0ce8db0 100644 (file)
@@ -39,7 +39,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0x9d050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=256M@0x60000000"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705_nommu"
+CONFIG_BUILTIN_DTB_SOURCE="kc705_nommu"
 CONFIG_BINFMT_FLAT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
index 11fed6c06a7c668cc870589dab6bf2e7f241c1e1..e29c5b179a5b793cf6ab30a5f0771883588f6faf 100644 (file)
@@ -33,11 +33,12 @@ CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX is not set
 # CONFIG_PCI is not set
+CONFIG_VECTORS_OFFSET=0x00002000
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=96M@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="lx200mx"
+CONFIG_BUILTIN_DTB_SOURCE="lx200mx"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
index da08e75100aba2351f67d72e89ba880850499852..7f009719304efeaf29bd998043e37a729ef77636 100644 (file)
@@ -276,12 +276,13 @@ should_never_return:
 
        movi    a2, cpu_start_ccount
 1:
+       memw
        l32i    a3, a2, 0
        beqi    a3, 0, 1b
        movi    a3, 0
        s32i    a3, a2, 0
-       memw
 1:
+       memw
        l32i    a3, a2, 0
        beqi    a3, 0, 1b
        wsr     a3, ccount
@@ -317,11 +318,13 @@ ENTRY(cpu_restart)
        rsr     a0, prid
        neg     a2, a0
        movi    a3, cpu_start_id
+       memw
        s32i    a2, a3, 0
 #if XCHAL_DCACHE_IS_WRITEBACK
        dhwbi   a3, 0
 #endif
 1:
+       memw
        l32i    a2, a3, 0
        dhi     a3, 0
        bne     a2, a0, 1b
index 932d64689bacbbbf3dc2ae981b3d3d1938172bce..be1f280c322cd17307e0377736abdb3d955e3ebc 100644 (file)
@@ -83,7 +83,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        unsigned i;
 
-       for (i = 0; i < max_cpus; ++i)
+       for_each_possible_cpu(i)
                set_cpu_present(i, true);
 }
 
@@ -96,6 +96,11 @@ void __init smp_init_cpus(void)
        pr_info("%s: Core Count = %d\n", __func__, ncpus);
        pr_info("%s: Core Id = %d\n", __func__, core_id);
 
+       if (ncpus > NR_CPUS) {
+               ncpus = NR_CPUS;
+               pr_info("%s: limiting core count by %d\n", __func__, ncpus);
+       }
+
        for (i = 0; i < ncpus; ++i)
                set_cpu_possible(i, true);
 }
@@ -195,9 +200,11 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
        int i;
 
 #ifdef CONFIG_HOTPLUG_CPU
-       cpu_start_id = cpu;
-       system_flush_invalidate_dcache_range(
-                       (unsigned long)&cpu_start_id, sizeof(cpu_start_id));
+       WRITE_ONCE(cpu_start_id, cpu);
+       /* Pairs with the third memw in the cpu_restart */
+       mb();
+       system_flush_invalidate_dcache_range((unsigned long)&cpu_start_id,
+                                            sizeof(cpu_start_id));
 #endif
        smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
 
@@ -206,18 +213,21 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
                        ccount = get_ccount();
                while (!ccount);
 
-               cpu_start_ccount = ccount;
+               WRITE_ONCE(cpu_start_ccount, ccount);
 
-               while (time_before(jiffies, timeout)) {
+               do {
+                       /*
+                        * Pairs with the first two memws in the
+                        * .Lboot_secondary.
+                        */
                        mb();
-                       if (!cpu_start_ccount)
-                               break;
-               }
+                       ccount = READ_ONCE(cpu_start_ccount);
+               } while (ccount && time_before(jiffies, timeout));
 
-               if (cpu_start_ccount) {
+               if (ccount) {
                        smp_call_function_single(0, mx_cpu_stop,
-                                       (void *)cpu, 1);
-                       cpu_start_ccount = 0;
+                                                (void *)cpu, 1);
+                       WRITE_ONCE(cpu_start_ccount, 0);
                        return -EIO;
                }
        }
@@ -237,6 +247,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
                        __func__, cpu, idle, start_info.stack);
 
+       init_completion(&cpu_running);
        ret = boot_secondary(cpu, idle);
        if (ret == 0) {
                wait_for_completion_timeout(&cpu_running,
@@ -298,8 +309,10 @@ void __cpu_die(unsigned int cpu)
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        while (time_before(jiffies, timeout)) {
                system_invalidate_dcache_range((unsigned long)&cpu_start_id,
-                               sizeof(cpu_start_id));
-               if (cpu_start_id == -cpu) {
+                                              sizeof(cpu_start_id));
+               /* Pairs with the second memw in the cpu_restart */
+               mb();
+               if (READ_ONCE(cpu_start_id) == -cpu) {
                        platform_cpu_kill(cpu);
                        return;
                }
index fd524a54d2ab5e8f82e5485c6105f84d1a748b02..378186b5eb401aba9246756b5d235b60a4d697d5 100644 (file)
@@ -89,7 +89,7 @@ static int ccount_timer_shutdown(struct clock_event_device *evt)
                container_of(evt, struct ccount_timer, evt);
 
        if (timer->irq_enabled) {
-               disable_irq(evt->irq);
+               disable_irq_nosync(evt->irq);
                timer->irq_enabled = 0;
        }
        return 0;
index 63e0f12be7c98fe7770eb9f1e817f5319690c392..72adbbe975d5c7b281558870af6e212b27cd479d 100644 (file)
@@ -1154,15 +1154,14 @@ static void bfq_activate_requeue_entity(struct bfq_entity *entity,
 }
 
 /**
- * __bfq_deactivate_entity - deactivate an entity from its service tree.
- * @entity: the entity to deactivate.
+ * __bfq_deactivate_entity - update sched_data and service trees for
+ * entity, so as to represent entity as inactive
+ * @entity: the entity being deactivated.
  * @ins_into_idle_tree: if false, the entity will not be put into the
  *                     idle tree.
  *
- * Deactivates an entity, independently of its previous state.  Must
- * be invoked only if entity is on a service tree. Extracts the entity
- * from that tree, and if necessary and allowed, puts it into the idle
- * tree.
+ * If necessary and allowed, puts entity into the idle tree. NOTE:
+ * entity may be on no tree if in service.
  */
 bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree)
 {
index 3c5f61ceeb671ee1c9181eb7fbc3d1dc65327917..6b78ec56a4f2daef624edb1bb025a76aa3520b52 100644 (file)
@@ -462,6 +462,10 @@ static void blk_rq_timed_out_timer(struct timer_list *t)
        kblockd_schedule_work(&q->timeout_work);
 }
 
+static void blk_timeout_work(struct work_struct *work)
+{
+}
+
 /**
  * blk_alloc_queue_node - allocate a request queue
  * @gfp_mask: memory allocation flags
@@ -505,7 +509,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        timer_setup(&q->backing_dev_info->laptop_mode_wb_timer,
                    laptop_mode_timer_fn, 0);
        timer_setup(&q->timeout, blk_rq_timed_out_timer, 0);
-       INIT_WORK(&q->timeout_work, NULL);
+       INIT_WORK(&q->timeout_work, blk_timeout_work);
        INIT_LIST_HEAD(&q->icq_list);
 #ifdef CONFIG_BLK_CGROUP
        INIT_LIST_HEAD(&q->blkg_list);
index a3fc7191c69428a2f81b107f827a847e10be1e98..6e0f2d97fc6d8f0a5b14e6dbea23f817706bef7a 100644 (file)
@@ -335,7 +335,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error)
        blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error);
        spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 
-       blk_mq_run_hw_queue(hctx, true);
+       blk_mq_sched_restart(hctx);
 }
 
 /**
index fc714ef402a6a5d61840659e8f3e32c2301ae172..2620baa1f6993db5e6706a36240ab4c6a2931038 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/sched/loadavg.h>
 #include <linux/sched/signal.h>
 #include <trace/events/block.h>
+#include <linux/blk-mq.h>
 #include "blk-rq-qos.h"
 #include "blk-stat.h"
 
@@ -591,6 +592,7 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
        u64 now = ktime_to_ns(ktime_get());
        bool issue_as_root = bio_issue_as_root_blkg(bio);
        bool enabled = false;
+       int inflight = 0;
 
        blkg = bio->bi_blkg;
        if (!blkg || !bio_flagged(bio, BIO_TRACKED))
@@ -601,6 +603,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
                return;
 
        enabled = blk_iolatency_enabled(iolat->blkiolat);
+       if (!enabled)
+               return;
+
        while (blkg && blkg->parent) {
                iolat = blkg_to_lat(blkg);
                if (!iolat) {
@@ -609,8 +614,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
                }
                rqw = &iolat->rq_wait;
 
-               atomic_dec(&rqw->inflight);
-               if (!enabled || iolat->min_lat_nsec == 0)
+               inflight = atomic_dec_return(&rqw->inflight);
+               WARN_ON_ONCE(inflight < 0);
+               if (iolat->min_lat_nsec == 0)
                        goto next;
                iolatency_record_time(iolat, &bio->bi_issue, now,
                                      issue_as_root);
@@ -754,10 +760,13 @@ int blk_iolatency_init(struct request_queue *q)
        return 0;
 }
 
-static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
+/*
+ * return 1 for enabling iolatency, return -1 for disabling iolatency, otherwise
+ * return 0.
+ */
+static int iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
 {
        struct iolatency_grp *iolat = blkg_to_lat(blkg);
-       struct blk_iolatency *blkiolat = iolat->blkiolat;
        u64 oldval = iolat->min_lat_nsec;
 
        iolat->min_lat_nsec = val;
@@ -766,9 +775,10 @@ static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
                                    BLKIOLATENCY_MAX_WIN_SIZE);
 
        if (!oldval && val)
-               atomic_inc(&blkiolat->enabled);
+               return 1;
        if (oldval && !val)
-               atomic_dec(&blkiolat->enabled);
+               return -1;
+       return 0;
 }
 
 static void iolatency_clear_scaling(struct blkcg_gq *blkg)
@@ -800,6 +810,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        u64 lat_val = 0;
        u64 oldval;
        int ret;
+       int enable = 0;
 
        ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx);
        if (ret)
@@ -834,7 +845,12 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        blkg = ctx.blkg;
        oldval = iolat->min_lat_nsec;
 
-       iolatency_set_min_lat_nsec(blkg, lat_val);
+       enable = iolatency_set_min_lat_nsec(blkg, lat_val);
+       if (enable) {
+               WARN_ON_ONCE(!blk_get_queue(blkg->q));
+               blkg_get(blkg);
+       }
+
        if (oldval != iolat->min_lat_nsec) {
                iolatency_clear_scaling(blkg);
        }
@@ -842,6 +858,24 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        ret = 0;
 out:
        blkg_conf_finish(&ctx);
+       if (ret == 0 && enable) {
+               struct iolatency_grp *tmp = blkg_to_lat(blkg);
+               struct blk_iolatency *blkiolat = tmp->blkiolat;
+
+               blk_mq_freeze_queue(blkg->q);
+
+               if (enable == 1)
+                       atomic_inc(&blkiolat->enabled);
+               else if (enable == -1)
+                       atomic_dec(&blkiolat->enabled);
+               else
+                       WARN_ON_ONCE(1);
+
+               blk_mq_unfreeze_queue(blkg->q);
+
+               blkg_put(blkg);
+               blk_put_queue(blkg->q);
+       }
        return ret ?: nbytes;
 }
 
@@ -977,8 +1011,14 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd)
 {
        struct iolatency_grp *iolat = pd_to_lat(pd);
        struct blkcg_gq *blkg = lat_to_blkg(iolat);
+       struct blk_iolatency *blkiolat = iolat->blkiolat;
+       int ret;
 
-       iolatency_set_min_lat_nsec(blkg, 0);
+       ret = iolatency_set_min_lat_nsec(blkg, 0);
+       if (ret == 1)
+               atomic_inc(&blkiolat->enabled);
+       if (ret == -1)
+               atomic_dec(&blkiolat->enabled);
        iolatency_clear_scaling(blkg);
 }
 
index fb2c82c351e4fd19553b3b2bb9eca84a8320218b..038cb627c86896e11282d1ad9173d9a26c913eb6 100644 (file)
@@ -1,8 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
- *
- * This file is released under the GPL.
  */
 
 #include <linux/blkdev.h>
index 90d68760af086bd6de78c71dc4a1f6954ceb7a5b..7921573aebbc28abd0a57a999792ede908acfd6c 100644 (file)
@@ -308,8 +308,9 @@ static const char *const cmd_flag_name[] = {
        CMD_FLAG_NAME(PREFLUSH),
        CMD_FLAG_NAME(RAHEAD),
        CMD_FLAG_NAME(BACKGROUND),
-       CMD_FLAG_NAME(NOUNMAP),
        CMD_FLAG_NAME(NOWAIT),
+       CMD_FLAG_NAME(NOUNMAP),
+       CMD_FLAG_NAME(HIPRI),
 };
 #undef CMD_FLAG_NAME
 
@@ -838,6 +839,9 @@ static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
 static bool debugfs_create_files(struct dentry *parent, void *data,
                                 const struct blk_mq_debugfs_attr *attr)
 {
+       if (IS_ERR_OR_NULL(parent))
+               return false;
+
        d_inode(parent)->i_private = data;
 
        for (; attr->name; attr++) {
index 3ba37b9e15e9ae7d7921de1ac9ead5cee707c21a..9437a5eb07cff63062ed459afc0b6b90e685e6f7 100644 (file)
@@ -737,12 +737,20 @@ static void blk_mq_requeue_work(struct work_struct *work)
        spin_unlock_irq(&q->requeue_lock);
 
        list_for_each_entry_safe(rq, next, &rq_list, queuelist) {
-               if (!(rq->rq_flags & RQF_SOFTBARRIER))
+               if (!(rq->rq_flags & (RQF_SOFTBARRIER | RQF_DONTPREP)))
                        continue;
 
                rq->rq_flags &= ~RQF_SOFTBARRIER;
                list_del_init(&rq->queuelist);
-               blk_mq_sched_insert_request(rq, true, false, false);
+               /*
+                * If RQF_DONTPREP, rq has contained some driver specific
+                * data, so insert it to hctx dispatch list to avoid any
+                * merge.
+                */
+               if (rq->rq_flags & RQF_DONTPREP)
+                       blk_mq_request_bypass_insert(rq, false);
+               else
+                       blk_mq_sched_insert_request(rq, true, false, false);
        }
 
        while (!list_empty(&rq_list)) {
@@ -1906,7 +1914,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 {
        const int is_sync = op_is_sync(bio->bi_opf);
        const int is_flush_fua = op_is_flush(bio->bi_opf);
-       struct blk_mq_alloc_data data = { .flags = 0, .cmd_flags = bio->bi_opf };
+       struct blk_mq_alloc_data data = { .flags = 0};
        struct request *rq;
        struct blk_plug *plug;
        struct request *same_queue_rq = NULL;
@@ -1928,6 +1936,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
        rq_qos_throttle(q, bio);
 
+       data.cmd_flags = bio->bi_opf;
        rq = blk_mq_get_request(q, bio, &data);
        if (unlikely(!rq)) {
                rq_qos_cleanup(q, bio);
index d943d46b078547e5f48d488575be5178fb0195e5..d0b3dd54ef8dd81cadbde86b8397c4d8e7c21025 100644 (file)
@@ -36,7 +36,6 @@ struct blk_mq_ctx {
        struct kobject          kobj;
 } ____cacheline_aligned_in_smp;
 
-void blk_mq_freeze_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
 int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr);
 void blk_mq_wake_waiters(struct request_queue *q);
index f0c56649775fcb35ae978b9dac27bcd4c4001fb3..fd166fbb0f6587c494e6095b8bf6e58de0c67360 100644 (file)
@@ -597,7 +597,7 @@ static void wbt_track(struct rq_qos *rqos, struct request *rq, struct bio *bio)
        rq->wbt_flags |= bio_to_wbt_flags(rwb, bio);
 }
 
-void wbt_issue(struct rq_qos *rqos, struct request *rq)
+static void wbt_issue(struct rq_qos *rqos, struct request *rq)
 {
        struct rq_wb *rwb = RQWB(rqos);
 
@@ -617,7 +617,7 @@ void wbt_issue(struct rq_qos *rqos, struct request *rq)
        }
 }
 
-void wbt_requeue(struct rq_qos *rqos, struct request *rq)
+static void wbt_requeue(struct rq_qos *rqos, struct request *rq)
 {
        struct rq_wb *rwb = RQWB(rqos);
        if (!rwb_enabled(rwb))
index 6651e713c45d6b2e3af4955cdecde6c671a2c874..5564e73266a6abb5ba91da29422ac86ba0ac153c 100644 (file)
@@ -539,6 +539,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
        ictx = skcipher_instance_ctx(inst);
 
        /* Stream cipher, e.g. "xchacha12" */
+       crypto_set_skcipher_spawn(&ictx->streamcipher_spawn,
+                                 skcipher_crypto_instance(inst));
        err = crypto_grab_skcipher(&ictx->streamcipher_spawn, streamcipher_name,
                                   0, crypto_requires_sync(algt->type,
                                                           algt->mask));
@@ -547,6 +549,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
        streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn);
 
        /* Block cipher, e.g. "aes" */
+       crypto_set_spawn(&ictx->blockcipher_spawn,
+                        skcipher_crypto_instance(inst));
        err = crypto_grab_spawn(&ictx->blockcipher_spawn, blockcipher_name,
                                CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK);
        if (err)
index 37f54d1b2f66921ce3d725634376dc32dc23e8aa..4be293a4b5f0fe00bc88dbadefa1fbc5e984da1e 100644 (file)
@@ -58,14 +58,22 @@ int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
                return -EINVAL;
        if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
                return -EINVAL;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+
+       /*
+        * RTA_OK() didn't align the rtattr's payload when validating that it
+        * fits in the buffer.  Yet, the keys should start on the next 4-byte
+        * aligned boundary.  To avoid confusion, require that the rtattr
+        * payload be exactly the param struct, which has a 4-byte aligned size.
+        */
+       if (RTA_PAYLOAD(rta) != sizeof(*param))
                return -EINVAL;
+       BUILD_BUG_ON(sizeof(*param) % RTA_ALIGNTO);
 
        param = RTA_DATA(rta);
        keys->enckeylen = be32_to_cpu(param->enckeylen);
 
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
+       key += rta->rta_len;
+       keylen -= rta->rta_len;
 
        if (keylen < keys->enckeylen)
                return -EINVAL;
index 80a25cc04aec760ca631a297a109cdb61673b191..4741fe89ba2cdee2b593c2ac4b44fc120e32f780 100644 (file)
@@ -279,7 +279,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
        struct aead_request *req = areq->data;
 
        err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
-       aead_request_complete(req, err);
+       authenc_esn_request_complete(req, err);
 }
 
 static int crypto_authenc_esn_decrypt(struct aead_request *req)
index 9a5c60f08aad8482cce58bf2a660aa37a4c652e6..c0cf87ae7ef6d0716e4e15f797603efaee96bb2b 100644 (file)
@@ -100,7 +100,7 @@ static void sm3_compress(u32 *w, u32 *wt, u32 *m)
 
        for (i = 0; i <= 63; i++) {
 
-               ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i)), 7);
+               ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i & 31)), 7);
 
                ss2 = ss1 ^ rol32(a, 12);
 
index 7c6afc111d76b7b5cd101b37924ec83577462c71..bb857421c2e8b7ad4b5213a07de586f122a2c7f8 100644 (file)
@@ -41,7 +41,8 @@ acpi-y                                += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-$(CONFIG_PCI)             += pci_root.o pci_link.o pci_irq.o
 obj-$(CONFIG_ACPI_MCFG)                += pci_mcfg.o
-acpi-y                         += acpi_lpss.o acpi_apd.o
+acpi-$(CONFIG_PCI)             += acpi_lpss.o
+acpi-y                         += acpi_apd.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += acpi_pnp.o
 acpi-$(CONFIG_ARM_AMBA)        += acpi_amba.o
index 99d820a693a8cfee517690f8a5eca9a4987cbf56..147f6c7ea59c80327babafc45726ffb91c3ad70c 100644 (file)
@@ -1029,6 +1029,9 @@ void __init acpi_early_init(void)
 
        acpi_permanent_mmap = true;
 
+       /* Initialize debug output. Linux does not use ACPICA defaults */
+       acpi_dbg_level = ACPI_LV_INFO | ACPI_LV_REPAIR;
+
 #ifdef CONFIG_X86
        /*
         * If the machine falls into the DMI check table,
@@ -1054,18 +1057,6 @@ void __init acpi_early_init(void)
                goto error0;
        }
 
-       /*
-        * ACPI 2.0 requires the EC driver to be loaded and work before
-        * the EC device is found in the namespace (i.e. before
-        * acpi_load_tables() is called).
-        *
-        * This is accomplished by looking for the ECDT table, and getting
-        * the EC parameters out of that.
-        *
-        * Ignore the result. Not having an ECDT is not fatal.
-        */
-       status = acpi_ec_ecdt_probe();
-
 #ifdef CONFIG_X86
        if (!acpi_ioapic) {
                /* compatible (0) means level (3) */
@@ -1142,6 +1133,18 @@ static int __init acpi_bus_init(void)
                goto error1;
        }
 
+       /*
+        * ACPI 2.0 requires the EC driver to be loaded and work before the EC
+        * device is found in the namespace.
+        *
+        * This is accomplished by looking for the ECDT table and getting the EC
+        * parameters out of that.
+        *
+        * Do that before calling acpi_initialize_objects() which may trigger EC
+        * address space accesses.
+        */
+       acpi_ec_ecdt_probe();
+
        status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
        if (ACPI_FAILURE(status)) {
                printk(KERN_ERR PREFIX
index 7e6952edb5b07d44c482f713b9e5349b2cfa760a..6a9e1fb8913aedb4774ea6418dbce1b5f57e3071 100644 (file)
@@ -81,7 +81,11 @@ void acpi_debugfs_init(void);
 #else
 static inline void acpi_debugfs_init(void) { return; }
 #endif
+#ifdef CONFIG_PCI
 void acpi_lpss_init(void);
+#else
+static inline void acpi_lpss_init(void) {}
+#endif
 
 void acpi_apd_init(void);
 
index 011d3db19c80aaa300ae417d26b118ba90c9055f..e18ade5d74e9ecf38126bce5301f027073779bc3 100644 (file)
@@ -26,7 +26,6 @@
 #include <acpi/nfit.h>
 #include "intel.h"
 #include "nfit.h"
-#include "intel.h"
 
 /*
  * For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
@@ -78,12 +77,6 @@ const guid_t *to_nfit_uuid(enum nfit_uuids id)
 }
 EXPORT_SYMBOL(to_nfit_uuid);
 
-static struct acpi_nfit_desc *to_acpi_nfit_desc(
-               struct nvdimm_bus_descriptor *nd_desc)
-{
-       return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
-}
-
 static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
 {
        struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
@@ -416,10 +409,36 @@ static bool payload_dumpable(struct nvdimm *nvdimm, unsigned int func)
        return true;
 }
 
+static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
+               struct nd_cmd_pkg *call_pkg)
+{
+       if (call_pkg) {
+               int i;
+
+               if (nfit_mem->family != call_pkg->nd_family)
+                       return -ENOTTY;
+
+               for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
+                       if (call_pkg->nd_reserved2[i])
+                               return -EINVAL;
+               return call_pkg->nd_command;
+       }
+
+       /* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */
+       if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
+               return cmd;
+
+       /*
+        * Force function number validation to fail since 0 is never
+        * published as a valid function in dsm_mask.
+        */
+       return 0;
+}
+
 int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
                unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
        union acpi_object in_obj, in_buf, *out_obj;
        const struct nd_cmd_desc *desc = NULL;
@@ -429,30 +448,23 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        unsigned long cmd_mask, dsm_mask;
        u32 offset, fw_status = 0;
        acpi_handle handle;
-       unsigned int func;
        const guid_t *guid;
-       int rc, i;
+       int func, rc, i;
 
        if (cmd_rc)
                *cmd_rc = -EINVAL;
-       func = cmd;
-       if (cmd == ND_CMD_CALL) {
-               call_pkg = buf;
-               func = call_pkg->nd_command;
-
-               for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
-                       if (call_pkg->nd_reserved2[i])
-                               return -EINVAL;
-       }
 
        if (nvdimm) {
                struct acpi_device *adev = nfit_mem->adev;
 
                if (!adev)
                        return -ENOTTY;
-               if (call_pkg && nfit_mem->family != call_pkg->nd_family)
-                       return -ENOTTY;
 
+               if (cmd == ND_CMD_CALL)
+                       call_pkg = buf;
+               func = cmd_to_func(nfit_mem, cmd, call_pkg);
+               if (func < 0)
+                       return func;
                dimm_name = nvdimm_name(nvdimm);
                cmd_name = nvdimm_cmd_name(cmd);
                cmd_mask = nvdimm_cmd_mask(nvdimm);
@@ -463,6 +475,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        } else {
                struct acpi_device *adev = to_acpi_dev(acpi_desc);
 
+               func = cmd;
                cmd_name = nvdimm_bus_cmd_name(cmd);
                cmd_mask = nd_desc->cmd_mask;
                dsm_mask = cmd_mask;
@@ -477,7 +490,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
                return -ENOTTY;
 
-       if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
+       /*
+        * Check for a valid command.  For ND_CMD_CALL, we also have to
+        * make sure that the DSM function is supported.
+        */
+       if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+               return -ENOTTY;
+       else if (!test_bit(cmd, &cmd_mask))
                return -ENOTTY;
 
        in_obj.type = ACPI_TYPE_PACKAGE;
@@ -721,6 +740,7 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
        struct acpi_nfit_memory_map *memdev;
        struct acpi_nfit_desc *acpi_desc;
        struct nfit_mem *nfit_mem;
+       u16 physical_id;
 
        mutex_lock(&acpi_desc_lock);
        list_for_each_entry(acpi_desc, &acpi_descs, list) {
@@ -728,10 +748,11 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
                list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
                        memdev = __to_nfit_memdev(nfit_mem);
                        if (memdev->device_handle == device_handle) {
+                               *flags = memdev->flags;
+                               physical_id = memdev->physical_id;
                                mutex_unlock(&acpi_desc->init_mutex);
                                mutex_unlock(&acpi_desc_lock);
-                               *flags = memdev->flags;
-                               return memdev->physical_id;
+                               return physical_id;
                        }
                }
                mutex_unlock(&acpi_desc->init_mutex);
@@ -1872,6 +1893,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
                return 0;
        }
 
+       /*
+        * Function 0 is the command interrogation function, don't
+        * export it to potential userspace use, and enable it to be
+        * used as an error value in acpi_nfit_ctl().
+        */
+       dsm_mask &= ~1UL;
+
        guid = to_nfit_uuid(nfit_mem->family);
        for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
                if (acpi_check_dsm(adev_dimm->handle, guid,
@@ -2047,11 +2075,6 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
                if (!nvdimm)
                        continue;
 
-               rc = nvdimm_security_setup_events(nvdimm);
-               if (rc < 0)
-                       dev_warn(acpi_desc->dev,
-                               "security event setup failed: %d\n", rc);
-
                nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit");
                if (nfit_kernfs)
                        nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs,
@@ -2231,7 +2254,6 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
        nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
        if (!nd_set)
                return -ENOMEM;
-       ndr_desc->nd_set = nd_set;
        guid_copy(&nd_set->type_guid, (guid_t *) spa->range_guid);
 
        info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL);
@@ -3367,7 +3389,7 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init);
 
 static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
        struct device *dev = acpi_desc->dev;
 
        /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
@@ -3384,7 +3406,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
 static int __acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
                struct nvdimm *nvdimm, unsigned int cmd)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
 
        if (nvdimm)
                return 0;
index 850b2927b4e7267317bac3b51e4c24d125a9511f..f70de71f79d6a699442f430dfa6606ad18a8f2dc 100644 (file)
@@ -146,7 +146,7 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
 
 static void nvdimm_invalidate_cache(void);
 
-static int intel_security_unlock(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key_data)
 {
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -227,7 +227,7 @@ static int intel_security_disable(struct nvdimm *nvdimm,
        return 0;
 }
 
-static int intel_security_erase(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key,
                enum nvdimm_passphrase_type ptype)
 {
@@ -276,7 +276,7 @@ static int intel_security_erase(struct nvdimm *nvdimm,
        return 0;
 }
 
-static int intel_security_query_overwrite(struct nvdimm *nvdimm)
+static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
 {
        int rc;
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -313,7 +313,7 @@ static int intel_security_query_overwrite(struct nvdimm *nvdimm)
        return 0;
 }
 
-static int intel_security_overwrite(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *nkey)
 {
        int rc;
index cdfc87629efb833213687c8996b17133bea19595..4d2b2ad1ee0e14c65b067077bfb560099ced6f1e 100644 (file)
@@ -5854,9 +5854,10 @@ static int __init init_binder_device(const char *name)
 static int __init binder_init(void)
 {
        int ret;
-       char *device_name, *device_names, *device_tmp;
+       char *device_name, *device_tmp;
        struct binder_device *device;
        struct hlist_node *tmp;
+       char *device_names = NULL;
 
        ret = binder_alloc_shrinker_init();
        if (ret)
@@ -5898,23 +5899,29 @@ static int __init binder_init(void)
                                    &transaction_log_fops);
        }
 
-       /*
-        * Copy the module_parameter string, because we don't want to
-        * tokenize it in-place.
-        */
-       device_names = kstrdup(binder_devices_param, GFP_KERNEL);
-       if (!device_names) {
-               ret = -ENOMEM;
-               goto err_alloc_device_names_failed;
-       }
+       if (strcmp(binder_devices_param, "") != 0) {
+               /*
+               * Copy the module_parameter string, because we don't want to
+               * tokenize it in-place.
+                */
+               device_names = kstrdup(binder_devices_param, GFP_KERNEL);
+               if (!device_names) {
+                       ret = -ENOMEM;
+                       goto err_alloc_device_names_failed;
+               }
 
-       device_tmp = device_names;
-       while ((device_name = strsep(&device_tmp, ","))) {
-               ret = init_binder_device(device_name);
-               if (ret)
-                       goto err_init_binder_device_failed;
+               device_tmp = device_names;
+               while ((device_name = strsep(&device_tmp, ","))) {
+                       ret = init_binder_device(device_name);
+                       if (ret)
+                               goto err_init_binder_device_failed;
+               }
        }
 
+       ret = init_binderfs();
+       if (ret)
+               goto err_init_binder_device_failed;
+
        return ret;
 
 err_init_binder_device_failed:
index 7fb97f503ef2b3c56c4f67fd3e2cb4e3e110fb3e..045b3e42d98b8336a9d069a79f38f5803402072a 100644 (file)
@@ -46,4 +46,13 @@ static inline bool is_binderfs_device(const struct inode *inode)
 }
 #endif
 
+#ifdef CONFIG_ANDROID_BINDERFS
+extern int __init init_binderfs(void);
+#else
+static inline int __init init_binderfs(void)
+{
+       return 0;
+}
+#endif
+
 #endif /* _LINUX_BINDER_INTERNAL_H */
index 7496b10532aafde54d68c95f264c2853c6f67f1c..e773f45d19d932dc1c8f997b5ea9ab50e4291c70 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kdev_t.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/namei.h>
 #include <linux/magic.h>
 #include <linux/major.h>
 #include <linux/miscdevice.h>
@@ -20,6 +21,7 @@
 #include <linux/parser.h>
 #include <linux/radix-tree.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/spinlock_types.h>
 #include <linux/stddef.h>
@@ -30,7 +32,7 @@
 #include <linux/xarray.h>
 #include <uapi/asm-generic/errno-base.h>
 #include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binder_ctl.h>
+#include <uapi/linux/android/binderfs.h>
 
 #include "binder_internal.h"
 
 #define INODE_OFFSET 3
 #define INTSTRLEN 21
 #define BINDERFS_MAX_MINOR (1U << MINORBITS)
-
-static struct vfsmount *binderfs_mnt;
+/* Ensure that the initial ipc namespace always has devices available. */
+#define BINDERFS_MAX_MINOR_CAPPED (BINDERFS_MAX_MINOR - 4)
 
 static dev_t binderfs_dev;
 static DEFINE_MUTEX(binderfs_minors_mutex);
 static DEFINE_IDA(binderfs_minors);
 
+/**
+ * binderfs_mount_opts - mount options for binderfs
+ * @max: maximum number of allocatable binderfs binder devices
+ */
+struct binderfs_mount_opts {
+       int max;
+};
+
+enum {
+       Opt_max,
+       Opt_err
+};
+
+static const match_table_t tokens = {
+       { Opt_max, "max=%d" },
+       { Opt_err, NULL     }
+};
+
 /**
  * binderfs_info - information about a binderfs mount
  * @ipc_ns:         The ipc namespace the binderfs mount belongs to.
@@ -55,13 +75,16 @@ static DEFINE_IDA(binderfs_minors);
  *                  created.
  * @root_gid:       gid that needs to be used when a new binder device is
  *                  created.
+ * @mount_opts:     The mount options in use.
+ * @device_count:   The current number of allocated binder devices.
  */
 struct binderfs_info {
        struct ipc_namespace *ipc_ns;
        struct dentry *control_dentry;
        kuid_t root_uid;
        kgid_t root_gid;
-
+       struct binderfs_mount_opts mount_opts;
+       int device_count;
 };
 
 static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
@@ -84,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode)
  * @userp:     buffer to copy information about new device for userspace to
  * @req:       struct binderfs_device as copied from userspace
  *
- * This function allocated a new binder_device and reserves a new minor
+ * This function allocates a new binder_device and reserves a new minor
  * number for it.
  * Minor numbers are limited and tracked globally in binderfs_minors. The
  * function will stash a struct binder_device for the specific binder
@@ -100,20 +123,34 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
                                         struct binderfs_device *req)
 {
        int minor, ret;
-       struct dentry *dentry, *dup, *root;
+       struct dentry *dentry, *root;
        struct binder_device *device;
-       size_t name_len = BINDERFS_MAX_NAME + 1;
        char *name = NULL;
+       size_t name_len;
        struct inode *inode = NULL;
        struct super_block *sb = ref_inode->i_sb;
        struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+       bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+       bool use_reserve = true;
+#endif
 
        /* Reserve new minor number for the new device. */
        mutex_lock(&binderfs_minors_mutex);
-       minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
-       mutex_unlock(&binderfs_minors_mutex);
-       if (minor < 0)
+       if (++info->device_count <= info->mount_opts.max)
+               minor = ida_alloc_max(&binderfs_minors,
+                                     use_reserve ? BINDERFS_MAX_MINOR :
+                                                   BINDERFS_MAX_MINOR_CAPPED,
+                                     GFP_KERNEL);
+       else
+               minor = -ENOSPC;
+       if (minor < 0) {
+               --info->device_count;
+               mutex_unlock(&binderfs_minors_mutex);
                return minor;
+       }
+       mutex_unlock(&binderfs_minors_mutex);
 
        ret = -ENOMEM;
        device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -132,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
        inode->i_uid = info->root_uid;
        inode->i_gid = info->root_gid;
 
-       name = kmalloc(name_len, GFP_KERNEL);
+       req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */
+       name_len = strlen(req->name);
+       /* Make sure to include terminating NUL byte */
+       name = kmemdup(req->name, name_len + 1, GFP_KERNEL);
        if (!name)
                goto err;
 
-       strscpy(name, req->name, name_len);
-
        device->binderfs_inode = inode;
        device->context.binder_context_mgr_uid = INVALID_UID;
        device->context.name = name;
@@ -156,28 +194,25 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
 
        root = sb->s_root;
        inode_lock(d_inode(root));
-       dentry = d_alloc_name(root, name);
-       if (!dentry) {
+
+       /* look it up */
+       dentry = lookup_one_len(name, root, name_len);
+       if (IS_ERR(dentry)) {
                inode_unlock(d_inode(root));
-               ret = -ENOMEM;
+               ret = PTR_ERR(dentry);
                goto err;
        }
 
-       /* Verify that the name userspace gave us is not already in use. */
-       dup = d_lookup(root, &dentry->d_name);
-       if (dup) {
-               if (d_really_is_positive(dup)) {
-                       dput(dup);
-                       dput(dentry);
-                       inode_unlock(d_inode(root));
-                       ret = -EEXIST;
-                       goto err;
-               }
-               dput(dup);
+       if (d_really_is_positive(dentry)) {
+               /* already exists */
+               dput(dentry);
+               inode_unlock(d_inode(root));
+               ret = -EEXIST;
+               goto err;
        }
 
        inode->i_private = device;
-       d_add(dentry, inode);
+       d_instantiate(dentry, inode);
        fsnotify_create(root->d_inode, dentry);
        inode_unlock(d_inode(root));
 
@@ -187,6 +222,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
        kfree(name);
        kfree(device);
        mutex_lock(&binderfs_minors_mutex);
+       --info->device_count;
        ida_free(&binderfs_minors, minor);
        mutex_unlock(&binderfs_minors_mutex);
        iput(inode);
@@ -232,6 +268,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd,
 static void binderfs_evict_inode(struct inode *inode)
 {
        struct binder_device *device = inode->i_private;
+       struct binderfs_info *info = BINDERFS_I(inode);
 
        clear_inode(inode);
 
@@ -239,6 +276,7 @@ static void binderfs_evict_inode(struct inode *inode)
                return;
 
        mutex_lock(&binderfs_minors_mutex);
+       --info->device_count;
        ida_free(&binderfs_minors, device->miscdev.minor);
        mutex_unlock(&binderfs_minors_mutex);
 
@@ -246,43 +284,87 @@ static void binderfs_evict_inode(struct inode *inode)
        kfree(device);
 }
 
+/**
+ * binderfs_parse_mount_opts - parse binderfs mount options
+ * @data: options to set (can be NULL in which case defaults are used)
+ */
+static int binderfs_parse_mount_opts(char *data,
+                                    struct binderfs_mount_opts *opts)
+{
+       char *p;
+       opts->max = BINDERFS_MAX_MINOR;
+
+       while ((p = strsep(&data, ",")) != NULL) {
+               substring_t args[MAX_OPT_ARGS];
+               int token;
+               int max_devices;
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_max:
+                       if (match_int(&args[0], &max_devices) ||
+                           (max_devices < 0 ||
+                            (max_devices > BINDERFS_MAX_MINOR)))
+                               return -EINVAL;
+
+                       opts->max = max_devices;
+                       break;
+               default:
+                       pr_err("Invalid mount options\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int binderfs_remount(struct super_block *sb, int *flags, char *data)
+{
+       struct binderfs_info *info = sb->s_fs_info;
+       return binderfs_parse_mount_opts(data, &info->mount_opts);
+}
+
+static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
+{
+       struct binderfs_info *info;
+
+       info = root->d_sb->s_fs_info;
+       if (info->mount_opts.max <= BINDERFS_MAX_MINOR)
+               seq_printf(seq, ",max=%d", info->mount_opts.max);
+
+       return 0;
+}
+
 static const struct super_operations binderfs_super_ops = {
-       .statfs = simple_statfs,
-       .evict_inode = binderfs_evict_inode,
+       .evict_inode    = binderfs_evict_inode,
+       .remount_fs     = binderfs_remount,
+       .show_options   = binderfs_show_mount_opts,
+       .statfs         = simple_statfs,
 };
 
+static inline bool is_binderfs_control_device(const struct dentry *dentry)
+{
+       struct binderfs_info *info = dentry->d_sb->s_fs_info;
+       return info->control_dentry == dentry;
+}
+
 static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry,
                           unsigned int flags)
 {
-       struct inode *inode = d_inode(old_dentry);
-
-       /* binderfs doesn't support directories. */
-       if (d_is_dir(old_dentry))
+       if (is_binderfs_control_device(old_dentry) ||
+           is_binderfs_control_device(new_dentry))
                return -EPERM;
 
-       if (flags & ~RENAME_NOREPLACE)
-               return -EINVAL;
-
-       if (!simple_empty(new_dentry))
-               return -ENOTEMPTY;
-
-       if (d_really_is_positive(new_dentry))
-               simple_unlink(new_dir, new_dentry);
-
-       old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
-               new_dir->i_mtime = inode->i_ctime = current_time(old_dir);
-
-       return 0;
+       return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
 }
 
 static int binderfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       /*
-        * The control dentry is only ever touched during mount so checking it
-        * here should not require us to take lock.
-        */
-       if (BINDERFS_I(dir)->control_dentry == dentry)
+       if (is_binderfs_control_device(dentry))
                return -EPERM;
 
        return simple_unlink(dir, dentry);
@@ -313,13 +395,16 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
        struct inode *inode = NULL;
        struct dentry *root = sb->s_root;
        struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+       bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+       bool use_reserve = true;
+#endif
 
        device = kzalloc(sizeof(*device), GFP_KERNEL);
        if (!device)
                return -ENOMEM;
 
-       inode_lock(d_inode(root));
-
        /* If we have already created a binder-control node, return. */
        if (info->control_dentry) {
                ret = 0;
@@ -333,7 +418,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
 
        /* Reserve a new minor number for the new device. */
        mutex_lock(&binderfs_minors_mutex);
-       minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
+       minor = ida_alloc_max(&binderfs_minors,
+                             use_reserve ? BINDERFS_MAX_MINOR :
+                                           BINDERFS_MAX_MINOR_CAPPED,
+                             GFP_KERNEL);
        mutex_unlock(&binderfs_minors_mutex);
        if (minor < 0) {
                ret = minor;
@@ -358,12 +446,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
        inode->i_private = device;
        info->control_dentry = dentry;
        d_add(dentry, inode);
-       inode_unlock(d_inode(root));
 
        return 0;
 
 out:
-       inode_unlock(d_inode(root));
        kfree(device);
        iput(inode);
 
@@ -378,12 +464,9 @@ static const struct inode_operations binderfs_dir_inode_operations = {
 
 static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
 {
+       int ret;
        struct binderfs_info *info;
-       int ret = -ENOMEM;
        struct inode *inode = NULL;
-       struct ipc_namespace *ipc_ns = sb->s_fs_info;
-
-       get_ipc_ns(ipc_ns);
 
        sb->s_blocksize = PAGE_SIZE;
        sb->s_blocksize_bits = PAGE_SHIFT;
@@ -405,11 +488,17 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op = &binderfs_super_ops;
        sb->s_time_gran = 1;
 
-       info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
-       if (!info)
-               goto err_without_dentry;
+       sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
+       if (!sb->s_fs_info)
+               return -ENOMEM;
+       info = sb->s_fs_info;
+
+       info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
+
+       ret = binderfs_parse_mount_opts(data, &info->mount_opts);
+       if (ret)
+               return ret;
 
-       info->ipc_ns = ipc_ns;
        info->root_gid = make_kgid(sb->s_user_ns, 0);
        if (!gid_valid(info->root_gid))
                info->root_gid = GLOBAL_ROOT_GID;
@@ -417,11 +506,9 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
        if (!uid_valid(info->root_uid))
                info->root_uid = GLOBAL_ROOT_UID;
 
-       sb->s_fs_info = info;
-
        inode = new_inode(sb);
        if (!inode)
-               goto err_without_dentry;
+               return -ENOMEM;
 
        inode->i_ino = FIRST_INODE;
        inode->i_fop = &simple_dir_operations;
@@ -432,79 +519,28 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_root = d_make_root(inode);
        if (!sb->s_root)
-               goto err_without_dentry;
-
-       ret = binderfs_binder_ctl_create(sb);
-       if (ret)
-               goto err_with_dentry;
-
-       return 0;
-
-err_with_dentry:
-       dput(sb->s_root);
-       sb->s_root = NULL;
-
-err_without_dentry:
-       put_ipc_ns(ipc_ns);
-       iput(inode);
-       kfree(info);
-
-       return ret;
-}
-
-static int binderfs_test_super(struct super_block *sb, void *data)
-{
-       struct binderfs_info *info = sb->s_fs_info;
-
-       if (info)
-               return info->ipc_ns == data;
-
-       return 0;
-}
+               return -ENOMEM;
 
-static int binderfs_set_super(struct super_block *sb, void *data)
-{
-       sb->s_fs_info = data;
-       return set_anon_super(sb, NULL);
+       return binderfs_binder_ctl_create(sb);
 }
 
 static struct dentry *binderfs_mount(struct file_system_type *fs_type,
                                     int flags, const char *dev_name,
                                     void *data)
 {
-       struct super_block *sb;
-       struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
-
-       if (!ns_capable(ipc_ns->user_ns, CAP_SYS_ADMIN))
-               return ERR_PTR(-EPERM);
-
-       sb = sget_userns(fs_type, binderfs_test_super, binderfs_set_super,
-                        flags, ipc_ns->user_ns, ipc_ns);
-       if (IS_ERR(sb))
-               return ERR_CAST(sb);
-
-       if (!sb->s_root) {
-               int ret = binderfs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
-               if (ret) {
-                       deactivate_locked_super(sb);
-                       return ERR_PTR(ret);
-               }
-
-               sb->s_flags |= SB_ACTIVE;
-       }
-
-       return dget(sb->s_root);
+       return mount_nodev(fs_type, flags, data, binderfs_fill_super);
 }
 
 static void binderfs_kill_super(struct super_block *sb)
 {
        struct binderfs_info *info = sb->s_fs_info;
 
+       kill_litter_super(sb);
+
        if (info && info->ipc_ns)
                put_ipc_ns(info->ipc_ns);
 
        kfree(info);
-       kill_litter_super(sb);
 }
 
 static struct file_system_type binder_fs_type = {
@@ -514,7 +550,7 @@ static struct file_system_type binder_fs_type = {
        .fs_flags       = FS_USERNS_MOUNT,
 };
 
-static int __init init_binderfs(void)
+int __init init_binderfs(void)
 {
        int ret;
 
@@ -530,15 +566,5 @@ static int __init init_binderfs(void)
                return ret;
        }
 
-       binderfs_mnt = kern_mount(&binder_fs_type);
-       if (IS_ERR(binderfs_mnt)) {
-               ret = PTR_ERR(binderfs_mnt);
-               binderfs_mnt = NULL;
-               unregister_filesystem(&binder_fs_type);
-               unregister_chrdev_region(binderfs_dev, BINDERFS_MAX_MINOR);
-       }
-
        return ret;
 }
-
-device_initcall(init_binderfs);
index 4ca7a6b4eaaef28b1708bcf2489631e5964ec30a..8218db17ebdb1df6cbe4011469704479b06d7f3a 100644 (file)
@@ -1091,7 +1091,7 @@ comment "Generic fallback / legacy drivers"
 
 config PATA_ACPI
        tristate "ACPI firmware driver for PATA"
-       depends on ATA_ACPI && ATA_BMDMA
+       depends on ATA_ACPI && ATA_BMDMA && PCI
        help
          This option enables an ACPI method driver which drives
          motherboard PATA controller interfaces through the ACPI
index b8c3f9e6af8994820c30b40889154f87511014e0..adf28788cab52c1feba478c9eb0b9742f9d78e79 100644 (file)
@@ -4554,6 +4554,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG SSD PM830 mSATA *",  "CXM13D1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG MZ7TD256HAFV-000L9", NULL,       ATA_HORKAGE_NOLPM, },
+       { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM, },
 
        /* devices that don't properly handle queued TRIM commands */
        { "Micron_M500IT_*",            "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
index 8cc9c429ad9589e54f06db537ff9688f94a28988..9e7fc302430ff2b43d86cf0dded1f81cb0576d88 100644 (file)
@@ -915,6 +915,10 @@ static struct scsi_host_template pata_macio_sht = {
        .sg_tablesize           = MAX_DCMDS,
        /* We may not need that strict one */
        .dma_boundary           = ATA_DMA_BOUNDARY,
+       /* Not sure what the real max is but we know it's less than 64K, let's
+        * use 64K minus 256
+        */
+       .max_segment_size       = MAX_DBDMA_SEG,
        .slave_configure        = pata_macio_slave_config,
 };
 
@@ -1044,11 +1048,6 @@ static int pata_macio_common_init(struct pata_macio_priv *priv,
        /* Make sure we have sane initial timings in the cache */
        pata_macio_default_timings(priv);
 
-       /* Not sure what the real max is but we know it's less than 64K, let's
-        * use 64K minus 256
-        */
-       dma_set_max_seg_size(priv->dev, MAX_DBDMA_SEG);
-
        /* Allocate libata host for 1 port */
        memset(&pinfo, 0, sizeof(struct ata_port_info));
        pmac_macio_calc_timing_masks(priv, &pinfo);
index e0bcf9b2dab040d7342c1eb4f4ead9abef550ba9..174e84ce437950702717bfbf6fc2cd6a734291b0 100644 (file)
@@ -245,8 +245,15 @@ struct inic_port_priv {
 
 static struct scsi_host_template inic_sht = {
        ATA_BASE_SHT(DRV_NAME),
-       .sg_tablesize   = LIBATA_MAX_PRD,       /* maybe it can be larger? */
-       .dma_boundary   = INIC_DMA_BOUNDARY,
+       .sg_tablesize           = LIBATA_MAX_PRD, /* maybe it can be larger? */
+
+       /*
+        * This controller is braindamaged.  dma_boundary is 0xffff like others
+        * but it will lock up the whole machine HARD if 65536 byte PRD entry
+        * is fed.  Reduce maximum segment size.
+        */
+       .dma_boundary           = INIC_DMA_BOUNDARY,
+       .max_segment_size       = 65536 - 512,
 };
 
 static const int scr_map[] = {
@@ -868,17 +875,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        }
 
-       /*
-        * This controller is braindamaged.  dma_boundary is 0xffff
-        * like others but it will lock up the whole machine HARD if
-        * 65536 byte PRD entry is fed. Reduce maximum segment size.
-        */
-       rc = dma_set_max_seg_size(&pdev->dev, 65536 - 512);
-       if (rc) {
-               dev_err(&pdev->dev, "failed to set the maximum segment size\n");
-               return rc;
-       }
-
        rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
        if (rc) {
                dev_err(&pdev->dev, "failed to initialize controller\n");
index 2e9d1cfe3aeb35dab6b0322617ec45c56ffad602..211607986134dcfd3864c11ce4201967b6702707 100644 (file)
@@ -718,7 +718,7 @@ static int he_init_cs_block_rcm(struct he_dev *he_dev)
                        instead of '/ 512', use '>> 9' to prevent a call
                        to divdu3 on x86 platforms
                */
-               rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+               rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9;
 
                if (rate_cps < 10)
                        rate_cps = 10;  /* 2.2.1 minimum payload rate is 10 cps */
index a43276c76fc688a5e158a0c930c720845fccbfd0..21393ec3b9a4a58fe13037f59be6a3d1466f747e 100644 (file)
@@ -509,7 +509,7 @@ static int ht16k33_remove(struct i2c_client *client)
        struct ht16k33_priv *priv = i2c_get_clientdata(client);
        struct ht16k33_fbdev *fbdev = &priv->fbdev;
 
-       cancel_delayed_work(&fbdev->work);
+       cancel_delayed_work_sync(&fbdev->work);
        unregister_framebuffer(fbdev->info);
        framebuffer_release(fbdev->info);
        free_page((unsigned long) fbdev->buffer);
index cf78fa6d470d471311dbc372d186ec27f74dc10d..a7359535caf5dfad5ec0c0a95da54d59174b0159 100644 (file)
@@ -79,8 +79,7 @@ static void cache_size(struct cacheinfo *this_leaf, struct device_node *np)
        ct_idx = get_cacheinfo_idx(this_leaf->type);
        propname = cache_type_info[ct_idx].size_prop;
 
-       if (of_property_read_u32(np, propname, &this_leaf->size))
-               this_leaf->size = 0;
+       of_property_read_u32(np, propname, &this_leaf->size);
 }
 
 /* not cache_line_size() because that's a macro in include/linux/cache.h */
@@ -114,8 +113,7 @@ static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np)
        ct_idx = get_cacheinfo_idx(this_leaf->type);
        propname = cache_type_info[ct_idx].nr_sets_prop;
 
-       if (of_property_read_u32(np, propname, &this_leaf->number_of_sets))
-               this_leaf->number_of_sets = 0;
+       of_property_read_u32(np, propname, &this_leaf->number_of_sets);
 }
 
 static void cache_associativity(struct cacheinfo *this_leaf)
index 457be03b744d276c9279b2a41686afdc49a05e20..0ea2139c50d875d0fdce8e9fb55374fd6bdc337b 100644 (file)
@@ -130,7 +130,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev)
 {
        int autosuspend_delay;
        u64 last_busy, expires = 0;
-       u64 now = ktime_to_ns(ktime_get());
+       u64 now = ktime_get_mono_fast_ns();
 
        if (!dev->power.use_autosuspend)
                goto out;
@@ -909,7 +909,7 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
         * If 'expires' is after the current time, we've been called
         * too early.
         */
-       if (expires > 0 && expires < ktime_to_ns(ktime_get())) {
+       if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
                dev->power.timer_expires = 0;
                rpm_suspend(dev, dev->power.timer_autosuspends ?
                    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
@@ -928,7 +928,7 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
 int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
        unsigned long flags;
-       ktime_t expires;
+       u64 expires;
        int retval;
 
        spin_lock_irqsave(&dev->power.lock, flags);
@@ -945,8 +945,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
        /* Other scheduled or pending requests need to be canceled. */
        pm_runtime_cancel_pending(dev);
 
-       expires = ktime_add(ktime_get(), ms_to_ktime(delay));
-       dev->power.timer_expires = ktime_to_ns(expires);
+       expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC;
+       dev->power.timer_expires = expires;
        dev->power.timer_autosuspends = 0;
        hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS);
 
index 1bd1145ad8b5ea595dfc3557be6eab0e54e1b076..330c1f7e96656a7f651ee9ca9b336b699cbb335e 100644 (file)
@@ -108,6 +108,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
         * suppress pointless writes.
         */
        for (i = 0; i < d->chip->num_regs; i++) {
+               if (!d->chip->mask_base)
+                       continue;
+
                reg = d->chip->mask_base +
                        (i * map->reg_stride * d->irq_reg_stride);
                if (d->chip->mask_invert) {
@@ -258,7 +261,7 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
        const struct regmap_irq_type *t = &irq_data->type;
 
        if ((t->types_supported & type) != type)
-               return -ENOTSUPP;
+               return 0;
 
        reg = t->type_reg_offset / map->reg_stride;
 
@@ -588,6 +591,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        /* Mask all the interrupts by default */
        for (i = 0; i < chip->num_regs; i++) {
                d->mask_buf[i] = d->mask_buf_def[i];
+               if (!chip->mask_base)
+                       continue;
+
                reg = chip->mask_base +
                        (i * map->reg_stride * d->irq_reg_stride);
                if (chip->mask_invert)
index 6f2856c6d0f2063d7a8cf70efd9921911a0cf1b0..55481b40df9a5ee57c11a05462bc03d1d46d3682 100644 (file)
@@ -4075,7 +4075,7 @@ static unsigned int floppy_check_events(struct gendisk *disk,
 
        if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
                if (lock_fdc(drive))
-                       return -EINTR;
+                       return 0;
                poll_drive(false, 0);
                process_fd_request();
        }
index 08696f5f00bb293c087a7725fd96113ef9ca105c..7c9a949e876b624b64e9879e3f19018939e39154 100644 (file)
@@ -288,9 +288,10 @@ static void nbd_size_update(struct nbd_device *nbd)
        blk_queue_physical_block_size(nbd->disk->queue, config->blksize);
        set_capacity(nbd->disk, config->bytesize >> 9);
        if (bdev) {
-               if (bdev->bd_disk)
+               if (bdev->bd_disk) {
                        bd_set_size(bdev, config->bytesize);
-               else
+                       set_blocksize(bdev, config->blksize);
+               } else
                        bdev->bd_invalidated = 1;
                bdput(bdev);
        }
index f94d33525771bace16dd6ffc3e5fc47e53a28602..d299ec79e4c38bd4b5117b87bd75d639fe596ea1 100644 (file)
@@ -781,12 +781,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
        SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        /* Some timers on omap4 and later */
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
        /* Uarts on omap4 and later */
index a74ce885b54125b3852cd9f7de66ec5ee2a52ea3..c518659b4d9fe17a39edc9a53651198c08aa2b5f 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/moduleparam.h>
 #include <linux/workqueue.h>
 #include <linux/uuid.h>
+#include <linux/nospec.h>
 
 #define IPMI_DRIVER_VERSION "39.2"
 
@@ -62,7 +63,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data,
 { }
 #endif
 
-static int initialized;
+static bool initialized;
+static bool drvregistered;
 
 enum ipmi_panic_event_op {
        IPMI_SEND_PANIC_EVENT_NONE,
@@ -612,7 +614,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
 
 static LIST_HEAD(ipmi_interfaces);
 static DEFINE_MUTEX(ipmi_interfaces_mutex);
-DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
+struct srcu_struct ipmi_interfaces_srcu;
 
 /*
  * List of watchers that want to know when smi's are added and deleted.
@@ -720,7 +722,15 @@ struct watcher_entry {
 int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
 {
        struct ipmi_smi *intf;
-       int index;
+       int index, rv;
+
+       /*
+        * Make sure the driver is actually initialized, this handles
+        * problems with initialization order.
+        */
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        mutex_lock(&smi_watchers_mutex);
 
@@ -884,7 +894,7 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
 
                if (user) {
                        user->handler->ipmi_recv_hndl(msg, user->handler_data);
-                       release_ipmi_user(msg->user, index);
+                       release_ipmi_user(user, index);
                } else {
                        /* User went away, give up. */
                        ipmi_free_recv_msg(msg);
@@ -1076,7 +1086,7 @@ int ipmi_create_user(unsigned int          if_num,
 {
        unsigned long flags;
        struct ipmi_user *new_user;
-       int           rv = 0, index;
+       int           rv, index;
        struct ipmi_smi *intf;
 
        /*
@@ -1094,18 +1104,9 @@ int ipmi_create_user(unsigned int          if_num,
         * Make sure the driver is actually initialized, this handles
         * problems with initialization order.
         */
-       if (!initialized) {
-               rv = ipmi_init_msghandler();
-               if (rv)
-                       return rv;
-
-               /*
-                * The init code doesn't return an error if it was turned
-                * off, but it won't initialize.  Check that.
-                */
-               if (!initialized)
-                       return -ENODEV;
-       }
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
        if (!new_user)
@@ -1183,6 +1184,7 @@ EXPORT_SYMBOL(ipmi_get_smi_info);
 static void free_user(struct kref *ref)
 {
        struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
+       cleanup_srcu_struct(&user->release_barrier);
        kfree(user);
 }
 
@@ -1259,7 +1261,6 @@ int ipmi_destroy_user(struct ipmi_user *user)
 {
        _ipmi_destroy_user(user);
 
-       cleanup_srcu_struct(&user->release_barrier);
        kref_put(&user->refcount, free_user);
 
        return 0;
@@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                user->intf->addrinfo[channel].address = address;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                *address = user->intf->addrinfo[channel].address;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                user->intf->addrinfo[channel].lun = LUN & 0x3;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                *address = user->intf->addrinfo[channel].lun;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi  *intf,
 {
        if (addr->channel >= IPMI_MAX_CHANNELS)
                return -EINVAL;
+       addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS);
        *lun = intf->addrinfo[addr->channel].lun;
        *saddr = intf->addrinfo[addr->channel].address;
        return 0;
@@ -3291,17 +3301,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
         * Make sure the driver is actually initialized, this handles
         * problems with initialization order.
         */
-       if (!initialized) {
-               rv = ipmi_init_msghandler();
-               if (rv)
-                       return rv;
-               /*
-                * The init code doesn't return an error if it was turned
-                * off, but it won't initialize.  Check that.
-                */
-               if (!initialized)
-                       return -ENODEV;
-       }
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        intf = kzalloc(sizeof(*intf), GFP_KERNEL);
        if (!intf)
@@ -5017,6 +5019,22 @@ static int panic_event(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
+/* Must be called with ipmi_interfaces_mutex held. */
+static int ipmi_register_driver(void)
+{
+       int rv;
+
+       if (drvregistered)
+               return 0;
+
+       rv = driver_register(&ipmidriver.driver);
+       if (rv)
+               pr_err("Could not register IPMI driver\n");
+       else
+               drvregistered = true;
+       return rv;
+}
+
 static struct notifier_block panic_block = {
        .notifier_call  = panic_event,
        .next           = NULL,
@@ -5027,66 +5045,75 @@ static int ipmi_init_msghandler(void)
 {
        int rv;
 
+       mutex_lock(&ipmi_interfaces_mutex);
+       rv = ipmi_register_driver();
+       if (rv)
+               goto out;
        if (initialized)
-               return 0;
-
-       rv = driver_register(&ipmidriver.driver);
-       if (rv) {
-               pr_err("Could not register IPMI driver\n");
-               return rv;
-       }
+               goto out;
 
-       pr_info("version " IPMI_DRIVER_VERSION "\n");
+       init_srcu_struct(&ipmi_interfaces_srcu);
 
        timer_setup(&ipmi_timer, ipmi_timeout, 0);
        mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
 
        atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
 
-       initialized = 1;
+       initialized = true;
 
-       return 0;
+out:
+       mutex_unlock(&ipmi_interfaces_mutex);
+       return rv;
 }
 
 static int __init ipmi_init_msghandler_mod(void)
 {
-       ipmi_init_msghandler();
-       return 0;
+       int rv;
+
+       pr_info("version " IPMI_DRIVER_VERSION "\n");
+
+       mutex_lock(&ipmi_interfaces_mutex);
+       rv = ipmi_register_driver();
+       mutex_unlock(&ipmi_interfaces_mutex);
+
+       return rv;
 }
 
 static void __exit cleanup_ipmi(void)
 {
        int count;
 
-       if (!initialized)
-               return;
-
-       atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
+       if (initialized) {
+               atomic_notifier_chain_unregister(&panic_notifier_list,
+                                                &panic_block);
 
-       /*
-        * This can't be called if any interfaces exist, so no worry
-        * about shutting down the interfaces.
-        */
+               /*
+                * This can't be called if any interfaces exist, so no worry
+                * about shutting down the interfaces.
+                */
 
-       /*
-        * Tell the timer to stop, then wait for it to stop.  This
-        * avoids problems with race conditions removing the timer
-        * here.
-        */
-       atomic_inc(&stop_operation);
-       del_timer_sync(&ipmi_timer);
+               /*
+                * Tell the timer to stop, then wait for it to stop.  This
+                * avoids problems with race conditions removing the timer
+                * here.
+                */
+               atomic_inc(&stop_operation);
+               del_timer_sync(&ipmi_timer);
 
-       driver_unregister(&ipmidriver.driver);
+               initialized = false;
 
-       initialized = 0;
+               /* Check for buffer leaks. */
+               count = atomic_read(&smi_msg_inuse_count);
+               if (count != 0)
+                       pr_warn("SMI message count %d at exit\n", count);
+               count = atomic_read(&recv_msg_inuse_count);
+               if (count != 0)
+                       pr_warn("recv message count %d at exit\n", count);
 
-       /* Check for buffer leaks. */
-       count = atomic_read(&smi_msg_inuse_count);
-       if (count != 0)
-               pr_warn("SMI message count %d at exit\n", count);
-       count = atomic_read(&recv_msg_inuse_count);
-       if (count != 0)
-               pr_warn("recv message count %d at exit\n", count);
+               cleanup_srcu_struct(&ipmi_interfaces_srcu);
+       }
+       if (drvregistered)
+               driver_unregister(&ipmidriver.driver);
 }
 module_exit(cleanup_ipmi);
 
index ca9528c4f183e7ea57cb71805b5a09aaf3bedd69..b7a1ae2afaeac7435410f6c100d7e9941f2cb486 100644 (file)
@@ -632,8 +632,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 
                /* Remove the multi-part read marker. */
                len -= 2;
+               data += 2;
                for (i = 0; i < len; i++)
-                       ssif_info->data[i] = data[i+2];
+                       ssif_info->data[i] = data[i];
                ssif_info->multi_len = len;
                ssif_info->multi_pos = 1;
 
@@ -661,8 +662,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
 
                blocknum = data[0];
+               len--;
+               data++;
+
+               if (blocknum != 0xff && len != 31) {
+                   /* All blocks but the last must have 31 data bytes. */
+                       result = -EIO;
+                       if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+                               pr_info("Received middle message <31\n");
 
-               if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
+                       goto continue_op;
+               }
+
+               if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
                        /* Received message too big, abort the operation. */
                        result = -E2BIG;
                        if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
@@ -671,16 +683,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                        goto continue_op;
                }
 
-               /* Remove the blocknum from the data. */
-               len--;
                for (i = 0; i < len; i++)
-                       ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
+                       ssif_info->data[i + ssif_info->multi_len] = data[i];
                ssif_info->multi_len += len;
                if (blocknum == 0xff) {
                        /* End of read */
                        len = ssif_info->multi_len;
                        data = ssif_info->data;
-               } else if (blocknum + 1 != ssif_info->multi_pos) {
+               } else if (blocknum != ssif_info->multi_pos) {
                        /*
                         * Out of sequence block, just abort.  Block
                         * numbers start at zero for the second block,
@@ -707,6 +717,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
        }
 
+ continue_op:
        if (result < 0) {
                ssif_inc_stat(ssif_info, receive_errors);
        } else {
@@ -714,8 +725,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                ssif_inc_stat(ssif_info, received_message_parts);
        }
 
-
- continue_op:
        if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
                pr_info("DONE 1: state = %d, result=%d\n",
                        ssif_info->ssif_state, result);
index b5e3103c1175575a0e16d3f4168b4d343aca7b6f..e43c876a92232d9fc0e8a18269c5c4fd7342a3ff 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
+#include <linux/nospec.h>
 #include "smapi.h"
 #include "mwavedd.h"
 #include "3780i.h"
@@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        PRINTK_3(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
                                " ipcnum %x entry usIntCount %x\n",
@@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                " Invalid ipcnum %x\n", ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        PRINTK_3(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
                                " ipcnum %x, usIntCount %x\n",
@@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        mutex_lock(&mwave_mutex);
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
                                pDrvData->IPCs[ipcnum].bIsEnabled = false;
index e5b2fe80eab432c699242cd3146e5c97e2928f7a..d2f0bb5ba47eabd3702a9c249f51f81f8d25a318 100644 (file)
@@ -293,7 +293,6 @@ config COMMON_CLK_BD718XX
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
-source "drivers/clk/imx/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
index 5b393e711e94b28559a23b215810c5bdbf3d0666..7d16ab0784ecf4258963a2429ef6ea95e3ecc777 100644 (file)
@@ -262,8 +262,10 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index)
 
                if (vc5->clk_mux_ins == VC5_MUX_IN_XIN)
                        src = VC5_PRIM_SRC_SHDN_EN_XTAL;
-               if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
+               else if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
                        src = VC5_PRIM_SRC_SHDN_EN_CLKIN;
+               else /* Invalid; should have been caught by vc5_probe() */
+                       return -EINVAL;
        }
 
        return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src);
index 75d13c0eff1243ebc29bbab45470e34f127e538c..d2477a5058ac2eb2d7925f04ae435479ff1efc9a 100644 (file)
@@ -1513,9 +1513,19 @@ static int clk_fetch_parent_index(struct clk_core *core,
        if (!parent)
                return -EINVAL;
 
-       for (i = 0; i < core->num_parents; i++)
-               if (clk_core_get_parent_by_index(core, i) == parent)
+       for (i = 0; i < core->num_parents; i++) {
+               if (core->parents[i] == parent)
+                       return i;
+
+               if (core->parents[i])
+                       continue;
+
+               /* Fallback to comparing globally unique names */
+               if (!strcmp(parent->name, core->parent_names[i])) {
+                       core->parents[i] = parent;
                        return i;
+               }
+       }
 
        return -EINVAL;
 }
@@ -2779,7 +2789,7 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
        seq_printf(s, "\"protect_count\": %d,", c->protect_count);
        seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
        seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
-       seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+       seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
        seq_printf(s, "\"duty_cycle\": %u",
                   clk_core_get_scaled_duty_cycle(c, 100000));
 }
index 0026c3969b1ec0ddb8aa77e9541905316901e2fe..76b9eb15604e1d241c0a91e7358de37e83a48a40 100644 (file)
@@ -155,13 +155,14 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_frac_pll *pll = to_clk_frac_pll(hw);
        u32 val, divfi, divff;
-       u64 temp64 = parent_rate;
+       u64 temp64;
        int ret;
 
        parent_rate *= 8;
        rate *= 2;
        divfi = rate / parent_rate;
-       temp64 *= rate - divfi;
+       temp64 = parent_rate * divfi;
+       temp64 = rate - temp64;
        temp64 *= PLL_FRAC_DENOM;
        do_div(temp64, parent_rate);
        divff = temp64;
index 99c2508de8e56777ea4ab6814470e7584fb3d700..fb6edf1b8aa2688bc1ce7e2e2555698d8c01a583 100644 (file)
@@ -169,6 +169,8 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
                return -ENODEV;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
        base = devm_ioremap(dev, res->start, resource_size(res));
        if (!base)
                return -ENOMEM;
index 61fefc046ec5ad8fd1de8df585e7c47d50be474b..d083b860f08333ad1caf8082664efdeaf1e0099d 100644 (file)
@@ -53,7 +53,6 @@
 #define APMU_DISP1     0x110
 #define APMU_CCIC0     0x50
 #define APMU_CCIC1     0xf4
-#define APMU_SP                0x68
 #define MPMU_UART_PLL  0x14
 
 struct mmp2_clk_unit {
@@ -210,8 +209,6 @@ static struct mmp_clk_mix_config ccic1_mix_config = {
        .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32),
 };
 
-static DEFINE_SPINLOCK(sp_lock);
-
 static struct mmp_param_mux_clk apmu_mux_clks[] = {
        {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock},
        {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock},
@@ -242,7 +239,6 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
        {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
-       {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock},
 };
 
 static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
index 1b1ba54e33dde801bc380280507ec933f65cddea..1c04575c118f722c5d94ad28c281bdb1a76ec611 100644 (file)
@@ -215,6 +215,7 @@ config MSM_MMCC_8996
 
 config MSM_GCC_8998
        tristate "MSM8998 Global Clock Controller"
+       select QCOM_GDSC
        help
          Support for the global clock controller on msm8998 devices.
          Say Y if you want to use peripheral devices such as UART, SPI,
index c782e62dd98b8949e469cc3c0ca12eb288d0f58f..58fa5c247af10d52cc596616db835bcd7994942d 100644 (file)
@@ -115,8 +115,8 @@ static const char * const gcc_parent_names_6[] = {
        "core_bi_pll_test_se",
 };
 
-static const char * const gcc_parent_names_7[] = {
-       "bi_tcxo",
+static const char * const gcc_parent_names_7_ao[] = {
+       "bi_tcxo_ao",
        "gpll0",
        "gpll0_out_even",
        "core_bi_pll_test_se",
@@ -128,6 +128,12 @@ static const char * const gcc_parent_names_8[] = {
        "core_bi_pll_test_se",
 };
 
+static const char * const gcc_parent_names_8_ao[] = {
+       "bi_tcxo_ao",
+       "gpll0",
+       "core_bi_pll_test_se",
+};
+
 static const struct parent_map gcc_parent_map_10[] = {
        { P_BI_TCXO, 0 },
        { P_GPLL0_OUT_MAIN, 1 },
@@ -210,7 +216,7 @@ static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
        .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "gcc_cpuss_ahb_clk_src",
-               .parent_names = gcc_parent_names_7,
+               .parent_names = gcc_parent_names_7_ao,
                .num_parents = 4,
                .ops = &clk_rcg2_ops,
        },
@@ -229,7 +235,7 @@ static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = {
        .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "gcc_cpuss_rbcpr_clk_src",
-               .parent_names = gcc_parent_names_8,
+               .parent_names = gcc_parent_names_8_ao,
                .num_parents = 3,
                .ops = &clk_rcg2_ops,
        },
index 2d5d8b43727e95a5bd8f9af70c4452fedc1c9c19..c4d0b6f6abf2e1bb1a6027cd19bf0c22dc1b5cfe 100644 (file)
@@ -43,7 +43,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
        /* Read mdiv and fdiv from the fdbck register */
        reg = readl(socfpgaclk->hw.reg + 0x4);
        mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
-       vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+       vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
 
        return (unsigned long)vco_freq;
 }
index 5b238fc314ac65c83f6bbc44af222ad1f0037110..8281dfbf38c2f8c6e88db7489df6482b70f2a232 100644 (file)
 
 #include "stratix10-clk.h"
 
-static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
-                                       "f2s_free_clk",};
+static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk",
+                                       "f2s-free-clk",};
 static const char * const cntr_mux[] = { "main_pll", "periph_pll",
-                                        "osc1", "cb_intosc_hs_div2_clk",
-                                        "f2s_free_clk"};
-static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+                                        "osc1", "cb-intosc-hs-div2-clk",
+                                        "f2s-free-clk"};
+static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",};
 
 static const char * const noc_free_mux[] = {"main_noc_base_clk",
                                            "peri_noc_base_clk",
-                                           "osc1", "cb_intosc_hs_div2_clk",
-                                           "f2s_free_clk"};
+                                           "osc1", "cb-intosc-hs-div2-clk",
+                                           "f2s-free-clk"};
 
 static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
 static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
@@ -33,14 +33,14 @@ static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"
 static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
 static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
 
-static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"};
 static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
 static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
 
 static const char * const mpu_free_mux[] = {"main_mpu_base_clk",
                                            "peri_mpu_base_clk",
-                                           "osc1", "cb_intosc_hs_div2_clk",
-                                           "f2s_free_clk"};
+                                           "osc1", "cb-intosc-hs-div2-clk",
+                                           "f2s-free-clk"};
 
 /* clocks in AO (always on) controller */
 static const struct stratix10_pll_clock s10_pll_clks[] = {
index 269d3595758bebabf0f72d6448ba6633e9cd3c8f..edc31bb56674ad1ea425c93ab4ceb44bf183730b 100644 (file)
@@ -133,9 +133,11 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
        struct tegra_dfll_soc_data *soc;
 
        soc = tegra_dfll_unregister(pdev);
-       if (IS_ERR(soc))
+       if (IS_ERR(soc)) {
                dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n",
                        PTR_ERR(soc));
+               return PTR_ERR(soc);
+       }
 
        tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
 
index 8d77090ad94aecd283ee085bb77a81491c9c6978..0241450f3eb3c8509e6a3bb5010c130d2e40a384 100644 (file)
@@ -403,8 +403,10 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
        num_dividers = i;
 
        tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
-       if (!tmp)
+       if (!tmp) {
+               *table = ERR_PTR(-ENOMEM);
                return -ENOMEM;
+       }
 
        valid_div = 0;
        *width = 0;
@@ -439,6 +441,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
 {
        struct clk_omap_divider *div;
        struct clk_omap_reg *reg;
+       int ret;
 
        if (!setup)
                return NULL;
@@ -458,6 +461,12 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
                div->flags |= CLK_DIVIDER_POWER_OF_TWO;
 
        div->table = _get_div_table_from_setup(setup, &div->width);
+       if (IS_ERR(div->table)) {
+               ret = PTR_ERR(div->table);
+               kfree(div);
+               return ERR_PTR(ret);
+       }
+
 
        div->shift = setup->bit_shift;
        div->latch = -EINVAL;
index f65cc0ff76abdb630b0694eb7c3babcc2c46ff71..b0908ec62f73b057828ec0965a80bd9582f8acb7 100644 (file)
@@ -669,8 +669,8 @@ static int zynqmp_clk_setup(struct device_node *np)
        if (ret)
                return ret;
 
-       zynqmp_data = kzalloc(sizeof(*zynqmp_data) + sizeof(*zynqmp_data) *
-                                               clock_max_idx, GFP_KERNEL);
+       zynqmp_data = kzalloc(struct_size(zynqmp_data, hws, clock_max_idx),
+                             GFP_KERNEL);
        if (!zynqmp_data)
                return -ENOMEM;
 
index 595124074821a93807a893a3336a6c5089ddf795..c364027638e1aeccdb02c76963ad3212a13096bc 100644 (file)
@@ -154,6 +154,10 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
        if (IS_ERR(parent))
                return -ENODEV;
 
+       /* Bail out if both clocks point to fck */
+       if (clk_is_match(parent, timer->fclk))
+               return 0;
+
        ret = clk_set_parent(timer->fclk, parent);
        if (ret < 0)
                pr_err("%s: failed to set parent\n", __func__);
@@ -864,7 +868,6 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
        timer->pdev = pdev;
 
        pm_runtime_enable(dev);
-       pm_runtime_irq_safe(dev);
 
        if (!timer->reserved) {
                ret = pm_runtime_get_sync(dev);
index 66b633b48eb17faafd40e0f1dec42ebcb81cc3ec..c47182fc64eadb914cc3d631defd6fe2d7697a0d 100644 (file)
@@ -184,8 +184,8 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
        struct scmi_data *priv = policy->driver_data;
 
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
-       kfree(priv);
        dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
+       kfree(priv);
 
        return 0;
 }
index b17d153e724fd3c693930ad67583e4804a8b580d..23a1b27579a54d5e35ea373421aec47597d9f241 100644 (file)
@@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
        local_irq_enable();
        if (!current_set_polling_and_test()) {
                unsigned int loop_count = 0;
-               u64 limit = TICK_USEC;
+               u64 limit = TICK_NSEC;
                int i;
 
                for (i = 1; i < drv->state_count; i++) {
index 5a90075f719d74c898e4f7fd7a1b3c61be38bc3e..0be55fcc19bada4527c91ee361fdbbde002257a7 100644 (file)
@@ -692,6 +692,7 @@ config CRYPTO_DEV_BCM_SPU
        depends on ARCH_BCM_IPROC
        depends on MAILBOX
        default m
+       select CRYPTO_AUTHENC
        select CRYPTO_DES
        select CRYPTO_MD5
        select CRYPTO_SHA1
index c9393ffb70ed80c57e87aa200e8e69d7b42aeb9f..5567cbda279807b8e95a356fd37654522a3c22b5 100644 (file)
@@ -2845,44 +2845,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
        struct spu_hw *spu = &iproc_priv.spu;
        struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
        struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
-       const u8 *origkey = key;
-       const unsigned int origkeylen = keylen;
-
-       int ret = 0;
+       struct crypto_authenc_keys keys;
+       int ret;
 
        flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
                 keylen);
        flow_dump("  key: ", key, keylen);
 
-       if (!RTA_OK(rta, keylen))
-               goto badkey;
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+       ret = crypto_authenc_extractkeys(&keys, key, keylen);
+       if (ret)
                goto badkey;
 
-       param = RTA_DATA(rta);
-       ctx->enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
-
-       if (keylen < ctx->enckeylen)
-               goto badkey;
-       if (ctx->enckeylen > MAX_KEY_SIZE)
+       if (keys.enckeylen > MAX_KEY_SIZE ||
+           keys.authkeylen > MAX_KEY_SIZE)
                goto badkey;
 
-       ctx->authkeylen = keylen - ctx->enckeylen;
-
-       if (ctx->authkeylen > MAX_KEY_SIZE)
-               goto badkey;
+       ctx->enckeylen = keys.enckeylen;
+       ctx->authkeylen = keys.authkeylen;
 
-       memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen);
+       memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
        /* May end up padding auth key. So make sure it's zeroed. */
        memset(ctx->authkey, 0, sizeof(ctx->authkey));
-       memcpy(ctx->authkey, key, ctx->authkeylen);
+       memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
 
        switch (ctx->alg->cipher_info.alg) {
        case CIPHER_ALG_DES:
@@ -2890,7 +2874,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                        u32 tmp[DES_EXPKEY_WORDS];
                        u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
 
-                       if (des_ekey(tmp, key) == 0) {
+                       if (des_ekey(tmp, keys.enckey) == 0) {
                                if (crypto_aead_get_flags(cipher) &
                                    CRYPTO_TFM_REQ_WEAK_KEY) {
                                        crypto_aead_set_flags(cipher, flags);
@@ -2905,7 +2889,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                break;
        case CIPHER_ALG_3DES:
                if (ctx->enckeylen == (DES_KEY_SIZE * 3)) {
-                       const u32 *K = (const u32 *)key;
+                       const u32 *K = (const u32 *)keys.enckey;
                        u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED;
 
                        if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -2956,9 +2940,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
                ctx->fallback_cipher->base.crt_flags |=
                    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
-               ret =
-                   crypto_aead_setkey(ctx->fallback_cipher, origkey,
-                                      origkeylen);
+               ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
                if (ret) {
                        flow_log("  fallback setkey() returned:%d\n", ret);
                        tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
index 92e593e2069ae1511a67e7addf17fffeb842947b..80ae69f906fbd360a8ca8f714aea9dfe990584e2 100644 (file)
@@ -3476,7 +3476,7 @@ static int __init caam_algapi_init(void)
                 * Skip algorithms requiring message digests
                 * if MD or MD size is not supported by device.
                 */
-               if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 &&
+               if (is_mdha(c2_alg_sel) &&
                    (!md_inst || t_alg->aead.maxauthsize > md_limit))
                        continue;
 
index 81712aa5d0f2fae6062efe706e6811e98c79db2e..bb1a2cdf195127070579d4988b662926af976549 100644 (file)
@@ -1072,13 +1072,16 @@ static int ahash_final_no_ctx(struct ahash_request *req)
 
        desc = edesc->hw_desc;
 
-       state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, state->buf_dma)) {
-               dev_err(jrdev, "unable to map src\n");
-               goto unmap;
-       }
+       if (buflen) {
+               state->buf_dma = dma_map_single(jrdev, buf, buflen,
+                                               DMA_TO_DEVICE);
+               if (dma_mapping_error(jrdev, state->buf_dma)) {
+                       dev_err(jrdev, "unable to map src\n");
+                       goto unmap;
+               }
 
-       append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+               append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+       }
 
        edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
                                                digestsize);
index ec10230178c5215a1f442be0cde4478629000a3c..4b6854bf896a74f0755dc32a697ef8f8ebee9916 100644 (file)
 #define OP_ALG_ALGSEL_DES      (0x20 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_3DES     (0x21 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_ARC4     (0x30 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_CHA_MDHA                (0x40 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_MD5      (0x40 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_SHA1     (0x41 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_SHA224   (0x42 << OP_ALG_ALGSEL_SHIFT)
index 67ea94079837e94073a5d079e1409af5f7da0959..8c6b83e02a70add5256b87dc37d3da026bac6c13 100644 (file)
@@ -7,6 +7,9 @@
 
 #ifndef CAAM_ERROR_H
 #define CAAM_ERROR_H
+
+#include "desc.h"
+
 #define CAAM_ERROR_STR_MAX 302
 
 void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
@@ -17,4 +20,10 @@ void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
 void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type,
                  int rowsize, int groupsize, struct scatterlist *sg,
                  size_t tlen, bool ascii);
+
+static inline bool is_mdha(u32 algtype)
+{
+       return (algtype & OP_ALG_ALGSEL_MASK & ~OP_ALG_ALGSEL_SUBMASK) ==
+              OP_ALG_CHA_MDHA;
+}
 #endif /* CAAM_ERROR_H */
index e34e4df8fd246275201dabdc53dc7f8570a6434f..4c97478d44bd2a3dec901f96846eb9a944cb57d4 100644 (file)
@@ -537,6 +537,8 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
        struct nitrox_device *ndev = cmdq->ndev;
        struct nitrox_softreq *sr;
        int req_completed = 0, err = 0, budget;
+       completion_t callback;
+       void *cb_arg;
 
        /* check all pending requests */
        budget = atomic_read(&cmdq->pending_count);
@@ -564,13 +566,13 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
                smp_mb__after_atomic();
                /* remove from response list */
                response_list_del(sr, cmdq);
-
                /* ORH error code */
                err = READ_ONCE(*sr->resp.orh) & 0xff;
+               callback = sr->callback;
+               cb_arg = sr->cb_arg;
                softreq_destroy(sr);
-
-               if (sr->callback)
-                       sr->callback(sr->cb_arg, err);
+               if (callback)
+                       callback(cb_arg, err);
 
                req_completed++;
        }
index f2643cda45db9eee4dfd06cf660e0aa4b878863a..a3527c00b29a99189c9578b32a12592f888f6fa7 100644 (file)
@@ -549,13 +549,12 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
                          unsigned int keylen)
 {
        struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct rtattr *rta = (struct rtattr *)key;
        struct cc_crypto_req cc_req = {};
-       struct crypto_authenc_key_param *param;
        struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
-       int rc = -EINVAL;
        unsigned int seq_len = 0;
        struct device *dev = drvdata_to_dev(ctx->drvdata);
+       const u8 *enckey, *authkey;
+       int rc;
 
        dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
                ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
@@ -563,35 +562,33 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        /* STAT_PHASE_0: Init and sanity checks */
 
        if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
-               if (!RTA_OK(rta, keylen))
-                       goto badkey;
-               if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-                       goto badkey;
-               if (RTA_PAYLOAD(rta) < sizeof(*param))
-                       goto badkey;
-               param = RTA_DATA(rta);
-               ctx->enc_keylen = be32_to_cpu(param->enckeylen);
-               key += RTA_ALIGN(rta->rta_len);
-               keylen -= RTA_ALIGN(rta->rta_len);
-               if (keylen < ctx->enc_keylen)
+               struct crypto_authenc_keys keys;
+
+               rc = crypto_authenc_extractkeys(&keys, key, keylen);
+               if (rc)
                        goto badkey;
-               ctx->auth_keylen = keylen - ctx->enc_keylen;
+               enckey = keys.enckey;
+               authkey = keys.authkey;
+               ctx->enc_keylen = keys.enckeylen;
+               ctx->auth_keylen = keys.authkeylen;
 
                if (ctx->cipher_mode == DRV_CIPHER_CTR) {
                        /* the nonce is stored in bytes at end of key */
+                       rc = -EINVAL;
                        if (ctx->enc_keylen <
                            (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
                                goto badkey;
                        /* Copy nonce from last 4 bytes in CTR key to
                         *  first 4 bytes in CTR IV
                         */
-                       memcpy(ctx->ctr_nonce, key + ctx->auth_keylen +
-                              ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE,
-                              CTR_RFC3686_NONCE_SIZE);
+                       memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen -
+                              CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
                        /* Set CTR key size */
                        ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
                }
        } else { /* non-authenc - has just one key */
+               enckey = key;
+               authkey = NULL;
                ctx->enc_keylen = keylen;
                ctx->auth_keylen = 0;
        }
@@ -603,13 +600,14 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        /* STAT_PHASE_1: Copy key to ctx */
 
        /* Get key material */
-       memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
+       memcpy(ctx->enckey, enckey, ctx->enc_keylen);
        if (ctx->enc_keylen == 24)
                memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
        if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
-               memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen);
+               memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey,
+                      ctx->auth_keylen);
        } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
-               rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen);
+               rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen);
                if (rc)
                        goto badkey;
        }
index 8ada308d72eea230ebfb75855324f811961472d9..b0125ad6582507ae523e553ea143a82df140f96a 100644 (file)
@@ -380,7 +380,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
        rc = cc_ivgen_init(new_drvdata);
        if (rc) {
                dev_err(dev, "cc_ivgen_init failed\n");
-               goto post_power_mgr_err;
+               goto post_buf_mgr_err;
        }
 
        /* Allocate crypto algs */
@@ -403,6 +403,9 @@ static int init_cc_resources(struct platform_device *plat_dev)
                goto post_hash_err;
        }
 
+       /* All set, we can allow autosuspend */
+       cc_pm_go(new_drvdata);
+
        /* If we got here and FIPS mode is enabled
         * it means all FIPS test passed, so let TEE
         * know we're good.
@@ -417,8 +420,6 @@ static int init_cc_resources(struct platform_device *plat_dev)
        cc_cipher_free(new_drvdata);
 post_ivgen_err:
        cc_ivgen_fini(new_drvdata);
-post_power_mgr_err:
-       cc_pm_fini(new_drvdata);
 post_buf_mgr_err:
         cc_buffer_mgr_fini(new_drvdata);
 post_req_mgr_err:
index d990f472e89fb35265de1872c31f5b08399cc3a5..6ff7e75ad90ebfaf54bafe4b118635e8b8ac3fe7 100644 (file)
@@ -100,20 +100,19 @@ int cc_pm_put_suspend(struct device *dev)
 
 int cc_pm_init(struct cc_drvdata *drvdata)
 {
-       int rc = 0;
        struct device *dev = drvdata_to_dev(drvdata);
 
        /* must be before the enabling to avoid resdundent suspending */
        pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
        pm_runtime_use_autosuspend(dev);
        /* activate the PM module */
-       rc = pm_runtime_set_active(dev);
-       if (rc)
-               return rc;
-       /* enable the PM module*/
-       pm_runtime_enable(dev);
+       return pm_runtime_set_active(dev);
+}
 
-       return rc;
+/* enable the PM module*/
+void cc_pm_go(struct cc_drvdata *drvdata)
+{
+       pm_runtime_enable(drvdata_to_dev(drvdata));
 }
 
 void cc_pm_fini(struct cc_drvdata *drvdata)
index 020a5403c58bac36961632075856a916d87fca60..f6262435702094effeb6356bf5636728ffb06fd2 100644 (file)
@@ -16,6 +16,7 @@
 extern const struct dev_pm_ops ccree_pm;
 
 int cc_pm_init(struct cc_drvdata *drvdata);
+void cc_pm_go(struct cc_drvdata *drvdata);
 void cc_pm_fini(struct cc_drvdata *drvdata);
 int cc_pm_suspend(struct device *dev);
 int cc_pm_resume(struct device *dev);
@@ -29,6 +30,8 @@ static inline int cc_pm_init(struct cc_drvdata *drvdata)
        return 0;
 }
 
+static void cc_pm_go(struct cc_drvdata *drvdata) {}
+
 static inline void cc_pm_fini(struct cc_drvdata *drvdata) {}
 
 static inline int cc_pm_suspend(struct device *dev)
index 45e20707cef8d708d2398a2e6d338bf1b053f7f6..f8e2c5c3f4eb1241d3b4993dfe2e29e57a8d90d8 100644 (file)
@@ -1361,23 +1361,18 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        struct talitos_private *priv = dev_get_drvdata(dev);
        bool is_sec1 = has_ftr_sec1(priv);
        int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
-       void *err;
 
        if (cryptlen + authsize > max_len) {
                dev_err(dev, "length exceeds h/w max limit\n");
                return ERR_PTR(-EINVAL);
        }
 
-       if (ivsize)
-               iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
-
        if (!dst || dst == src) {
                src_len = assoclen + cryptlen + authsize;
                src_nents = sg_nents_for_len(src, src_len);
                if (src_nents < 0) {
                        dev_err(dev, "Invalid number of src SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_nents = dst ? src_nents : 0;
@@ -1387,16 +1382,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                src_nents = sg_nents_for_len(src, src_len);
                if (src_nents < 0) {
                        dev_err(dev, "Invalid number of src SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
                dst_nents = sg_nents_for_len(dst, dst_len);
                if (dst_nents < 0) {
                        dev_err(dev, "Invalid number of dst SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
@@ -1423,11 +1416,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        /* if its a ahash, add space for a second desc next to the first one */
        if (is_sec1 && !dst)
                alloc_len += sizeof(struct talitos_desc);
+       alloc_len += ivsize;
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
-       if (!edesc) {
-               err = ERR_PTR(-ENOMEM);
-               goto error_sg;
+       if (!edesc)
+               return ERR_PTR(-ENOMEM);
+       if (ivsize) {
+               iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
+               iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
        }
        memset(&edesc->desc, 0, sizeof(edesc->desc));
 
@@ -1445,10 +1441,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                     DMA_BIDIRECTIONAL);
        }
        return edesc;
-error_sg:
-       if (iv_dma)
-               dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
-       return err;
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
index 4e557684f792d74f493abf922fbef63ed9045b63..fe69dccfa0c059f14b2a451974fceb8a0575acef 100644 (file)
@@ -203,6 +203,7 @@ struct at_xdmac_chan {
        u32                             save_cim;
        u32                             save_cnda;
        u32                             save_cndc;
+       u32                             irq_status;
        unsigned long                   status;
        struct tasklet_struct           tasklet;
        struct dma_slave_config         sconfig;
@@ -1580,8 +1581,8 @@ static void at_xdmac_tasklet(unsigned long data)
        struct at_xdmac_desc    *desc;
        u32                     error_mask;
 
-       dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n",
-                __func__, atchan->status);
+       dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n",
+               __func__, atchan->irq_status);
 
        error_mask = AT_XDMAC_CIS_RBEIS
                     | AT_XDMAC_CIS_WBEIS
@@ -1589,15 +1590,15 @@ static void at_xdmac_tasklet(unsigned long data)
 
        if (at_xdmac_chan_is_cyclic(atchan)) {
                at_xdmac_handle_cyclic(atchan);
-       } else if ((atchan->status & AT_XDMAC_CIS_LIS)
-                  || (atchan->status & error_mask)) {
+       } else if ((atchan->irq_status & AT_XDMAC_CIS_LIS)
+                  || (atchan->irq_status & error_mask)) {
                struct dma_async_tx_descriptor  *txd;
 
-               if (atchan->status & AT_XDMAC_CIS_RBEIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
                        dev_err(chan2dev(&atchan->chan), "read bus error!!!");
-               if (atchan->status & AT_XDMAC_CIS_WBEIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
                        dev_err(chan2dev(&atchan->chan), "write bus error!!!");
-               if (atchan->status & AT_XDMAC_CIS_ROIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
                        dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
 
                spin_lock(&atchan->lock);
@@ -1652,7 +1653,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
                        atchan = &atxdmac->chan[i];
                        chan_imr = at_xdmac_chan_read(atchan, AT_XDMAC_CIM);
                        chan_status = at_xdmac_chan_read(atchan, AT_XDMAC_CIS);
-                       atchan->status = chan_status & chan_imr;
+                       atchan->irq_status = chan_status & chan_imr;
                        dev_vdbg(atxdmac->dma.dev,
                                 "%s: chan%d: imr=0x%x, status=0x%x\n",
                                 __func__, i, chan_imr, chan_status);
@@ -1666,7 +1667,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
                                 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
                                 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
 
-                       if (atchan->status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
+                       if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
                                at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
 
                        tasklet_schedule(&atchan->tasklet);
index 1a44c8086d77a9e23d16a19f14033963ffb14ef7..ae10f5614f953e5fee68a60b85bddff0947b238e 100644 (file)
@@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
        }
 }
 
-static int bcm2835_dma_abort(void __iomem *chan_base)
+static int bcm2835_dma_abort(struct bcm2835_chan *c)
 {
-       unsigned long cs;
+       void __iomem *chan_base = c->chan_base;
        long int timeout = 10000;
 
-       cs = readl(chan_base + BCM2835_DMA_CS);
-       if (!(cs & BCM2835_DMA_ACTIVE))
+       /*
+        * A zero control block address means the channel is idle.
+        * (The ACTIVE flag in the CS register is not a reliable indicator.)
+        */
+       if (!readl(chan_base + BCM2835_DMA_ADDR))
                return 0;
 
        /* Write 0 to the active bit - Pause the DMA */
        writel(0, chan_base + BCM2835_DMA_CS);
 
        /* Wait for any current AXI transfer to complete */
-       while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) {
+       while ((readl(chan_base + BCM2835_DMA_CS) &
+               BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
                cpu_relax();
-               cs = readl(chan_base + BCM2835_DMA_CS);
-       }
 
-       /* We'll un-pause when we set of our next DMA */
+       /* Peripheral might be stuck and fail to signal AXI write responses */
        if (!timeout)
-               return -ETIMEDOUT;
-
-       if (!(cs & BCM2835_DMA_ACTIVE))
-               return 0;
-
-       /* Terminate the control block chain */
-       writel(0, chan_base + BCM2835_DMA_NEXTCB);
-
-       /* Abort the whole DMA */
-       writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE,
-              chan_base + BCM2835_DMA_CS);
+               dev_err(c->vc.chan.device->dev,
+                       "failed to complete outstanding writes\n");
 
+       writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS);
        return 0;
 }
 
@@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 
        spin_lock_irqsave(&c->vc.lock, flags);
 
-       /* Acknowledge interrupt */
-       writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS);
+       /*
+        * Clear the INT flag to receive further interrupts. Keep the channel
+        * active in case the descriptor is cyclic or in case the client has
+        * already terminated the descriptor and issued a new one. (May happen
+        * if this IRQ handler is threaded.) If the channel is finished, it
+        * will remain idle despite the ACTIVE flag being set.
+        */
+       writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
+              c->chan_base + BCM2835_DMA_CS);
 
        d = c->desc;
 
@@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
                if (d->cyclic) {
                        /* call the cyclic callback */
                        vchan_cyclic_callback(&d->vd);
-
-                       /* Keep the DMA engine running */
-                       writel(BCM2835_DMA_ACTIVE,
-                              c->chan_base + BCM2835_DMA_CS);
-               } else {
+               } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
                        vchan_cookie_complete(&c->desc->vd);
                        bcm2835_dma_start_desc(c);
                }
@@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
        struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
        struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device);
        unsigned long flags;
-       int timeout = 10000;
        LIST_HEAD(head);
 
        spin_lock_irqsave(&c->vc.lock, flags);
@@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
        list_del_init(&c->node);
        spin_unlock(&d->lock);
 
-       /*
-        * Stop DMA activity: we assume the callback will not be called
-        * after bcm_dma_abort() returns (even if it does, it will see
-        * c->desc is NULL and exit.)
-        */
+       /* stop DMA activity */
        if (c->desc) {
                vchan_terminate_vdesc(&c->desc->vd);
                c->desc = NULL;
-               bcm2835_dma_abort(c->chan_base);
-
-               /* Wait for stopping */
-               while (--timeout) {
-                       if (!(readl(c->chan_base + BCM2835_DMA_CS) &
-                                               BCM2835_DMA_ACTIVE))
-                               break;
-
-                       cpu_relax();
-               }
-
-               if (!timeout)
-                       dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+               bcm2835_dma_abort(c);
        }
 
        vchan_get_all_descriptors(&c->vc, &head);
index 2eea4ef729153637d79fe187bb02b2645f92ca14..6511928b4cdfe11c944223a8c7e3e8b0f8b9cc96 100644 (file)
@@ -711,11 +711,9 @@ static int dmatest_func(void *data)
                        srcs[i] = um->addr[i] + src_off;
                        ret = dma_mapping_error(dev->dev, um->addr[i]);
                        if (ret) {
-                               dmaengine_unmap_put(um);
                                result("src mapping error", total_tests,
                                       src_off, dst_off, len, ret);
-                               failed_tests++;
-                               continue;
+                               goto error_unmap_continue;
                        }
                        um->to_cnt++;
                }
@@ -730,11 +728,9 @@ static int dmatest_func(void *data)
                                               DMA_BIDIRECTIONAL);
                        ret = dma_mapping_error(dev->dev, dsts[i]);
                        if (ret) {
-                               dmaengine_unmap_put(um);
                                result("dst mapping error", total_tests,
                                       src_off, dst_off, len, ret);
-                               failed_tests++;
-                               continue;
+                               goto error_unmap_continue;
                        }
                        um->bidi_cnt++;
                }
@@ -762,12 +758,10 @@ static int dmatest_func(void *data)
                }
 
                if (!tx) {
-                       dmaengine_unmap_put(um);
                        result("prep error", total_tests, src_off,
                               dst_off, len, ret);
                        msleep(100);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
 
                done->done = false;
@@ -776,12 +770,10 @@ static int dmatest_func(void *data)
                cookie = tx->tx_submit(tx);
 
                if (dma_submit_error(cookie)) {
-                       dmaengine_unmap_put(um);
                        result("submit error", total_tests, src_off,
                               dst_off, len, ret);
                        msleep(100);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
                dma_async_issue_pending(chan);
 
@@ -790,22 +782,20 @@ static int dmatest_func(void *data)
 
                status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
-               dmaengine_unmap_put(um);
-
                if (!done->done) {
                        result("test timed out", total_tests, src_off, dst_off,
                               len, 0);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                } else if (status != DMA_COMPLETE) {
                        result(status == DMA_ERROR ?
                               "completion error status" :
                               "completion busy status", total_tests, src_off,
                               dst_off, len, ret);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
 
+               dmaengine_unmap_put(um);
+
                if (params->noverify) {
                        verbose_result("test passed", total_tests, src_off,
                                       dst_off, len, 0);
@@ -846,6 +836,12 @@ static int dmatest_func(void *data)
                        verbose_result("test passed", total_tests, src_off,
                                       dst_off, len, 0);
                }
+
+               continue;
+
+error_unmap_continue:
+               dmaengine_unmap_put(um);
+               failed_tests++;
        }
        ktime = ktime_sub(ktime_get(), ktime);
        ktime = ktime_sub(ktime, comparetime);
index c2fff3f6c9ca5f49054e1fd41e94d36b849669a9..4a09af3cd546a4c3569d3ed828fa5407fc5aadc8 100644 (file)
@@ -618,7 +618,7 @@ static void imxdma_tasklet(unsigned long data)
 {
        struct imxdma_channel *imxdmac = (void *)data;
        struct imxdma_engine *imxdma = imxdmac->imxdma;
-       struct imxdma_desc *desc;
+       struct imxdma_desc *desc, *next_desc;
        unsigned long flags;
 
        spin_lock_irqsave(&imxdma->lock, flags);
@@ -648,10 +648,10 @@ static void imxdma_tasklet(unsigned long data)
        list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
 
        if (!list_empty(&imxdmac->ld_queue)) {
-               desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
-                                       node);
+               next_desc = list_first_entry(&imxdmac->ld_queue,
+                                            struct imxdma_desc, node);
                list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
-               if (imxdma_xfer_desc(desc) < 0)
+               if (imxdma_xfer_desc(next_desc) < 0)
                        dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
                                 __func__, imxdmac->channel);
        }
index 4213cb0bb2a792cc6bdb2da5e2cc2ff621687654..f8664bac9fa82bae6d1bf7be616c3a3a83b562bb 100644 (file)
@@ -295,8 +295,8 @@ struct altr_sdram_mc_data {
 #define S10_SYSMGR_ECC_INTSTAT_DERR_OFST  0xA0
 
 /* Sticky registers for Uncorrected Errors */
-#define S10_SYSMGR_UE_VAL_OFST            0x120
-#define S10_SYSMGR_UE_ADDR_OFST           0x124
+#define S10_SYSMGR_UE_VAL_OFST            0x220
+#define S10_SYSMGR_UE_ADDR_OFST           0x224
 
 #define S10_DDR0_IRQ_MASK                 BIT(16)
 
index 09b845e901140b9e1bcb79e4a7e773337a07d85d..a785ffd5af891abe95938da021afb5358ec6d84b 100644 (file)
@@ -1144,10 +1144,6 @@ static int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
        if (device->is_local)
                return -ENODEV;
 
-       if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
-               WARN_ON(dma_set_max_seg_size(device->card->device,
-                                            SBP2_MAX_SEG_SIZE));
-
        shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
        if (shost == NULL)
                return -ENOMEM;
@@ -1610,6 +1606,7 @@ static struct scsi_host_template scsi_driver_template = {
        .eh_abort_handler       = sbp2_scsi_abort,
        .this_id                = -1,
        .sg_tablesize           = SG_ALL,
+       .max_segment_size       = SBP2_MAX_SEG_SIZE,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
 };
index 472c88ae1c0f9d37ffae6d094a8500ca85ed3146..92f843eaf1e0156cf56d7839cec8d766bff6e86f 100644 (file)
@@ -119,6 +119,11 @@ void scmi_driver_unregister(struct scmi_driver *driver)
 }
 EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 
+static void scmi_device_release(struct device *dev)
+{
+       kfree(to_scmi_dev(dev));
+}
+
 struct scmi_device *
 scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 {
@@ -138,6 +143,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
        scmi_dev->dev.parent = parent;
        scmi_dev->dev.of_node = np;
        scmi_dev->dev.bus = &scmi_bus_type;
+       scmi_dev->dev.release = scmi_device_release;
        dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
 
        retval = device_register(&scmi_dev->dev);
@@ -156,9 +162,8 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 void scmi_device_destroy(struct scmi_device *scmi_dev)
 {
        scmi_handle_put(scmi_dev->handle);
-       device_unregister(&scmi_dev->dev);
        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
-       kfree(scmi_dev);
+       device_unregister(&scmi_dev->dev);
 }
 
 void scmi_set_handle(struct scmi_device *scmi_dev)
index 23ea1ed409d1bbc6f77ce4374a0e6bdc8aae3d5b..352bd2473162ed37f608b660e89617b4d50cba09 100644 (file)
@@ -37,8 +37,9 @@ extern u64 efi_system_table;
 static struct ptdump_info efi_ptdump_info = {
        .mm             = &efi_mm,
        .markers        = (struct addr_marker[]){
-               { 0,            "UEFI runtime start" },
-               { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" }
+               { 0,                            "UEFI runtime start" },
+               { DEFAULT_MAP_WINDOW_64,        "UEFI runtime end" },
+               { -1,                           NULL }
        },
        .base_addr      = 0,
 };
index 4c46ff6f2242d93874bc9af700283eab370cbdb2..55b77c576c428e96c8d10615087470916ede502a 100644 (file)
@@ -592,11 +592,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 
                early_memunmap(tbl, sizeof(*tbl));
        }
-       return 0;
-}
 
-int __init efi_apply_persistent_mem_reservations(void)
-{
        if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
                unsigned long prsv = efi.mem_reserve;
 
index eee42d5e25eecacbcf379ef9138f73f1e6ffb27b..c037c6c5d0b76505f9993b59a37ed2a993575e9e 100644 (file)
@@ -75,9 +75,6 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
        efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
        efi_status_t status;
 
-       if (IS_ENABLED(CONFIG_ARM))
-               return;
-
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
                                (void **)&rsv);
        if (status != EFI_SUCCESS) {
index 8903b9ccfc2b8da6cdc5341fef8619744d904c88..e2abfdb5cee6a2339e73ba6ec753dce1f83b2dbd 100644 (file)
@@ -146,6 +146,13 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
  */
 static DEFINE_SEMAPHORE(efi_runtime_lock);
 
+/*
+ * Expose the EFI runtime lock to the UV platform
+ */
+#ifdef CONFIG_X86_UV
+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
+#endif
+
 /*
  * Calls the appropriate efi_runtime_service() with the appropriate
  * arguments.
index a1a09e04fab89de2f1b5399a91ddc85da3f78e96..13851b3d1c565dc9e3878efc53474915b4eec9d3 100644 (file)
@@ -508,14 +508,11 @@ static int __init s10_init(void)
                return -ENODEV;
 
        np = of_find_matching_node(fw_np, s10_of_match);
-       if (!np) {
-               of_node_put(fw_np);
+       if (!np)
                return -ENODEV;
-       }
 
        of_node_put(np);
        ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);
-       of_node_put(fw_np);
        if (ret)
                return ret;
 
index 6b11f131424848b9cd911936f7a124e2edcf32ee..7f9e0304b5109a8b51fc108679cc32d4d8fbb9e8 100644 (file)
@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
 static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
                                            unsigned int nr, int value)
 {
-       if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+       if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
+               altr_a10sr_gpio_set(gc, nr, value);
                return 0;
+       }
        return -EINVAL;
 }
 
index e0d6a0a7bc697d0de1e3f1b364a0dc4041ad9b2a..e41223c05f6e2fb9e8ff3492e875e62da72ab684 100644 (file)
@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
 
 static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
 {
-       return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+       struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
+
+       switch (sprd_eic->type) {
+       case SPRD_EIC_DEBOUNCE:
+               return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+       case SPRD_EIC_ASYNC:
+               return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
+       case SPRD_EIC_SYNC:
+               return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
+       default:
+               return -ENOTSUPP;
+       }
 }
 
 static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset)
@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
                        irq_set_handler_locked(data, handle_edge_irq);
                        break;
                case IRQ_TYPE_EDGE_BOTH:
+                       sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
                        sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
                        irq_set_handler_locked(data, handle_edge_irq);
                        break;
index 83617fdc661d27012712a4591907335e8d7e5d14..0dc96419efe367b4d34c0ef99749ae2e5e12c622 100644 (file)
@@ -289,7 +289,7 @@ static bool pca953x_volatile_register(struct device *dev, unsigned int reg)
        return pca953x_check_register(chip, reg, bank);
 }
 
-const struct regmap_config pca953x_i2c_regmap = {
+static const struct regmap_config pca953x_i2c_regmap = {
        .reg_bits = 8,
        .val_bits = 8,
 
index adf72dda25a2b543e32e6e2aee1d2f4d1b82d352..68a35b65925aca762ca349f0f54704b306b72190 100644 (file)
@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
  */
 struct pcf857x {
        struct gpio_chip        chip;
+       struct irq_chip         irqchip;
        struct i2c_client       *client;
        struct mutex            lock;           /* protect 'out' */
        unsigned                out;            /* software latch */
@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
        mutex_unlock(&gpio->lock);
 }
 
-static struct irq_chip pcf857x_irq_chip = {
-       .name           = "pcf857x",
-       .irq_enable     = pcf857x_irq_enable,
-       .irq_disable    = pcf857x_irq_disable,
-       .irq_ack        = noop,
-       .irq_mask       = noop,
-       .irq_unmask     = noop,
-       .irq_set_wake   = pcf857x_irq_set_wake,
-       .irq_bus_lock           = pcf857x_irq_bus_lock,
-       .irq_bus_sync_unlock    = pcf857x_irq_bus_sync_unlock,
-};
-
 /*-------------------------------------------------------------------------*/
 
 static int pcf857x_probe(struct i2c_client *client,
@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
 
        /* Enable irqchip if we have an interrupt */
        if (client->irq) {
+               gpio->irqchip.name = "pcf857x",
+               gpio->irqchip.irq_enable = pcf857x_irq_enable,
+               gpio->irqchip.irq_disable = pcf857x_irq_disable,
+               gpio->irqchip.irq_ack = noop,
+               gpio->irqchip.irq_mask = noop,
+               gpio->irqchip.irq_unmask = noop,
+               gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
+               gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
+               gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
                status = gpiochip_irqchip_add_nested(&gpio->chip,
-                                                    &pcf857x_irq_chip,
+                                                    &gpio->irqchip,
                                                     0, handle_level_irq,
                                                     IRQ_TYPE_NONE);
                if (status) {
@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
                if (status)
                        goto fail;
 
-               gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+               gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
                                            client->irq);
                gpio->irq_parent = client->irq;
        }
index 1b79ebcfce3e5c3e9d59d3586155642bf84ef6ad..541fa6ac399d24b288d7f148717874d2392e9023 100644 (file)
@@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        struct vf610_gpio_port *port;
        struct resource *iores;
        struct gpio_chip *gc;
+       int i;
        int ret;
 
        port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
@@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
+       /* Mask all GPIO interrupts */
+       for (i = 0; i < gc->ngpio; i++)
+               vf610_gpio_writel(0, port->base + PORT_PCR(i));
+
        /* Clear the interrupt status register for all GPIO's */
        vf610_gpio_writel(~0, port->base + PORT_ISFR);
 
index 48534bda73d39eb90e6ffde1a305e32582f8ef51..259cf6ab969b0d61a02ee768e0f16e5dda237573 100644 (file)
@@ -357,8 +357,6 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
        mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
 
        list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
-               struct gpio_desc *desc;
-
                if (event->irq_requested) {
                        if (event->irq_is_wake)
                                disable_irq_wake(event->irq);
@@ -366,11 +364,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
                        free_irq(event->irq, event);
                }
 
-               desc = event->desc;
-               if (WARN_ON(IS_ERR(desc)))
-                       continue;
                gpiochip_unlock_as_irq(chip, event->pin);
-               gpiochip_free_own_desc(desc);
+               gpiochip_free_own_desc(event->desc);
                list_del(&event->node);
                kfree(event);
        }
index 1651d7f0a303c3e7ea77f3924e83751dd9a41d47..d1adfdf50fb301b3f0be76af309963b955c31884 100644 (file)
@@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
        /* Do not leak kernel stack to userspace */
        memset(&ge, 0, sizeof(ge));
 
-       ge.timestamp = le->timestamp;
+       /*
+        * We may be running from a nested threaded interrupt in which case
+        * we didn't get the timestamp from lineevent_irq_handler().
+        */
+       if (!le->timestamp)
+               ge.timestamp = ktime_get_real_ns();
+       else
+               ge.timestamp = le->timestamp;
 
        if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
            && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
index a028661d9e2013dd2a6e5611448438c7590fec82..92b11de1958132c28e4ffd68e1fd782a8e2e5771 100644 (file)
@@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
        { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
+       { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0, 0, 0, 0, 0 },
 };
 
index dafc645b2e4ee5e18afe3615d79a691650e57fbd..b083b219b1a966e9e38c318cb30c91e478f650c7 100644 (file)
@@ -531,17 +531,6 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
        struct drm_gem_object *obj;
        struct amdgpu_framebuffer *amdgpu_fb;
        int ret;
-       int height;
-       struct amdgpu_device *adev = dev->dev_private;
-       int cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
-       int pitch = mode_cmd->pitches[0] / cpp;
-
-       pitch = amdgpu_align_pitch(adev, pitch, cpp, false);
-       if (mode_cmd->pitches[0] != pitch) {
-               DRM_DEBUG_KMS("Invalid pitch: expecting %d but got %d\n",
-                             pitch, mode_cmd->pitches[0]);
-               return ERR_PTR(-EINVAL);
-       }
 
        obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
        if (obj ==  NULL) {
@@ -556,13 +545,6 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       height = ALIGN(mode_cmd->height, 8);
-       if (obj->size < pitch * height) {
-               DRM_DEBUG_KMS("Invalid GEM size: expecting >= %d but got %zu\n",
-                             pitch * height, obj->size);
-               return ERR_PTR(-EINVAL);
-       }
-
        amdgpu_fb = kzalloc(sizeof(*amdgpu_fb), GFP_KERNEL);
        if (amdgpu_fb == NULL) {
                drm_gem_object_put_unlocked(obj);
index 6896dec97fc73c97b0a4a296aa6291c84f675d5b..0ed41a9d2d77161ccf5bad0498484e76cafbd03f 100644 (file)
@@ -1686,7 +1686,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
                effective_mode &= ~S_IWUSR;
 
        if ((adev->flags & AMD_IS_APU) &&
-           (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
+           (attr == &sensor_dev_attr_power1_average.dev_attr.attr ||
+            attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
             attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
             attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
                return 0;
index 71913a18d142cb028fe4077b0d4dca0d36be7f02..a38e0fb4a6fe15633de07db19b47bef89e64c991 100644 (file)
@@ -38,6 +38,7 @@
 #include "amdgpu_gem.h"
 #include <drm/amdgpu_drm.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-fence-array.h>
 
 /**
  * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table
@@ -187,6 +188,48 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
        return ERR_PTR(ret);
 }
 
+static int
+__reservation_object_make_exclusive(struct reservation_object *obj)
+{
+       struct dma_fence **fences;
+       unsigned int count;
+       int r;
+
+       if (!reservation_object_get_list(obj)) /* no shared fences to convert */
+               return 0;
+
+       r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences);
+       if (r)
+               return r;
+
+       if (count == 0) {
+               /* Now that was unexpected. */
+       } else if (count == 1) {
+               reservation_object_add_excl_fence(obj, fences[0]);
+               dma_fence_put(fences[0]);
+               kfree(fences);
+       } else {
+               struct dma_fence_array *array;
+
+               array = dma_fence_array_create(count, fences,
+                                              dma_fence_context_alloc(1), 0,
+                                              false);
+               if (!array)
+                       goto err_fences_put;
+
+               reservation_object_add_excl_fence(obj, &array->base);
+               dma_fence_put(&array->base);
+       }
+
+       return 0;
+
+err_fences_put:
+       while (count--)
+               dma_fence_put(fences[count]);
+       kfree(fences);
+       return -ENOMEM;
+}
+
 /**
  * amdgpu_gem_map_attach - &dma_buf_ops.attach implementation
  * @dma_buf: Shared DMA buffer
@@ -218,16 +261,16 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
 
        if (attach->dev->driver != adev->dev->driver) {
                /*
-                * Wait for all shared fences to complete before we switch to future
-                * use of exclusive fence on this prime shared bo.
+                * We only create shared fences for internal use, but importers
+                * of the dmabuf rely on exclusive fences for implicitly
+                * tracking write hazards. As any of the current fences may
+                * correspond to a write, we need to convert all existing
+                * fences on the reservation object into a single exclusive
+                * fence.
                 */
-               r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
-                                                       true, false,
-                                                       MAX_SCHEDULE_TIMEOUT);
-               if (unlikely(r < 0)) {
-                       DRM_DEBUG_PRIME("Fence wait failed: %li\n", r);
+               r = __reservation_object_make_exclusive(bo->tbo.resv);
+               if (r)
                        goto error_unreserve;
-               }
        }
 
        /* pin buffer into GTT */
index 8fab0d637ee51f96fa31cb5d81178d60f52db458..3a9b48b227acf8614d7473cc0ca9e251f8d91412 100644 (file)
@@ -90,8 +90,10 @@ static int psp_sw_fini(void *handle)
        adev->psp.sos_fw = NULL;
        release_firmware(adev->psp.asd_fw);
        adev->psp.asd_fw = NULL;
-       release_firmware(adev->psp.ta_fw);
-       adev->psp.ta_fw = NULL;
+       if (adev->psp.ta_fw) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+       }
        return 0;
 }
 
@@ -435,6 +437,9 @@ static int psp_xgmi_initialize(struct psp_context *psp)
        struct ta_xgmi_shared_memory *xgmi_cmd;
        int ret;
 
+       if (!psp->adev->psp.ta_fw)
+               return -ENOENT;
+
        if (!psp->xgmi_context.initialized) {
                ret = psp_xgmi_init_shared_buf(psp);
                if (ret)
index d2ea5ce2cefbee26506e4eeeeb3ed2ac24663cab..7c108e687683489fa5d247a1d42177bb225bdb99 100644 (file)
@@ -3363,14 +3363,15 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
                         struct amdgpu_task_info *task_info)
 {
        struct amdgpu_vm *vm;
+       unsigned long flags;
 
-       spin_lock(&adev->vm_manager.pasid_lock);
+       spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
 
        vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
        if (vm)
                *task_info = vm->task_info;
 
-       spin_unlock(&adev->vm_manager.pasid_lock);
+       spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
 }
 
 /**
index 4cd31a276dcd29a29cc2187d54ffff4ce083d170..186db182f924d5eb5166d87a9bdc46077d50cde6 100644 (file)
@@ -93,7 +93,20 @@ static void nbio_v7_4_enable_doorbell_aperture(struct amdgpu_device *adev,
 static void nbio_v7_4_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
                                                        bool enable)
 {
+       u32 tmp = 0;
 
+       if (enable) {
+               tmp = REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_EN, 1) |
+                     REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_MODE, 1) |
+                     REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_SIZE, 0);
+
+               WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_LOW,
+                            lower_32_bits(adev->doorbell.base));
+               WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_HIGH,
+                            upper_32_bits(adev->doorbell.base));
+       }
+
+       WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_CNTL, tmp);
 }
 
 static void nbio_v7_4_ih_doorbell_range(struct amdgpu_device *adev,
index 0c6e7f9b143fa692f50996aeb93de86ed19d6d13..189fcb004579a442629f0d5feb63671fc9caacf6 100644 (file)
@@ -152,18 +152,22 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
        err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
-       if (err)
-               goto out2;
-
-       err = amdgpu_ucode_validate(adev->psp.ta_fw);
-       if (err)
-               goto out2;
-
-       ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
-       adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
-       adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
-       adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
-               le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+       if (err) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+               dev_info(adev->dev,
+                        "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
+       } else {
+               err = amdgpu_ucode_validate(adev->psp.ta_fw);
+               if (err)
+                       goto out2;
+
+               ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
+               adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
+               adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
+               adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
+                       le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+       }
 
        return 0;
 
index 8849b74078d6e5373d82fba3f82980cf1bc4c8a7..9b639974c70cf1bd924526d4c92b21523ccda7ef 100644 (file)
@@ -729,11 +729,13 @@ static int soc15_common_early_init(void *handle)
        case CHIP_RAVEN:
                adev->asic_funcs = &soc15_asic_funcs;
                if (adev->rev_id >= 0x8)
-                       adev->external_rev_id = adev->rev_id + 0x81;
+                       adev->external_rev_id = adev->rev_id + 0x79;
                else if (adev->pdev->device == 0x15d8)
                        adev->external_rev_id = adev->rev_id + 0x41;
+               else if (adev->rev_id == 1)
+                       adev->external_rev_id = adev->rev_id + 0x20;
                else
-                       adev->external_rev_id = 0x1;
+                       adev->external_rev_id = adev->rev_id + 0x01;
 
                if (adev->rev_id >= 0x8) {
                        adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
index fbf0ee5201c370b1a09f51d6b2dfd6557b89b496..c3613604a4f8bc2d8d6bd60b4fc5dd31aa4dee55 100644 (file)
@@ -4,8 +4,8 @@
 
 config HSA_AMD
        bool "HSA kernel driver for AMD GPU devices"
-       depends on DRM_AMDGPU && X86_64
-       imply AMD_IOMMU_V2
+       depends on DRM_AMDGPU && (X86_64 || ARM64)
+       imply AMD_IOMMU_V2 if X86_64
        select MMU_NOTIFIER
        help
          Enable this if you want to use HSA features on AMD GPU devices.
index b7bc7d7d048f679cb11d58184578859868bd9bd4..2e7c44955f432a282e464315d0be46f054c4dcab 100644 (file)
@@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
        return 0;
 }
 
+#ifdef CONFIG_X86_64
 static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
                                uint32_t *num_entries,
                                struct crat_subtype_iolink *sub_type_hdr)
@@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
 
        return 0;
 }
+#endif
 
 /* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU
  *
@@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
        struct crat_subtype_generic *sub_type_hdr;
        int avail_size = *size;
        int numa_node_id;
+#ifdef CONFIG_X86_64
        uint32_t entries = 0;
+#endif
        int ret = 0;
 
        if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU)
@@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
                        sub_type_hdr->length);
 
                /* Fill in Subtype: IO Link */
+#ifdef CONFIG_X86_64
                ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,
                                &entries,
                                (struct crat_subtype_iolink *)sub_type_hdr);
@@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
 
                sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
                                sub_type_hdr->length * entries);
+#else
+               pr_info("IO link not available for non x86 platforms\n");
+#endif
 
                crat_table->num_domains++;
        }
index 5f5b2acedbac3bf0e15d8727d5327af37e3f7a79..09da91644f9fc6e15d29c628d6e16f1a2ddd0f69 100644 (file)
@@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
  *             the GPU device is not already present in the topology device
  *             list then return NULL. This means a new topology device has to
  *             be created for this GPU.
- * TODO: Rather than assiging @gpu to first topology device withtout
- *             gpu attached, it will better to have more stringent check.
  */
 static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
 {
@@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
        struct kfd_topology_device *out_dev = NULL;
 
        down_write(&topology_lock);
-       list_for_each_entry(dev, &topology_device_list, list)
+       list_for_each_entry(dev, &topology_device_list, list) {
+               /* Discrete GPUs need their own topology device list
+                * entries. Don't assign them to CPU/APU nodes.
+                */
+               if (!gpu->device_info->needs_iommu_device &&
+                   dev->node_props.cpu_cores_count)
+                       continue;
+
                if (!dev->gpu && (dev->node_props.simd_count > 0)) {
                        dev->gpu = gpu;
                        out_dev = dev;
                        break;
                }
+       }
        up_write(&topology_lock);
        return out_dev;
 }
@@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
 
 static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
 {
-       const struct cpuinfo_x86 *cpuinfo;
        int first_cpu_of_numa_node;
 
        if (!cpumask || cpumask == cpu_none_mask)
@@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
        first_cpu_of_numa_node = cpumask_first(cpumask);
        if (first_cpu_of_numa_node >= nr_cpu_ids)
                return -1;
-       cpuinfo = &cpu_data(first_cpu_of_numa_node);
-
-       return cpuinfo->apicid;
+#ifdef CONFIG_X86_64
+       return cpu_data(first_cpu_of_numa_node).apicid;
+#else
+       return first_cpu_of_numa_node;
+#endif
 }
 
 /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor
index 34f35e9a3c46da6c3fa7f455e9b884bed9a3bf3d..0b392bfca28475adc3e5921c7ab8b8ba1a5a7288 100644 (file)
@@ -1772,7 +1772,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
                + caps.min_input_signal * 0x101;
 
        if (dc_link_set_backlight_level(dm->backlight_link,
-                       brightness, 0, 0))
+                       brightness, 0))
                return 0;
        else
                return 1;
@@ -4082,7 +4082,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        }
 
        if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-           connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+           connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector_type == DRM_MODE_CONNECTOR_eDP) {
                drm_connector_attach_vrr_capable_property(
                        &aconnector->base);
        }
@@ -5933,7 +5934,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
                    !new_crtc_state->color_mgmt_changed &&
-                   !new_crtc_state->vrr_enabled)
+                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
                        continue;
 
                if (!new_crtc_state->enable)
index 9a7ac58eb18ea702383df1548e7013484b1edf62..ddd75a4d8ba5d4e19b0bc32c4fac813b43c91056 100644 (file)
@@ -671,6 +671,25 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us
        return bytes_from_user;
 }
 
+/*
+ * Returns the min and max vrr vfreq through the connector's debugfs file.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
+ */
+static int vrr_range_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+       if (connector->status != connector_status_connected)
+               return -ENODEV;
+
+       seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq);
+       seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq);
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vrr_range);
+
 static const struct file_operations dp_link_settings_debugfs_fops = {
        .owner = THIS_MODULE,
        .read = dp_link_settings_read,
@@ -697,7 +716,8 @@ static const struct {
 } dp_debugfs_entries[] = {
                {"link_settings", &dp_link_settings_debugfs_fops},
                {"phy_settings", &dp_phy_settings_debugfs_fop},
-               {"test_pattern", &dp_phy_test_pattern_fops}
+               {"test_pattern", &dp_phy_test_pattern_fops},
+               {"vrr_range", &vrr_range_fops}
 };
 
 int connector_debugfs_init(struct amdgpu_dm_connector *connector)
index 52deacf398411378c1f63f02d62dc117ff0b522a..b0265dbebd4c909bedceb2502eb27d1a14eb6ad9 100644 (file)
@@ -2190,8 +2190,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
 
 bool dc_link_set_backlight_level(const struct dc_link *link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream)
+               uint32_t frame_ramp)
 {
        struct dc  *core_dc = link->ctx->dc;
        struct abm *abm = core_dc->res_pool->abm;
@@ -2206,10 +2205,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                (abm->funcs->set_backlight_level_pwm == NULL))
                return false;
 
-       if (stream)
-               ((struct dc_stream_state *)stream)->bl_pwm_level =
-                               backlight_pwm_u16_16;
-
        use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
 
        DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
@@ -2637,11 +2632,6 @@ void core_link_enable_stream(
 
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        enable_stream_features(pipe_ctx);
-
-               dc_link_set_backlight_level(pipe_ctx->stream->sink->link,
-                               pipe_ctx->stream->bl_pwm_level,
-                               0,
-                               pipe_ctx->stream);
        }
 
 }
index 29f19d57ff7abd1e132ba89e65caa5d4f6bb2161..b2243e0dad1f50490d7a0be49b6ecb4fbbb574d8 100644 (file)
@@ -146,8 +146,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_
  */
 bool dc_link_set_backlight_level(const struct dc_link *dc_link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream);
+               uint32_t frame_ramp);
 
 int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
index be34d638e15dfee01416e82e38d209d102403fde..d70c9e1cda3d90ba1065981ca0eac0a471ae8db5 100644 (file)
@@ -91,7 +91,6 @@ struct dc_stream_state {
 
        /* DMCU info */
        unsigned int abm_level;
-       unsigned int bl_pwm_level;
 
        /* from core_stream struct */
        struct dc_context *ctx;
index afd287f08bc9520840ce1593c23d2cd98ae06cb1..19801bdba0d21fe7aa67ca19589e27a0e5ba4a46 100644 (file)
@@ -591,7 +591,15 @@ static void dce11_pplib_apply_display_requirements(
                        dc,
                        context->bw.dce.sclk_khz);
 
-       pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz;
+       /*
+        * As workaround for >4x4K lightup set dcfclock to min_engine_clock value.
+        * This is not required for less than 5 displays,
+        * thus don't request decfclk in dc to avoid impact
+        * on power saving.
+        *
+        */
+       pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4)?
+                       pp_display_cfg->min_engine_clock_khz : 0;
 
        pp_display_cfg->min_engine_clock_deep_sleep_khz
                        = context->bw.dce.sclk_deep_sleep_khz;
index 4bf24758217fdf7ad6537a0f5ec2fde7b5ad1950..8f09b8625c5dfc1fa6787077d3a76b4abb8783f6 100644 (file)
@@ -1000,7 +1000,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 
                pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
 
-               if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+               if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
                        /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
                        pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
                /* un-mute audio */
@@ -1017,6 +1017,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
        pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
                        pipe_ctx->stream_res.stream_enc, true);
        if (pipe_ctx->stream_res.audio) {
+               struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
+
                if (option != KEEP_ACQUIRED_RESOURCE ||
                                !dc->debug.az_endpoint_mute_only) {
                        /*only disalbe az_endpoint if power down or free*/
@@ -1036,6 +1038,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
                        update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
                        pipe_ctx->stream_res.audio = NULL;
                }
+               if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+                       /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
+                       pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
 
                /* TODO: notify audio driver for if audio modes list changed
                 * add audio mode list change flag */
index dcb3c55302365f84f06a07700f76509ee2016526..cd1ebe57ed594844a392ec2e1f2f0071c3dddbfe 100644 (file)
@@ -463,7 +463,7 @@ void dpp1_set_cursor_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0)
+       if (src_y_offset + (int)height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        REG_UPDATE(CURSOR0_CONTROL,
index 345af015d061f0850ccf64b633a9404293d7f381..d1acd7165bc8f1865391c31458aa44f166397638 100644 (file)
@@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0) //+ (int)hubp->curs_attr.height
+       if (src_y_offset + (int)hubp->curs_attr.height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
index 91e015e143550d9a4b10d8a6249df35db72c6e62..58a12ddf12f31a3ec718d51a56b8663c8a3e6e69 100644 (file)
@@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface(
                        top_pipe_to_program->plane_state->update_flags.bits.full_update)
                for (i = 0; i < dc->res_pool->pipe_count; i++) {
                        struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
+                       tg = pipe_ctx->stream_res.tg;
                        /* Skip inactive pipes and ones already updated */
                        if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                                       || !pipe_ctx->plane_state)
+                                       || !pipe_ctx->plane_state
+                                       || !tg->funcs->is_tg_enabled(tg))
                                continue;
 
-                       pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
+                       tg->funcs->lock(tg);
 
                        pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
                                pipe_ctx->plane_res.hubp,
                                &pipe_ctx->dlg_regs,
                                &pipe_ctx->ttu_regs);
-               }
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
-               if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                               || !pipe_ctx->plane_state)
-                       continue;
-
-               dcn10_pipe_control_lock(dc, pipe_ctx, false);
-       }
+                       tg->funcs->unlock(tg);
+               }
 
        if (num_planes == 0)
                false_optc_underflow_wa(dc, stream, tg);
index 00f63b7dd32f77828409d4b1b34008b3b316d9c2..c11a443dcbc8927fc2e9920ce7a72b332c139cd4 100644 (file)
@@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le
 #define NUM_POWER_FN_SEGS 8
 #define NUM_BL_CURVE_SEGS 16
 
+#pragma pack(push, 1)
 /* NOTE: iRAM is 256B in size */
 struct iram_table_v_2 {
        /* flags                      */
@@ -100,6 +101,7 @@ struct iram_table_v_2 {
        uint8_t dummy8;                                                 /* 0xfe       */
        uint8_t dummy9;                                                 /* 0xff       */
 };
+#pragma pack(pop)
 
 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
 {
index f95c5f50eb0f0cfda70912aaa6d1805d93306976..5273de3c5b9821422efde2440a1592a8474ebe9d 100644 (file)
@@ -1033,6 +1033,7 @@ static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
                break;
        case amd_pp_dpp_clock:
                pclk_vol_table = pinfo->vdd_dep_on_dppclk;
+               break;
        default:
                return -EINVAL;
        }
index b8747a5c9204d6341a92ab16e51091616f4715d6..99d596dc0e8976a78fee73261526001146490a76 100644 (file)
@@ -32,6 +32,7 @@
 #include "vega10_pptable.h"
 
 #define NUM_DSPCLK_LEVELS 8
+#define VEGA10_ENGINECLOCK_HARDMAX 198000
 
 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
                enum phm_platform_caps cap)
@@ -258,7 +259,26 @@ static int init_over_drive_limits(
                struct pp_hwmgr *hwmgr,
                const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
 {
-       hwmgr->platform_descriptor.overdriveLimit.engineClock =
+       const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
+                       (const ATOM_Vega10_GFXCLK_Dependency_Table *)
+                       (((unsigned long) powerplay_table) +
+                       le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
+       bool is_acg_enabled = false;
+       ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2;
+
+       if (gfxclk_dep_table->ucRevId == 1) {
+               patom_record_v2 =
+                       (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
+               is_acg_enabled =
+                       (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable;
+       }
+
+       if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX &&
+               !is_acg_enabled)
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
+                       VEGA10_ENGINECLOCK_HARDMAX;
+       else
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
                        le32_to_cpu(powerplay_table->ulMaxODEngineClock);
        hwmgr->platform_descriptor.overdriveLimit.memoryClock =
                        le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
index 54364444ecd121dd611c30148f4e292a8ee18e1a..0c8212902275e498375faafc1a4663c1d1996645 100644 (file)
@@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr)
+{
+       uint32_t result;
+
+       PP_ASSERT_WITH_CODE(
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0,
+               "[Run_ACG_BTC] Attempt to run ACG BTC failed!",
+               return -EINVAL);
+
+       result = smum_get_argument(hwmgr);
+       PP_ASSERT_WITH_CODE(result == 1,
+                       "Failed to run ACG BTC!", return -EINVAL);
+
+       return 0;
+}
+
 static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 {
        struct vega12_hwmgr *data =
@@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
                        "Failed to initialize SMC table!",
                        result = tmp_result);
 
+       tmp_result = vega12_run_acg_btc(hwmgr);
+       PP_ASSERT_WITH_CODE(!tmp_result,
+                       "Failed to run ACG BTC!",
+                       result = tmp_result);
+
        result = vega12_enable_all_smu_features(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to enable all smu features!",
index 99cba8ea5d825596d7d86120f2ad6346926c64ba..5df1256618cc23f1c930ccde41671a63a536d2c7 100644 (file)
@@ -528,7 +528,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 
        object_count = cl->object_count;
 
-       object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32));
+       object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
+                       array_size(object_count, sizeof(__u32)));
        if (IS_ERR(object_ids))
                return PTR_ERR(object_ids);
 
index 24a7504365596c32c60333ad04e25ba1c26306bf..f91e02c87fd8ca6a28a8005be5899d2fae78cc09 100644 (file)
@@ -758,7 +758,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
        if (mode->hsync)
                return mode->hsync;
 
-       if (mode->htotal < 0)
+       if (mode->htotal <= 0)
                return 0;
 
        calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
index b5475c91e2ef1b337ed083aae4c67a1d94fbe2e9..e9f343b124b0c45a722be24747623335f6e63441 100644 (file)
@@ -2799,6 +2799,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(_MMIO(0xe2a0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xe2b0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xe2c0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(_MMIO(0x21f0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        return 0;
 }
 
index 5af11cf1b48235c46079f376686112c5234abbfd..e1675a00df1269913ff73de8ab5ea17b20f6bb9e 100644 (file)
@@ -41,7 +41,7 @@ struct intel_gvt_mpt {
        int (*host_init)(struct device *dev, void *gvt, const void *ops);
        void (*host_exit)(struct device *dev, void *gvt);
        int (*attach_vgpu)(void *vgpu, unsigned long *handle);
-       void (*detach_vgpu)(unsigned long handle);
+       void (*detach_vgpu)(void *vgpu);
        int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
        unsigned long (*from_virt_to_mfn)(void *p);
        int (*enable_page_track)(unsigned long handle, u64 gfn);
index c1072143da1dc3968767b94573383d3b06f25883..dd3dfd00f4e60088e350a22a061cf0ba4eb0dfc8 100644 (file)
@@ -996,7 +996,7 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
 {
        unsigned int index;
        u64 virtaddr;
-       unsigned long req_size, pgoff = 0;
+       unsigned long req_size, pgoff, req_start;
        pgprot_t pg_prot;
        struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
 
@@ -1014,7 +1014,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
        pg_prot = vma->vm_page_prot;
        virtaddr = vma->vm_start;
        req_size = vma->vm_end - vma->vm_start;
-       pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+       pgoff = vma->vm_pgoff &
+               ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+       req_start = pgoff << PAGE_SHIFT;
+
+       if (!intel_vgpu_in_aperture(vgpu, req_start))
+               return -EINVAL;
+       if (req_start + req_size >
+           vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu))
+               return -EINVAL;
+
+       pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff;
 
        return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);
 }
@@ -1662,9 +1672,21 @@ static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)
        return 0;
 }
 
-static void kvmgt_detach_vgpu(unsigned long handle)
+static void kvmgt_detach_vgpu(void *p_vgpu)
 {
-       /* nothing to do here */
+       int i;
+       struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu;
+
+       if (!vgpu->vdev.region)
+               return;
+
+       for (i = 0; i < vgpu->vdev.num_regions; i++)
+               if (vgpu->vdev.region[i].ops->release)
+                       vgpu->vdev.region[i].ops->release(vgpu,
+                                       &vgpu->vdev.region[i]);
+       vgpu->vdev.num_regions = 0;
+       kfree(vgpu->vdev.region);
+       vgpu->vdev.region = NULL;
 }
 
 static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
index 67f19992b226f29a13d408be36da8b4820095b13..3ed34123d8d1373e10687665d1a03cb91380d6b5 100644 (file)
@@ -101,7 +101,7 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)
        if (!intel_gvt_host.mpt->detach_vgpu)
                return;
 
-       intel_gvt_host.mpt->detach_vgpu(vgpu->handle);
+       intel_gvt_host.mpt->detach_vgpu(vgpu);
 }
 
 #define MSI_CAP_CONTROL(offset) (offset + 2)
index 5567ddc7760f031de674fc5016a17cbd96d3cac0..55bb7885e22880b258ab3b7a108b5b4b0ca1770f 100644 (file)
@@ -332,6 +332,9 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 
        i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
        i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+
+       wa_ctx->indirect_ctx.obj = NULL;
+       wa_ctx->indirect_ctx.shadow_va = NULL;
 }
 
 static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
@@ -911,11 +914,6 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 
        list_del_init(&workload->list);
 
-       if (!workload->status) {
-               release_shadow_batch_buffer(workload);
-               release_shadow_wa_ctx(&workload->wa_ctx);
-       }
-
        if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {
                /* if workload->status is not successful means HW GPU
                 * has occurred GPU hang or something wrong with i915/GVT,
@@ -1283,6 +1281,9 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu_submission *s = &workload->vgpu->submission;
 
+       release_shadow_batch_buffer(workload);
+       release_shadow_wa_ctx(&workload->wa_ctx);
+
        if (workload->shadow_mm)
                intel_vgpu_mm_put(workload->shadow_mm);
 
index 216f52b744a637fca6406fe31a25f5d5befa4c2c..c882ea94172c46a645855193d6caaf2dabf968d6 100644 (file)
@@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static inline bool
+__vma_matches(struct vm_area_struct *vma, struct file *filp,
+             unsigned long addr, unsigned long size)
+{
+       if (vma->vm_file != filp)
+               return false;
+
+       return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size;
+}
+
 /**
  * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address
  *                      it is mapped to.
@@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
                        return -EINTR;
                }
                vma = find_vma(mm, addr);
-               if (vma)
+               if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
                        vma->vm_page_prot =
                                pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
                else
index d6c8f8fdfda5f106776e0a148e034e10e64ccbb7..017fc602a10e838586c40a5a5e7dbbd43e433376 100644 (file)
@@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event)
         * Update the bitmask of enabled events and increment
         * the event reference counter.
         */
-       GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+       BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS);
+       GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
        GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
        i915->pmu.enable |= BIT_ULL(bit);
        i915->pmu.enable_count[bit]++;
@@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event)
                engine = intel_engine_lookup_user(i915,
                                                  engine_event_class(event),
                                                  engine_event_instance(event));
-               GEM_BUG_ON(!engine);
-               engine->pmu.enable |= BIT(sample);
 
-               GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+               BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
+                            I915_ENGINE_SAMPLE_COUNT);
+               BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
+                            I915_ENGINE_SAMPLE_COUNT);
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
                GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
+
+               engine->pmu.enable |= BIT(sample);
                engine->pmu.enable_count[sample]++;
        }
 
@@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event)
                engine = intel_engine_lookup_user(i915,
                                                  engine_event_class(event),
                                                  engine_event_instance(event));
-               GEM_BUG_ON(!engine);
-               GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
                GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
+
                /*
                 * Decrement the reference count and clear the enabled
                 * bitmask when the last listener on an event goes away.
@@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event)
                        engine->pmu.enable &= ~BIT(sample);
        }
 
-       GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+       GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
        GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
        /*
         * Decrement the reference count and clear the enabled
index 7f164ca3db129472d3262439f5290d505ea6e14a..b3728c5f13e739f7c3a1e5c0d5e1a55deca1c342 100644 (file)
@@ -31,6 +31,8 @@ enum {
        ((1 << I915_PMU_SAMPLE_BITS) + \
         (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0)))
 
+#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
+
 struct i915_pmu_sample {
        u64 cur;
 };
index 0a7d60509ca7527f018a12208316bff91c7c6be8..067054cf4a864e26d6fa29d33056c34c218833c3 100644 (file)
@@ -1790,7 +1790,7 @@ enum i915_power_well_id {
 #define _CNL_PORT_TX_C_LN0_OFFSET              0x162C40
 #define _CNL_PORT_TX_D_LN0_OFFSET              0x162E40
 #define _CNL_PORT_TX_F_LN0_OFFSET              0x162840
-#define _CNL_PORT_TX_DW_GRP(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_GRP(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
@@ -1798,7 +1798,7 @@ enum i915_power_well_id {
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_F_GRP_OFFSET) + \
                                               4 * (dw))
-#define _CNL_PORT_TX_DW_LN0(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_LN0(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
@@ -1834,9 +1834,9 @@ enum i915_power_well_id {
 
 #define _CNL_PORT_TX_DW4_LN0_AE                0x162450
 #define _CNL_PORT_TX_DW4_LN1_AE                0x1624D0
-#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 4))
-#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 4))
-#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \
+#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
+#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
+#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
                                           ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
                                                    _CNL_PORT_TX_DW4_LN0_AE)))
 #define ICL_PORT_TX_DW4_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(4, port))
@@ -1864,8 +1864,12 @@ enum i915_power_well_id {
 #define   RTERM_SELECT(x)              ((x) << 3)
 #define   RTERM_SELECT_MASK            (0x7 << 3)
 
-#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 7))
-#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 7))
+#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
+#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
+#define ICL_PORT_TX_DW7_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(7, port))
+#define ICL_PORT_TX_DW7_GRP(port)      _MMIO(_ICL_PORT_TX_DW_GRP(7, port))
+#define ICL_PORT_TX_DW7_LN0(port)      _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port))
+#define ICL_PORT_TX_DW7_LN(port, ln)   _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))
 #define   N_SCALAR(x)                  ((x) << 24)
 #define   N_SCALAR_MASK                        (0x7F << 24)
 
index f3e1d6a0b7dda7cabb0cc882e40aecbd83a1501c..7edce1b7b348e0d8301a47aa3a7e7ba25da3d142 100644 (file)
@@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {
        { 0x2, 0x7F, 0x3F, 0x00, 0x00 },        /* 400   400      0.0   */
 };
 
-struct icl_combo_phy_ddi_buf_trans {
-       u32 dw2_swing_select;
-       u32 dw2_swing_scalar;
-       u32 dw4_scaling;
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0xB, 0x70, 0x0018 },  /* 600         0.0   */
-       { 0xB, 0x70, 0x3015 },  /* 600         3.5   */
-       { 0xB, 0x70, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x00, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x00, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
-};
-
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.85V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x76, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x76, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+/* icl_combo_phy_ddi_translations */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.95V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0x0, 0x7F, 0x3F, 0x00, 0x00 },        /* 200   200      0.0   */
+       { 0x8, 0x7F, 0x38, 0x00, 0x07 },        /* 200   250      1.9   */
+       { 0x1, 0x7F, 0x33, 0x00, 0x0C },        /* 200   300      3.5   */
+       { 0x9, 0x7F, 0x31, 0x00, 0x0E },        /* 200   350      4.9   */
+       { 0x8, 0x7F, 0x3F, 0x00, 0x00 },        /* 250   250      0.0   */
+       { 0x1, 0x7F, 0x38, 0x00, 0x07 },        /* 250   300      1.6   */
+       { 0x9, 0x7F, 0x35, 0x00, 0x0A },        /* 250   350      2.9   */
+       { 0x1, 0x7F, 0x3F, 0x00, 0x00 },        /* 300   300      0.0   */
+       { 0x9, 0x7F, 0x38, 0x00, 0x07 },        /* 300   350      1.3   */
+       { 0x9, 0x7F, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
 };
 
-/* Voltage Swing Programming for VccIO 1.05V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x71, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x71, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 1.05V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x60, 0x3F, 0x00, 0x00 },        /* 450   450      0.0   */
+       { 0xB, 0x73, 0x36, 0x00, 0x09 },        /* 450   650      3.2   */
+       { 0x6, 0x7F, 0x31, 0x00, 0x0E },        /* 450   850      5.5   */
+       { 0xB, 0x73, 0x3F, 0x00, 0x00 },        /* 650   650      0.0   ALS */
+       { 0x6, 0x7F, 0x37, 0x00, 0x08 },        /* 650   850      2.3   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 850   850      0.0   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   850      3.0   */
 };
 
 struct icl_mg_phy_ddi_buf_trans {
@@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
        }
 }
 
-static const struct icl_combo_phy_ddi_buf_trans *
+static const struct cnl_ddi_buf_trans *
 icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
-                       int type, int *n_entries)
+                       int type, int rate, int *n_entries)
 {
-       u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
-
-       if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
-                       return icl_combo_phy_ddi_translations_edp_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
-                       return icl_combo_phy_ddi_translations_edp_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
-                       return icl_combo_phy_ddi_translations_edp_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
-       } else {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
+       if (type == INTEL_OUTPUT_HDMI) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
+               return icl_combo_phy_ddi_translations_hdmi;
+       } else if (rate > 540000 && type == INTEL_OUTPUT_EDP) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
+               return icl_combo_phy_ddi_translations_edp_hbr3;
+       } else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
+               return icl_combo_phy_ddi_translations_edp_hbr2;
        }
+
+       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
+       return icl_combo_phy_ddi_translations_dp_hbr2;
 }
 
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
@@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
-                       icl_get_combo_buf_trans(dev_priv, port,
-                                               INTEL_OUTPUT_HDMI, &n_entries);
+                       icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI,
+                                               0, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
                default_entry = n_entries - 1;
@@ -1086,7 +1021,7 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
                        return DDI_CLK_SEL_TBT_810;
                default:
                        MISSING_CASE(clock);
-                       break;
+                       return DDI_CLK_SEL_NONE;
                }
        case DPLL_ID_ICL_MGPLL1:
        case DPLL_ID_ICL_MGPLL2:
@@ -2275,13 +2210,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        enum port port = encoder->port;
        int n_entries;
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
                        icl_get_combo_buf_trans(dev_priv, port, encoder->type,
-                                               &n_entries);
+                                               intel_dp->link_rate, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
        } else if (IS_CANNONLAKE(dev_priv)) {
@@ -2462,14 +2398,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
 }
 
 static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
-                                        u32 level, enum port port, int type)
+                                       u32 level, enum port port, int type,
+                                       int rate)
 {
-       const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+       const struct cnl_ddi_buf_trans *ddi_translations = NULL;
        u32 n_entries, val;
        int ln;
 
        ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
-                                                  &n_entries);
+                                                  rate, &n_entries);
        if (!ddi_translations)
                return;
 
@@ -2478,34 +2415,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                level = n_entries - 1;
        }
 
-       /* Set PORT_TX_DW5 Rterm Sel to 110b. */
+       /* Set PORT_TX_DW5 */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       val &= ~RTERM_SELECT_MASK;
+       val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
+                 TAP2_DISABLE | TAP3_DISABLE);
+       val |= SCALING_MODE_SEL(0x2);
        val |= RTERM_SELECT(0x6);
-       I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
-
-       /* Program PORT_TX_DW5 */
-       val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       /* Set DisableTap2 and DisableTap3 if MIPI DSI
-        * Clear DisableTap2 and DisableTap3 for all other Ports
-        */
-       if (type == INTEL_OUTPUT_DSI) {
-               val |= TAP2_DISABLE;
-               val |= TAP3_DISABLE;
-       } else {
-               val &= ~TAP2_DISABLE;
-               val &= ~TAP3_DISABLE;
-       }
+       val |= TAP3_DISABLE;
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* Program PORT_TX_DW2 */
        val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
        val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
                 RCOMP_SCALAR_MASK);
-       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
-       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
+       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
        /* Program Rcomp scalar for every table entry */
-       val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+       val |= RCOMP_SCALAR(0x98);
        I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
 
        /* Program PORT_TX_DW4 */
@@ -2514,9 +2440,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
                val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                         CURSOR_COEFF_MASK);
-               val |= ddi_translations[level].dw4_scaling;
+               val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
+               val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
+               val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
                I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
        }
+
+       /* Program PORT_TX_DW7 */
+       val = I915_READ(ICL_PORT_TX_DW7_LN0(port));
+       val &= ~N_SCALAR_MASK;
+       val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
+       I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);
 }
 
 static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
@@ -2581,7 +2515,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* 5. Program swing and de-emphasis */
-       icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+       icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);
 
        /* 6. Set training enable to trigger update */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
index 3da9c0f9e9485c7c4b9ccf8fefe5c71f72f1ea02..248128126422be28214b2b3c797cc31b16fe8ca3 100644 (file)
@@ -15415,16 +15415,45 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
        }
 }
 
+static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+       /*
+        * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
+        * the hardware when a high res displays plugged in. DPLL P
+        * divider is zero, and the pipe timings are bonkers. We'll
+        * try to disable everything in that case.
+        *
+        * FIXME would be nice to be able to sanitize this state
+        * without several WARNs, but for now let's take the easy
+        * road.
+        */
+       return IS_GEN6(dev_priv) &&
+               crtc_state->base.active &&
+               crtc_state->shared_dpll &&
+               crtc_state->port_clock == 0;
+}
+
 static void intel_sanitize_encoder(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_connector *connector;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+       struct intel_crtc_state *crtc_state = crtc ?
+               to_intel_crtc_state(crtc->base.state) : NULL;
 
        /* We need to check both for a crtc link (meaning that the
         * encoder is active and trying to read from a pipe) and the
         * pipe itself being active. */
-       bool has_active_crtc = encoder->base.crtc &&
-               to_intel_crtc(encoder->base.crtc)->active;
+       bool has_active_crtc = crtc_state &&
+               crtc_state->base.active;
+
+       if (crtc_state && has_bogus_dpll_config(crtc_state)) {
+               DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n",
+                             pipe_name(crtc->pipe));
+               has_active_crtc = false;
+       }
 
        connector = intel_encoder_find_connector(encoder);
        if (connector && !has_active_crtc) {
@@ -15435,16 +15464,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                /* Connector is active, but has no active pipe. This is
                 * fallout from our resume register restoring. Disable
                 * the encoder manually again. */
-               if (encoder->base.crtc) {
-                       struct drm_crtc_state *crtc_state = encoder->base.crtc->state;
+               if (crtc_state) {
+                       struct drm_encoder *best_encoder;
 
                        DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
                                      encoder->base.base.id,
                                      encoder->base.name);
+
+                       /* avoid oopsing in case the hooks consult best_encoder */
+                       best_encoder = connector->base.state->best_encoder;
+                       connector->base.state->best_encoder = &encoder->base;
+
                        if (encoder->disable)
-                               encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+                               encoder->disable(encoder, crtc_state,
+                                                connector->base.state);
                        if (encoder->post_disable)
-                               encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+                               encoder->post_disable(encoder, crtc_state,
+                                                     connector->base.state);
+
+                       connector->base.state->best_encoder = best_encoder;
                }
                encoder->base.crtc = NULL;
 
index fdd2cbc56fa335b6bf084c00451eca8a0ef957e3..22a74608c6e493192b2f1e144c11f961ac6af4d0 100644 (file)
@@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
 static int icl_max_source_rate(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+       struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum port port = dig_port->base.port;
 
-       if (port == PORT_B)
+       if (intel_port_is_combophy(dev_priv, port) &&
+           !intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
index f94a04b4ad8788bcc1d8f9ca3073eaa00f33648a..e9ddeaf05a1413f022b569c49ded1a9f92102d32 100644 (file)
@@ -209,6 +209,16 @@ struct intel_fbdev {
        unsigned long vma_flags;
        async_cookie_t cookie;
        int preferred_bpp;
+
+       /* Whether or not fbdev hpd processing is temporarily suspended */
+       bool hpd_suspended : 1;
+       /* Set when a hotplug was received while HPD processing was
+        * suspended
+        */
+       bool hpd_waiting : 1;
+
+       /* Protects hpd_suspended */
+       struct mutex hpd_lock;
 };
 
 struct intel_encoder {
index fb5bb5b32a6034d152516ae11c15913e2f97597d..7f365ac0b549d557447352906d670da18ae36a1f 100644 (file)
@@ -679,6 +679,7 @@ int intel_fbdev_init(struct drm_device *dev)
        if (ifbdev == NULL)
                return -ENOMEM;
 
+       mutex_init(&ifbdev->hpd_lock);
        drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
 
        if (!intel_fbdev_init_bios(dev, ifbdev))
@@ -752,6 +753,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)
        intel_fbdev_destroy(ifbdev);
 }
 
+/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
+ * processing, fbdev will perform a full connector reprobe if a hotplug event
+ * was received while HPD was suspended.
+ */
+static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
+{
+       bool send_hpd = false;
+
+       mutex_lock(&ifbdev->hpd_lock);
+       ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
+       send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
+       ifbdev->hpd_waiting = false;
+       mutex_unlock(&ifbdev->hpd_lock);
+
+       if (send_hpd) {
+               DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
+               drm_fb_helper_hotplug_event(&ifbdev->helper);
+       }
+}
+
 void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -773,6 +794,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
                 */
                if (state != FBINFO_STATE_RUNNING)
                        flush_work(&dev_priv->fbdev_suspend_work);
+
                console_lock();
        } else {
                /*
@@ -800,17 +822,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
 
        drm_fb_helper_set_suspend(&ifbdev->helper, state);
        console_unlock();
+
+       intel_fbdev_hpd_set_suspend(ifbdev, state);
 }
 
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
        struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
+       bool send_hpd;
 
        if (!ifbdev)
                return;
 
        intel_fbdev_sync(ifbdev);
-       if (ifbdev->vma || ifbdev->helper.deferred_setup)
+
+       mutex_lock(&ifbdev->hpd_lock);
+       send_hpd = !ifbdev->hpd_suspended;
+       ifbdev->hpd_waiting = true;
+       mutex_unlock(&ifbdev->hpd_lock);
+
+       if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
                drm_fb_helper_hotplug_event(&ifbdev->helper);
 }
 
index 4796f40a6d4f11a997083eaf0493725942eb3daa..eab9341a5152f90214427aa20cfc7b6414a94858 100644 (file)
@@ -303,6 +303,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine)
         */
        if (!(prio & I915_PRIORITY_NEWCLIENT)) {
                prio |= I915_PRIORITY_NEWCLIENT;
+               active->sched.attr.priority = prio;
                list_move_tail(&active->sched.link,
                               i915_sched_lookup_priolist(engine, prio));
        }
@@ -645,6 +646,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                int i;
 
                priolist_for_each_request_consume(rq, rn, p, i) {
+                       GEM_BUG_ON(last &&
+                                  need_preempt(engine, last, rq_prio(rq)));
+
                        /*
                         * Can we combine this request with the current port?
                         * It has to be the same context/ringbuffer and not
index b8f106d9ecf8b1be6286b2dfaeac1c5188629528..3ac20153705a22d27ee2e8f4ae5b112ab40f42c3 100644 (file)
 struct opregion_header {
        u8 signature[16];
        u32 size;
-       u32 opregion_ver;
+       struct {
+               u8 rsvd;
+               u8 revision;
+               u8 minor;
+               u8 major;
+       }  __packed over;
        u8 bios_ver[32];
        u8 vbios_ver[16];
        u8 driver_ver[16];
@@ -119,7 +124,8 @@ struct opregion_asle {
        u64 fdss;
        u32 fdsp;
        u32 stat;
-       u64 rvda;       /* Physical address of raw vbt data */
+       u64 rvda;       /* Physical (2.0) or relative from opregion (2.1+)
+                        * address of raw VBT data. */
        u32 rvds;       /* Size of raw vbt data */
        u8 rsvd[58];
 } __packed;
@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
        opregion->header = base;
        opregion->lid_state = base + ACPI_CLID;
 
+       DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n",
+                        opregion->header->over.major,
+                        opregion->header->over.minor,
+                        opregion->header->over.revision);
+
        mboxes = opregion->header->mboxes;
        if (mboxes & MBOX_ACPI) {
                DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
        if (dmi_check_system(intel_no_opregion_vbt))
                goto out;
 
-       if (opregion->header->opregion_ver >= 2 && opregion->asle &&
+       if (opregion->header->over.major >= 2 && opregion->asle &&
            opregion->asle->rvda && opregion->asle->rvds) {
-               opregion->rvda = memremap(opregion->asle->rvda,
-                                         opregion->asle->rvds,
+               resource_size_t rvda = opregion->asle->rvda;
+
+               /*
+                * opregion 2.0: rvda is the physical VBT address.
+                *
+                * opregion 2.1+: rvda is unsigned, relative offset from
+                * opregion base, and should never point within opregion.
+                */
+               if (opregion->header->over.major > 2 ||
+                   opregion->header->over.minor >= 1) {
+                       WARN_ON(rvda < OPREGION_SIZE);
+
+                       rvda += asls;
+               }
+
+               opregion->rvda = memremap(rvda, opregion->asle->rvds,
                                          MEMREMAP_WB);
+
                vbt = opregion->rvda;
                vbt_size = opregion->asle->rvds;
                if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
                        goto out;
                } else {
                        DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
+                       memunmap(opregion->rvda);
+                       opregion->rvda = NULL;
                }
        }
 
index 72edaa7ff4114fc61894f298f8d3952e8c5855c9..a1a7cc29fdd1a5e8131e0b70f8bc40189006cefb 100644 (file)
@@ -415,16 +415,17 @@ struct intel_engine_cs {
                /**
                 * @enable_count: Reference count for the enabled samplers.
                 *
-                * Index number corresponds to the bit number from @enable.
+                * Index number corresponds to @enum drm_i915_pmu_engine_sample.
                 */
-               unsigned int enable_count[I915_PMU_SAMPLE_BITS];
+               unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT];
                /**
                 * @sample: Counter values for sampling events.
                 *
                 * Our internal timer stores the current counters in this field.
+                *
+                * Index number corresponds to @enum drm_i915_pmu_engine_sample.
                 */
-#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1)
-               struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+               struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];
        } pmu;
 
        /*
index d2e003d8f3dbe64247cac7de9baf6a6fcaa0c986..5170a0f5fe7b6b39ed36e750b853475a7a4a5b0d 100644 (file)
@@ -494,7 +494,7 @@ skl_program_plane(struct intel_plane *plane,
 
        keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
 
-       keymsk = key->channel_mask & 0x3ffffff;
+       keymsk = key->channel_mask & 0x7ffffff;
        if (alpha < 0xff)
                keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
 
index 2c5bbe3173537346e1ea0d5c0b0f0e011ea485e7..e31e263cf86bd60464d1daa220ac1d45d1c763fd 100644 (file)
@@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                int bus_format;
 
                ret = of_property_read_u32(child, "reg", &i);
-               if (ret || i < 0 || i > 1)
-                       return -EINVAL;
+               if (ret || i < 0 || i > 1) {
+                       ret = -EINVAL;
+                       goto free_child;
+               }
 
                if (!of_device_is_available(child))
                        continue;
@@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                channel = &imx_ldb->channel[i];
                channel->ldb = imx_ldb;
                channel->chno = i;
-               channel->child = child;
 
                /*
                 * The output port is port@4 with an external 4-port mux or
@@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                                                  imx_ldb->lvds_mux ? 4 : 2, 0,
                                                  &channel->panel, &channel->bridge);
                if (ret && ret != -ENODEV)
-                       return ret;
+                       goto free_child;
 
                /* panel ddc only if there is no bridge */
                if (!channel->bridge) {
                        ret = imx_ldb_panel_ddc(dev, channel, child);
                        if (ret)
-                               return ret;
+                               goto free_child;
                }
 
                bus_format = of_get_bus_format(dev, child);
@@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                if (bus_format < 0) {
                        dev_err(dev, "could not determine data mapping: %d\n",
                                bus_format);
-                       return bus_format;
+                       ret = bus_format;
+                       goto free_child;
                }
                channel->bus_format = bus_format;
+               channel->child = child;
 
                ret = imx_ldb_register(drm, channel);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       channel->child = NULL;
+                       goto free_child;
+               }
        }
 
        dev_set_drvdata(dev, imx_ldb);
 
        return 0;
+
+free_child:
+       of_node_put(child);
+       return ret;
 }
 
 static void imx_ldb_unbind(struct device *dev, struct device *master,
index c390924de93d978d3acb4200c846fe6b53f753c8..21e964f6ab5cf58559e059d7d34c4bb26359c042 100644 (file)
@@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
        if (ret)
                return ret;
 
-       /* CRTC should be enabled */
+       /* nothing to check when disabling or disabled */
        if (!crtc_state->enable)
-               return -EINVAL;
+               return 0;
 
        switch (plane->type) {
        case DRM_PLANE_TYPE_PRIMARY:
index 75d97f1b2e8fbf08e69b289f8a383ec4fd13291e..4f5c67f70c4d30169d2129dcde75188fcdac96ae 100644 (file)
@@ -46,7 +46,6 @@ struct meson_crtc {
        struct drm_crtc base;
        struct drm_pending_vblank_event *event;
        struct meson_drm *priv;
-       bool enabled;
 };
 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
 
@@ -82,7 +81,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
 
 };
 
-static void meson_crtc_enable(struct drm_crtc *crtc)
+static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_state)
 {
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct drm_crtc_state *crtc_state = crtc->state;
@@ -108,20 +108,6 @@ static void meson_crtc_enable(struct drm_crtc *crtc)
 
        drm_crtc_vblank_on(crtc);
 
-       meson_crtc->enabled = true;
-}
-
-static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
-                                    struct drm_crtc_state *old_state)
-{
-       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
-       struct meson_drm *priv = meson_crtc->priv;
-
-       DRM_DEBUG_DRIVER("\n");
-
-       if (!meson_crtc->enabled)
-               meson_crtc_enable(crtc);
-
        priv->viu.osd1_enabled = true;
 }
 
@@ -153,8 +139,6 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 
                crtc->state->event = NULL;
        }
-
-       meson_crtc->enabled = false;
 }
 
 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -163,9 +147,6 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        unsigned long flags;
 
-       if (crtc->state->enable && !meson_crtc->enabled)
-               meson_crtc_enable(crtc);
-
        if (crtc->state->event) {
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
index 3ee4d4a4ecbae1e59c1fb5e0dfb873b24bf4497c..12ff47b1366834c5942fbf377bc1b45511e6eec4 100644 (file)
@@ -75,6 +75,10 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = {
        .fb_create           = drm_gem_fb_create,
 };
 
+static const struct drm_mode_config_helper_funcs meson_mode_config_helpers = {
+       .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
+
 static irqreturn_t meson_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
@@ -266,6 +270,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
        drm->mode_config.max_width = 3840;
        drm->mode_config.max_height = 2160;
        drm->mode_config.funcs = &meson_mode_config_funcs;
+       drm->mode_config.helper_private = &meson_mode_config_helpers;
 
        /* Hardware Initialization */
 
@@ -388,8 +393,10 @@ static int meson_probe_remote(struct platform_device *pdev,
                remote_node = of_graph_get_remote_port_parent(ep);
                if (!remote_node ||
                    remote_node == parent || /* Ignore parent endpoint */
-                   !of_device_is_available(remote_node))
+                   !of_device_is_available(remote_node)) {
+                       of_node_put(remote_node);
                        continue;
+               }
 
                count += meson_probe_remote(pdev, match, remote, remote_node);
 
@@ -408,10 +415,13 @@ static int meson_drv_probe(struct platform_device *pdev)
 
        for_each_endpoint_of_node(np, ep) {
                remote = of_graph_get_remote_port_parent(ep);
-               if (!remote || !of_device_is_available(remote))
+               if (!remote || !of_device_is_available(remote)) {
+                       of_node_put(remote);
                        continue;
+               }
 
                count += meson_probe_remote(pdev, &match, np, remote);
+               of_node_put(remote);
        }
 
        if (count && !match)
index 5beb83d1cf87769948575b74957777ce0e5b5d6e..ce1b3cc4bf6d5aea13aa213eccbeea37719f166c 100644 (file)
@@ -944,7 +944,7 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
        np = dev_pm_opp_get_of_node(opp);
 
        if (np) {
-               of_property_read_u32(np, "qcom,level", &val);
+               of_property_read_u32(np, "opp-level", &val);
                of_node_put(np);
        }
 
index 2e4372ef17a34fd2fc3028c6f8a543477ce54247..2cfee1a4fe0b871ee4cd241ad2b874bc39bd1f94 100644 (file)
@@ -765,7 +765,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        adreno_gpu->rev = config->rev;
 
        adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";
-       adreno_gpu_config.irqname = "kgsl_3d0_irq";
 
        adreno_gpu_config.va_start = SZ_16M;
        adreno_gpu_config.va_end = 0xffffffff;
index fd75870eb17f7c7d5e8f8446f526b19715042b03..6aefcd6db46b4d36295f66bae809d99acc2ada85 100644 (file)
@@ -365,19 +365,6 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
                        &pdpu->pipe_qos_cfg);
 }
 
-static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
-{
-       struct dpu_plane *pdpu = to_dpu_plane(plane);
-       struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
-
-       if (!pdpu->is_rt_pipe)
-               return;
-
-       pm_runtime_get_sync(&dpu_kms->pdev->dev);
-       _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
-       pm_runtime_put_sync(&dpu_kms->pdev->dev);
-}
-
 /**
  * _dpu_plane_set_ot_limit - set OT limit for the given plane
  * @plane:             Pointer to drm plane
@@ -1248,6 +1235,19 @@ static void dpu_plane_reset(struct drm_plane *plane)
 }
 
 #ifdef CONFIG_DEBUG_FS
+static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
+{
+       struct dpu_plane *pdpu = to_dpu_plane(plane);
+       struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+
+       if (!pdpu->is_rt_pipe)
+               return;
+
+       pm_runtime_get_sync(&dpu_kms->pdev->dev);
+       _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
+       pm_runtime_put_sync(&dpu_kms->pdev->dev);
+}
+
 static ssize_t _dpu_plane_danger_read(struct file *file,
                        char __user *buff, size_t count, loff_t *ppos)
 {
index 9cd6a96c6bf2a522d413681f20d918753921f554..927e5d86f7c17a77eca29c8836d87efeefd984b7 100644 (file)
@@ -250,7 +250,8 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma);
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
-               struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
+               struct msm_gem_vma *vma, int prot,
+               struct sg_table *sgt, int npages);
 void msm_gem_close_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma);
 
@@ -333,6 +334,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo,
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
                struct dma_buf *dmabuf, struct sg_table *sgt);
 
+__printf(2, 3)
 void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...);
 
 int msm_framebuffer_prepare(struct drm_framebuffer *fb,
@@ -396,12 +398,14 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
 int msm_debugfs_late_init(struct drm_device *dev);
 int msm_rd_debugfs_init(struct drm_minor *minor);
 void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);
+__printf(3, 4)
 void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
                const char *fmt, ...);
 int msm_perf_debugfs_init(struct drm_minor *minor);
 void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
 #else
 static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
+__printf(3, 4)
 static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
                const char *fmt, ...) {}
 static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}
index 51a95da694d8d498dee29bd91ddb880b3478c356..c8886d3071fa35756682d9a27662b61074c27713 100644 (file)
@@ -391,6 +391,10 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        struct msm_gem_vma *vma;
        struct page **pages;
+       int prot = IOMMU_READ;
+
+       if (!(msm_obj->flags & MSM_BO_GPU_READONLY))
+               prot |= IOMMU_WRITE;
 
        WARN_ON(!mutex_is_locked(&msm_obj->lock));
 
@@ -405,8 +409,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
-       return msm_gem_map_vma(aspace, vma, msm_obj->sgt,
-                       obj->size >> PAGE_SHIFT);
+       return msm_gem_map_vma(aspace, vma, prot,
+                       msm_obj->sgt, obj->size >> PAGE_SHIFT);
 }
 
 /* get iova and pin it. Should have a matching put */
index 557360788084eb3db21e0c964722a0ce1923f92b..49c04829cf34412ae0b07f6358f596e3b11eae58 100644 (file)
@@ -68,7 +68,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 
 int
 msm_gem_map_vma(struct msm_gem_address_space *aspace,
-               struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
+               struct msm_gem_vma *vma, int prot,
+               struct sg_table *sgt, int npages)
 {
        unsigned size = npages << PAGE_SHIFT;
        int ret = 0;
@@ -86,7 +87,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
 
        if (aspace->mmu)
                ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
-                               size, IOMMU_READ | IOMMU_WRITE);
+                               size, prot);
 
        if (ret)
                vma->mapped = false;
index 5f3eff3043554491eca50a559599b0e5293e1357..10babd18e28605b1c76faf55c51748c5e85504f1 100644 (file)
@@ -900,7 +900,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        }
 
        /* Get Interrupt: */
-       gpu->irq = platform_get_irq_byname(pdev, config->irqname);
+       gpu->irq = platform_get_irq(pdev, 0);
        if (gpu->irq < 0) {
                ret = gpu->irq;
                DRM_DEV_ERROR(drm->dev, "failed to get irq: %d\n", ret);
index efb49bb64191732a0a8ee683e1f9790389295fa9..ca17086f72c923352328674a9aa50da5c71a6ff1 100644 (file)
@@ -31,7 +31,6 @@ struct msm_gpu_state;
 
 struct msm_gpu_config {
        const char *ioname;
-       const char *irqname;
        uint64_t va_start;
        uint64_t va_end;
        unsigned int nr_rings;
@@ -63,7 +62,7 @@ struct msm_gpu_funcs {
        struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu);
        void (*recover)(struct msm_gpu *gpu);
        void (*destroy)(struct msm_gpu *gpu);
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
        /* show GPU status in debugfs: */
        void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state,
                        struct drm_printer *p);
index 90e9d0a48dc0409feca3c8feab838fa83aeed946..d21172933d92804f7847b9a1b4d1ec14001c8570 100644 (file)
@@ -115,7 +115,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
                char *fptr = &fifo->buf[fifo->head];
                int n;
 
-               wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0);
+               wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open);
+               if (!rd->open)
+                       return;
 
                /* Note that smp_load_acquire() is not strictly required
                 * as CIRC_SPACE_TO_END() does not access the tail more
@@ -213,7 +215,10 @@ static int rd_open(struct inode *inode, struct file *file)
 static int rd_release(struct inode *inode, struct file *file)
 {
        struct msm_rd_state *rd = inode->i_private;
+
        rd->open = false;
+       wake_up_all(&rd->fifo_event);
+
        return 0;
 }
 
index bfbc9341e0c21f361746ec81363a687119f97a92..d9edb5785813f988b9654eaeba682903d0fe8c1e 100644 (file)
@@ -2434,6 +2434,38 @@ nv140_chipset = {
        .sec2 = gp102_sec2_new,
 };
 
+static const struct nvkm_device_chip
+nv162_chipset = {
+       .name = "TU102",
+       .bar = tu104_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = tu104_devinit_new,
+       .fault = tu104_fault_new,
+       .fb = gv100_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gp102_ltc_new,
+       .mc = tu104_mc_new,
+       .mmu = tu104_mmu_new,
+       .pci = gp100_pci_new,
+       .pmu = gp102_pmu_new,
+       .therm = gp100_therm_new,
+       .timer = gk20a_timer_new,
+       .top = gk104_top_new,
+       .ce[0] = tu104_ce_new,
+       .ce[1] = tu104_ce_new,
+       .ce[2] = tu104_ce_new,
+       .ce[3] = tu104_ce_new,
+       .ce[4] = tu104_ce_new,
+       .disp = tu104_disp_new,
+       .dma = gv100_dma_new,
+       .fifo = tu104_fifo_new,
+};
+
 static const struct nvkm_device_chip
 nv164_chipset = {
        .name = "TU104",
@@ -2950,6 +2982,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x138: device->chip = &nv138_chipset; break;
                case 0x13b: device->chip = &nv13b_chipset; break;
                case 0x140: device->chip = &nv140_chipset; break;
+               case 0x162: device->chip = &nv162_chipset; break;
                case 0x164: device->chip = &nv164_chipset; break;
                case 0x166: device->chip = &nv166_chipset; break;
                default:
index 00a9c2ab9e6c8932baecc9b5591b07626201c589..64fb788b664749473ac89894ae9f1c8eeda5f323 100644 (file)
@@ -1406,7 +1406,7 @@ static void dsi_pll_disable(struct dss_pll *pll)
 
 static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
        struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
        enum dss_clk_source dispc_clk_src, dsi_clk_src;
        int dsi_module = dsi->module_id;
@@ -1467,7 +1467,7 @@ static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
        unsigned long flags;
        struct dsi_irq_stats stats;
 
@@ -1558,7 +1558,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
 
 static int dsi_dump_dsi_regs(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
 
        if (dsi_runtime_get(dsi))
                return 0;
@@ -4751,6 +4751,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
        dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
        dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
        dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+       /*
+        * HACK: These flags should be handled through the omap_dss_device bus
+        * flags, but this will only be possible when the DSI encoder will be
+        * converted to the omapdrm-managed encoder model.
+        */
+       dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+       dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+       dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+       dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+       dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+       dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
 
        dss_mgr_set_timings(&dsi->output, &dsi->vm);
 
@@ -5083,15 +5094,15 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
 
        snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
        dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_regs, &dsi);
+                                                   dsi_dump_dsi_regs, dsi);
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
        dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_irqs, &dsi);
+                                                   dsi_dump_dsi_irqs, dsi);
 #endif
        snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
        dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_clocks, &dsi);
+                                                   dsi_dump_dsi_clocks, dsi);
 
        return 0;
 }
@@ -5104,8 +5115,6 @@ static void dsi_unbind(struct device *dev, struct device *master, void *data)
        dss_debugfs_remove_file(dsi->debugfs.irqs);
        dss_debugfs_remove_file(dsi->debugfs.regs);
 
-       of_platform_depopulate(dev);
-
        WARN_ON(dsi->scp_clk_refcount > 0);
 
        dss_pll_unregister(&dsi->pll);
@@ -5457,6 +5466,8 @@ static int dsi_remove(struct platform_device *pdev)
 
        dsi_uninit_output(dsi);
 
+       of_platform_depopulate(&pdev->dev);
+
        pm_runtime_disable(&pdev->dev);
 
        if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
index 13c8a662f9b4113cc3d60840253c66780aec712f..ccb090f3ab30a5956407c470cdfe5ef32b15f615 100644 (file)
@@ -250,14 +250,10 @@ static struct drm_driver qxl_driver = {
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = qxl_debugfs_init,
 #endif
-       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
-       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = qxl_gem_prime_pin,
        .gem_prime_unpin = qxl_gem_prime_unpin,
-       .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,
        .gem_prime_vmap = qxl_gem_prime_vmap,
        .gem_prime_vunmap = qxl_gem_prime_vunmap,
        .gem_prime_mmap = qxl_gem_prime_mmap,
index a55dece118b292a5b6958a64b5a5c47d12d82033..df65d3c1a7b892a23470ba502173a8b75f8d1bd0 100644 (file)
@@ -38,20 +38,6 @@ void qxl_gem_prime_unpin(struct drm_gem_object *obj)
        WARN_ONCE(1, "not implemented");
 }
 
-struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENOSYS);
-}
-
-struct drm_gem_object *qxl_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENOSYS);
-}
-
 void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
 {
        WARN_ONCE(1, "not implemented");
index d587779a80b4d0748785b5430078a638ef290798..a97294ac96d5914b2cfdd561649a0ccdf56a9fb6 100644 (file)
@@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev)
        u16 data_offset, size;
        u8 frev, crev;
        struct ci_power_info *pi;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev)
                return -ENOMEM;
        rdev->pm.dpm.priv = pi;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                pi->sys_pcie_mask = 0;
        } else {
index 8fb60b3af015804d6d5ee3ef5d6f24ba74e2b1d9..0a785ef0ab660f41c2a204fb766068c93dcfa044 100644 (file)
@@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev)
        struct ni_power_info *ni_pi;
        struct si_power_info *si_pi;
        struct atom_clock_dividers dividers;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev)
        eg_pi = &ni_pi->eg;
        pi = &eg_pi->rv7xx;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                si_pi->sys_pcie_mask = 0;
        } else {
index 96ac1458a59c945ff11fe9640adcb4444d8e3606..c0351abf83a35e7b0afe6cf36b5d6dafb7c112fc 100644 (file)
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  * Author:
  *      Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <drm/drmP.h>
@@ -113,8 +104,10 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
                child_count++;
                ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,
                                                  &panel, &bridge);
-               if (!ret)
+               if (!ret) {
+                       of_node_put(endpoint);
                        break;
+               }
        }
 
        of_node_put(port);
index 38b52e63b2b04f583296e700af528c4eacd2c080..27b9635124bc1d0e563e52fd8eb71acac50ae87a 100644 (file)
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  * Author:
  *      Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifdef CONFIG_ROCKCHIP_RGB
index 4463d3826ecbec0432ee363087c8e6d1f86755cc..e2942c9a11a7aeccb6710cdb7890cc56e1558d73 100644 (file)
@@ -440,13 +440,10 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
 
        while ((entity->dependency =
                        sched->ops->dependency(sched_job, entity))) {
+               trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
 
-               if (drm_sched_entity_add_dependency_cb(entity)) {
-
-                       trace_drm_sched_job_wait_dep(sched_job,
-                                                    entity->dependency);
+               if (drm_sched_entity_add_dependency_cb(entity))
                        return NULL;
-               }
        }
 
        /* skip jobs from entity that marked guilty */
index 9e9255ee59cd83138f5572f0d31df50aec9cc244..a021bab11a4f9b1ee8f0c3172fc42d626ec979e2 100644 (file)
@@ -786,17 +786,18 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
                remote = of_graph_get_remote_port_parent(ep);
                if (!remote)
                        continue;
+               of_node_put(remote);
 
                /* does this node match any registered engines? */
                list_for_each_entry(frontend, &drv->frontend_list, list) {
                        if (remote == frontend->node) {
-                               of_node_put(remote);
                                of_node_put(port);
+                               of_node_put(ep);
                                return frontend;
                        }
                }
        }
-
+       of_node_put(port);
        return ERR_PTR(-EINVAL);
 }
 
index 061d2e0d9011ee88991b3f0fb1b4e2dd54925bee..416da53767018ca9acbcef98689c173af0732fca 100644 (file)
@@ -92,6 +92,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
        val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
        val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
        writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
+
+       clk_disable_unprepare(hdmi->tmds_clk);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
@@ -102,6 +104,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 
        DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
+       clk_prepare_enable(hdmi->tmds_clk);
+
        sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
index 0420f5c978b9d641926150f0d7987331b9fdb55d..cf45d0f940f9b3e5bc0c4d883a5c878ca50d6305 100644 (file)
@@ -761,6 +761,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
                        return PTR_ERR(tcon->sclk0);
                }
        }
+       clk_prepare_enable(tcon->sclk0);
 
        if (tcon->quirks->has_channel_1) {
                tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
@@ -775,6 +776,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
 
 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
 {
+       clk_disable_unprepare(tcon->sclk0);
        clk_disable_unprepare(tcon->clk);
 }
 
index f7f32a885af79902a4c02ce4c4c801c1a119cc83..2d1aaca4910502b33403565536e5c8d089eefed4 100644 (file)
@@ -127,14 +127,10 @@ static struct drm_driver driver = {
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = virtio_gpu_debugfs_init,
 #endif
-       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
-       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = virtgpu_gem_prime_pin,
        .gem_prime_unpin = virtgpu_gem_prime_unpin,
-       .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
        .gem_prime_vmap = virtgpu_gem_prime_vmap,
        .gem_prime_vunmap = virtgpu_gem_prime_vunmap,
        .gem_prime_mmap = virtgpu_gem_prime_mmap,
index 1deb41d42ea4d2ffa7d08a06c15d411be556cce4..0c15000f926ebad9c2260a2a9e2a4110991d4914 100644 (file)
@@ -372,10 +372,6 @@ int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait);
 /* virtgpu_prime.c */
 int virtgpu_gem_prime_pin(struct drm_gem_object *obj);
 void virtgpu_gem_prime_unpin(struct drm_gem_object *obj);
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *sgt);
 void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);
 void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
index 86ce0ae93f595978fdfed4a1b478ac716417c16b..c59ec34c80a5df2c6b3a91f7ec73cd05f85445ad 100644 (file)
@@ -39,20 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj)
        WARN_ONCE(1, "not implemented");
 }
 
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
 void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj)
 {
        struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
index 9d9e8146db90ca04d1e67194d9547dc95582f125..d7b409a3c0f8cfd5fcd20a7e628e5a8aafd2d3fe 100644 (file)
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+
 #include "vkms_drv.h"
 #include <linux/crc32.h>
 #include <drm/drm_atomic.h>
index 177bbcb38306363b05d4dea04bedb83e617dc258..eb56ee893761fae168776aa1b4499bad0406a99f 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_atomic_helper.h>
index 83087877565cf77b9104d67636c183231fdd19c4..7dcbecb5fac26b4c4b3216feea1bba239f74827f 100644 (file)
@@ -1,9 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 /**
  * DOC: vkms (Virtual Kernel Modesetting)
index e4469cd3d25491198209e3898189fc52e54e5ed7..81f1cfbeb9362e4edc9a39f1688060d1d23124c0 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
index 80311daed47a0ac752a3e1e68bd54f9d8b60d412..138b0bb325cf9662cd59b5a54158947dc691a2d9 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include <linux/shmem_fs.h>
 
index 271a0eb9042c3ee7ba01a3c73329f883dbb13bd3..4173e4f483341307965aeed3c9a20376d8ae9f2f 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_crtc_helper.h>
index 418817600ad11052105418572e6c2a6965bba71a..0e67d2d42f0cc4014fe88b263237fa347af07116 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_plane_helper.h>
index 25afb1d594e326c10e435e19a8f4346db2561459..7ef5dcb06104336f5cf2591b6f4e1a75d490d75c 100644 (file)
@@ -26,6 +26,7 @@
  **************************************************************************/
 #include <linux/module.h>
 #include <linux/console.h>
+#include <linux/dma-mapping.h>
 
 #include <drm/drmP.h>
 #include "vmwgfx_drv.h"
@@ -34,7 +35,6 @@
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_module.h>
-#include <linux/intel-iommu.h>
 
 #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
 #define VMWGFX_CHIP_SVGAII 0
@@ -545,6 +545,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
        dev_priv->initial_height = height;
 }
 
+/**
+ * vmw_assume_iommu - Figure out whether coherent dma-remapping might be
+ * taking place.
+ * @dev: Pointer to the struct drm_device.
+ *
+ * Return: true if iommu present, false otherwise.
+ */
+static bool vmw_assume_iommu(struct drm_device *dev)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev->dev);
+
+       return !dma_is_direct(ops) && ops &&
+               ops->map_page != dma_direct_map_page;
+}
+
 /**
  * vmw_dma_select_mode - Determine how DMA mappings should be set up for this
  * system.
@@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
                [vmw_dma_alloc_coherent] = "Using coherent TTM pages.",
                [vmw_dma_map_populate] = "Keeping DMA mappings.",
                [vmw_dma_map_bind] = "Giving up DMA mappings early."};
-#ifdef CONFIG_X86
-       const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev);
 
-#ifdef CONFIG_INTEL_IOMMU
-       if (intel_iommu_enabled) {
+       if (vmw_force_coherent)
+               dev_priv->map_mode = vmw_dma_alloc_coherent;
+       else if (vmw_assume_iommu(dev_priv->dev))
                dev_priv->map_mode = vmw_dma_map_populate;
-               goto out_fixup;
-       }
-#endif
-
-       if (!(vmw_force_iommu || vmw_force_coherent)) {
+       else if (!vmw_force_iommu)
                dev_priv->map_mode = vmw_dma_phys;
-               DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-               return 0;
-       }
-
-       dev_priv->map_mode = vmw_dma_map_populate;
-
-       if (dma_ops && dma_ops->sync_single_for_cpu)
+       else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl())
                dev_priv->map_mode = vmw_dma_alloc_coherent;
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb_nr_tbl() == 0)
+       else
                dev_priv->map_mode = vmw_dma_map_populate;
-#endif
 
-#ifdef CONFIG_INTEL_IOMMU
-out_fixup:
-#endif
-       if (dev_priv->map_mode == vmw_dma_map_populate &&
-           vmw_restrict_iommu)
+       if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu)
                dev_priv->map_mode = vmw_dma_map_bind;
 
-       if (vmw_force_coherent)
-               dev_priv->map_mode = vmw_dma_alloc_coherent;
-
-#if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU)
-       /*
-        * No coherent page pool
-        */
-       if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+       /* No TTM coherent page pool? FIXME: Ask TTM instead! */
+        if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) &&
+           (dev_priv->map_mode == vmw_dma_alloc_coherent))
                return -EINVAL;
-#endif
-
-#else /* CONFIG_X86 */
-       dev_priv->map_mode = vmw_dma_map_populate;
-#endif /* CONFIG_X86 */
 
        DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-
        return 0;
 }
 
@@ -625,24 +612,20 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
  * With 32-bit we can only handle 32 bit PFNs. Optionally set that
  * restriction also for 64-bit systems.
  */
-#ifdef CONFIG_INTEL_IOMMU
 static int vmw_dma_masks(struct vmw_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
+       int ret = 0;
 
-       if (intel_iommu_enabled &&
+       ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
+       if (dev_priv->map_mode != vmw_dma_phys &&
            (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
                DRM_INFO("Restricting DMA addresses to 44 bits.\n");
-               return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+               return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
        }
-       return 0;
-}
-#else
-static int vmw_dma_masks(struct vmw_private *dev_priv)
-{
-       return 0;
+
+       return ret;
 }
-#endif
 
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
index f2d13a72c05d3ef1785422b8b5285536453aecee..88b8178d4687116725902a9700e44a946ebf6583 100644 (file)
@@ -3570,7 +3570,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
                *p_fence = NULL;
        }
 
-       return 0;
+       return ret;
 }
 
 /**
index b351fb5214d33b9b84f6223ba72a6210862e9b80..ed2f67822f45912557d08c26ff46d10c57473af9 100644 (file)
@@ -1646,7 +1646,7 @@ static int vmw_kms_check_topology(struct drm_device *dev,
                struct drm_connector_state *conn_state;
                struct vmw_connector_state *vmw_conn_state;
 
-               if (!du->pref_active) {
+               if (!du->pref_active && new_crtc_state->enable) {
                        ret = -EINVAL;
                        goto clean;
                }
@@ -2554,8 +2554,8 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
                                      user_fence_rep)
 {
        struct vmw_fence_obj *fence = NULL;
-       uint32_t handle;
-       int ret;
+       uint32_t handle = 0;
+       int ret = 0;
 
        if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) ||
            out_fence)
index 474b00e19697d90e7a60ee60fb8f8badd330f81e..0a7d4395d427bacf0e27cb5251ab74bb6e816ac1 100644 (file)
@@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = {
        .cpmem_ofs = 0x1f000000,
        .srm_ofs = 0x1f040000,
        .tpm_ofs = 0x1f060000,
-       .csi0_ofs = 0x1f030000,
-       .csi1_ofs = 0x1f038000,
+       .csi0_ofs = 0x1e030000,
+       .csi1_ofs = 0x1e038000,
        .ic_ofs = 0x1e020000,
        .disp0_ofs = 0x1e040000,
        .disp1_ofs = 0x1e048000,
@@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = {
        .cpmem_ofs = 0x07000000,
        .srm_ofs = 0x07040000,
        .tpm_ofs = 0x07060000,
-       .csi0_ofs = 0x07030000,
-       .csi1_ofs = 0x07038000,
+       .csi0_ofs = 0x06030000,
+       .csi1_ofs = 0x06038000,
        .ic_ofs = 0x06020000,
        .disp0_ofs = 0x06040000,
        .disp1_ofs = 0x06048000,
index 2f8db9d625514928006c6b31adeccbe312514ef3..4a28f3fbb0a28c55630be20edbb8c2df4de74645 100644 (file)
@@ -106,6 +106,7 @@ struct ipu_pre {
        void                    *buffer_virt;
        bool                    in_use;
        unsigned int            safe_window_end;
+       unsigned int            last_bufaddr;
 };
 
 static DEFINE_MUTEX(ipu_pre_list_mutex);
@@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
 
        writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+       pre->last_bufaddr = bufaddr;
 
        val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
              IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
@@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
        unsigned short current_yblock;
        u32 val;
 
+       if (bufaddr == pre->last_bufaddr)
+               return;
+
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+       pre->last_bufaddr = bufaddr;
 
        do {
                if (time_after(jiffies, timeout)) {
index b677e5d524e698234f2af458c73b07cf4a22f116..d5f1d8e1c6f84e75172d88c222df4754fd21d861 100644 (file)
@@ -21,6 +21,7 @@ config VGA_SWITCHEROO
        bool "Laptop Hybrid Graphics - GPU switching support"
        depends on X86
        depends on ACPI
+       depends on PCI
        select VGA_ARB
        help
          Many laptops released in 2008/9/10 have two GPUs with a multiplexer
index f41d5fe51abe3b812b600c7fa79d789f350ef3ce..9993b692598fb84d1700e26ef7f97856ff842955 100644 (file)
@@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 {
        struct hid_collection *collection;
        unsigned usage;
+       int collection_index;
 
        usage = parser->local.usage[0];
 
@@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type)
        parser->collection_stack[parser->collection_stack_ptr++] =
                parser->device->maxcollection;
 
-       collection = parser->device->collection +
-               parser->device->maxcollection++;
+       collection_index = parser->device->maxcollection++;
+       collection = parser->device->collection + collection_index;
        collection->type = type;
        collection->usage = usage;
        collection->level = parser->collection_stack_ptr - 1;
-       collection->parent = parser->active_collection;
-       parser->active_collection = collection;
+       collection->parent_idx = (collection->level == 0) ? -1 :
+               parser->collection_stack[collection->level - 1];
 
        if (type == HID_COLLECTION_APPLICATION)
                parser->device->maxapplication++;
@@ -192,8 +193,6 @@ static int close_collection(struct hid_parser *parser)
                return -EINVAL;
        }
        parser->collection_stack_ptr--;
-       if (parser->active_collection)
-               parser->active_collection = parser->active_collection->parent;
        return 0;
 }
 
@@ -1006,10 +1005,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid,
                usage = &field->usage[i];
 
                collection = &hid->collection[usage->collection_index];
-               while (collection && collection != multiplier_collection)
-                       collection = collection->parent;
+               while (collection->parent_idx != -1 &&
+                      collection != multiplier_collection)
+                       collection = &hid->collection[collection->parent_idx];
 
-               if (collection || multiplier_collection == NULL)
+               if (collection->parent_idx != -1 ||
+                   multiplier_collection == NULL)
                        usage->resolution_multiplier = effective_multiplier;
 
        }
@@ -1044,9 +1045,9 @@ static void hid_apply_multiplier(struct hid_device *hid,
         * applicable fields later.
         */
        multiplier_collection = &hid->collection[multiplier->usage->collection_index];
-       while (multiplier_collection &&
+       while (multiplier_collection->parent_idx != -1 &&
               multiplier_collection->type != HID_COLLECTION_LOGICAL)
-               multiplier_collection = multiplier_collection->parent;
+               multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
 
        effective_multiplier = hid_calculate_multiplier(hid, multiplier);
 
index c530476edba62b7804b892e47a675396dfe1c3c8..ac9fda1b5a7233c227cd5517dcf6331a29483a60 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/kfifo.h>
 #include <linux/sched/signal.h>
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
 /* enqueue string to 'events' ring buffer */
 void hid_debug_event(struct hid_device *hdev, char *buf)
 {
-       unsigned i;
        struct hid_debug_list *list;
        unsigned long flags;
 
        spin_lock_irqsave(&hdev->debug_list_lock, flags);
-       list_for_each_entry(list, &hdev->debug_list, node) {
-               for (i = 0; buf[i]; i++)
-                       list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
-                               buf[i];
-               list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
-        }
+       list_for_each_entry(list, &hdev->debug_list, node)
+               kfifo_in(&list->hid_debug_fifo, buf, strlen(buf));
        spin_unlock_irqrestore(&hdev->debug_list_lock, flags);
 
        wake_up_interruptible(&hdev->debug_wait);
@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
        hid_debug_event(hdev, buf);
 
        kfree(buf);
-        wake_up_interruptible(&hdev->debug_wait);
-
+       wake_up_interruptible(&hdev->debug_wait);
 }
 EXPORT_SYMBOL_GPL(hid_dump_input);
 
@@ -1083,8 +1078,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
-               err = -ENOMEM;
+       err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL);
+       if (err) {
                kfree(list);
                goto out;
        }
@@ -1104,77 +1099,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
                size_t count, loff_t *ppos)
 {
        struct hid_debug_list *list = file->private_data;
-       int ret = 0, len;
+       int ret = 0, copied;
        DECLARE_WAITQUEUE(wait, current);
 
        mutex_lock(&list->read_mutex);
-       while (ret == 0) {
-               if (list->head == list->tail) {
-                       add_wait_queue(&list->hdev->debug_wait, &wait);
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       while (list->head == list->tail) {
-                               if (file->f_flags & O_NONBLOCK) {
-                                       ret = -EAGAIN;
-                                       break;
-                               }
-                               if (signal_pending(current)) {
-                                       ret = -ERESTARTSYS;
-                                       break;
-                               }
+       if (kfifo_is_empty(&list->hid_debug_fifo)) {
+               add_wait_queue(&list->hdev->debug_wait, &wait);
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               while (kfifo_is_empty(&list->hid_debug_fifo)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               ret = -EAGAIN;
+                               break;
+                       }
 
-                               if (!list->hdev || !list->hdev->debug) {
-                                       ret = -EIO;
-                                       set_current_state(TASK_RUNNING);
-                                       goto out;
-                               }
+                       if (signal_pending(current)) {
+                               ret = -ERESTARTSYS;
+                               break;
+                       }
 
-                               /* allow O_NONBLOCK from other threads */
-                               mutex_unlock(&list->read_mutex);
-                               schedule();
-                               mutex_lock(&list->read_mutex);
-                               set_current_state(TASK_INTERRUPTIBLE);
+                       /* if list->hdev is NULL we cannot remove_wait_queue().
+                        * if list->hdev->debug is 0 then hid_debug_unregister()
+                        * was already called and list->hdev is being destroyed.
+                        * if we add remove_wait_queue() here we can hit a race.
+                        */
+                       if (!list->hdev || !list->hdev->debug) {
+                               ret = -EIO;
+                               set_current_state(TASK_RUNNING);
+                               goto out;
                        }
 
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&list->hdev->debug_wait, &wait);
+                       /* allow O_NONBLOCK from other threads */
+                       mutex_unlock(&list->read_mutex);
+                       schedule();
+                       mutex_lock(&list->read_mutex);
+                       set_current_state(TASK_INTERRUPTIBLE);
                }
 
-               if (ret)
-                       goto out;
+               __set_current_state(TASK_RUNNING);
+               remove_wait_queue(&list->hdev->debug_wait, &wait);
 
-               /* pass the ringbuffer contents to userspace */
-copy_rest:
-               if (list->tail == list->head)
+               if (ret)
                        goto out;
-               if (list->tail > list->head) {
-                       len = list->tail - list->head;
-                       if (len > count)
-                               len = count;
-
-                       if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       ret += len;
-                       list->head += len;
-               } else {
-                       len = HID_DEBUG_BUFSIZE - list->head;
-                       if (len > count)
-                               len = count;
-
-                       if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       list->head = 0;
-                       ret += len;
-                       count -= len;
-                       if (count > 0)
-                               goto copy_rest;
-               }
-
        }
+
+       /* pass the fifo content to userspace, locking is not needed with only
+        * one concurrent reader and one concurrent writer
+        */
+       ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied);
+       if (ret)
+               goto out;
+       ret = copied;
 out:
        mutex_unlock(&list->read_mutex);
        return ret;
@@ -1185,7 +1160,7 @@ static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait)
        struct hid_debug_list *list = file->private_data;
 
        poll_wait(file, &list->hdev->debug_wait, wait);
-       if (list->head != list->tail)
+       if (!kfifo_is_empty(&list->hid_debug_fifo))
                return EPOLLIN | EPOLLRDNORM;
        if (!list->hdev->debug)
                return EPOLLERR | EPOLLHUP;
@@ -1200,7 +1175,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
        spin_lock_irqsave(&list->hdev->debug_list_lock, flags);
        list_del(&list->node);
        spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
-       kfree(list->hid_debug_buf);
+       kfifo_free(&list->hid_debug_fifo);
        kfree(list);
 
        return 0;
@@ -1246,4 +1221,3 @@ void hid_debug_exit(void)
 {
        debugfs_remove_recursive(hid_debug_root);
 }
-
index 518fa76414f560f8e76d88a2079310cc8b8c4936..24f846d67478cec0d71501569cef2ea5f706cbab 100644 (file)
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
 
+#define I2C_VENDOR_ID_GOODIX           0x27c6
+#define I2C_DEVICE_ID_GOODIX_01F0      0x01f0
+
 #define USB_VENDOR_ID_GOODTOUCH                0x1aad
 #define USB_DEVICE_ID_GOODTOUCH_000f   0x000f
 
index 8555ce7e737b37a78160d930a9ba12ed311e001b..c5edfa966343dc098c63af7d4513ffeed02348de 100644 (file)
@@ -179,6 +179,8 @@ static const struct i2c_hid_quirks {
                I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
        { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
                I2C_HID_QUIRK_NO_RUNTIME_PM },
+       { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
+               I2C_HID_QUIRK_NO_RUNTIME_PM },
        { 0, 0 }
 };
 
index ce0ba20627236dde727d2f6fd486a1b8d281d327..bea4c9850247bcdbdc9a4668719e2f6fa8ad4fe2 100644 (file)
@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
 int vmbus_disconnect_ring(struct vmbus_channel *channel)
 {
        struct vmbus_channel *cur_channel, *tmp;
-       unsigned long flags;
-       LIST_HEAD(list);
        int ret;
 
        if (channel->primary_channel != NULL)
                return -EINVAL;
 
-       /* Snapshot the list of subchannels */
-       spin_lock_irqsave(&channel->lock, flags);
-       list_splice_init(&channel->sc_list, &list);
-       spin_unlock_irqrestore(&channel->lock, flags);
-
-       list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) {
+       list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
                if (cur_channel->rescind)
                        wait_for_completion(&cur_channel->rescind_event);
 
index 5301fef16c31b740fab409ced2f3e7ef6c5bbe23..7c6349a50ef173421cdafea3b289ae9868da711e 100644 (file)
@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
                        pfn_cnt -= pgs_ol;
                        /*
                         * Check if the corresponding memory block is already
-                        * online by checking its last previously backed page.
-                        * In case it is we need to bring rest (which was not
-                        * backed previously) online too.
+                        * online. It is possible to observe struct pages still
+                        * being uninitialized here so check section instead.
+                        * In case the section is online we need to bring the
+                        * rest of pfns (which were not backed previously)
+                        * online too.
                         */
                        if (start_pfn > has->start_pfn &&
-                           !PageReserved(pfn_to_page(start_pfn - 1)))
+                           online_section_nr(pfn_to_section_nr(start_pfn)))
                                hv_bring_pgs_online(has, start_pfn, pgs_ol);
 
                }
index 64d0c85d51611199f9bd98e97efe0b54d992df5f..1f1a55e077338cabf233bba7630d805f84fd96f6 100644 (file)
@@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
 }
 
 /* Get various debug metrics for the specified ring buffer. */
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-                                struct hv_ring_buffer_debug_info *debug_info)
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+                               struct hv_ring_buffer_debug_info *debug_info)
 {
        u32 bytes_avail_towrite;
        u32 bytes_avail_toread;
 
-       if (ring_info->ring_buffer) {
-               hv_get_ringbuffer_availbytes(ring_info,
-                                       &bytes_avail_toread,
-                                       &bytes_avail_towrite);
-
-               debug_info->bytes_avail_toread = bytes_avail_toread;
-               debug_info->bytes_avail_towrite = bytes_avail_towrite;
-               debug_info->current_read_index =
-                       ring_info->ring_buffer->read_index;
-               debug_info->current_write_index =
-                       ring_info->ring_buffer->write_index;
-               debug_info->current_interrupt_mask =
-                       ring_info->ring_buffer->interrupt_mask;
-       }
+       if (!ring_info->ring_buffer)
+               return -EINVAL;
+
+       hv_get_ringbuffer_availbytes(ring_info,
+                                    &bytes_avail_toread,
+                                    &bytes_avail_towrite);
+       debug_info->bytes_avail_toread = bytes_avail_toread;
+       debug_info->bytes_avail_towrite = bytes_avail_towrite;
+       debug_info->current_read_index = ring_info->ring_buffer->read_index;
+       debug_info->current_write_index = ring_info->ring_buffer->write_index;
+       debug_info->current_interrupt_mask
+               = ring_info->ring_buffer->interrupt_mask;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
 
index d0ff65675292bd8b9ac7c6fa99d708e94484a62b..403fee01572c5c93cefadebf0895a7302f777325 100644 (file)
@@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(out_intr_mask);
@@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.current_read_index);
 }
 static DEVICE_ATTR_RO(out_read_index);
@@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.current_write_index);
 }
 static DEVICE_ATTR_RO(out_write_index);
@@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(out_read_bytes_avail);
@@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(out_write_bytes_avail);
@@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(in_intr_mask);
@@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_read_index);
 }
 static DEVICE_ATTR_RO(in_read_index);
@@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_write_index);
 }
 static DEVICE_ATTR_RO(in_write_index);
@@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(in_read_bytes_avail);
@@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(in_write_bytes_avail);
index 0e30fa00204cdd65ad927ee38d4bb00e61b49f58..f9b8e3e23a8e8d22293b4e22ee27dc3563f13fa4 100644 (file)
@@ -393,8 +393,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        }
 
        rv = lm80_read_value(client, LM80_REG_FANDIV);
-       if (rv < 0)
+       if (rv < 0) {
+               mutex_unlock(&data->update_lock);
                return rv;
+       }
        reg = (rv & ~(3 << (2 * (nr + 1))))
            | (data->fan_div[nr] << (2 * (nr + 1)));
        lm80_write_value(client, LM80_REG_FANDIV, reg);
index c3040079b1cb645ef10d66f0f23edd3c8b10483c..59ee01f3d022397e638dcecdb2cdd1ce497f6129 100644 (file)
@@ -44,8 +44,8 @@
  * nct6796d    14      7       7       2+6    0xd420 0xc1    0x5ca3
  * nct6797d    14      7       7       2+6    0xd450 0xc1    0x5ca3
  *                                           (0xd451)
- * nct6798d    14      7       7       2+6    0xd458 0xc1    0x5ca3
- *                                           (0xd459)
+ * nct6798d    14      7       7       2+6    0xd428 0xc1    0x5ca3
+ *                                           (0xd429)
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -138,7 +138,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6795_ID         0xd350
 #define SIO_NCT6796_ID         0xd420
 #define SIO_NCT6797_ID         0xd450
-#define SIO_NCT6798_ID         0xd458
+#define SIO_NCT6798_ID         0xd428
 #define SIO_ID_MASK            0xFFF8
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -3594,7 +3594,8 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                        fan5pin |= cr1b & BIT(5);
                        fan5pin |= creb & BIT(5);
 
-                       fan6pin = creb & BIT(3);
+                       fan6pin = !dsw_en && (cr2d & BIT(1));
+                       fan6pin |= creb & BIT(3);
 
                        pwm5pin |= cr2d & BIT(7);
                        pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
@@ -4508,7 +4509,8 @@ static int __maybe_unused nct6775_resume(struct device *dev)
 
        if (data->kind == nct6791 || data->kind == nct6792 ||
            data->kind == nct6793 || data->kind == nct6795 ||
-           data->kind == nct6796)
+           data->kind == nct6796 || data->kind == nct6797 ||
+           data->kind == nct6798)
                nct6791_enable_io_mapping(sioreg);
 
        superio_exit(sioreg);
@@ -4644,7 +4646,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
 
        if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
            sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
-           sio_data->kind == nct6796)
+           sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
+           sio_data->kind == nct6798)
                nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
index 423903f87955510e6f8ae9cf5f583667d2335f80..391118c8aae8c7182cea59edda670b6b3bfa90a4 100644 (file)
@@ -380,8 +380,8 @@ static ssize_t occ_show_power_1(struct device *dev,
                val *= 1000000ULL;
                break;
        case 2:
-               val = get_unaligned_be32(&power->update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -425,8 +425,8 @@ static ssize_t occ_show_power_2(struct device *dev,
                                       &power->update_tag);
                break;
        case 2:
-               val = get_unaligned_be32(&power->update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -463,8 +463,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->system.update_tag);
                break;
        case 2:
-               val = get_unaligned_be32(&power->system.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->system.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->system.value) * 1000000ULL;
@@ -477,8 +477,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->proc.update_tag);
                break;
        case 6:
-               val = get_unaligned_be32(&power->proc.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->proc.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 7:
                val = get_unaligned_be16(&power->proc.value) * 1000000ULL;
@@ -491,8 +491,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->vdd.update_tag);
                break;
        case 10:
-               val = get_unaligned_be32(&power->vdd.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 11:
                val = get_unaligned_be16(&power->vdd.value) * 1000000ULL;
@@ -505,8 +505,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->vdn.update_tag);
                break;
        case 14:
-               val = get_unaligned_be32(&power->vdn.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->vdn.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 15:
                val = get_unaligned_be16(&power->vdn.value) * 1000000ULL;
index 8844c9565d2a49eae8cd4fcbc9c7fa828e914ccb..7053be59ad2e4d6eaebf28ddee8f7769c0924b9c 100644 (file)
@@ -88,7 +88,7 @@ static const struct of_device_id tmp421_of_match[] = {
                .data = (void *)2
        },
        {
-               .compatible = "ti,tmp422",
+               .compatible = "ti,tmp442",
                .data = (void *)3
        },
        { },
index ec6e69aa3a8e5ac455c0ede516d96b75fc7a87a8..d2fbb4bb4a4371b5954789f0221c5c65216b7614 100644 (file)
@@ -183,6 +183,15 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
        bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
 }
 
+static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c_dev *i2c_dev)
+{
+       i2c_dev->curr_msg = NULL;
+       i2c_dev->num_msgs = 0;
+
+       i2c_dev->msg_buf = NULL;
+       i2c_dev->msg_buf_remaining = 0;
+}
+
 /*
  * Note about I2C_C_CLEAR on error:
  * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
@@ -283,6 +292,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 
        time_left = wait_for_completion_timeout(&i2c_dev->completion,
                                                adap->timeout);
+
+       bcm2835_i2c_finish_transfer(i2c_dev);
+
        if (!time_left) {
                bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
                                   BCM2835_I2C_C_CLEAR);
index b13605718291619f29e8fc6d21bb513ef513b21e..d917cefc5a19c62882234fa9f88ea382007bf2a3 100644 (file)
@@ -382,8 +382,10 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
         */
-       if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
+       if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
+       else
+               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
 
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
@@ -440,8 +442,11 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
         */
-       if (id->send_count > CDNS_I2C_FIFO_DEPTH)
+       if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
+       else
+               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
+
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
        /* Clear the interrupts in interrupt status register. */
index b1086bfb04656aa45422ff1f89a57647f53da369..cd9c65f3d404ff92f0eef87d4d99236b370e82cc 100644 (file)
@@ -1500,8 +1500,7 @@ static int omap_i2c_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int omap_i2c_runtime_suspend(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev)
 {
        struct omap_i2c_dev *omap = dev_get_drvdata(dev);
 
@@ -1527,7 +1526,7 @@ static int omap_i2c_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int omap_i2c_runtime_resume(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_resume(struct device *dev)
 {
        struct omap_i2c_dev *omap = dev_get_drvdata(dev);
 
@@ -1542,20 +1541,18 @@ static int omap_i2c_runtime_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops omap_i2c_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                                     pm_runtime_force_resume)
        SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
                           omap_i2c_runtime_resume, NULL)
 };
-#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
-#else
-#define OMAP_I2C_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static struct platform_driver omap_i2c_driver = {
        .probe          = omap_i2c_probe,
        .remove         = omap_i2c_remove,
        .driver         = {
                .name   = "omap_i2c",
-               .pm     = OMAP_I2C_PM_OPS,
+               .pm     = &omap_i2c_pm_ops,
                .of_match_table = of_match_ptr(omap_i2c_of_match),
        },
 };
index c39f89d2debaae9bd37bb3d5f4e252628a8435fd..2dc628d4f1aee1b5c07593f85e7d75a6bdb3d0be 100644 (file)
@@ -1828,7 +1828,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
 
        ret = i3c_master_retrieve_dev_info(newdev);
        if (ret)
-               goto err_free_dev;
+               goto err_detach_dev;
 
        olddev = i3c_master_search_i3c_dev_duplicate(newdev);
        if (olddev) {
index b532e2c9cf5c617396de17ba038ec055fced9a11..bb03079fbade164806047e17aa697c0f886bd5b0 100644 (file)
@@ -419,12 +419,9 @@ static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master,
        spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 }
 
-static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
-                                      struct dw_i3c_xfer *xfer)
+static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master,
+                                             struct dw_i3c_xfer *xfer)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&master->xferqueue.lock, flags);
        if (master->xferqueue.cur == xfer) {
                u32 status;
 
@@ -439,6 +436,15 @@ static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
        } else {
                list_del_init(&xfer->node);
        }
+}
+
+static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
+                                      struct dw_i3c_xfer *xfer)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&master->xferqueue.lock, flags);
+       dw_i3c_master_dequeue_xfer_locked(master, xfer);
        spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 }
 
@@ -494,7 +500,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
        complete(&xfer->comp);
 
        if (ret < 0) {
-               dw_i3c_master_dequeue_xfer(master, xfer);
+               dw_i3c_master_dequeue_xfer_locked(master, xfer);
                writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
                       master->regs + DEVICE_CTRL);
        }
@@ -901,9 +907,6 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
               master->regs +
               DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
 
-       if (!old_dyn_addr)
-               return 0;
-
        master->addrs[data->index] = dev->info.dyn_addr;
 
        return 0;
@@ -925,11 +928,11 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
                return -ENOMEM;
 
        data->index = pos;
-       master->addrs[pos] = dev->info.dyn_addr;
+       master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr;
        master->free_pos &= ~BIT(pos);
        i3c_dev_set_master_data(dev, data);
 
-       writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr),
+       writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]),
               master->regs +
               DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
 
index bbd79b8b1a8093189ee69eebe5e77f4df876a2ca..8889a4fdb4541a06a94dfc0d0b858adf661f37e9 100644 (file)
@@ -1556,8 +1556,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
                return PTR_ERR(master->pclk);
 
        master->sysclk = devm_clk_get(&pdev->dev, "sysclk");
-       if (IS_ERR(master->pclk))
-               return PTR_ERR(master->pclk);
+       if (IS_ERR(master->sysclk))
+               return PTR_ERR(master->sysclk);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
index da58020a144eebfd47c169eca77cc438e218d8c0..33a28cde126c9013b7ab38e38d21232f47571f87 100644 (file)
@@ -235,21 +235,28 @@ EXPORT_SYMBOL_GPL(ide_prep_sense);
 
 int ide_queue_sense_rq(ide_drive_t *drive, void *special)
 {
-       struct request *sense_rq = drive->sense_rq;
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *sense_rq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&hwif->lock, flags);
 
        /* deferred failure from ide_prep_sense() */
        if (!drive->sense_rq_armed) {
                printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
                       drive->name);
+               spin_unlock_irqrestore(&hwif->lock, flags);
                return -ENOMEM;
        }
 
+       sense_rq = drive->sense_rq;
        ide_req(sense_rq)->special = special;
        drive->sense_rq_armed = false;
 
        drive->hwif->rq = NULL;
 
        ide_insert_request_head(drive, sense_rq);
+       spin_unlock_irqrestore(&hwif->lock, flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
index 8445b484ae69ed3f813860731c137a6d4b32789b..b137f27a34d585b5d1472624d9d021fee833a8f0 100644 (file)
@@ -68,8 +68,10 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
        }
 
        if (!blk_update_request(rq, error, nr_bytes)) {
-               if (rq == drive->sense_rq)
+               if (rq == drive->sense_rq) {
                        drive->sense_rq = NULL;
+                       drive->sense_rq_active = false;
+               }
 
                __blk_mq_end_request(rq, error);
                return 0;
@@ -451,16 +453,11 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
                blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3);
 }
 
-/*
- * Issue a new request to a device.
- */
-blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
-                         const struct blk_mq_queue_data *bd)
+blk_status_t ide_issue_rq(ide_drive_t *drive, struct request *rq,
+                         bool local_requeue)
 {
-       ide_drive_t     *drive = hctx->queue->queuedata;
-       ide_hwif_t      *hwif = drive->hwif;
+       ide_hwif_t *hwif = drive->hwif;
        struct ide_host *host = hwif->host;
-       struct request  *rq = bd->rq;
        ide_startstop_t startstop;
 
        if (!blk_rq_is_passthrough(rq) && !(rq->rq_flags & RQF_DONTPREP)) {
@@ -474,8 +471,6 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (ide_lock_host(host, hwif))
                return BLK_STS_DEV_RESOURCE;
 
-       blk_mq_start_request(rq);
-
        spin_lock_irq(&hwif->lock);
 
        if (!ide_lock_port(hwif)) {
@@ -510,18 +505,6 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
                hwif->cur_dev = drive;
                drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
 
-               /*
-                * we know that the queue isn't empty, but this can happen
-                * if ->prep_rq() decides to kill a request
-                */
-               if (!rq) {
-                       rq = bd->rq;
-                       if (!rq) {
-                               ide_unlock_port(hwif);
-                               goto out;
-                       }
-               }
-
                /*
                 * Sanity: don't accept a request that isn't a PM request
                 * if we are currently power managed. This is very important as
@@ -560,9 +543,12 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
                }
        } else {
 plug_device:
+               if (local_requeue)
+                       list_add(&rq->queuelist, &drive->rq_list);
                spin_unlock_irq(&hwif->lock);
                ide_unlock_host(host);
-               ide_requeue_and_plug(drive, rq);
+               if (!local_requeue)
+                       ide_requeue_and_plug(drive, rq);
                return BLK_STS_OK;
        }
 
@@ -573,6 +559,26 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
        return BLK_STS_OK;
 }
 
+/*
+ * Issue a new request to a device.
+ */
+blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
+                         const struct blk_mq_queue_data *bd)
+{
+       ide_drive_t *drive = hctx->queue->queuedata;
+       ide_hwif_t *hwif = drive->hwif;
+
+       spin_lock_irq(&hwif->lock);
+       if (drive->sense_rq_active) {
+               spin_unlock_irq(&hwif->lock);
+               return BLK_STS_DEV_RESOURCE;
+       }
+       spin_unlock_irq(&hwif->lock);
+
+       blk_mq_start_request(bd->rq);
+       return ide_issue_rq(drive, bd->rq, false);
+}
+
 static int drive_is_ready(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
@@ -893,13 +899,8 @@ EXPORT_SYMBOL_GPL(ide_pad_transfer);
 
 void ide_insert_request_head(ide_drive_t *drive, struct request *rq)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       unsigned long flags;
-
-       spin_lock_irqsave(&hwif->lock, flags);
+       drive->sense_rq_active = true;
        list_add_tail(&rq->queuelist, &drive->rq_list);
-       spin_unlock_irqrestore(&hwif->lock, flags);
-
        kblockd_schedule_work(&drive->rq_work);
 }
 EXPORT_SYMBOL_GPL(ide_insert_request_head);
index 102aa3bc3e7fc11e672bd15051f4c4a94de6a669..8af7af6001eb36cd28bdfd840c206942e1fda5c0 100644 (file)
@@ -54,7 +54,9 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
        scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS;
        scsi_req(rq)->cmd_len = 1;
        ide_req(rq)->type = ATA_PRIV_MISC;
+       spin_lock_irq(&hwif->lock);
        ide_insert_request_head(drive, rq);
+       spin_unlock_irq(&hwif->lock);
 
 out:
        return;
index 63627be0811a740142c769bcc66da80f64cc101e..5aeaca24a28f35a9f11744deeab46f9dcb18745d 100644 (file)
@@ -1159,18 +1159,27 @@ static void drive_rq_insert_work(struct work_struct *work)
        ide_drive_t *drive = container_of(work, ide_drive_t, rq_work);
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq;
+       blk_status_t ret;
        LIST_HEAD(list);
 
-       spin_lock_irq(&hwif->lock);
-       if (!list_empty(&drive->rq_list))
-               list_splice_init(&drive->rq_list, &list);
-       spin_unlock_irq(&hwif->lock);
+       blk_mq_quiesce_queue(drive->queue);
 
-       while (!list_empty(&list)) {
-               rq = list_first_entry(&list, struct request, queuelist);
+       ret = BLK_STS_OK;
+       spin_lock_irq(&hwif->lock);
+       while (!list_empty(&drive->rq_list)) {
+               rq = list_first_entry(&drive->rq_list, struct request, queuelist);
                list_del_init(&rq->queuelist);
-               blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL);
+
+               spin_unlock_irq(&hwif->lock);
+               ret = ide_issue_rq(drive, rq, true);
+               spin_lock_irq(&hwif->lock);
        }
+       spin_unlock_irq(&hwif->lock);
+
+       blk_mq_unquiesce_queue(drive->queue);
+
+       if (ret != BLK_STS_OK)
+               kblockd_schedule_work(&drive->rq_work);
 }
 
 static const u8 ide_hwif_to_major[] =
index 4c8c7a620d08dae851de513eebe2710dee3ca89e..a5dc13576394ffa8d7be2c2ae9298211ea216f47 100644 (file)
@@ -544,7 +544,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
                drive->proc = proc_mkdir(drive->name, parent);
                if (drive->proc) {
                        ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-                       proc_create_data("setting", S_IFREG|S_IRUSR|S_IWUSR,
+                       proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR,
                                        drive->proc, &ide_settings_proc_fops,
                                        drive);
                }
index 031d568b4972fa59e6426b3dfe013b0c3b94ad9e..4e339cfd0c546db8751f7d547ce14d2ce33bb5ed 100644 (file)
 #include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
-#define AXP288_ADC_EN_MASK             0xF1
-#define AXP288_ADC_TS_PIN_GPADC                0xF2
-#define AXP288_ADC_TS_PIN_ON           0xF3
+/*
+ * This mask enables all ADCs except for the battery temp-sensor (TS), that is
+ * left as-is to avoid breaking charging on devices without a temp-sensor.
+ */
+#define AXP288_ADC_EN_MASK                             0xF0
+#define AXP288_ADC_TS_ENABLE                           0x01
+
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK              GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF                      (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING         (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND              (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON                       (3 << 0)
 
 enum axp288_adc_id {
        AXP288_ADC_TS,
@@ -44,6 +53,7 @@ enum axp288_adc_id {
 struct axp288_adc_info {
        int irq;
        struct regmap *regmap;
+       bool ts_enabled;
 };
 
 static const struct iio_chan_spec axp288_adc_channels[] = {
@@ -115,21 +125,33 @@ static int axp288_adc_read_channel(int *val, unsigned long address,
        return IIO_VAL_INT;
 }
 
-static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
-                               unsigned long address)
+/*
+ * The current-source used for the battery temp-sensor (TS) is shared
+ * with the GPADC. For proper fuel-gauge and charger operation the TS
+ * current-source needs to be permanently on. But to read the GPADC we
+ * need to temporary switch the TS current-source to ondemand, so that
+ * the GPADC can use it, otherwise we will always read an all 0 value.
+ */
+static int axp288_adc_set_ts(struct axp288_adc_info *info,
+                            unsigned int mode, unsigned long address)
 {
        int ret;
 
-       /* channels other than GPADC do not need to switch TS pin */
+       /* No need to switch the current-source if the TS pin is disabled */
+       if (!info->ts_enabled)
+               return 0;
+
+       /* Channels other than GPADC do not need the current source */
        if (address != AXP288_GP_ADC_H)
                return 0;
 
-       ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+       ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                AXP288_ADC_TS_CURRENT_ON_OFF_MASK, mode);
        if (ret)
                return ret;
 
        /* When switching to the GPADC pin give things some time to settle */
-       if (mode == AXP288_ADC_TS_PIN_GPADC)
+       if (mode == AXP288_ADC_TS_CURRENT_ON_ONDEMAND)
                usleep_range(6000, 10000);
 
        return 0;
@@ -145,14 +167,14 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+               if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON_ONDEMAND,
                                        chan->address)) {
                        dev_err(&indio_dev->dev, "GPADC mode\n");
                        ret = -EINVAL;
                        break;
                }
                ret = axp288_adc_read_channel(val, chan->address, info->regmap);
-               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+               if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON,
                                                chan->address))
                        dev_err(&indio_dev->dev, "TS pin restore\n");
                break;
@@ -164,13 +186,35 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
        return ret;
 }
 
-static int axp288_adc_set_state(struct regmap *regmap)
+static int axp288_adc_initialize(struct axp288_adc_info *info)
 {
-       /* ADC should be always enabled for internal FG to function */
-       if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
-               return -EIO;
+       int ret, adc_enable_val;
+
+       /*
+        * Determine if the TS pin is enabled and set the TS current-source
+        * accordingly.
+        */
+       ret = regmap_read(info->regmap, AXP20X_ADC_EN1, &adc_enable_val);
+       if (ret)
+               return ret;
+
+       if (adc_enable_val & AXP288_ADC_TS_ENABLE) {
+               info->ts_enabled = true;
+               ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_ON);
+       } else {
+               info->ts_enabled = false;
+               ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_OFF);
+       }
+       if (ret)
+               return ret;
 
-       return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+       /* Turn on the ADC for all channels except TS, leave TS as is */
+       return regmap_update_bits(info->regmap, AXP20X_ADC_EN1,
+                                 AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK);
 }
 
 static const struct iio_info axp288_adc_iio_info = {
@@ -200,7 +244,7 @@ static int axp288_adc_probe(struct platform_device *pdev)
         * Set ADC to enabled state at all time, including system suspend.
         * otherwise internal fuel gauge functionality may be affected.
         */
-       ret = axp288_adc_set_state(axp20x->regmap);
+       ret = axp288_adc_initialize(info);
        if (ret) {
                dev_err(&pdev->dev, "unable to enable ADC device\n");
                return ret;
index 184d686ebd9958ec316a53b16e1cab667b4518fa..8b4568edd5cb6e93a7567523999313c3d64c781b 100644 (file)
@@ -41,6 +41,7 @@
 
 #define ADS8688_VREF_MV                        4096
 #define ADS8688_REALBITS               16
+#define ADS8688_MAX_CHANNELS           8
 
 /*
  * enum ads8688_range - ADS8688 reference voltage range
@@ -385,7 +386,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
-       u16 buffer[8];
+       u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
        int i, j = 0;
 
        for (i = 0; i < indio_dev->masklength; i++) {
index cafb1dcadc488c4af2664d66409f0eb02d12d16f..9d984f2a8ba7489e2920e43af6d14a8b141a541d 100644 (file)
@@ -142,7 +142,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
                        stepconfig |= STEPCONFIG_MODE_SWCNT;
 
                tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
-                               stepconfig | STEPCONFIG_INP(chan));
+                               stepconfig | STEPCONFIG_INP(chan) |
+                               STEPCONFIG_INM_ADCREFM |
+                               STEPCONFIG_RFP_VREFP |
+                               STEPCONFIG_RFM_VREFN);
 
                if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
                        dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
index a406ad31b096f6755121fede4b7a6e2de3a24342..3a20cb5d9bffc29b6869954a6bbef94ecdcd42b5 100644 (file)
@@ -444,9 +444,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_TEMP:
-                       *val = 1; /* 0.01 */
-                       *val2 = 100;
-                       break;
+                       *val = 10;
+                       return IIO_VAL_INT;
                case IIO_PH:
                        *val = 1; /* 0.001 */
                        *val2 = 1000;
@@ -477,7 +476,7 @@ static int atlas_write_raw(struct iio_dev *indio_dev,
                           int val, int val2, long mask)
 {
        struct atlas_data *data = iio_priv(indio_dev);
-       __be32 reg = cpu_to_be32(val);
+       __be32 reg = cpu_to_be32(val / 10);
 
        if (val2 != 0 || val < 0 || val > 20000)
                return -EINVAL;
index 63a7cc00bae0b1578254cd228e2a72feac084b03..84f077b2b90a7cb2afdfececa42a1f5639f9324f 100644 (file)
@@ -494,7 +494,10 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
        id_priv->id.route.addr.dev_addr.transport =
                rdma_node_get_transport(cma_dev->device->node_type);
        list_add_tail(&id_priv->list, &cma_dev->id_list);
-       rdma_restrack_kadd(&id_priv->res);
+       if (id_priv->res.kern_name)
+               rdma_restrack_kadd(&id_priv->res);
+       else
+               rdma_restrack_uadd(&id_priv->res);
 }
 
 static void cma_attach_to_dev(struct rdma_id_private *id_priv,
index 3cd830d52967eb252d6646094a46f52e0e003174..616734313f0c698ef6d3868b37a5599f901dba74 100644 (file)
@@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
 #endif
 
 struct ib_device *ib_device_get_by_index(u32 ifindex);
-void ib_device_put(struct ib_device *device);
 /* RDMA device netlink */
 void nldev_init(void);
 void nldev_exit(void);
index 8872453e26c07c65c12b2aca5f9f14a6924f91f7..238ec42778ef39ce4594e9633dc49223e4eb6866 100644 (file)
@@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index)
        down_read(&lists_rwsem);
        device = __ib_device_get_by_index(index);
        if (device) {
-               /* Do not return a device if unregistration has started. */
-               if (!refcount_inc_not_zero(&device->refcount))
+               if (!ib_device_try_get(device))
                        device = NULL;
        }
        up_read(&lists_rwsem);
        return device;
 }
 
+/**
+ * ib_device_put - Release IB device reference
+ * @device: device whose reference to be released
+ *
+ * ib_device_put() releases reference to the IB device to allow it to be
+ * unregistered and eventually free.
+ */
 void ib_device_put(struct ib_device *device)
 {
        if (refcount_dec_and_test(&device->refcount))
                complete(&device->unreg_completion);
 }
+EXPORT_SYMBOL(ib_device_put);
 
 static struct ib_device *__ib_device_get_by_name(const char *name)
 {
@@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size)
        rwlock_init(&device->client_data_lock);
        INIT_LIST_HEAD(&device->client_data_list);
        INIT_LIST_HEAD(&device->port_list);
-       refcount_set(&device->refcount, 1);
        init_completion(&device->unreg_completion);
 
        return device;
@@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name,
                goto cg_cleanup;
        }
 
+       refcount_set(&device->refcount, 1);
        device->reg_state = IB_DEV_REGISTERED;
 
        list_for_each_entry(client, &client_list, list)
index e600fc23ae62fc2e09f85aa5f5dc3a504875473b..3c97a8b6bf1e0f881671cdc70895624050b265c1 100644 (file)
@@ -584,10 +584,6 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
        if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
                              atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))
                goto err;
-       if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) &&
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,
-                       pd->unsafe_global_rkey))
-               goto err;
 
        if (fill_res_name_pid(msg, res))
                goto err;
index be6b8e1257d07e64d5729a114c482b071713f1fe..69f8db66925ea6ad15c4e2e7c743537dee067300 100644 (file)
@@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
                           enum uverbs_obj_access access,
                           bool commit);
 
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
+
 void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 
index a4ec43093cb3a73bd87197aa9d72557cdbe93029..acb882f279cb9f5140a9c22b1de89831af6b729f 100644 (file)
@@ -352,6 +352,8 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
        umem->writable   = 1;
        umem->is_odp = 1;
        odp_data->per_mm = per_mm;
+       umem->owning_mm  = per_mm->mm;
+       mmgrab(umem->owning_mm);
 
        mutex_init(&odp_data->umem_mutex);
        init_completion(&odp_data->notifier_completion);
@@ -384,6 +386,7 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
 out_page_list:
        vfree(odp_data->page_list);
 out_odp_data:
+       mmdrop(umem->owning_mm);
        kfree(odp_data);
        return ERR_PTR(ret);
 }
index 6b12cc5f97b2520516fe25c4f4557479c0da083c..3317300ab0362b7ef245ab66e48945d0f67b4fb9 100644 (file)
@@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp,
 {
        int ret;
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+               return uverbs_copy_to_struct_or_zero(
+                       attrs, UVERBS_ATTR_CORE_OUT, resp, resp_len);
+
        if (copy_to_user(attrs->ucore.outbuf, resp,
                         min(attrs->ucore.outlen, resp_len)))
                return -EFAULT;
@@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
                goto out_put;
        }
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+               ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT);
+
        ret = 0;
 
 out_put:
@@ -2012,8 +2019,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
                return -ENOMEM;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp)
+       if (!qp) {
+               ret = -EINVAL;
                goto out;
+       }
 
        is_ud = qp->qp_type == IB_QPT_UD;
        sg_ind = 0;
index 8c81ff6980527663b68417a6b5c129ff40d81734..0ca04d2240157fc3f7cd41e7d164e500551cf400 100644 (file)
@@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
                           0, uattr->len - len);
 }
 
+static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
+                            const struct uverbs_attr *attr)
+{
+       struct bundle_priv *pbundle =
+               container_of(bundle, struct bundle_priv, bundle);
+       u16 flags;
+
+       flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
+               UVERBS_ATTR_F_VALID_OUTPUT;
+       if (put_user(flags,
+                    &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
+               return -EFAULT;
+       return 0;
+}
+
 static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
                                     const struct uverbs_api_attr *attr_uapi,
                                     struct uverbs_objs_arr_attr *attr,
@@ -455,6 +470,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
                ret = handler(&pbundle->bundle);
        }
 
+       /*
+        * Until the drivers are revised to use the bundle directly we have to
+        * assume that the driver wrote to its UHW_OUT and flag userspace
+        * appropriately.
+        */
+       if (!ret && pbundle->method_elm->has_udata) {
+               const struct uverbs_attr *attr =
+                       uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
+
+               if (!IS_ERR(attr))
+                       ret = uverbs_set_output(&pbundle->bundle, attr);
+       }
+
        /*
         * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
         * not invoke the method because the request is not supported.  No
@@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
 int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
                   const void *from, size_t size)
 {
-       struct bundle_priv *pbundle =
-               container_of(bundle, struct bundle_priv, bundle);
        const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
-       u16 flags;
        size_t min_size;
 
        if (IS_ERR(attr))
@@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
        if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
                return -EFAULT;
 
-       flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
-               UVERBS_ATTR_F_VALID_OUTPUT;
-       if (put_user(flags,
-                    &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
-               return -EFAULT;
-
-       return 0;
+       return uverbs_set_output(bundle, attr);
 }
 EXPORT_SYMBOL(uverbs_copy_to);
 
+
+/*
+ * This is only used if the caller has directly used copy_to_use to write the
+ * data.  It signals to user space that the buffer is filled in.
+ */
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx)
+{
+       const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
+
+       if (IS_ERR(attr))
+               return PTR_ERR(attr);
+
+       return uverbs_set_output(bundle, attr);
+}
+
 int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
                      size_t idx, s64 lower_bound, u64 upper_bound,
                      s64  *def_val)
@@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
 {
        const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
 
-       if (clear_user(u64_to_user_ptr(attr->ptr_attr.data),
-                      attr->ptr_attr.len))
-               return -EFAULT;
+       if (size < attr->ptr_attr.len) {
+               if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size,
+                              attr->ptr_attr.len - size))
+                       return -EFAULT;
+       }
        return uverbs_copy_to(bundle, idx, from, size);
 }
index fb0007aa0c27eb8dd279b58dfb4a40c5d51950d2..5f366838b7ff38805c715159eac6490b8c945ceb 100644 (file)
@@ -204,6 +204,9 @@ void ib_uverbs_release_file(struct kref *ref)
        if (atomic_dec_and_test(&file->device->refcount))
                ib_uverbs_comp_dev(file->device);
 
+       if (file->async_file)
+               kref_put(&file->async_file->ref,
+                        ib_uverbs_release_async_event_file);
        put_device(&file->device->dev);
        kfree(file);
 }
@@ -690,6 +693,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 
        buf += sizeof(hdr);
 
+       memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
        bundle.ufile = file;
        if (!method_elm->is_ex) {
                size_t in_len = hdr.in_words * 4 - sizeof(hdr);
@@ -963,11 +967,19 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 
                /* Get an arbitrary mm pointer that hasn't been cleaned yet */
                mutex_lock(&ufile->umap_lock);
-               if (!list_empty(&ufile->umaps)) {
-                       mm = list_first_entry(&ufile->umaps,
-                                             struct rdma_umap_priv, list)
-                                    ->vma->vm_mm;
-                       mmget(mm);
+               while (!list_empty(&ufile->umaps)) {
+                       int ret;
+
+                       priv = list_first_entry(&ufile->umaps,
+                                               struct rdma_umap_priv, list);
+                       mm = priv->vma->vm_mm;
+                       ret = mmget_not_zero(mm);
+                       if (!ret) {
+                               list_del_init(&priv->list);
+                               mm = NULL;
+                               continue;
+                       }
+                       break;
                }
                mutex_unlock(&ufile->umap_lock);
                if (!mm)
@@ -1095,10 +1107,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
        list_del_init(&file->list);
        mutex_unlock(&file->device->lists_mutex);
 
-       if (file->async_file)
-               kref_put(&file->async_file->ref,
-                        ib_uverbs_release_async_event_file);
-
        kref_put(&file->ref, ib_uverbs_release_file);
 
        return 0;
index 5030ec480370cd3ebc5c79c5c83c60c84097ca5c..2a3f2f01028d3f16964424a4fecb8cacbbb2debb 100644 (file)
@@ -168,12 +168,18 @@ void copy_port_attr_to_resp(struct ib_port_attr *attr,
 static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)(
        struct uverbs_attr_bundle *attrs)
 {
-       struct ib_device *ib_dev = attrs->ufile->device->ib_dev;
+       struct ib_device *ib_dev;
        struct ib_port_attr attr = {};
        struct ib_uverbs_query_port_resp_ex resp = {};
+       struct ib_ucontext *ucontext;
        int ret;
        u8 port_num;
 
+       ucontext = ib_uverbs_get_ucontext(attrs);
+       if (IS_ERR(ucontext))
+               return PTR_ERR(ucontext);
+       ib_dev = ucontext->device;
+
        /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
        if (!ib_dev->ops.query_port)
                return -EOPNOTSUPP;
index c22ebc774a6a40add10f6c160545e784b3f79944..f9a7e9d29c8ba2aeff77d3bb2c2f72b398e427da 100644 (file)
@@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
                vmf = 1;
                break;
        case STATUS:
-               if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
+               if (flags & VM_WRITE) {
                        ret = -EPERM;
                        goto done;
                }
index 88242fe95eaae89f58c98882c80abd32d8ac7c3f..bf96067876c92f6576858fc9c0be544c1293b9bb 100644 (file)
@@ -987,7 +987,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
            opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
                wc.ex.imm_data = packet->ohdr->u.ud.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
-               tlen -= sizeof(u32);
        } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
                wc.ex.imm_data = 0;
                wc.wc_flags = 0;
index 960b1946c3650312322644501ce0f5485df38050..12deacf442cff379d25ba3408f16245510596046 100644 (file)
@@ -210,6 +210,7 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
                                   struct ib_udata *udata)
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
+       struct hns_roce_ib_create_srq_resp resp = {};
        struct hns_roce_srq *srq;
        int srq_desc_size;
        int srq_buf_size;
@@ -378,16 +379,21 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
 
        srq->event = hns_roce_ib_srq_event;
        srq->ibsrq.ext.xrc.srq_num = srq->srqn;
+       resp.srqn = srq->srqn;
 
        if (udata) {
-               if (ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) {
+               if (ib_copy_to_udata(udata, &resp,
+                                    min(udata->outlen, sizeof(resp)))) {
                        ret = -EFAULT;
-                       goto err_wrid;
+                       goto err_srqc_alloc;
                }
        }
 
        return &srq->ibsrq;
 
+err_srqc_alloc:
+       hns_roce_srq_free(hr_dev, srq);
+
 err_wrid:
        kvfree(srq->wrid);
 
index 25439da8976c749c4ba553eff30375b138106f9d..936ee1314bcd1470b7671dccd1210110b8df7750 100644 (file)
@@ -1411,7 +1411,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
 
        sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
        if (sqp->tx_ring[wire_tx_ix].ah)
-               rdma_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
+               mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
        sqp->tx_ring[wire_tx_ix].ah = ah;
        ib_dma_sync_single_for_cpu(&dev->ib_dev,
                                   sqp->tx_ring[wire_tx_ix].buf.map,
@@ -1902,7 +1902,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
                if (wc.status == IB_WC_SUCCESS) {
                        switch (wc.opcode) {
                        case IB_WC_SEND:
-                               rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+                               mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
                                              (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
                                sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
                                        = NULL;
@@ -1931,7 +1931,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
                                 " status = %d, wrid = 0x%llx\n",
                                 ctx->slave, wc.status, wc.wr_id);
                        if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
-                               rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+                               mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
                                              (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
                                sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
                                        = NULL;
index e8a1e4498e3ff3147e9f8530cbc079b6ef7a4f43..798591a184848590a91c540f70acf8618d29a31f 100644 (file)
@@ -630,8 +630,7 @@ const struct uapi_definition mlx5_ib_flow_defs[] = {
                UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
        UAPI_DEF_CHAIN_OBJ_TREE(
                UVERBS_OBJECT_FLOW,
-               &mlx5_ib_fs,
-               UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
+               &mlx5_ib_fs),
        UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
                                &mlx5_ib_flow_actions),
        {},
index 01e0f62006314f63b5cda5580366cdeb16f1736e..4ee32964e1dd9cf7f8ce5094fdd8673c98af714a 100644 (file)
@@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
        struct prefetch_mr_work *w =
                container_of(work, struct prefetch_mr_work, work);
 
-       if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED)
+       if (ib_device_try_get(&w->dev->ib_dev)) {
                mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
                                         w->num_sge);
-
+               ib_device_put(&w->dev->ib_dev);
+       }
+       put_device(&w->dev->ib_dev.dev);
        kfree(w);
 }
 
@@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
                return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
                                                num_sge);
 
-       if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
-               return -ENODEV;
-
        work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
        if (!work)
                return -ENOMEM;
 
        memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
 
+       get_device(&dev->ib_dev.dev);
        work->dev = dev;
        work->pf_flags = pf_flags;
        work->num_sge = num_sge;
index dd2ae640bc848add5f316d2285b497347e6d69ea..7db778d96ef5c96a4a866005f17ff304e9a3257f 100644 (file)
@@ -1912,14 +1912,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
                }
 
                if (!check_flags_mask(ucmd.flags,
+                                     MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
+                                     MLX5_QP_FLAG_BFREG_INDEX |
+                                     MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE |
+                                     MLX5_QP_FLAG_SCATTER_CQE |
                                      MLX5_QP_FLAG_SIGNATURE |
-                                             MLX5_QP_FLAG_SCATTER_CQE |
-                                             MLX5_QP_FLAG_TUNNEL_OFFLOADS |
-                                             MLX5_QP_FLAG_BFREG_INDEX |
-                                             MLX5_QP_FLAG_TYPE_DCT |
-                                             MLX5_QP_FLAG_TYPE_DCI |
-                                             MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
-                                             MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE))
+                                     MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC |
+                                     MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC |
+                                     MLX5_QP_FLAG_TUNNEL_OFFLOADS |
+                                     MLX5_QP_FLAG_TYPE_DCI |
+                                     MLX5_QP_FLAG_TYPE_DCT))
                        return -EINVAL;
 
                err = get_qp_user_index(to_mucontext(pd->uobject->context),
index 82cb6b71ac7c8328425ddac92ae84f30b67d9e2d..e3e9dd54caa2b453fb6cb2b164e4b6e59492e7b6 100644 (file)
@@ -534,7 +534,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
        {
                struct mthca_ucontext *context;
 
-               qp = kmalloc(sizeof *qp, GFP_KERNEL);
+               qp = kzalloc(sizeof(*qp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
@@ -600,7 +600,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
                if (udata)
                        return ERR_PTR(-EINVAL);
 
-               qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
+               qp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
index 868da0ece7ba6bd3a06684d267084d941a32eb0a..445ea19a2ec83c3412ed7ab27ae5995c4c2e5f5d 100644 (file)
@@ -512,7 +512,6 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr,
            opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
                wc.ex.imm_data = ohdr->u.ud.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
-               tlen -= sizeof(u32);
        } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
                wc.ex.imm_data = 0;
                wc.wc_flags = 0;
index 42b8685c997eb9b5dd59397e094ec84e5bce1bcb..3c633ab58052847e4ba05da464f420a937750c2f 100644 (file)
@@ -427,7 +427,40 @@ static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state)
 
 static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op)
 {
-       return (enum pvrdma_wr_opcode)op;
+       switch (op) {
+       case IB_WR_RDMA_WRITE:
+               return PVRDMA_WR_RDMA_WRITE;
+       case IB_WR_RDMA_WRITE_WITH_IMM:
+               return PVRDMA_WR_RDMA_WRITE_WITH_IMM;
+       case IB_WR_SEND:
+               return PVRDMA_WR_SEND;
+       case IB_WR_SEND_WITH_IMM:
+               return PVRDMA_WR_SEND_WITH_IMM;
+       case IB_WR_RDMA_READ:
+               return PVRDMA_WR_RDMA_READ;
+       case IB_WR_ATOMIC_CMP_AND_SWP:
+               return PVRDMA_WR_ATOMIC_CMP_AND_SWP;
+       case IB_WR_ATOMIC_FETCH_AND_ADD:
+               return PVRDMA_WR_ATOMIC_FETCH_AND_ADD;
+       case IB_WR_LSO:
+               return PVRDMA_WR_LSO;
+       case IB_WR_SEND_WITH_INV:
+               return PVRDMA_WR_SEND_WITH_INV;
+       case IB_WR_RDMA_READ_WITH_INV:
+               return PVRDMA_WR_RDMA_READ_WITH_INV;
+       case IB_WR_LOCAL_INV:
+               return PVRDMA_WR_LOCAL_INV;
+       case IB_WR_REG_MR:
+               return PVRDMA_WR_FAST_REG_MR;
+       case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
+               return PVRDMA_WR_MASKED_ATOMIC_CMP_AND_SWP;
+       case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
+               return PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD;
+       case IB_WR_REG_SIG_MR:
+               return PVRDMA_WR_REG_SIG_MR;
+       default:
+               return PVRDMA_WR_ERROR;
+       }
 }
 
 static inline enum ib_wc_status pvrdma_wc_status_to_ib(
index 3acf74cbe2663c70156dc31659a2bd345c2f8ffd..1ec3646087ba6a121c29b54f2d481226ee3b2352 100644 (file)
@@ -721,6 +721,12 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
                    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
                        wqe_hdr->ex.imm_data = wr->ex.imm_data;
 
+               if (unlikely(wqe_hdr->opcode == PVRDMA_WR_ERROR)) {
+                       *bad_wr = wr;
+                       ret = -EINVAL;
+                       goto out;
+               }
+
                switch (qp->ibqp.qp_type) {
                case IB_QPT_GSI:
                case IB_QPT_UD:
index a1bd8cfc2c2565dfc8edbaa9b07a7fc43735e522..c6cc3e4ab71dc02adf0480a9c2d6ab1a33c97f02 100644 (file)
@@ -2910,6 +2910,8 @@ void rvt_ruc_loopback(struct rvt_qp *sqp)
                        goto op_err;
                if (!ret)
                        goto rnr_nak;
+               if (wqe->length > qp->r_len)
+                       goto inv_err;
                break;
 
        case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -3078,7 +3080,10 @@ void rvt_ruc_loopback(struct rvt_qp *sqp)
        goto err;
 
 inv_err:
-       send_status = IB_WC_REM_INV_REQ_ERR;
+       send_status =
+               sqp->ibqp.qp_type == IB_QPT_RC ?
+                       IB_WC_REM_INV_REQ_ERR :
+                       IB_WC_SUCCESS;
        wc.status = IB_WC_LOC_QP_OP_ERR;
        goto err;
 
index 1da119d901a90784fb083be135fde36ffcf0c71f..73e808c1e6adacfdfdc61a9bc85d9a350e7edaaa 100644 (file)
@@ -248,7 +248,6 @@ struct ipoib_cm_tx {
        struct list_head     list;
        struct net_device   *dev;
        struct ipoib_neigh  *neigh;
-       struct ipoib_path   *path;
        struct ipoib_tx_buf *tx_ring;
        unsigned int         tx_head;
        unsigned int         tx_tail;
index 0428e01e8f691d691bc153cdce52f454ec5d8e7c..aa9dcfc36cd35b81b9ad961f13c5e7303467ad5e 100644 (file)
@@ -1312,7 +1312,6 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path
 
        neigh->cm = tx;
        tx->neigh = neigh;
-       tx->path = path;
        tx->dev = dev;
        list_add(&tx->list, &priv->cm.start_list);
        set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
@@ -1371,7 +1370,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
                                neigh->daddr + QPN_AND_OPTIONS_OFFSET);
                        goto free_neigh;
                }
-               memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec));
+               memcpy(&pathrec, &path->pathrec, sizeof(pathrec));
 
                spin_unlock_irqrestore(&priv->lock, flags);
                netif_tx_unlock_bh(dev);
index cfc8b94527b97cda3f4b20782af0fbc2b6260f2b..aa4e431cbcd3543ebd617eb4c7a880868eb3f723 100644 (file)
@@ -252,6 +252,8 @@ static const struct xpad_device {
        { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
        { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
+       { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
+       { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
        { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
        { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
@@ -428,6 +430,7 @@ static const struct usb_device_id xpad_table[] = {
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f X-Box One controllers */
        XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
        XPAD_XBOXONE_VENDOR(0x0f0d),            /* Hori Controllers */
+       XPAD_XBOX360_VENDOR(0x1038),            /* SteelSeries Controllers */
        XPAD_XBOX360_VENDOR(0x11c9),            /* Nacon GC100XF */
        XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
index 4713957b0cbba11e942a01c2b2138854d648637f..a878351f16439859e3931ec71506c705eb9a6f6e 100644 (file)
@@ -420,7 +420,7 @@ config KEYBOARD_MPR121
 
 config KEYBOARD_SNVS_PWRKEY
        tristate "IMX SNVS Power Key Driver"
-       depends on SOC_IMX6SX
+       depends on SOC_IMX6SX || SOC_IMX7D
        depends on OF
        help
          This is the snvs powerkey driver for the Freescale i.MX application
index 312916f99597ad5dc6949296edc7b42cd459f9b8..73686c2460ce2e94e9fe757a5ad6e49852fd5170 100644 (file)
@@ -75,9 +75,7 @@
 struct cap11xx_led {
        struct cap11xx_priv *priv;
        struct led_classdev cdev;
-       struct work_struct work;
        u32 reg;
-       enum led_brightness new_brightness;
 };
 #endif
 
@@ -233,30 +231,21 @@ static void cap11xx_input_close(struct input_dev *idev)
 }
 
 #ifdef CONFIG_LEDS_CLASS
-static void cap11xx_led_work(struct work_struct *work)
+static int cap11xx_led_set(struct led_classdev *cdev,
+                           enum led_brightness value)
 {
-       struct cap11xx_led *led = container_of(work, struct cap11xx_led, work);
+       struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
        struct cap11xx_priv *priv = led->priv;
-       int value = led->new_brightness;
 
        /*
-        * All LEDs share the same duty cycle as this is a HW limitation.
-        * Brightness levels per LED are either 0 (OFF) and 1 (ON).
+        * All LEDs share the same duty cycle as this is a HW
+        * limitation. Brightness levels per LED are either
+        * 0 (OFF) and 1 (ON).
         */
-       regmap_update_bits(priv->regmap, CAP11XX_REG_LED_OUTPUT_CONTROL,
-                               BIT(led->reg), value ? BIT(led->reg) : 0);
-}
-
-static void cap11xx_led_set(struct led_classdev *cdev,
-                          enum led_brightness value)
-{
-       struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
-
-       if (led->new_brightness == value)
-               return;
-
-       led->new_brightness = value;
-       schedule_work(&led->work);
+       return regmap_update_bits(priv->regmap,
+                                 CAP11XX_REG_LED_OUTPUT_CONTROL,
+                                 BIT(led->reg),
+                                 value ? BIT(led->reg) : 0);
 }
 
 static int cap11xx_init_leds(struct device *dev,
@@ -299,7 +288,7 @@ static int cap11xx_init_leds(struct device *dev,
                led->cdev.default_trigger =
                        of_get_property(child, "linux,default-trigger", NULL);
                led->cdev.flags = 0;
-               led->cdev.brightness_set = cap11xx_led_set;
+               led->cdev.brightness_set_blocking = cap11xx_led_set;
                led->cdev.max_brightness = 1;
                led->cdev.brightness = LED_OFF;
 
@@ -312,8 +301,6 @@ static int cap11xx_init_leds(struct device *dev,
                led->reg = reg;
                led->priv = priv;
 
-               INIT_WORK(&led->work, cap11xx_led_work);
-
                error = devm_led_classdev_register(dev, &led->cdev);
                if (error) {
                        of_node_put(child);
index 403452ef00e6f257d67ca44bdf5626b0e5cc53a4..3d1cb7bf5e35feba1b355cef7e81c657db97be07 100644 (file)
@@ -222,7 +222,7 @@ static void matrix_keypad_stop(struct input_dev *dev)
        keypad->stopped = true;
        spin_unlock_irq(&keypad->lock);
 
-       flush_work(&keypad->work.work);
+       flush_delayed_work(&keypad->work);
        /*
         * matrix_keypad_scan() will leave IRQs enabled;
         * we should disable them now.
index 43b86482dda01b51c1d4ff38353756cd75bcfc5b..d466bc07aebb2b3de14fd6994d7bd3c15c6807ee 100644 (file)
@@ -58,10 +58,9 @@ static unsigned char qt2160_key2code[] = {
 struct qt2160_led {
        struct qt2160_data *qt2160;
        struct led_classdev cdev;
-       struct work_struct work;
        char name[32];
        int id;
-       enum led_brightness new_brightness;
+       enum led_brightness brightness;
 };
 #endif
 
@@ -74,7 +73,6 @@ struct qt2160_data {
        u16 key_matrix;
 #ifdef CONFIG_LEDS_CLASS
        struct qt2160_led leds[QT2160_NUM_LEDS_X];
-       struct mutex led_lock;
 #endif
 };
 
@@ -83,46 +81,39 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
 
 #ifdef CONFIG_LEDS_CLASS
 
-static void qt2160_led_work(struct work_struct *work)
+static int qt2160_led_set(struct led_classdev *cdev,
+                         enum led_brightness value)
 {
-       struct qt2160_led *led = container_of(work, struct qt2160_led, work);
+       struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
        struct qt2160_data *qt2160 = led->qt2160;
        struct i2c_client *client = qt2160->client;
-       int value = led->new_brightness;
        u32 drive, pwmen;
 
-       mutex_lock(&qt2160->led_lock);
-
-       drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
-       pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
-       if (value != LED_OFF) {
-               drive |= (1 << led->id);
-               pwmen |= (1 << led->id);
-
-       } else {
-               drive &= ~(1 << led->id);
-               pwmen &= ~(1 << led->id);
-       }
-       qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
-       qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
+       if (value != led->brightness) {
+               drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
+               pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
+               if (value != LED_OFF) {
+                       drive |= BIT(led->id);
+                       pwmen |= BIT(led->id);
 
-       /*
-        * Changing this register will change the brightness
-        * of every LED in the qt2160. It's a HW limitation.
-        */
-       if (value != LED_OFF)
-               qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
+               } else {
+                       drive &= ~BIT(led->id);
+                       pwmen &= ~BIT(led->id);
+               }
+               qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
+               qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
 
-       mutex_unlock(&qt2160->led_lock);
-}
+               /*
+                * Changing this register will change the brightness
+                * of every LED in the qt2160. It's a HW limitation.
+                */
+               if (value != LED_OFF)
+                       qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
 
-static void qt2160_led_set(struct led_classdev *cdev,
-                          enum led_brightness value)
-{
-       struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
+               led->brightness = value;
+       }
 
-       led->new_brightness = value;
-       schedule_work(&led->work);
+       return 0;
 }
 
 #endif /* CONFIG_LEDS_CLASS */
@@ -293,20 +284,16 @@ static int qt2160_register_leds(struct qt2160_data *qt2160)
        int ret;
        int i;
 
-       mutex_init(&qt2160->led_lock);
-
        for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
                struct qt2160_led *led = &qt2160->leds[i];
 
                snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
                led->cdev.name = led->name;
-               led->cdev.brightness_set = qt2160_led_set;
+               led->cdev.brightness_set_blocking = qt2160_led_set;
                led->cdev.brightness = LED_OFF;
                led->id = i;
                led->qt2160 = qt2160;
 
-               INIT_WORK(&led->work, qt2160_led_work);
-
                ret = led_classdev_register(&client->dev, &led->cdev);
                if (ret < 0)
                        return ret;
@@ -324,10 +311,8 @@ static void qt2160_unregister_leds(struct qt2160_data *qt2160)
 {
        int i;
 
-       for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
+       for (i = 0; i < QT2160_NUM_LEDS_X; i++)
                led_classdev_unregister(&qt2160->leds[i].cdev);
-               cancel_work_sync(&qt2160->leds[i].work);
-       }
 }
 
 #else
index babcfb165e4f0060c854ee524582b3ec436e8978..3b85631fde9182931a1a5f3a43cf2ec64d52dbb9 100644 (file)
@@ -153,6 +153,8 @@ static int keyscan_probe(struct platform_device *pdev)
 
        input_dev->id.bustype = BUS_HOST;
 
+       keypad_data->input_dev = input_dev;
+
        error = keypad_matrix_key_parse_dt(keypad_data);
        if (error)
                return error;
@@ -168,8 +170,6 @@ static int keyscan_probe(struct platform_device *pdev)
 
        input_set_drvdata(input_dev, keypad_data);
 
-       keypad_data->input_dev = input_dev;
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(keypad_data->base))
index 094bddf56755f11310ee18c6eb5fda33242f57ff..c1e66f45d552a3b64058611bbc8e18c741f6aad9 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/input-polldev.h>
 #include <linux/i2c.h>
-#include <linux/workqueue.h>
 #include <linux/leds.h>
 
 #define APANEL_NAME    "Fujitsu Application Panel"
@@ -59,8 +58,6 @@ struct apanel {
        struct i2c_client *client;
        unsigned short keymap[MAX_PANEL_KEYS];
        u16    nkeys;
-       u16    led_bits;
-       struct work_struct led_work;
        struct led_classdev mail_led;
 };
 
@@ -109,25 +106,13 @@ static void apanel_poll(struct input_polled_dev *ipdev)
                        report_key(idev, ap->keymap[i]);
 }
 
-/* Track state changes of LED */
-static void led_update(struct work_struct *work)
-{
-       struct apanel *ap = container_of(work, struct apanel, led_work);
-
-       i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits);
-}
-
-static void mail_led_set(struct led_classdev *led,
+static int mail_led_set(struct led_classdev *led,
                         enum led_brightness value)
 {
        struct apanel *ap = container_of(led, struct apanel, mail_led);
+       u16 led_bits = value != LED_OFF ? 0x8000 : 0x0000;
 
-       if (value != LED_OFF)
-               ap->led_bits |= 0x8000;
-       else
-               ap->led_bits &= ~0x8000;
-
-       schedule_work(&ap->led_work);
+       return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
 }
 
 static int apanel_remove(struct i2c_client *client)
@@ -179,7 +164,7 @@ static struct apanel apanel = {
        },
        .mail_led = {
                .name = "mail:blue",
-               .brightness_set = mail_led_set,
+               .brightness_set_blocking = mail_led_set,
        },
 };
 
@@ -235,7 +220,6 @@ static int apanel_probe(struct i2c_client *client,
        if (err)
                goto out3;
 
-       INIT_WORK(&ap->led_work, led_update);
        if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
                err = led_classdev_register(&client->dev, &ap->mail_led);
                if (err)
index 1efcfdf9f8a84c89ab0e1a8d5729046473b79ed7..dd9dd4e4082718f43b923ff8ad984b148a15ee29 100644 (file)
@@ -481,13 +481,14 @@ static int bma150_register_input_device(struct bma150_data *bma150)
        idev->close = bma150_irq_close;
        input_set_drvdata(idev, bma150);
 
+       bma150->input = idev;
+
        error = input_register_device(idev);
        if (error) {
                input_free_device(idev);
                return error;
        }
 
-       bma150->input = idev;
        return 0;
 }
 
@@ -510,15 +511,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
 
        bma150_init_input_device(bma150, ipoll_dev->input);
 
+       bma150->input_polled = ipoll_dev;
+       bma150->input = ipoll_dev->input;
+
        error = input_register_polled_device(ipoll_dev);
        if (error) {
                input_free_polled_device(ipoll_dev);
                return error;
        }
 
-       bma150->input_polled = ipoll_dev;
-       bma150->input = ipoll_dev->input;
-
        return 0;
 }
 
index 55da191ae550743edf6505a01cc3af53404910a9..dbb6d9e1b9471380b50d66af222c89c75d472ac5 100644 (file)
@@ -34,6 +34,7 @@ struct pwm_vibrator {
        struct work_struct play_work;
        u16 level;
        u32 direction_duty_cycle;
+       bool vcc_on;
 };
 
 static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
@@ -42,10 +43,13 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
        struct pwm_state state;
        int err;
 
-       err = regulator_enable(vibrator->vcc);
-       if (err) {
-               dev_err(pdev, "failed to enable regulator: %d", err);
-               return err;
+       if (!vibrator->vcc_on) {
+               err = regulator_enable(vibrator->vcc);
+               if (err) {
+                       dev_err(pdev, "failed to enable regulator: %d", err);
+                       return err;
+               }
+               vibrator->vcc_on = true;
        }
 
        pwm_get_state(vibrator->pwm, &state);
@@ -76,11 +80,14 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
 
 static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
 {
-       regulator_disable(vibrator->vcc);
-
        if (vibrator->pwm_dir)
                pwm_disable(vibrator->pwm_dir);
        pwm_disable(vibrator->pwm);
+
+       if (vibrator->vcc_on) {
+               regulator_disable(vibrator->vcc);
+               vibrator->vcc_on = false;
+       }
 }
 
 static void pwm_vibrator_play_work(struct work_struct *work)
index 8ec483e8688be194078d07f3b47fa40d7f75e9ac..26ec603fe2208522bf562954e452d69e2500527a 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/overflow.h>
 #include <linux/input/mt.h>
 #include "../input-compat.h"
 
@@ -405,7 +406,7 @@ static int uinput_open(struct inode *inode, struct file *file)
 static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
                                   const struct input_absinfo *abs)
 {
-       int min, max;
+       int min, max, range;
 
        min = abs->minimum;
        max = abs->maximum;
@@ -417,7 +418,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
                return -EINVAL;
        }
 
-       if (abs->flat > max - min) {
+       if (!check_sub_overflow(max, min, &range) && abs->flat > range) {
                printk(KERN_DEBUG
                       "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
                       UINPUT_NAME, code, abs->flat, min, max);
index f322a1768fbb5537f4c3523c7a2fcb220277b90a..225ae6980182f778c2987827952afc668afb021f 100644 (file)
@@ -1336,7 +1336,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
 static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0000", 0 },
        { "ELAN0100", 0 },
-       { "ELAN0501", 0 },
        { "ELAN0600", 0 },
        { "ELAN0602", 0 },
        { "ELAN0605", 0 },
@@ -1346,6 +1345,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN060C", 0 },
        { "ELAN0611", 0 },
        { "ELAN0612", 0 },
+       { "ELAN0617", 0 },
        { "ELAN0618", 0 },
        { "ELAN061C", 0 },
        { "ELAN061D", 0 },
index 9fe075c137dc41bb513060d5b69871ed922e493f..a7f8b16145595bd004b5fec8fdf27e2d6cf7f441 100644 (file)
@@ -1119,6 +1119,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu CELSIUS H760    0x570f02        40, 14, 0c      3 hw buttons (**)
+ * Fujitsu CELSIUS H780    0x5d0f02        41, 16, 0d      3 hw buttons (**)
  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E546   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
@@ -1171,6 +1173,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
                },
        },
+       {
+               /* Fujitsu H780 also has a middle button */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"),
+               },
+       },
 #endif
        { }
 };
index b36084710f696626b3f9a595f22c357169a30fdf..a7cfab3db9ee4b344f5e4c64316d8baaf6c6522a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 
 /*
  * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller.
@@ -75,7 +74,6 @@ struct olpc_apsp {
        struct serio *kbio;
        struct serio *padio;
        void __iomem *base;
-       struct clk *clk;
        int open_count;
        int irq;
 };
@@ -148,17 +146,11 @@ static int olpc_apsp_open(struct serio *port)
        struct olpc_apsp *priv = port->port_data;
        unsigned int tmp;
        unsigned long l;
-       int error;
 
        if (priv->open_count++ == 0) {
-               error = clk_prepare_enable(priv->clk);
-               if (error)
-                       return error;
-
                l = readl(priv->base + COMMAND_FIFO_STATUS);
                if (!(l & CMD_STS_MASK)) {
                        dev_err(priv->dev, "SP cannot accept commands.\n");
-                       clk_disable_unprepare(priv->clk);
                        return -EIO;
                }
 
@@ -179,8 +171,6 @@ static void olpc_apsp_close(struct serio *port)
                /* Disable interrupt 0 */
                tmp = readl(priv->base + PJ_INTERRUPT_MASK);
                writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
-
-               clk_disable_unprepare(priv->clk);
        }
 }
 
@@ -195,6 +185,8 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       priv->dev = &pdev->dev;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->base)) {
@@ -206,10 +198,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (priv->irq < 0)
                return priv->irq;
 
-       priv->clk = devm_clk_get(&pdev->dev, "sp");
-       if (IS_ERR(priv->clk))
-               return PTR_ERR(priv->clk);
-
        /* KEYBOARD */
        kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (!kb_serio)
@@ -248,7 +236,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       priv->dev = &pdev->dev;
        device_init_wakeup(priv->dev, 1);
        platform_set_drvdata(pdev, priv);
 
index c62cceb97bb15bc9ff172a51757ea88673226bde..5e8d8384aa2a5da4508f789f96a23ddd3cbde425 100644 (file)
@@ -76,6 +76,7 @@ static void ps2_gpio_close(struct serio *serio)
 {
        struct ps2_gpio_data *drvdata = serio->port_data;
 
+       flush_delayed_work(&drvdata->tx_work);
        disable_irq(drvdata->irq);
 }
 
index af6027cc7bbfae2687c1524ee6265c53f6feb39b..068dbbc610fce4d8c9f79c7a9466cd39614ed625 100644 (file)
@@ -698,7 +698,7 @@ config TOUCHSCREEN_EDT_FT5X06
 
 config TOUCHSCREEN_RASPBERRYPI_FW
        tristate "Raspberry Pi's firmware base touch screen support"
-       depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+       depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST)
        help
          Say Y here if you have the official Raspberry Pi 7 inch screen on
          your system.
index 87ba23a75b381ff245690a1106ddf190b0b327f7..2a7b78bb98b43a7b8ed9ede772d1f15f706afb99 100644 (file)
@@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+       struct protection_domain *domain = dev_data->domain;
        struct amd_iommu *iommu;
        u16 alias;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        alias = dev_data->alias;
 
-       /* decrease reference counters */
-       dev_data->domain->dev_iommu[iommu->index] -= 1;
-       dev_data->domain->dev_cnt                 -= 1;
-
        /* Update data structures */
        dev_data->domain = NULL;
        list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
        /* Flush the DTE entry */
        device_flush_dte(dev_data);
+
+       /* Flush IOTLB */
+       domain_flush_tlb_pde(domain);
+
+       /* Wait for the flushes to finish */
+       domain_flush_complete(domain);
+
+       /* decrease reference counters - needs to happen after the flushes */
+       domain->dev_iommu[iommu->index] -= 1;
+       domain->dev_cnt                 -= 1;
 }
 
 /*
@@ -2617,13 +2624,13 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
                        bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
                        iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-                       if (--mapped_pages)
+                       if (--mapped_pages == 0)
                                goto out_free_iova;
                }
        }
 
 out_free_iova:
-       free_iova_fast(&dma_dom->iovad, address, npages);
+       free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
        return 0;
index 2bd9ac285c0dee363fe9b9feecf2f9082e49ebbe..78188bf7e90d7a42f6dbc263f2e412c77de92e0c 100644 (file)
@@ -363,7 +363,7 @@ static int dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
 static int intel_iommu_superpage = 1;
-static int intel_iommu_sm = 1;
+static int intel_iommu_sm;
 static int iommu_identity_mapping;
 
 #define IDENTMAP_ALL           1
@@ -456,9 +456,9 @@ static int __init intel_iommu_setup(char *str)
                } else if (!strncmp(str, "sp_off", 6)) {
                        pr_info("Disable supported super page\n");
                        intel_iommu_superpage = 0;
-               } else if (!strncmp(str, "sm_off", 6)) {
-                       pr_info("Intel-IOMMU: disable scalable mode support\n");
-                       intel_iommu_sm = 0;
+               } else if (!strncmp(str, "sm_on", 5)) {
+                       pr_info("Intel-IOMMU: scalable mode supported\n");
+                       intel_iommu_sm = 1;
                } else if (!strncmp(str, "tboot_noforce", 13)) {
                        printk(KERN_INFO
                                "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
@@ -5294,7 +5294,7 @@ static void intel_iommu_put_resv_regions(struct device *dev,
        struct iommu_resv_region *entry, *next;
 
        list_for_each_entry_safe(entry, next, head, list) {
-               if (entry->type == IOMMU_RESV_RESERVED)
+               if (entry->type == IOMMU_RESV_MSI)
                        kfree(entry);
        }
 }
index 730f7dabcf37bf1495df35024c57d8117c964da1..7e0df67bd3e976077102ec659f4cb21d3a26652a 100644 (file)
@@ -441,6 +441,10 @@ static int mtk_iommu_add_device(struct device *dev)
                iommu_spec.args_count = count;
 
                mtk_iommu_create_mapping(dev, &iommu_spec);
+
+               /* dev->iommu_fwspec might have changed */
+               fwspec = dev_iommu_fwspec_get(dev);
+
                of_node_put(iommu_spec.np);
        }
 
index d8947b28db2d832523e91db80f7b7a57aa13064e..f04a6df65eb856db877859a06064aa8a182446fa 100644 (file)
@@ -224,7 +224,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
         * If we have reason to believe the IOMMU driver missed the initial
         * probe for dev, replay it to get things in order.
         */
-       if (dev->bus && !device_iommu_mapped(dev))
+       if (!err && dev->bus && !device_iommu_mapped(dev))
                err = iommu_probe_device(dev);
 
        /* Ignore all other errors apart from EPROBE_DEFER */
index db20e992a40f2b617c1c4d5858e4b1e0555ffbce..c3aba3fc818d3c190166e07c8179dee5832b46bc 100644 (file)
@@ -97,9 +97,14 @@ struct its_device;
  * The ITS structure - contains most of the infrastructure, with the
  * top-level MSI domain, the command queue, the collections, and the
  * list of devices writing to it.
+ *
+ * dev_alloc_lock has to be taken for device allocations, while the
+ * spinlock must be taken to parse data structures such as the device
+ * list.
  */
 struct its_node {
        raw_spinlock_t          lock;
+       struct mutex            dev_alloc_lock;
        struct list_head        entry;
        void __iomem            *base;
        phys_addr_t             phys_base;
@@ -156,6 +161,7 @@ struct its_device {
        void                    *itt;
        u32                     nr_ites;
        u32                     device_id;
+       bool                    shared;
 };
 
 static struct {
@@ -1580,6 +1586,9 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
                nr_irqs /= 2;
        } while (nr_irqs > 0);
 
+       if (!nr_irqs)
+               err = -ENOSPC;
+
        if (err)
                goto out;
 
@@ -2059,6 +2068,29 @@ static int __init allocate_lpi_tables(void)
        return 0;
 }
 
+static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
+{
+       u32 count = 1000000;    /* 1s! */
+       bool clean;
+       u64 val;
+
+       val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+       val &= ~GICR_VPENDBASER_Valid;
+       gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+
+       do {
+               val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+               clean = !(val & GICR_VPENDBASER_Dirty);
+               if (!clean) {
+                       count--;
+                       cpu_relax();
+                       udelay(1);
+               }
+       } while (!clean && count);
+
+       return val;
+}
+
 static void its_cpu_init_lpis(void)
 {
        void __iomem *rbase = gic_data_rdist_rd_base();
@@ -2144,6 +2176,30 @@ static void its_cpu_init_lpis(void)
        val |= GICR_CTLR_ENABLE_LPIS;
        writel_relaxed(val, rbase + GICR_CTLR);
 
+       if (gic_rdists->has_vlpis) {
+               void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+
+               /*
+                * It's possible for CPU to receive VLPIs before it is
+                * sheduled as a vPE, especially for the first CPU, and the
+                * VLPI with INTID larger than 2^(IDbits+1) will be considered
+                * as out of range and dropped by GIC.
+                * So we initialize IDbits to known value to avoid VLPI drop.
+                */
+               val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
+               pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n",
+                       smp_processor_id(), val);
+               gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
+
+               /*
+                * Also clear Valid bit of GICR_VPENDBASER, in case some
+                * ancient programming gets left in and has possibility of
+                * corrupting memory.
+                */
+               val = its_clear_vpend_valid(vlpi_base);
+               WARN_ON(val & GICR_VPENDBASER_Dirty);
+       }
+
        /* Make sure the GIC has seen the above */
        dsb(sy);
 out:
@@ -2399,13 +2455,14 @@ static void its_free_device(struct its_device *its_dev)
        kfree(its_dev);
 }
 
-static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
+static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
 {
        int idx;
 
-       idx = find_first_zero_bit(dev->event_map.lpi_map,
-                                 dev->event_map.nr_lpis);
-       if (idx == dev->event_map.nr_lpis)
+       idx = bitmap_find_free_region(dev->event_map.lpi_map,
+                                     dev->event_map.nr_lpis,
+                                     get_count_order(nvecs));
+       if (idx < 0)
                return -ENOSPC;
 
        *hwirq = dev->event_map.lpi_base + idx;
@@ -2421,6 +2478,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
        struct its_device *its_dev;
        struct msi_domain_info *msi_info;
        u32 dev_id;
+       int err = 0;
 
        /*
         * We ignore "dev" entierely, and rely on the dev_id that has
@@ -2443,6 +2501,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                return -EINVAL;
        }
 
+       mutex_lock(&its->dev_alloc_lock);
        its_dev = its_find_device(its, dev_id);
        if (its_dev) {
                /*
@@ -2450,18 +2509,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                 * another alias (PCI bridge of some sort). No need to
                 * create the device.
                 */
+               its_dev->shared = true;
                pr_debug("Reusing ITT for devID %x\n", dev_id);
                goto out;
        }
 
        its_dev = its_create_device(its, dev_id, nvec, true);
-       if (!its_dev)
-               return -ENOMEM;
+       if (!its_dev) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
 out:
+       mutex_unlock(&its->dev_alloc_lock);
        info->scratchpad[0].ptr = its_dev;
-       return 0;
+       return err;
 }
 
 static struct msi_domain_ops its_msi_domain_ops = {
@@ -2501,21 +2564,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
        int err;
        int i;
 
-       for (i = 0; i < nr_irqs; i++) {
-               err = its_alloc_device_irq(its_dev, &hwirq);
-               if (err)
-                       return err;
+       err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
+       if (err)
+               return err;
 
-               err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
+       for (i = 0; i < nr_irqs; i++) {
+               err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
                if (err)
                        return err;
 
                irq_domain_set_hwirq_and_chip(domain, virq + i,
-                                             hwirq, &its_irq_chip, its_dev);
+                                             hwirq + i, &its_irq_chip, its_dev);
                irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
                pr_debug("ID:%d pID:%d vID:%d\n",
-                        (int)(hwirq - its_dev->event_map.lpi_base),
-                        (int) hwirq, virq + i);
+                        (int)(hwirq + i - its_dev->event_map.lpi_base),
+                        (int)(hwirq + i), virq + i);
        }
 
        return 0;
@@ -2565,6 +2628,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 {
        struct irq_data *d = irq_domain_get_irq_data(domain, virq);
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+       struct its_node *its = its_dev->its;
        int i;
 
        for (i = 0; i < nr_irqs; i++) {
@@ -2579,8 +2643,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                irq_domain_reset_irq_data(data);
        }
 
-       /* If all interrupts have been freed, start mopping the floor */
-       if (bitmap_empty(its_dev->event_map.lpi_map,
+       mutex_lock(&its->dev_alloc_lock);
+
+       /*
+        * If all interrupts have been freed, start mopping the
+        * floor. This is conditionned on the device not being shared.
+        */
+       if (!its_dev->shared &&
+           bitmap_empty(its_dev->event_map.lpi_map,
                         its_dev->event_map.nr_lpis)) {
                its_lpi_free(its_dev->event_map.lpi_map,
                             its_dev->event_map.lpi_base,
@@ -2592,6 +2662,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                its_free_device(its_dev);
        }
 
+       mutex_unlock(&its->dev_alloc_lock);
+
        irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
@@ -2754,26 +2826,11 @@ static void its_vpe_schedule(struct its_vpe *vpe)
 static void its_vpe_deschedule(struct its_vpe *vpe)
 {
        void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
-       u32 count = 1000000;    /* 1s! */
-       bool clean;
        u64 val;
 
-       /* We're being scheduled out */
-       val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
-       val &= ~GICR_VPENDBASER_Valid;
-       gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
-
-       do {
-               val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
-               clean = !(val & GICR_VPENDBASER_Dirty);
-               if (!clean) {
-                       count--;
-                       cpu_relax();
-                       udelay(1);
-               }
-       } while (!clean && count);
+       val = its_clear_vpend_valid(vlpi_base);
 
-       if (unlikely(!clean && !count)) {
+       if (unlikely(val & GICR_VPENDBASER_Dirty)) {
                pr_err_ratelimited("ITS virtual pending table not cleaning\n");
                vpe->idai = false;
                vpe->pending_last = true;
@@ -3516,6 +3573,7 @@ static int __init its_probe_one(struct resource *res,
        }
 
        raw_spin_lock_init(&its->lock);
+       mutex_init(&its->dev_alloc_lock);
        INIT_LIST_HEAD(&its->entry);
        INIT_LIST_HEAD(&its->its_device_list);
        typer = gic_read_typer(its_base + GITS_TYPER);
index ad70e7c416e3014ca95d76e7e058cdec986c17ab..fbfa7ff6deb1644aa1fbec858a0567ada0d7cb44 100644 (file)
@@ -24,7 +24,7 @@ struct mbi_range {
        unsigned long           *bm;
 };
 
-static struct mutex            mbi_lock;
+static DEFINE_MUTEX(mbi_lock);
 static phys_addr_t             mbi_phys_base;
 static struct mbi_range                *mbi_ranges;
 static unsigned int            mbi_range_nr;
index e9256dee1a45d93a799fa31dab24b892ae7973e7..8b81271c823c69975d17bd74ea520cab11eb2299 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -16,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/irqchip/irq-madera.h>
 #include <linux/mfd/madera/core.h>
index 25f32e1d77647d0be5d8a59d3d214127ba05b9ac..3496b61a312aef87cc9668189fd9047a844e8ca3 100644 (file)
@@ -34,6 +34,9 @@
 #define SEL_INT_PENDING                (1 << 6)
 #define SEL_INT_NUM_MASK       0x3f
 
+#define MMP2_ICU_INT_ROUTE_PJ4_IRQ     (1 << 5)
+#define MMP2_ICU_INT_ROUTE_PJ4_FIQ     (1 << 6)
+
 struct icu_chip_data {
        int                     nr_irqs;
        unsigned int            virq_base;
@@ -190,7 +193,8 @@ static const struct mmp_intc_conf mmp_conf = {
 static const struct mmp_intc_conf mmp2_conf = {
        .conf_enable    = 0x20,
        .conf_disable   = 0x0,
-       .conf_mask      = 0x7f,
+       .conf_mask      = MMP2_ICU_INT_ROUTE_PJ4_IRQ |
+                         MMP2_ICU_INT_ROUTE_PJ4_FIQ,
 };
 
 static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
index 6edfd4bfa169ecbf488c897154d5e7000a9c5581..a93296b9b45debecfb723e780f3f381b15660d2e 100644 (file)
@@ -822,6 +822,7 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
 static const struct irq_domain_ops stm32_exti_h_domain_ops = {
        .alloc  = stm32_exti_h_domain_alloc,
        .free   = irq_domain_free_irqs_common,
+       .xlate = irq_domain_xlate_twocell,
 };
 
 static int
index 5385f5768345ef3aa22bdeed8bd22195469d2f9d..27933338f7b363d8d0061b86acbe260e688a4ce6 100644 (file)
@@ -71,14 +71,17 @@ static void xtensa_mx_irq_mask(struct irq_data *d)
        unsigned int mask = 1u << d->hwirq;
 
        if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
-                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
-               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
-                                       HW_IRQ_MX_BASE), MIENG);
-       } else {
-               mask = __this_cpu_read(cached_irq_mask) & ~mask;
-               __this_cpu_write(cached_irq_mask, mask);
-               xtensa_set_sr(mask, intenable);
+                   XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+               if (ext_irq >= HW_IRQ_MX_BASE) {
+                       set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENG);
+                       return;
+               }
        }
+       mask = __this_cpu_read(cached_irq_mask) & ~mask;
+       __this_cpu_write(cached_irq_mask, mask);
+       xtensa_set_sr(mask, intenable);
 }
 
 static void xtensa_mx_irq_unmask(struct irq_data *d)
@@ -86,14 +89,17 @@ static void xtensa_mx_irq_unmask(struct irq_data *d)
        unsigned int mask = 1u << d->hwirq;
 
        if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
-                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
-               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
-                                       HW_IRQ_MX_BASE), MIENGSET);
-       } else {
-               mask |= __this_cpu_read(cached_irq_mask);
-               __this_cpu_write(cached_irq_mask, mask);
-               xtensa_set_sr(mask, intenable);
+                   XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+               if (ext_irq >= HW_IRQ_MX_BASE) {
+                       set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENGSET);
+                       return;
+               }
        }
+       mask |= __this_cpu_read(cached_irq_mask);
+       __this_cpu_write(cached_irq_mask, mask);
+       xtensa_set_sr(mask, intenable);
 }
 
 static void xtensa_mx_irq_enable(struct irq_data *d)
@@ -113,7 +119,11 @@ static void xtensa_mx_irq_ack(struct irq_data *d)
 
 static int xtensa_mx_irq_retrigger(struct irq_data *d)
 {
-       xtensa_set_sr(1 << d->hwirq, intset);
+       unsigned int mask = 1u << d->hwirq;
+
+       if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+               return 0;
+       xtensa_set_sr(mask, intset);
        return 1;
 }
 
index c200234dd2c9d68555f79e2b4a7a2127b645ff01..ab12328be5eed398621e003272fd132c755841a0 100644 (file)
@@ -70,7 +70,11 @@ static void xtensa_irq_ack(struct irq_data *d)
 
 static int xtensa_irq_retrigger(struct irq_data *d)
 {
-       xtensa_set_sr(1 << d->hwirq, intset);
+       unsigned int mask = 1u << d->hwirq;
+
+       if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+               return 0;
+       xtensa_set_sr(mask, intset);
        return 1;
 }
 
index 4ac378e489023f19b42eaf95eff35d6a8ef1913d..40ca1e8fa09fc7884e664b473274df8cb6101a86 100644 (file)
@@ -423,7 +423,7 @@ void b1_parse_version(avmctrl_info *cinfo)
        int i, j;
 
        for (j = 0; j < AVM_MAXVERSION; j++)
-               cinfo->version[j] = "\0\0" + 1;
+               cinfo->version[j] = "";
        for (i = 0, j = 0;
             j < AVM_MAXVERSION && i < cinfo->versionlen;
             j++, i += cinfo->versionbuf[i] + 1)
index 6d05946b445eb039aeb6c9c755e94dbe8b8f1dac..124ff530da82ae2edae23de0f45e57456a16eca0 100644 (file)
@@ -262,8 +262,7 @@ hfcsusb_ph_info(struct hfcsusb *hw)
        struct dchannel *dch = &hw->dch;
        int i;
 
-       phi = kzalloc(sizeof(struct ph_info) +
-                     dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC);
+       phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
        phi->dch.ch.protocol = hw->protocol;
        phi->dch.ch.Flags = dch->Flags;
        phi->dch.state = dch->state;
index 1b2239c1d5694fb8d8fd49004dff60bb1887438f..dc1cded716c1aa4aa3c092c7e9bebd4740ab263a 100644 (file)
@@ -1437,15 +1437,19 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        modem_info *info = (modem_info *) tty->driver_data;
 
+       mutex_lock(&modem_info_mutex);
        if (!old_termios)
                isdn_tty_change_speed(info);
        else {
                if (tty->termios.c_cflag == old_termios->c_cflag &&
                    tty->termios.c_ispeed == old_termios->c_ispeed &&
-                   tty->termios.c_ospeed == old_termios->c_ospeed)
+                   tty->termios.c_ospeed == old_termios->c_ospeed) {
+                       mutex_unlock(&modem_info_mutex);
                        return;
+               }
                isdn_tty_change_speed(info);
        }
+       mutex_unlock(&modem_info_mutex);
 }
 
 /*
index 211ed6cffd10e1be817884a7724f3f37687afb93..57897871188706339dc9dfd140a9b55426b478af 100644 (file)
@@ -170,8 +170,8 @@ dev_expire_timer(struct timer_list *t)
        spin_lock_irqsave(&timer->dev->lock, flags);
        if (timer->id >= 0)
                list_move_tail(&timer->list, &timer->dev->expired);
-       spin_unlock_irqrestore(&timer->dev->lock, flags);
        wake_up_interruptible(&timer->dev->wait);
+       spin_unlock_irqrestore(&timer->dev->lock, flags);
 }
 
 static int
index a2e74feee2b2fa2c2dbb92d29c54a5174ba192c0..fd64df5a57a5e0d41d97cd500a22f3fc99fe463e 100644 (file)
@@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
 
        /* Let the programs run for couple of ms and check the engine status */
        usleep_range(3000, 6000);
-       lp55xx_read(chip, LP5523_REG_STATUS, &status);
+       ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
+       if (ret)
+               return ret;
        status &= LP5523_ENG_STATUS_MASK;
 
        if (status != LP5523_ENG_STATUS_MASK) {
index 0ff22159a0ca96d6b9c831bdd8a1e8ba724b90a9..dd538e6b27480c5583731cab60738adb4064f1c0 100644 (file)
@@ -932,7 +932,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
        if (IS_ERR(bip))
                return PTR_ERR(bip);
 
-       tag_len = io->cc->on_disk_tag_size * bio_sectors(bio);
+       tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
 
        bip->bip_iter.bi_size = tag_len;
        bip->bip_iter.bi_sector = io->cc->start + io->sector;
@@ -2414,9 +2414,21 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
         * capi:cipher_api_spec-iv:ivopts
         */
        tmp = &cipher_in[strlen("capi:")];
-       cipher_api = strsep(&tmp, "-");
-       *ivmode = strsep(&tmp, ":");
-       *ivopts = tmp;
+
+       /* Separate IV options if present, it can contain another '-' in hash name */
+       *ivopts = strrchr(tmp, ':');
+       if (*ivopts) {
+               **ivopts = '\0';
+               (*ivopts)++;
+       }
+       /* Parse IV mode */
+       *ivmode = strrchr(tmp, '-');
+       if (*ivmode) {
+               **ivmode = '\0';
+               (*ivmode)++;
+       }
+       /* The rest is crypto API spec */
+       cipher_api = tmp;
 
        if (*ivmode && !strcmp(*ivmode, "lmk"))
                cc->tfms_count = 64;
@@ -2486,11 +2498,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
                goto bad_mem;
 
        chainmode = strsep(&tmp, "-");
-       *ivopts = strsep(&tmp, "-");
-       *ivmode = strsep(&*ivopts, ":");
-
-       if (tmp)
-               DMWARN("Ignoring unexpected additional cipher options");
+       *ivmode = strsep(&tmp, ":");
+       *ivopts = tmp;
 
        /*
         * For compatibility with the original dm-crypt mapping format, if
index 4eb5f8c5653553a448d2b0971a3dca04ca0ffe4b..a20531e5f3b4c6936f75d0b647b8b05267a6ca03 100644 (file)
@@ -131,7 +131,7 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig)
 static void rq_completed(struct mapped_device *md)
 {
        /* nudge anyone waiting on suspend queue */
-       if (unlikely(waitqueue_active(&md->wait)))
+       if (unlikely(wq_has_sleeper(&md->wait)))
                wake_up(&md->wait);
 
        /*
index 20b0776e39ef3307aa5c418016afff4758850a68..ed3caceaed07c07c33e16b9038f0c3bffd7616d5 100644 (file)
@@ -1678,7 +1678,7 @@ int dm_thin_remove_range(struct dm_thin_device *td,
        return r;
 }
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
 {
        int r;
        uint32_t ref_count;
@@ -1686,7 +1686,7 @@ int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *resu
        down_read(&pmd->root_lock);
        r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
        if (!r)
-               *result = (ref_count != 0);
+               *result = (ref_count > 1);
        up_read(&pmd->root_lock);
 
        return r;
index 35e954ea20a9b5923ffc5b4d1a7a2cb5cdb3c314..f6be0d733c20267f569b72ab14314d0565425e80 100644 (file)
@@ -195,7 +195,7 @@ int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
 
 int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
 
 int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
 int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
index dadd9696340c00d13a47d38822fe886aaf5713d8..e83b63608262ac46bf4fa0f8f869294de6bdf22f 100644 (file)
@@ -257,6 +257,7 @@ struct pool {
 
        spinlock_t lock;
        struct bio_list deferred_flush_bios;
+       struct bio_list deferred_flush_completions;
        struct list_head prepared_mappings;
        struct list_head prepared_discards;
        struct list_head prepared_discards_pt2;
@@ -956,6 +957,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
        mempool_free(m, &m->tc->pool->mapping_pool);
 }
 
+static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+       unsigned long flags;
+
+       /*
+        * If the bio has the REQ_FUA flag set we must commit the metadata
+        * before signaling its completion.
+        */
+       if (!bio_triggers_commit(tc, bio)) {
+               bio_endio(bio);
+               return;
+       }
+
+       /*
+        * Complete bio with an error if earlier I/O caused changes to the
+        * metadata that can't be committed, e.g, due to I/O errors on the
+        * metadata device.
+        */
+       if (dm_thin_aborted_changes(tc->td)) {
+               bio_io_error(bio);
+               return;
+       }
+
+       /*
+        * Batch together any bios that trigger commits and then issue a
+        * single commit for them in process_deferred_bios().
+        */
+       spin_lock_irqsave(&pool->lock, flags);
+       bio_list_add(&pool->deferred_flush_completions, bio);
+       spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 static void process_prepared_mapping(struct dm_thin_new_mapping *m)
 {
        struct thin_c *tc = m->tc;
@@ -988,7 +1022,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        if (bio) {
                inc_remap_and_issue_cell(tc, m->cell, m->data_block);
-               bio_endio(bio);
+               complete_overwrite_bio(tc, bio);
        } else {
                inc_all_io_entry(tc->pool, m->cell->holder);
                remap_and_issue(tc, m->cell->holder, m->data_block);
@@ -1048,7 +1082,7 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
         * passdown we have to check that these blocks are now unused.
         */
        int r = 0;
-       bool used = true;
+       bool shared = true;
        struct thin_c *tc = m->tc;
        struct pool *pool = tc->pool;
        dm_block_t b = m->data_block, e, end = m->data_block + m->virt_end - m->virt_begin;
@@ -1058,11 +1092,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
        while (b != end) {
                /* find start of unmapped run */
                for (; b < end; b++) {
-                       r = dm_pool_block_is_used(pool->pmd, b, &used);
+                       r = dm_pool_block_is_shared(pool->pmd, b, &shared);
                        if (r)
                                goto out;
 
-                       if (!used)
+                       if (!shared)
                                break;
                }
 
@@ -1071,11 +1105,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
 
                /* find end of run */
                for (e = b + 1; e != end; e++) {
-                       r = dm_pool_block_is_used(pool->pmd, e, &used);
+                       r = dm_pool_block_is_shared(pool->pmd, e, &shared);
                        if (r)
                                goto out;
 
-                       if (used)
+                       if (shared)
                                break;
                }
 
@@ -2317,7 +2351,7 @@ static void process_deferred_bios(struct pool *pool)
 {
        unsigned long flags;
        struct bio *bio;
-       struct bio_list bios;
+       struct bio_list bios, bio_completions;
        struct thin_c *tc;
 
        tc = get_first_thin(pool);
@@ -2328,26 +2362,36 @@ static void process_deferred_bios(struct pool *pool)
        }
 
        /*
-        * If there are any deferred flush bios, we must commit
-        * the metadata before issuing them.
+        * If there are any deferred flush bios, we must commit the metadata
+        * before issuing them or signaling their completion.
         */
        bio_list_init(&bios);
+       bio_list_init(&bio_completions);
+
        spin_lock_irqsave(&pool->lock, flags);
        bio_list_merge(&bios, &pool->deferred_flush_bios);
        bio_list_init(&pool->deferred_flush_bios);
+
+       bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
+       bio_list_init(&pool->deferred_flush_completions);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios) &&
+       if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
            !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
                return;
 
        if (commit(pool)) {
+               bio_list_merge(&bios, &bio_completions);
+
                while ((bio = bio_list_pop(&bios)))
                        bio_io_error(bio);
                return;
        }
        pool->last_commit_jiffies = jiffies;
 
+       while ((bio = bio_list_pop(&bio_completions)))
+               bio_endio(bio);
+
        while ((bio = bio_list_pop(&bios)))
                generic_make_request(bio);
 }
@@ -2954,6 +2998,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
        spin_lock_init(&pool->lock);
        bio_list_init(&pool->deferred_flush_bios);
+       bio_list_init(&pool->deferred_flush_completions);
        INIT_LIST_HEAD(&pool->prepared_mappings);
        INIT_LIST_HEAD(&pool->prepared_discards);
        INIT_LIST_HEAD(&pool->prepared_discards_pt2);
index d67c95ef8d7e9487c21a994977e182c0976e7264..515e6af9bed2c7ab5e94e356215020422316a3ce 100644 (file)
@@ -699,7 +699,7 @@ static void end_io_acct(struct dm_io *io)
                                    true, duration, &io->stats_aux);
 
        /* nudge anyone waiting on suspend queue */
-       if (unlikely(waitqueue_active(&md->wait)))
+       if (unlikely(wq_has_sleeper(&md->wait)))
                wake_up(&md->wait);
 }
 
@@ -1320,7 +1320,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
 
        __bio_clone_fast(clone, bio);
 
-       if (unlikely(bio_integrity(bio) != NULL)) {
+       if (bio_integrity(bio)) {
                int r;
 
                if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
@@ -1339,7 +1339,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
        bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
        clone->bi_iter.bi_size = to_bytes(len);
 
-       if (unlikely(bio_integrity(bio) != NULL))
+       if (bio_integrity(bio))
                bio_integrity_trim(clone);
 
        return 0;
@@ -1588,6 +1588,9 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
        ci->sector = bio->bi_iter.bi_sector;
 }
 
+#define __dm_part_stat_sub(part, field, subnd) \
+       (part_stat_get(part, field) -= (subnd))
+
 /*
  * Entry point to split a bio into clones and submit them to the targets.
  */
@@ -1642,7 +1645,21 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
                                struct bio *b = bio_split(bio, bio_sectors(bio) - ci.sector_count,
                                                          GFP_NOIO, &md->queue->bio_split);
                                ci.io->orig_bio = b;
+
+                               /*
+                                * Adjust IO stats for each split, otherwise upon queue
+                                * reentry there will be redundant IO accounting.
+                                * NOTE: this is a stop-gap fix, a proper fix involves
+                                * significant refactoring of DM core's bio splitting
+                                * (by eliminating DM's splitting and just using bio_split)
+                                */
+                               part_stat_lock();
+                               __dm_part_stat_sub(&dm_disk(md)->part0,
+                                                  sectors[op_stat_group(bio_op(bio))], ci.sector_count);
+                               part_stat_unlock();
+
                                bio_chain(b, bio);
+                               trace_block_split(md->queue, b, bio->bi_iter.bi_sector);
                                ret = generic_make_request(bio);
                                break;
                        }
@@ -1713,6 +1730,15 @@ static blk_qc_t __process_bio(struct mapped_device *md,
        return ret;
 }
 
+static blk_qc_t dm_process_bio(struct mapped_device *md,
+                              struct dm_table *map, struct bio *bio)
+{
+       if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
+               return __process_bio(md, map, bio);
+       else
+               return __split_and_process_bio(md, map, bio);
+}
+
 static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
 {
        struct mapped_device *md = q->queuedata;
@@ -1733,10 +1759,7 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
                return ret;
        }
 
-       if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
-               ret = __process_bio(md, map, bio);
-       else
-               ret = __split_and_process_bio(md, map, bio);
+       ret = dm_process_bio(md, map, bio);
 
        dm_put_live_table(md, srcu_idx);
        return ret;
@@ -2415,9 +2438,9 @@ static void dm_wq_work(struct work_struct *work)
                        break;
 
                if (dm_request_based(md))
-                       generic_make_request(c);
+                       (void) generic_make_request(c);
                else
-                       __split_and_process_bio(md, map, c);
+                       (void) dm_process_bio(md, map, c);
        }
 
        dm_put_live_table(md, srcu_idx);
index fd4af4de03b40117c98a4584bf0c4b7eedd3dba9..05ffffb8b7694ac8583f2285d483d4997a06aaec 100644 (file)
@@ -207,15 +207,10 @@ static bool create_on_open = true;
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                            struct mddev *mddev)
 {
-       struct bio *b;
-
        if (!mddev || !bioset_initialized(&mddev->bio_set))
                return bio_alloc(gfp_mask, nr_iovecs);
 
-       b = bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
-       if (!b)
-               return NULL;
-       return b;
+       return bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
 }
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 
index 1d54109071cc87a0f95be9aec0801072389fcedf..fa47249fa3e42819a76f2931963cebec4accda40 100644 (file)
@@ -1863,6 +1863,20 @@ static void end_sync_read(struct bio *bio)
                reschedule_retry(r1_bio);
 }
 
+static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio)
+{
+       sector_t sync_blocks = 0;
+       sector_t s = r1_bio->sector;
+       long sectors_to_go = r1_bio->sectors;
+
+       /* make sure these bits don't get cleared. */
+       do {
+               md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
+               s += sync_blocks;
+               sectors_to_go -= sync_blocks;
+       } while (sectors_to_go > 0);
+}
+
 static void end_sync_write(struct bio *bio)
 {
        int uptodate = !bio->bi_status;
@@ -1874,15 +1888,7 @@ static void end_sync_write(struct bio *bio)
        struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev;
 
        if (!uptodate) {
-               sector_t sync_blocks = 0;
-               sector_t s = r1_bio->sector;
-               long sectors_to_go = r1_bio->sectors;
-               /* make sure these bits doesn't get cleared. */
-               do {
-                       md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
-                       s += sync_blocks;
-                       sectors_to_go -= sync_blocks;
-               } while (sectors_to_go > 0);
+               abort_sync_write(mddev, r1_bio);
                set_bit(WriteErrorSeen, &rdev->flags);
                if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED, &
@@ -2172,8 +2178,10 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
                     (i == r1_bio->read_disk ||
                      !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
                        continue;
-               if (test_bit(Faulty, &conf->mirrors[i].rdev->flags))
+               if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+                       abort_sync_write(mddev, r1_bio);
                        continue;
+               }
 
                bio_set_op_attrs(wbio, REQ_OP_WRITE, 0);
                if (test_bit(FailFast, &conf->mirrors[i].rdev->flags))
index ec3a5ef7fee0b8c099e729d49ad4a0665eddad82..cbbe6b6535be89fefec626bf759ddfedae9cb07e 100644 (file)
@@ -1935,12 +1935,14 @@ r5l_recovery_replay_one_stripe(struct r5conf *conf,
 }
 
 static struct stripe_head *
-r5c_recovery_alloc_stripe(struct r5conf *conf,
-                         sector_t stripe_sect)
+r5c_recovery_alloc_stripe(
+               struct r5conf *conf,
+               sector_t stripe_sect,
+               int noblock)
 {
        struct stripe_head *sh;
 
-       sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
+       sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
        if (!sh)
                return NULL;  /* no more stripe available */
 
@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                                stripe_sect);
 
                if (!sh) {
-                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
+                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
                        /*
                         * cannot get stripe from raid5_get_active_stripe
                         * try replay some stripes
@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                r5c_recovery_replay_stripes(
                                        cached_stripe_list, ctx);
                                sh = r5c_recovery_alloc_stripe(
-                                       conf, stripe_sect);
+                                       conf, stripe_sect, 1);
                        }
                        if (!sh) {
+                               int new_size = conf->min_nr_stripes * 2;
                                pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
                                        mdname(mddev),
-                                       conf->min_nr_stripes * 2);
-                               raid5_set_cache_size(mddev,
-                                                    conf->min_nr_stripes * 2);
-                               sh = r5c_recovery_alloc_stripe(conf,
-                                                              stripe_sect);
+                                       new_size);
+                               ret = raid5_set_cache_size(mddev, new_size);
+                               if (conf->min_nr_stripes <= new_size / 2) {
+                                       pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
+                                               mdname(mddev),
+                                               ret,
+                                               new_size,
+                                               conf->min_nr_stripes,
+                                               conf->max_nr_stripes);
+                                       return -ENOMEM;
+                               }
+                               sh = r5c_recovery_alloc_stripe(
+                                       conf, stripe_sect, 0);
                        }
                        if (!sh) {
                                pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
-                                      mdname(mddev));
+                                       mdname(mddev));
                                return -ENOMEM;
                        }
                        list_add_tail(&sh->lru, cached_stripe_list);
index 4990f0319f6cf729165a2c55a73aaf7e9bf3f567..cecea901ab8c5f666a7eb7ea4c345323efcbff1a 100644 (file)
@@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
 int
 raid5_set_cache_size(struct mddev *mddev, int size)
 {
+       int result = 0;
        struct r5conf *conf = mddev->private;
 
        if (size <= 16 || size > 32768)
@@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev, int size)
 
        mutex_lock(&conf->cache_size_mutex);
        while (size > conf->max_nr_stripes)
-               if (!grow_one_stripe(conf, GFP_KERNEL))
+               if (!grow_one_stripe(conf, GFP_KERNEL)) {
+                       conf->min_nr_stripes = conf->max_nr_stripes;
+                       result = -ENOMEM;
                        break;
+               }
        mutex_unlock(&conf->cache_size_mutex);
 
-       return 0;
+       return result;
 }
 EXPORT_SYMBOL(raid5_set_cache_size);
 
index d01821a6906a778ffb20b810b72ab21d2cb9464a..89d9c4c21037e566cd026d280e48f984075a1906 100644 (file)
@@ -807,7 +807,9 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
        struct vb2_v4l2_buffer *vbuf;
        unsigned long flags;
 
-       cancel_delayed_work_sync(&dev->work_run);
+       if (v4l2_m2m_get_curr_priv(dev->m2m_dev) == ctx)
+               cancel_delayed_work_sync(&dev->work_run);
+
        for (;;) {
                if (V4L2_TYPE_IS_OUTPUT(q->type))
                        vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
index 1441a73ce64cf609637c202566756fb98de54c79..90aad465f9ed4f29fb9e37801cb49a68270f1e95 100644 (file)
@@ -287,6 +287,7 @@ static void v4l_print_format(const void *arg, bool write_only)
        const struct v4l2_window *win;
        const struct v4l2_sdr_format *sdr;
        const struct v4l2_meta_format *meta;
+       u32 planes;
        unsigned i;
 
        pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -317,7 +318,8 @@ static void v4l_print_format(const void *arg, bool write_only)
                        prt_names(mp->field, v4l2_field_names),
                        mp->colorspace, mp->num_planes, mp->flags,
                        mp->ycbcr_enc, mp->quantization, mp->xfer_func);
-               for (i = 0; i < mp->num_planes; i++)
+               planes = min_t(u32, mp->num_planes, VIDEO_MAX_PLANES);
+               for (i = 0; i < planes; i++)
                        printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
                                        mp->plane_fmt[i].bytesperline,
                                        mp->plane_fmt[i].sizeimage);
@@ -1551,8 +1553,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!ops->vidioc_s_fmt_vid_overlay))
@@ -1581,8 +1586,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay))
@@ -1648,8 +1656,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!ops->vidioc_try_fmt_vid_overlay))
@@ -1678,8 +1689,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay))
index 8c5dfdce4326c8f0f8fc6b9402b18e52f15286ea..76f9909cf3966e82e19aef759d03c18a0b5a2c72 100644 (file)
@@ -102,6 +102,7 @@ config MFD_AAT2870_CORE
 config MFD_AT91_USART
        tristate "AT91 USART Driver"
        select MFD_CORE
+       depends on ARCH_AT91 || COMPILE_TEST
        help
          Select this to get support for AT91 USART IP. This is a wrapper
          over at91-usart-serial driver and usart-spi-driver. Only one function
@@ -1418,7 +1419,7 @@ config MFD_TPS65217
 
 config MFD_TPS68470
        bool "TI TPS68470 Power Management / LED chips"
-       depends on ACPI && I2C=y
+       depends on ACPI && PCI && I2C=y
        select MFD_CORE
        select REGMAP_I2C
        select I2C_DESIGNWARE_PLATFORM
index 30d09d17717179005ecd37202d20ce2f2ea93790..11ab17f64c6491953341c8055d7d23a2a8689c3a 100644 (file)
@@ -261,7 +261,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
        mutex_unlock(&ab8500->lock);
        dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
 
-       return ret;
+       return (ret < 0) ? ret : 0;
 }
 
 static int ab8500_get_register(struct device *dev, u8 bank,
index e1450a56fc070c42c718843b406270d589a20715..3c97f2c0fdfed37288d9e57744f3e97df2b2725d 100644 (file)
@@ -641,9 +641,9 @@ static const struct mfd_cell axp221_cells[] = {
 
 static const struct mfd_cell axp223_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp22x_pek_resources),
-               .resources              = axp22x_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp22x_pek_resources),
+               .resources      = axp22x_pek_resources,
        }, {
                .name           = "axp22x-adc",
                .of_compatible  = "x-powers,axp221-adc",
@@ -651,7 +651,7 @@ static const struct mfd_cell axp223_cells[] = {
                .name           = "axp20x-battery-power-supply",
                .of_compatible  = "x-powers,axp221-battery-power-supply",
        }, {
-               .name                   = "axp20x-regulator",
+               .name           = "axp20x-regulator",
        }, {
                .name           = "axp20x-ac-power-supply",
                .of_compatible  = "x-powers,axp221-ac-power-supply",
@@ -667,9 +667,9 @@ static const struct mfd_cell axp223_cells[] = {
 
 static const struct mfd_cell axp152_cells[] = {
        {
-               .name                   = "axp20x-pek",
-               .num_resources          = ARRAY_SIZE(axp152_pek_resources),
-               .resources              = axp152_pek_resources,
+               .name           = "axp20x-pek",
+               .num_resources  = ARRAY_SIZE(axp152_pek_resources),
+               .resources      = axp152_pek_resources,
        },
 };
 
@@ -698,87 +698,101 @@ static const struct resource axp288_charger_resources[] = {
 
 static const struct mfd_cell axp288_cells[] = {
        {
-               .name = "axp288_adc",
-               .num_resources = ARRAY_SIZE(axp288_adc_resources),
-               .resources = axp288_adc_resources,
-       },
-       {
-               .name = "axp288_extcon",
-               .num_resources = ARRAY_SIZE(axp288_extcon_resources),
-               .resources = axp288_extcon_resources,
-       },
-       {
-               .name = "axp288_charger",
-               .num_resources = ARRAY_SIZE(axp288_charger_resources),
-               .resources = axp288_charger_resources,
-       },
-       {
-               .name = "axp288_fuel_gauge",
-               .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
-               .resources = axp288_fuel_gauge_resources,
-       },
-       {
-               .name = "axp221-pek",
-               .num_resources = ARRAY_SIZE(axp288_power_button_resources),
-               .resources = axp288_power_button_resources,
-       },
-       {
-               .name = "axp288_pmic_acpi",
+               .name           = "axp288_adc",
+               .num_resources  = ARRAY_SIZE(axp288_adc_resources),
+               .resources      = axp288_adc_resources,
+       }, {
+               .name           = "axp288_extcon",
+               .num_resources  = ARRAY_SIZE(axp288_extcon_resources),
+               .resources      = axp288_extcon_resources,
+       }, {
+               .name           = "axp288_charger",
+               .num_resources  = ARRAY_SIZE(axp288_charger_resources),
+               .resources      = axp288_charger_resources,
+       }, {
+               .name           = "axp288_fuel_gauge",
+               .num_resources  = ARRAY_SIZE(axp288_fuel_gauge_resources),
+               .resources      = axp288_fuel_gauge_resources,
+       }, {
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp288_power_button_resources),
+               .resources      = axp288_power_button_resources,
+       }, {
+               .name           = "axp288_pmic_acpi",
        },
 };
 
 static const struct mfd_cell axp803_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp803_pek_resources),
-               .resources              = axp803_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp803_pek_resources),
+               .resources      = axp803_pek_resources,
+       }, {
+               .name           = "axp20x-gpio",
+               .of_compatible  = "x-powers,axp813-gpio",
+       }, {
+               .name           = "axp813-adc",
+               .of_compatible  = "x-powers,axp813-adc",
+       }, {
+               .name           = "axp20x-battery-power-supply",
+               .of_compatible  = "x-powers,axp813-battery-power-supply",
+       }, {
+               .name           = "axp20x-ac-power-supply",
+               .of_compatible  = "x-powers,axp813-ac-power-supply",
+               .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+               .resources      = axp20x_ac_power_supply_resources,
        },
-       {       .name                   = "axp20x-regulator" },
+       {       .name           = "axp20x-regulator" },
 };
 
 static const struct mfd_cell axp806_self_working_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp806_pek_resources),
-               .resources              = axp806_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp806_pek_resources),
+               .resources      = axp806_pek_resources,
        },
-       {       .name                   = "axp20x-regulator" },
+       {       .name           = "axp20x-regulator" },
 };
 
 static const struct mfd_cell axp806_cells[] = {
        {
-               .id                     = 2,
-               .name                   = "axp20x-regulator",
+               .id             = 2,
+               .name           = "axp20x-regulator",
        },
 };
 
 static const struct mfd_cell axp809_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp809_pek_resources),
-               .resources              = axp809_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp809_pek_resources),
+               .resources      = axp809_pek_resources,
        }, {
-               .id                     = 1,
-               .name                   = "axp20x-regulator",
+               .id             = 1,
+               .name           = "axp20x-regulator",
        },
 };
 
 static const struct mfd_cell axp813_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp803_pek_resources),
-               .resources              = axp803_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp803_pek_resources),
+               .resources      = axp803_pek_resources,
        }, {
-               .name                   = "axp20x-regulator",
+               .name           = "axp20x-regulator",
        }, {
-               .name                   = "axp20x-gpio",
-               .of_compatible          = "x-powers,axp813-gpio",
+               .name           = "axp20x-gpio",
+               .of_compatible  = "x-powers,axp813-gpio",
        }, {
-               .name                   = "axp813-adc",
-               .of_compatible          = "x-powers,axp813-adc",
+               .name           = "axp813-adc",
+               .of_compatible  = "x-powers,axp813-adc",
        }, {
                .name           = "axp20x-battery-power-supply",
                .of_compatible  = "x-powers,axp813-battery-power-supply",
+       }, {
+               .name           = "axp20x-ac-power-supply",
+               .of_compatible  = "x-powers,axp813-ac-power-supply",
+               .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+               .resources      = axp20x_ac_power_supply_resources,
        },
 };
 
index 503979c81dae11bbd3203f5482e398f0455a2597..fab3cdc27ed64539b7089da302f41b037dad3b1e 100644 (file)
@@ -59,6 +59,7 @@ static const struct regmap_access_table bd9571mwv_writable_table = {
 };
 
 static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
+       regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
        regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
        regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
        regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
index b99a194ce5a4a2926d8eda42e610c64ab34c5edb..2d0fee488c5aa85ad9fa906f6decdbc68dd54ee0 100644 (file)
@@ -499,6 +499,7 @@ static int ec_device_remove(struct platform_device *pdev)
 
        cros_ec_debugfs_remove(ec);
 
+       mfd_remove_devices(ec->dev);
        cdev_del(&ec->cdev);
        device_unregister(&ec->class_dev);
        return 0;
index 5970b8def5487ea3b7f40296d7da61824905df0e..aec20e1c7d3d517072739daa11d192bea8fdf071 100644 (file)
@@ -2584,7 +2584,7 @@ static struct irq_chip prcmu_irq_chip = {
        .irq_unmask     = prcmu_irq_unmask,
 };
 
-static __init char *fw_project_name(u32 project)
+static char *fw_project_name(u32 project)
 {
        switch (project) {
        case PRCMU_FW_PROJECT_U8500:
@@ -2732,7 +2732,7 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
        INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 }
 
-static void __init init_prcm_registers(void)
+static void init_prcm_registers(void)
 {
        u32 val;
 
index ca829f85672f8f0663b6bc8b3d7dffe79cac8a05..2713de989f0534523d96b121cfc22ac75f872d72 100644 (file)
@@ -82,11 +82,13 @@ static void exynos_lpass_enable(struct exynos_lpass *lpass)
                     LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
 
        regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK,
-                    LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
+                    LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S |
+                    LPASS_INTR_UART);
 
        exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET);
        exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET);
        exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET);
+       exynos_lpass_core_sw_reset(lpass, LPASS_UART_SW_RESET);
 }
 
 static void exynos_lpass_disable(struct exynos_lpass *lpass)
index 440030cecbbdae952d2a64f1050473b2f254337d..2a77988d046259dbde20f7c5547c6441958d590e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio.h>
 #include <linux/mfd/core.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
@@ -155,7 +156,7 @@ static int madera_wait_for_boot(struct madera *madera)
                usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
                             MADERA_BOOT_POLL_INTERVAL_USEC);
                regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
-       };
+       }
 
        if (!(val & MADERA_BOOT_DONE_STS1)) {
                dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
@@ -357,6 +358,8 @@ int madera_dev_init(struct madera *madera)
 
        dev_set_drvdata(madera->dev, madera);
        BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
+       mutex_init(&madera->dapm_ptr_lock);
+
        madera_set_micbias_info(madera);
 
        /*
index d8217366ed361da3def90ea2ed0cd8a03784bc62..d8ddd1a6f30497ff7a866b40fe21f25ad45badea 100644 (file)
@@ -280,7 +280,7 @@ static int max77620_config_fps(struct max77620_chip *chip,
 
        for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
                sprintf(fps_name, "fps%d", fps_id);
-               if (!strcmp(fps_np->name, fps_name))
+               if (of_node_name_eq(fps_np, fps_name))
                        break;
        }
 
index f475e848252fa43a0f47997c627196dd6a02630c..d0bf50e3568d7e770835092430e33175a4475601 100644 (file)
@@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
 
        mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
 
-       mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+       ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+       if (ret)
+               goto out;
 
        adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
               MC13XXX_ADC0_CHRGRAWDIV;
index 77b64bd64df36aab2dd805a5dd2e056003c3c6e7..ab24e176ef4487a0f2101dec3496aaa440c1b8c1 100644 (file)
@@ -329,8 +329,7 @@ static int mt6397_probe(struct platform_device *pdev)
 
        default:
                dev_err(&pdev->dev, "unsupported chip: %d\n", id);
-               ret = -ENODEV;
-               break;
+               return -ENODEV;
        }
 
        if (ret) {
index 52fafea06067e17cfd7ea14c0fc033764fc561c9..8d420c37b2a613c87f45970c8abe06390c234c04 100644 (file)
@@ -638,6 +638,10 @@ static int qcom_rpm_probe(struct platform_device *pdev)
                return -EFAULT;
        }
 
+       writel(fw_version[0], RPM_CTRL_REG(rpm, 0));
+       writel(fw_version[1], RPM_CTRL_REG(rpm, 1));
+       writel(fw_version[2], RPM_CTRL_REG(rpm, 2));
+
        dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
                                                        fw_version[1],
                                                        fw_version[2]);
index 2a8369657e38875f31f1ef7cb215b11ead123f59..26c7b63e008a89260ebd80bf016cca25e81005c2 100644 (file)
@@ -109,7 +109,7 @@ struct rave_sp_reply {
 /**
  * struct rave_sp_checksum - Variant specific checksum implementation details
  *
- * @length:    Caculated checksum length
+ * @length:    Calculated checksum length
  * @subroutine:        Utilized checksum algorithm implementation
  */
 struct rave_sp_checksum {
index 566caca4efd8ee509540b1c65df396015e37d042..7569a4be0608a4a11febed09fde09d7a5f94f9ad 100644 (file)
@@ -1302,17 +1302,17 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
        pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
 
        for_each_child_of_node(np, child) {
-               if (!strcmp(child->name, "stmpe_gpio")) {
+               if (of_node_name_eq(child, "stmpe_gpio")) {
                        pdata->blocks |= STMPE_BLOCK_GPIO;
-               } else if (!strcmp(child->name, "stmpe_keypad")) {
+               } else if (of_node_name_eq(child, "stmpe_keypad")) {
                        pdata->blocks |= STMPE_BLOCK_KEYPAD;
-               } else if (!strcmp(child->name, "stmpe_touchscreen")) {
+               } else if (of_node_name_eq(child, "stmpe_touchscreen")) {
                        pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
-               } else if (!strcmp(child->name, "stmpe_adc")) {
+               } else if (of_node_name_eq(child, "stmpe_adc")) {
                        pdata->blocks |= STMPE_BLOCK_ADC;
-               } else if (!strcmp(child->name, "stmpe_pwm")) {
+               } else if (of_node_name_eq(child, "stmpe_pwm")) {
                        pdata->blocks |= STMPE_BLOCK_PWM;
-               } else if (!strcmp(child->name, "stmpe_rotator")) {
+               } else if (of_node_name_eq(child, "stmpe_rotator")) {
                        pdata->blocks |= STMPE_BLOCK_ROTATOR;
                }
        }
index c2d47d78705b8358845fbf0c46908ebd2cce0438..fd111296b959255c5a7fdeb61fcd2649594ebbd7 100644 (file)
@@ -264,8 +264,9 @@ static      int ti_tscadc_probe(struct platform_device *pdev)
                cell->pdata_size = sizeof(tscadc);
        }
 
-       err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
-                       tscadc->used_cells, NULL, 0, NULL);
+       err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+                             tscadc->cells, tscadc->used_cells, NULL,
+                             0, NULL);
        if (err < 0)
                goto err_disable_clk;
 
index 910f569ff77c1b7313c4c03c6d3a57b92f6c73b4..8bcdecf494d050b5fc69290af8c908369fa9ed79 100644 (file)
@@ -235,9 +235,9 @@ static int tps65218_probe(struct i2c_client *client,
 
        mutex_init(&tps->tps_lock);
 
-       ret = regmap_add_irq_chip(tps->regmap, tps->irq,
-                       IRQF_ONESHOT, 0, &tps65218_irq_chip,
-                       &tps->irq_data);
+       ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq,
+                                      IRQF_ONESHOT, 0, &tps65218_irq_chip,
+                                      &tps->irq_data);
        if (ret < 0)
                return ret;
 
@@ -253,26 +253,9 @@ static int tps65218_probe(struct i2c_client *client,
                              ARRAY_SIZE(tps65218_cells), NULL, 0,
                              regmap_irq_get_domain(tps->irq_data));
 
-       if (ret < 0)
-               goto err_irq;
-
-       return 0;
-
-err_irq:
-       regmap_del_irq_chip(tps->irq, tps->irq_data);
-
        return ret;
 }
 
-static int tps65218_remove(struct i2c_client *client)
-{
-       struct tps65218 *tps = i2c_get_clientdata(client);
-
-       regmap_del_irq_chip(tps->irq, tps->irq_data);
-
-       return 0;
-}
-
 static const struct i2c_device_id tps65218_id_table[] = {
        { "tps65218", TPS65218 },
        { },
@@ -285,7 +268,6 @@ static struct i2c_driver tps65218_driver = {
                .of_match_table = of_tps65218_match_table,
        },
        .probe          = tps65218_probe,
-       .remove         = tps65218_remove,
        .id_table       = tps65218_id_table,
 };
 
index b893797827410c25450abd76fa47581c5c09d4df..9c7925ca13cf008f6580bad59554eeb86a1b70dd 100644 (file)
@@ -592,6 +592,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       if (tps6586x->client->irq)
+               disable_irq(tps6586x->client->irq);
+
+       return 0;
+}
+
+static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       if (tps6586x->client->irq)
+               enable_irq(tps6586x->client->irq);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
+                        tps6586x_i2c_resume);
+
 static const struct i2c_device_id tps6586x_id_table[] = {
        { "tps6586x", 0 },
        { },
@@ -602,6 +625,7 @@ static struct i2c_driver tps6586x_driver = {
        .driver = {
                .name   = "tps6586x",
                .of_match_table = of_match_ptr(tps6586x_of_match),
+               .pm     = &tps6586x_pm_ops,
        },
        .probe          = tps6586x_i2c_probe,
        .remove         = tps6586x_i2c_remove,
index 4be3d239da9ec8a2db40eea62f608f6559cff5a3..299016bc46d909b4164708044ae21c9d5d5d14f4 100644 (file)
@@ -979,7 +979,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
  * letting it generate the right frequencies for USB, MADC, and
  * other purposes.
  */
-static inline int __init protect_pm_master(void)
+static inline int protect_pm_master(void)
 {
        int e = 0;
 
@@ -988,7 +988,7 @@ static inline int __init protect_pm_master(void)
        return e;
 }
 
-static inline int __init unprotect_pm_master(void)
+static inline int unprotect_pm_master(void)
 {
        int e = 0;
 
index 1ee68bd440fbc279874ceaf7ccefc37c692e9f5c..16c6e2accfaa5e49b9ddb53edbf8c234092e110f 100644 (file)
@@ -1618,6 +1618,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000ECD, 0x0000 },    /* R3789  - HPLPF4_2 */
        { 0x00000EE0, 0x0000 },    /* R3808  - ASRC_ENABLE */
        { 0x00000EE2, 0x0000 },    /* R3810  - ASRC_RATE1 */
+       { 0x00000EE3, 0x4000 },    /* R3811  - ASRC_RATE2 */
        { 0x00000EF0, 0x0000 },    /* R3824  - ISRC 1 CTRL 1 */
        { 0x00000EF1, 0x0000 },    /* R3825  - ISRC 1 CTRL 2 */
        { 0x00000EF2, 0x0000 },    /* R3826  - ISRC 1 CTRL 3 */
@@ -2869,6 +2870,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_ASRC_ENABLE:
        case ARIZONA_ASRC_STATUS:
        case ARIZONA_ASRC_RATE1:
+       case ARIZONA_ASRC_RATE2:
        case ARIZONA_ISRC_1_CTRL_1:
        case ARIZONA_ISRC_1_CTRL_2:
        case ARIZONA_ISRC_1_CTRL_3:
index b8aaa684c397b0b8be8fe0c5ae00a37b087b6997..2ed23c99f59fdbebab6cc49b032e04fa5f0c020c 100644 (file)
@@ -820,21 +820,24 @@ static int ibmvmc_send_msg(struct crq_server_adapter *adapter,
  *
  * Return:
  *     0 - Success
+ *     Non-zero - Failure
  */
 static int ibmvmc_open(struct inode *inode, struct file *file)
 {
        struct ibmvmc_file_session *session;
-       int rc = 0;
 
        pr_debug("%s: inode = 0x%lx, file = 0x%lx, state = 0x%x\n", __func__,
                 (unsigned long)inode, (unsigned long)file,
                 ibmvmc.state);
 
        session = kzalloc(sizeof(*session), GFP_KERNEL);
+       if (!session)
+               return -ENOMEM;
+
        session->file = file;
        file->private_data = session;
 
-       return rc;
+       return 0;
 }
 
 /**
index 1fc8ea0f519bb28d2c4e2640cda8caeddba55a75..ca4c9cc218a22b9644957f04efa0d28142aab41c 100644 (file)
@@ -401,8 +401,11 @@ static void mei_io_list_flush_cl(struct list_head *head,
        struct mei_cl_cb *cb, *next;
 
        list_for_each_entry_safe(cb, next, head, list) {
-               if (cl == cb->cl)
+               if (cl == cb->cl) {
                        list_del_init(&cb->list);
+                       if (cb->fop_type == MEI_FOP_READ)
+                               mei_io_cb_free(cb);
+               }
        }
 }
 
index 78c26cebf5d40c9e547ffc0d7cd3e0dbbedae62c..8f7616557c97acd18d7808a71012a643affa68a1 100644 (file)
@@ -1187,9 +1187,15 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
 
                if (dma_setup_res->status) {
-                       dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
-                                dma_setup_res->status,
-                                mei_hbm_status_str(dma_setup_res->status));
+                       u8 status = dma_setup_res->status;
+
+                       if (status == MEI_HBMS_NOT_ALLOWED) {
+                               dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
+                       } else {
+                               dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
+                                        status,
+                                        mei_hbm_status_str(status));
+                       }
                        dev->hbm_f_dr_supported = 0;
                        mei_dmam_ring_free(dev);
                }
index e4b10b2d1a0838af03f16f29922b86c653cf99ba..bb1ee9834a029d28fdd690ed660f6f6355c89b67 100644 (file)
 #define MEI_DEV_ID_BXT_M      0x1A9A  /* Broxton M */
 #define MEI_DEV_ID_APL_I      0x5A9A  /* Apollo Lake I */
 
+#define MEI_DEV_ID_DNV_IE     0x19E5  /* Denverton IE */
+
 #define MEI_DEV_ID_GLK        0x319A  /* Gemini Lake */
 
 #define MEI_DEV_ID_KBP        0xA2BA  /* Kaby Point */
 #define MEI_DEV_ID_CNP_H      0xA360  /* Cannon Point H */
 #define MEI_DEV_ID_CNP_H_4    0xA364  /* Cannon Point H 4 (iTouch) */
 
+#define MEI_DEV_ID_ICP_LP     0x34E0  /* Ice Lake Point LP */
+
 /*
  * MEI HW Section
  */
index 73ace2d59dea9787c010d07769ed20b9881bcb76..3ab946ad32570ce645d18950d8be8d8582f0484a 100644 (file)
@@ -88,11 +88,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)},
+
        {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
@@ -103,6 +105,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
+
        /* required last entry */
        {0, }
 };
index 6b212c8b78e7fdedc27b62688ecc32a4766cbffc..744757f541be40f4ea4349579ff534ae88b06e53 100644 (file)
@@ -47,7 +47,8 @@
  * @dc: Virtio device control
  * @vpdev: VOP device which is the parent for this virtio device
  * @vr: Buffer for accessing the VRING
- * @used: Buffer for used
+ * @used_virt: Virtual address of used ring
+ * @used: DMA address of used ring
  * @used_size: Size of the used buffer
  * @reset_done: Track whether VOP reset is complete
  * @virtio_cookie: Cookie returned upon requesting a interrupt
@@ -61,6 +62,7 @@ struct _vop_vdev {
        struct mic_device_ctrl __iomem *dc;
        struct vop_device *vpdev;
        void __iomem *vr[VOP_MAX_VRINGS];
+       void *used_virt[VOP_MAX_VRINGS];
        dma_addr_t used[VOP_MAX_VRINGS];
        int used_size[VOP_MAX_VRINGS];
        struct completion reset_done;
@@ -260,12 +262,12 @@ static bool vop_notify(struct virtqueue *vq)
 static void vop_del_vq(struct virtqueue *vq, int n)
 {
        struct _vop_vdev *vdev = to_vopvdev(vq->vdev);
-       struct vring *vr = (struct vring *)(vq + 1);
        struct vop_device *vpdev = vdev->vpdev;
 
        dma_unmap_single(&vpdev->dev, vdev->used[n],
                         vdev->used_size[n], DMA_BIDIRECTIONAL);
-       free_pages((unsigned long)vr->used, get_order(vdev->used_size[n]));
+       free_pages((unsigned long)vdev->used_virt[n],
+                  get_order(vdev->used_size[n]));
        vring_del_virtqueue(vq);
        vpdev->hw_ops->iounmap(vpdev, vdev->vr[n]);
        vdev->vr[n] = NULL;
@@ -283,6 +285,26 @@ static void vop_del_vqs(struct virtio_device *dev)
                vop_del_vq(vq, idx++);
 }
 
+static struct virtqueue *vop_new_virtqueue(unsigned int index,
+                                     unsigned int num,
+                                     struct virtio_device *vdev,
+                                     bool context,
+                                     void *pages,
+                                     bool (*notify)(struct virtqueue *vq),
+                                     void (*callback)(struct virtqueue *vq),
+                                     const char *name,
+                                     void *used)
+{
+       bool weak_barriers = false;
+       struct vring vring;
+
+       vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN);
+       vring.used = used;
+
+       return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+                                    notify, callback, name);
+}
+
 /*
  * This routine will assign vring's allocated in host/io memory. Code in
  * virtio_ring.c however continues to access this io memory as if it were local
@@ -302,7 +324,6 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
        struct _mic_vring_info __iomem *info;
        void *used;
        int vr_size, _vr_size, err, magic;
-       struct vring *vr;
        u8 type = ioread8(&vdev->desc->type);
 
        if (index >= ioread8(&vdev->desc->num_vq))
@@ -322,17 +343,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                return ERR_PTR(-ENOMEM);
        vdev->vr[index] = va;
        memset_io(va, 0x0, _vr_size);
-       vq = vring_new_virtqueue(
-                               index,
-                               le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN,
-                               dev,
-                               false,
-                               ctx,
-                               (void __force *)va, vop_notify, callback, name);
-       if (!vq) {
-               err = -ENOMEM;
-               goto unmap;
-       }
+
        info = va + _vr_size;
        magic = ioread32(&info->magic);
 
@@ -341,18 +352,27 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                goto unmap;
        }
 
-       /* Allocate and reassign used ring now */
        vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
                                             sizeof(struct vring_used_elem) *
                                             le16_to_cpu(config.num));
        used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(vdev->used_size[index]));
+       vdev->used_virt[index] = used;
        if (!used) {
                err = -ENOMEM;
                dev_err(_vop_dev(vdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
-               goto del_vq;
+               goto unmap;
        }
+
+       vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx,
+                              (void __force *)va, vop_notify, callback,
+                              name, used);
+       if (!vq) {
+               err = -ENOMEM;
+               goto free_used;
+       }
+
        vdev->used[index] = dma_map_single(&vpdev->dev, used,
                                            vdev->used_size[index],
                                            DMA_BIDIRECTIONAL);
@@ -360,26 +380,17 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                err = -ENOMEM;
                dev_err(_vop_dev(vdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
-               goto free_used;
+               goto del_vq;
        }
        writeq(vdev->used[index], &vqconfig->used_address);
-       /*
-        * To reassign the used ring here we are directly accessing
-        * struct vring_virtqueue which is a private data structure
-        * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
-        * vring_new_virtqueue() would ensure that
-        *  (&vq->vring == (struct vring *) (&vq->vq + 1));
-        */
-       vr = (struct vring *)(vq + 1);
-       vr->used = used;
 
        vq->priv = vdev;
        return vq;
+del_vq:
+       vring_del_virtqueue(vq);
 free_used:
        free_pages((unsigned long)used,
                   get_order(vdev->used_size[index]));
-del_vq:
-       vring_del_virtqueue(vq);
 unmap:
        vpdev->hw_ops->iounmap(vpdev, vdev->vr[index]);
        return ERR_PTR(err);
@@ -394,16 +405,21 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
        struct _vop_vdev *vdev = to_vopvdev(dev);
        struct vop_device *vpdev = vdev->vpdev;
        struct mic_device_ctrl __iomem *dc = vdev->dc;
-       int i, err, retry;
+       int i, err, retry, queue_idx = 0;
 
        /* We must have this many virtqueues. */
        if (nvqs > ioread8(&vdev->desc->num_vq))
                return -ENOENT;
 
        for (i = 0; i < nvqs; ++i) {
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
                dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
                        __func__, i, names[i]);
-               vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i],
+               vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        err = PTR_ERR(vqs[i]);
@@ -576,6 +592,8 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
        int ret = -1;
 
        if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
+               struct device *dev = get_device(&vdev->vdev.dev);
+
                dev_dbg(&vpdev->dev,
                        "%s %d config_change %d type %d vdev %p\n",
                        __func__, __LINE__,
@@ -587,7 +605,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
                iowrite8(-1, &dc->h2c_vdev_db);
                if (status & VIRTIO_CONFIG_S_DRIVER_OK)
                        wait_for_completion(&vdev->reset_done);
-               put_device(&vdev->vdev.dev);
+               put_device(dev);
                iowrite8(1, &dc->guest_ack);
                dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n",
                        __func__, __LINE__, ioread8(&dc->guest_ack));
index 595ac065b4016d762b7fd69aaf7932dd6152cac6..95ff7c5a1dfb62c1363006b5a0919562572cfbce 100644 (file)
@@ -70,8 +70,12 @@ pvpanic_walk_resources(struct acpi_resource *res, void *context)
        struct resource r;
 
        if (acpi_dev_resource_io(res, &r)) {
+#ifdef CONFIG_HAS_IOPORT_MAP
                base = ioport_map(r.start, resource_size(&r));
                return AE_OK;
+#else
+               return AE_ERROR;
+#endif
        } else if (acpi_dev_resource_memory(res, &r)) {
                base = ioremap(r.start, resource_size(&r));
                return AE_OK;
index aef1185f383d42f3a3f7192b2003d521471acd18..14f3fdb8c6bb7aad30d3b9f1337afcb1f6e34f7e 100644 (file)
@@ -2112,7 +2112,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq)
                if (waiting)
                        wake_up(&mq->wait);
                else
-                       kblockd_schedule_work(&mq->complete_work);
+                       queue_work(mq->card->complete_wq, &mq->complete_work);
 
                return;
        }
@@ -2924,6 +2924,13 @@ static int mmc_blk_probe(struct mmc_card *card)
 
        mmc_fixup_device(card, mmc_blk_fixups);
 
+       card->complete_wq = alloc_workqueue("mmc_complete",
+                                       WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+       if (unlikely(!card->complete_wq)) {
+               pr_err("Failed to create mmc completion workqueue");
+               return -ENOMEM;
+       }
+
        md = mmc_blk_alloc(card);
        if (IS_ERR(md))
                return PTR_ERR(md);
@@ -2987,6 +2994,7 @@ static void mmc_blk_remove(struct mmc_card *card)
        pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
        dev_set_drvdata(&card->dev, NULL);
+       destroy_workqueue(card->complete_wq);
 }
 
 static int _mmc_blk_suspend(struct mmc_card *card)
index f57f5de5420647619714c65861896252700d302c..cf58ccaf22d50f742e72b76876ad58eb0f966233 100644 (file)
@@ -234,7 +234,7 @@ int mmc_of_parse(struct mmc_host *host)
                if (device_property_read_bool(dev, "broken-cd"))
                        host->caps |= MMC_CAP_NEEDS_POLL;
 
-               ret = mmc_gpiod_request_cd(host, "cd", 0, true,
+               ret = mmc_gpiod_request_cd(host, "cd", 0, false,
                                           cd_debounce_delay_ms * 1000,
                                           &cd_gpio_invert);
                if (!ret)
index e26b8145efb32411bf4feb2659163a8b7ae59350..a44ec8bb54181d048f5cdd7dc64a8c3aed91e208 100644 (file)
@@ -116,7 +116,7 @@ config MMC_RICOH_MMC
 
 config MMC_SDHCI_ACPI
        tristate "SDHCI support for ACPI enumerated SDHCI controllers"
-       depends on MMC_SDHCI && ACPI
+       depends on MMC_SDHCI && ACPI && PCI
        select IOSF_MBI if X86
        help
          This selects support for ACPI enumerated SDHCI controllers,
@@ -978,7 +978,7 @@ config MMC_SDHCI_OMAP
        tristate "TI SDHCI Controller Support"
        depends on MMC_SDHCI_PLTFM && OF
        select THERMAL
-       select TI_SOC_THERMAL
+       imply TI_SOC_THERMAL
        help
          This selects the Secure Digital Host Controller Interface (SDHCI)
          support present in TI's DRA7 SOCs. The controller supports
index 50293529d6dec7c8f4b13cfc02eea8d9f940fb4b..c9e7aa50bb0ab5d05884d8ebfe6ef740adeda150 100644 (file)
@@ -1431,6 +1431,8 @@ static int bcm2835_probe(struct platform_device *pdev)
 
 err:
        dev_dbg(dev, "%s -> err %d\n", __func__, ret);
+       if (host->dma_chan_rxtx)
+               dma_release_channel(host->dma_chan_rxtx);
        mmc_free_host(mmc);
 
        return ret;
index ed8f2254b66a842adf97213628d0ba8dcb6a3dd2..aa38b1a8017e8c0a522adf49efacd92593f8f22c 100644 (file)
@@ -1,11 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2018 Mellanox Technologies.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #include <linux/bitfield.h>
index c2690c1a50ffc1e2a086916d3aa4b870d2c80c07..2eba507790e49bf2a2c5500a22cdb9ecfcbfe19d 100644 (file)
@@ -179,6 +179,8 @@ struct meson_host {
        struct sd_emmc_desc *descs;
        dma_addr_t descs_dma_addr;
 
+       int irq;
+
        bool vqmmc_enabled;
 };
 
@@ -738,6 +740,11 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,
 static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct meson_host *host = mmc_priv(mmc);
+       int adj = 0;
+
+       /* enable signal resampling w/o delay */
+       adj = ADJUST_ADJ_EN;
+       writel(adj, host->regs + host->data->adjust);
 
        return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
 }
@@ -768,6 +775,9 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
 
+               /* disable signal resampling */
+               writel(0, host->regs + host->data->adjust);
+
                /* Reset rx phase */
                clk_set_phase(host->rx_clk, 0);
 
@@ -1166,7 +1176,7 @@ static int meson_mmc_get_cd(struct mmc_host *mmc)
 
 static void meson_mmc_cfg_init(struct meson_host *host)
 {
-       u32 cfg = 0, adj = 0;
+       u32 cfg = 0;
 
        cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK,
                          ilog2(SD_EMMC_CFG_RESP_TIMEOUT));
@@ -1177,10 +1187,6 @@ static void meson_mmc_cfg_init(struct meson_host *host)
        cfg |= CFG_ERR_ABORT;
 
        writel(cfg, host->regs + SD_EMMC_CFG);
-
-       /* enable signal resampling w/o delay */
-       adj = ADJUST_ADJ_EN;
-       writel(adj, host->regs + host->data->adjust);
 }
 
 static int meson_mmc_card_busy(struct mmc_host *mmc)
@@ -1231,7 +1237,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        struct resource *res;
        struct meson_host *host;
        struct mmc_host *mmc;
-       int ret, irq;
+       int ret;
 
        mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
        if (!mmc)
@@ -1276,8 +1282,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
                goto free_host;
        }
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq <= 0) {
+       host->irq = platform_get_irq(pdev, 0);
+       if (host->irq <= 0) {
                dev_err(&pdev->dev, "failed to get interrupt resource.\n");
                ret = -EINVAL;
                goto free_host;
@@ -1331,9 +1337,9 @@ static int meson_mmc_probe(struct platform_device *pdev)
        writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
               host->regs + SD_EMMC_IRQ_EN);
 
-       ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
-                                       meson_mmc_irq_thread, IRQF_SHARED,
-                                       NULL, host);
+       ret = request_threaded_irq(host->irq, meson_mmc_irq,
+                                  meson_mmc_irq_thread, IRQF_SHARED,
+                                  dev_name(&pdev->dev), host);
        if (ret)
                goto err_init_clk;
 
@@ -1351,7 +1357,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (host->bounce_buf == NULL) {
                dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
                ret = -ENOMEM;
-               goto err_init_clk;
+               goto err_free_irq;
        }
 
        host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
@@ -1370,6 +1376,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
 err_bounce_buf:
        dma_free_coherent(host->dev, host->bounce_buf_size,
                          host->bounce_buf, host->bounce_dma_addr);
+err_free_irq:
+       free_irq(host->irq, host);
 err_init_clk:
        clk_disable_unprepare(host->mmc_clk);
 err_core_clk:
@@ -1387,6 +1395,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
 
        /* disable interrupts */
        writel(0, host->regs + SD_EMMC_IRQ_EN);
+       free_irq(host->irq, host);
 
        dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
                          host->descs, host->descs_dma_addr);
index 8afeaf81ae6636c8ff8cc370d6858452d8e8a097..833ef0590af81d3c2d0897492beaf9e1542c7926 100644 (file)
@@ -846,7 +846,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
 
        if (timing == MMC_TIMING_MMC_HS400 &&
            host->dev_comp->hs400_tune)
-               sdr_set_field(host->base + PAD_CMD_TUNE,
+               sdr_set_field(host->base + tune_reg,
                              MSDC_PAD_TUNE_CMDRRDLY,
                              host->hs400_cmd_int_delay);
        dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock,
index 0db99057c44f7185ae0f6642d47b9c833faa77cb..9d12c06c7fd683b97ae8e8c241ec9a53cdbc033d 100644 (file)
@@ -296,7 +296,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
 
        iproc_host->data = iproc_data;
 
-       mmc_of_parse(host->mmc);
+       ret = mmc_of_parse(host->mmc);
+       if (ret)
+               goto err;
+
        sdhci_get_property(pdev);
 
        host->mmc->caps |= iproc_host->data->mmc_caps;
index 279e326e397e1e28b4ce9012d2f0e19b4000d503..70fadc9767955c66fca6980d288ae32c260e2720 100644 (file)
@@ -1399,13 +1399,37 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
        mmc->caps              |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                                  MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
 
-       if (host->cfg->clk_delays || host->use_new_timings)
+       /*
+        * Some H5 devices do not have signal traces precise enough to
+        * use HS DDR mode for their eMMC chips.
+        *
+        * We still enable HS DDR modes for all the other controller
+        * variants that support them.
+        */
+       if ((host->cfg->clk_delays || host->use_new_timings) &&
+           !of_device_is_compatible(pdev->dev.of_node,
+                                    "allwinner,sun50i-h5-emmc"))
                mmc->caps      |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR;
 
        ret = mmc_of_parse(mmc);
        if (ret)
                goto error_free_dma;
 
+       /*
+        * If we don't support delay chains in the SoC, we can't use any
+        * of the higher speed modes. Mask them out in case the device
+        * tree specifies the properties for them, which gets added to
+        * the caps by mmc_of_parse() above.
+        */
+       if (!(host->cfg->clk_delays || host->use_new_timings)) {
+               mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR |
+                              MMC_CAP_1_2V_DDR | MMC_CAP_UHS);
+               mmc->caps2 &= ~MMC_CAP2_HS200;
+       }
+
+       /* TODO: This driver doesn't support HS400 mode yet */
+       mmc->caps2 &= ~MMC_CAP2_HS400;
+
        ret = sunxi_mmc_init_host(host);
        if (ret)
                goto error_free_dma;
index 60104e1079c5357f4919e0d7f684efc003ab159f..37f174ccbcec4b1f10d0af717707a38fa46d4499 100644 (file)
@@ -480,6 +480,10 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent,
                /* let's register it anyway to preserve ordering */
                slave->offset = 0;
                slave->mtd.size = 0;
+
+               /* Initialize ->erasesize to make add_mtd_device() happy. */
+               slave->mtd.erasesize = parent->erasesize;
+
                printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
                        part->name);
                goto out_register;
@@ -632,7 +636,6 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
        mutex_unlock(&mtd_partitions_mutex);
 
        free_partition(new);
-       pr_info("%s:%i\n", __func__, __LINE__);
 
        return ret;
 }
index eebac35304c6f2be99b7f551e5be2dc9b8789480..6e8edc9375dde933470541dc3123ae515965a2de 100644 (file)
@@ -1322,7 +1322,7 @@ int denali_init(struct denali_nand_info *denali)
        }
 
        /* clk rate info is needed for setup_data_interface */
-       if (denali->clk_rate && denali->clk_x_rate)
+       if (!denali->clk_rate || !denali->clk_x_rate)
                chip->options |= NAND_KEEP_TIMINGS;
 
        chip->legacy.dummy_controller.ops = &denali_controller_ops;
index 325b4414dcccdaae2064dfe4416a6e5b39fb812e..c9149a37f8f0a16c40ed9fdd7989dad7403c1680 100644 (file)
@@ -593,23 +593,6 @@ static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf,
        dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
 }
 
-/* fsmc_select_chip - assert or deassert nCE */
-static void fsmc_ce_ctrl(struct fsmc_nand_data *host, bool assert)
-{
-       u32 pc = readl(host->regs_va + FSMC_PC);
-
-       if (!assert)
-               writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + FSMC_PC);
-       else
-               writel_relaxed(pc | FSMC_ENABLE, host->regs_va + FSMC_PC);
-
-       /*
-        * nCE line changes must be applied before returning from this
-        * function.
-        */
-       mb();
-}
-
 /*
  * fsmc_exec_op - hook called by the core to execute NAND operations
  *
@@ -627,8 +610,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
 
        pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
 
-       fsmc_ce_ctrl(host, true);
-
        for (op_id = 0; op_id < op->ninstrs; op_id++) {
                instr = &op->instrs[op_id];
 
@@ -686,8 +667,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
                }
        }
 
-       fsmc_ce_ctrl(host, false);
-
        return ret;
 }
 
index bd4cfac6b5aa69e8dbc6cec34c02ca59a8399912..a4768df5083f9633a965bf85f12dce4b1d6ad35c 100644 (file)
@@ -155,9 +155,10 @@ int gpmi_init(struct gpmi_nand_data *this)
 
        /*
         * Reset BCH here, too. We got failures otherwise :(
-        * See later BCH reset for explanation of MX23 handling
+        * See later BCH reset for explanation of MX23 and MX28 handling
         */
-       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+       ret = gpmi_reset_block(r->bch_regs,
+                              GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
        if (ret)
                goto err_out;
 
@@ -263,12 +264,10 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        /*
        * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
        * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
-       * On the other hand, the MX28 needs the reset, because one case has been
-       * seen where the BCH produced ECC errors constantly after 10000
-       * consecutive reboots. The latter case has not been seen on the MX23
-       * yet, still we don't know if it could happen there as well.
+       * and MX28.
        */
-       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+       ret = gpmi_reset_block(r->bch_regs,
+                              GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
        if (ret)
                goto err_out;
 
index f92ae5aa2a548939eb5636d12a774158f16ddc16..9526d5b23c809886dbb824808a5b67d0a0967f5b 100644 (file)
@@ -260,7 +260,7 @@ static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat,
 }
 
 static int jz_nand_ioremap_resource(struct platform_device *pdev,
-       const char *name, struct resource **res, void *__iomem *base)
+       const char *name, struct resource **res, void __iomem **base)
 {
        int ret;
 
index cca4b24d2ffa8e13151b61721053101f2a55644e..839494ac457c15c4697a357f2136f0cf0852acc6 100644 (file)
@@ -410,6 +410,7 @@ static int nand_check_wp(struct nand_chip *chip)
 
 /**
  * nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @chip: NAND chip object
  * @oob: oob data buffer
  * @len: oob data write length
  * @ops: oob ops structure
index 1b722fe9213c31ca56fedd21736eb1e7b678c9f2..19a2b563acdfe63644572434efed785b78cc7692 100644 (file)
@@ -158,7 +158,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
 
 /**
  * read_bbt - [GENERIC] Read the bad block table starting from page
- * @chip: NAND chip object
+ * @this: NAND chip object
  * @buf: temporary buffer
  * @page: the starting page
  * @num: the number of bbt descriptors to read
index 479c2f2cf17f91ee44978b221391f91a928c0b95..fa87ae28cdfecd21fb6fb435fac35047a3b37325 100644 (file)
@@ -304,24 +304,30 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
        struct nand_device *nand = spinand_to_nand(spinand);
        struct mtd_info *mtd = nanddev_to_mtd(nand);
        struct nand_page_io_req adjreq = *req;
-       unsigned int nbytes = 0;
-       void *buf = NULL;
+       void *buf = spinand->databuf;
+       unsigned int nbytes;
        u16 column = 0;
        int ret;
 
-       memset(spinand->databuf, 0xff,
-              nanddev_page_size(nand) +
-              nanddev_per_page_oobsize(nand));
+       /*
+        * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
+        * the cache content to 0xFF (depends on vendor implementation), so we
+        * must fill the page cache entirely even if we only want to program
+        * the data portion of the page, otherwise we might corrupt the BBM or
+        * user data previously programmed in OOB area.
+        */
+       nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
+       memset(spinand->databuf, 0xff, nbytes);
+       adjreq.dataoffs = 0;
+       adjreq.datalen = nanddev_page_size(nand);
+       adjreq.databuf.out = spinand->databuf;
+       adjreq.ooblen = nanddev_per_page_oobsize(nand);
+       adjreq.ooboffs = 0;
+       adjreq.oobbuf.out = spinand->oobbuf;
 
-       if (req->datalen) {
+       if (req->datalen)
                memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
                       req->datalen);
-               adjreq.dataoffs = 0;
-               adjreq.datalen = nanddev_page_size(nand);
-               adjreq.databuf.out = spinand->databuf;
-               nbytes = adjreq.datalen;
-               buf = spinand->databuf;
-       }
 
        if (req->ooblen) {
                if (req->mode == MTD_OPS_AUTO_OOB)
@@ -332,14 +338,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
                else
                        memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
                               req->ooblen);
-
-               adjreq.ooblen = nanddev_per_page_oobsize(nand);
-               adjreq.ooboffs = 0;
-               nbytes += nanddev_per_page_oobsize(nand);
-               if (!buf) {
-                       buf = spinand->oobbuf;
-                       column = nanddev_page_size(nand);
-               }
        }
 
        spinand_cache_op_adjust_colum(spinand, &adjreq, &column);
@@ -370,8 +368,8 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 
                /*
                 * We need to use the RANDOM LOAD CACHE operation if there's
-                * more than one iteration, because the LOAD operation resets
-                * the cache to 0xff.
+                * more than one iteration, because the LOAD operation might
+                * reset the cache to 0xff.
                 */
                if (nbytes) {
                        column = op.addr.val;
@@ -1018,11 +1016,11 @@ static int spinand_init(struct spinand_device *spinand)
        for (i = 0; i < nand->memorg.ntargets; i++) {
                ret = spinand_select_target(spinand, i);
                if (ret)
-                       goto err_free_bufs;
+                       goto err_manuf_cleanup;
 
                ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED);
                if (ret)
-                       goto err_free_bufs;
+                       goto err_manuf_cleanup;
        }
 
        ret = nanddev_init(nand, &spinand_ops, THIS_MODULE);
index 6371958dd17048768837c6eaf322a9ea59693239..21bf8ac783808fe0f0b00ee27a445dd4d2165095 100644 (file)
@@ -197,9 +197,9 @@ config VXLAN
 
 config GENEVE
        tristate "Generic Network Virtualization Encapsulation"
-       depends on INET && NET_UDP_TUNNEL
+       depends on INET
        depends on IPV6 || !IPV6
-       select NET_IP_TUNNEL
+       select NET_UDP_TUNNEL
        select GRO_CELLS
        ---help---
          This allows one to create geneve virtual interfaces that provide
@@ -519,7 +519,7 @@ config NET_FAILOVER
          and destroy a failover master netdev and manages a primary and
          standby slave netdevs that get registered via the generic failover
          infrastructure. This can be used by paravirtual drivers to enable
-         an alternate low latency datapath. It alsoenables live migration of
+         an alternate low latency datapath. It also enables live migration of
          a VM with direct attached VF by failing over to the paravirtual
          datapath when the VF is unplugged.
 
index a9d597f28023f874fa69102e4d2f8adb173214a7..485462d3087fcadcdbdb6fefc4b0846dbbb56838 100644 (file)
@@ -1963,6 +1963,9 @@ static int __bond_release_one(struct net_device *bond_dev,
        if (!bond_has_slaves(bond)) {
                bond_set_carrier(bond);
                eth_hw_addr_random(bond_dev);
+               bond->nest_level = SINGLE_DEPTH_NESTING;
+       } else {
+               bond->nest_level = dev_get_nest_level(bond_dev) + 1;
        }
 
        unblock_netpoll_tx();
index a0f954f36c09f37371dea2e74cd6de489fcf7b26..44e6c7b1b2226f06c66bc84b9463e69e0e09000e 100644 (file)
@@ -257,10 +257,7 @@ static int handle_tx(struct ser_device *ser)
                if (skb->len == 0) {
                        struct sk_buff *tmp = skb_dequeue(&ser->head);
                        WARN_ON(tmp != skb);
-                       if (in_interrupt())
-                               dev_kfree_skb_irq(skb);
-                       else
-                               kfree_skb(skb);
+                       dev_consume_skb_any(skb);
                }
        }
        /* Send flow off if queue is empty */
index 3b3f88ffab53cded04a2c1586727bf82472f43ad..c05e4d50d43d74a32ef38c656fb85bbb8b06e962 100644 (file)
@@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 {
        struct can_priv *priv = netdev_priv(dev);
-       struct sk_buff *skb = priv->echo_skb[idx];
-       struct canfd_frame *cf;
 
        if (idx >= priv->echo_skb_max) {
                netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -489,20 +487,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
                return NULL;
        }
 
-       if (!skb) {
-               netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
-                          __func__, idx);
-               return NULL;
-       }
+       if (priv->echo_skb[idx]) {
+               /* Using "struct canfd_frame::len" for the frame
+                * length is supported on both CAN and CANFD frames.
+                */
+               struct sk_buff *skb = priv->echo_skb[idx];
+               struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+               u8 len = cf->len;
 
-       /* Using "struct canfd_frame::len" for the frame
-        * length is supported on both CAN and CANFD frames.
-        */
-       cf = (struct canfd_frame *)skb->data;
-       *len_ptr = cf->len;
-       priv->echo_skb[idx] = NULL;
+               *len_ptr = len;
+               priv->echo_skb[idx] = NULL;
 
-       return skb;
+               return skb;
+       }
+
+       return NULL;
 }
 
 /*
index 0f36eafe3ac16d5ba55432608acfd12eee0dd8e0..1c66fb2ad76bebbfbcdce793d0685fef5a627773 100644 (file)
@@ -1106,7 +1106,7 @@ static int flexcan_chip_start(struct net_device *dev)
                }
        } else {
                /* clear and invalidate unused mailboxes first */
-               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) {
+               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) {
                        mb = flexcan_get_mb(priv, i);
                        priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
                                    &mb->can_ctrl);
@@ -1432,7 +1432,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
        gpr_np = of_find_node_by_phandle(phandle);
        if (!gpr_np) {
                dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
-               return PTR_ERR(gpr_np);
+               return -ENODEV;
        }
 
        priv = netdev_priv(dev);
index 90f51425298709ff47b09cb7de4e1b80acd14e7f..d9c56a779c088e3b68913615ffb000e742026caa 100644 (file)
@@ -511,9 +511,6 @@ static void b53_srab_prepare_irq(struct platform_device *pdev)
        /* Clear all pending interrupts */
        writel(0xffffffff, priv->regs + B53_SRAB_INTR);
 
-       if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID)
-               return;
-
        for (i = 0; i < B53_N_PORTS; i++) {
                port = &priv->port_intrs[i];
 
index 361fbde766540230348367b3766a829bdcd3dd12..17ec32b0a1cc0522ca7e250c859750cbf2d2c26a 100644 (file)
@@ -690,7 +690,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
         * port, the other ones have already been disabled during
         * bcm_sf2_sw_setup
         */
-       for (port = 0; port < DSA_MAX_PORTS; port++) {
+       for (port = 0; port < ds->num_ports; port++) {
                if (dsa_is_user_port(ds, port) || dsa_is_cpu_port(ds, port))
                        bcm_sf2_port_disable(ds, port, NULL);
        }
index 3b12e2dcff31b2690553df377d58e05163858833..8a5111f9414c07ae3aebc3950a7e64b337f827ac 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <linux/delay.h>
 #include <linux/export.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -15,7 +14,6 @@
 #include <linux/phy.h>
 #include <linux/etherdevice.h>
 #include <linux/if_bridge.h>
-#include <linux/of_gpio.h>
 #include <linux/of_net.h>
 #include <net/dsa.h>
 #include <net/switchdev.h>
index 74547f43b938971ef401a2e1ff191c779f579e99..a8a2c728afba01bd2bd2e6da4d843e5dd1e07628 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/of_gpio.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
index 8a517d8fb9d1613eeb3c9490201ab3e15f78580e..12fd7ce3f1ffdb7cdd9875af49468ff729a82c7a 100644 (file)
@@ -261,6 +261,7 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
        unsigned int sub_irq;
        unsigned int n;
        u16 reg;
+       u16 ctl1;
        int err;
 
        mutex_lock(&chip->reg_lock);
@@ -270,13 +271,28 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
        if (err)
                goto out;
 
-       for (n = 0; n < chip->g1_irq.nirqs; ++n) {
-               if (reg & (1 << n)) {
-                       sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
-                       handle_nested_irq(sub_irq);
-                       ++nhandled;
+       do {
+               for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+                       if (reg & (1 << n)) {
+                               sub_irq = irq_find_mapping(chip->g1_irq.domain,
+                                                          n);
+                               handle_nested_irq(sub_irq);
+                               ++nhandled;
+                       }
                }
-       }
+
+               mutex_lock(&chip->reg_lock);
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
+               if (err)
+                       goto unlock;
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
+unlock:
+               mutex_unlock(&chip->reg_lock);
+               if (err)
+                       goto out;
+               ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
+       } while (reg & ctl1);
+
 out:
        return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 }
@@ -2403,6 +2419,107 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
        return mv88e6xxx_g1_stats_clear(chip);
 }
 
+/* The mv88e6390 has some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
+                                 int reg, u16 val)
+{
+       u16 ctrl;
+       int err;
+
+       err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
+                                  PORT_RESERVED_1A, val);
+       if (err)
+               return err;
+
+       ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
+              PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+              reg;
+
+       return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+                                   PORT_RESERVED_1A, ctrl);
+}
+
+static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+       return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
+                             PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
+}
+
+
+static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
+                                 int reg, u16 *val)
+{
+       u16 ctrl;
+       int err;
+
+       ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
+              PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+              reg;
+
+       err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+                                  PORT_RESERVED_1A, ctrl);
+       if (err)
+               return err;
+
+       err = mv88e6390_hidden_wait(chip);
+       if (err)
+               return err;
+
+       return  mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
+                                   PORT_RESERVED_1A, val);
+}
+
+/* Check if the errata has already been applied. */
+static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+       u16 val;
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6390_hidden_read(chip, port, 0, &val);
+               if (err) {
+                       dev_err(chip->dev,
+                               "Error reading hidden register: %d\n", err);
+                       return false;
+               }
+               if (val != 0x01c0)
+                       return false;
+       }
+
+       return true;
+}
+
+/* The 6390 copper ports have an errata which require poking magic
+ * values into undocumented hidden registers and then performing a
+ * software reset.
+ */
+static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+
+       if (mv88e6390_setup_errata_applied(chip))
+               return 0;
+
+       /* Set the ports into blocking mode */
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
+               if (err)
+                       return err;
+       }
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+               if (err)
+                       return err;
+       }
+
+       return mv88e6xxx_software_reset(chip);
+}
+
 static int mv88e6xxx_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
@@ -2415,6 +2532,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 
        mutex_lock(&chip->reg_lock);
 
+       if (chip->info->ops->setup_errata) {
+               err = chip->info->ops->setup_errata(chip);
+               if (err)
+                       goto unlock;
+       }
+
        /* Cache the cmode of each port. */
        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
                if (chip->info->ops->port_get_cmode) {
@@ -3226,6 +3349,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3269,6 +3393,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3312,6 +3437,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 
 static const struct mv88e6xxx_ops mv88e6191_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3404,6 +3530,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3709,6 +3836,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3756,6 +3884,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
index f9ecb7872d32cd3a6f0807e176a8fc04f63692a7..546651d8c3e1fd5e395d2da1527c7a04f02a00f3 100644 (file)
@@ -300,6 +300,11 @@ struct mv88e6xxx_mdio_bus {
 };
 
 struct mv88e6xxx_ops {
+       /* Switch Setup Errata, called early in the switch setup to
+        * allow any errata actions to be performed
+        */
+       int (*setup_errata)(struct mv88e6xxx_chip *chip);
+
        int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
        int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
 
index 5200e4bdce93d19f3a3938f3fabbe74743b1352d..ea243840ee0fe62e28c5ccc6599533d406e22de8 100644 (file)
@@ -314,6 +314,7 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
 {
        struct mv88e6xxx_chip *chip = dev_id;
        struct mv88e6xxx_atu_entry entry;
+       int spid;
        int err;
        u16 val;
 
@@ -336,6 +337,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
        if (err)
                goto out;
 
+       spid = entry.state;
+
        if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) {
                dev_err_ratelimited(chip->dev,
                                    "ATU age out violation for %pM\n",
@@ -344,23 +347,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
 
        if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU member violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_member_violation++;
+                                   "ATU member violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_member_violation++;
        }
 
        if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU miss violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_miss_violation++;
+                                   "ATU miss violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_miss_violation++;
        }
 
        if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU full violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_full_violation++;
+                                   "ATU full violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_full_violation++;
        }
        mutex_unlock(&chip->reg_lock);
 
index 0d81866d0e4a9d2e91055338728b806598939354..e583641de758e816c321e980c81266a5b5d696c3 100644 (file)
 /* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
 #define MV88E6095_PORT_IEEE_PRIO_REMAP_4567    0x19
 
+/* Offset 0x1a: Magic undocumented errata register */
+#define PORT_RESERVED_1A                       0x1a
+#define PORT_RESERVED_1A_BUSY                  BIT(15)
+#define PORT_RESERVED_1A_WRITE                 BIT(14)
+#define PORT_RESERVED_1A_READ                  0
+#define PORT_RESERVED_1A_PORT_SHIFT            5
+#define PORT_RESERVED_1A_BLOCK                 (0xf << 10)
+#define PORT_RESERVED_1A_CTRL_PORT             4
+#define PORT_RESERVED_1A_DATA_PORT             5
+
 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
                        u16 *val);
 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
index 2caa8c8b4b55a02a0e3e242507acf847da3f3f1e..1bfc5ff8d81dc51a9b9c03551615126b0750bc77 100644 (file)
@@ -664,7 +664,7 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
        if (port < 9)
                return 0;
 
-       return mv88e6390_serdes_irq_setup(chip, port);
+       return mv88e6390x_serdes_irq_setup(chip, port);
 }
 
 void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
index b4b839a1d09521c521b340679592b3f36b5fb33f..ad41ec63cc9f03aae553e43660afbe08dbc85522 100644 (file)
@@ -347,16 +347,17 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
        struct device_node *mdio_np;
        int ret;
 
-       mdio_np = of_find_compatible_node(smi->dev->of_node, NULL,
-                                         "realtek,smi-mdio");
+       mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio");
        if (!mdio_np) {
                dev_err(smi->dev, "no MDIO bus node\n");
                return -ENODEV;
        }
 
        smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev);
-       if (!smi->slave_mii_bus)
-               return -ENOMEM;
+       if (!smi->slave_mii_bus) {
+               ret = -ENOMEM;
+               goto err_put_node;
+       }
        smi->slave_mii_bus->priv = smi;
        smi->slave_mii_bus->name = "SMI slave MII";
        smi->slave_mii_bus->read = realtek_smi_mdio_read;
@@ -371,10 +372,15 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
        if (ret) {
                dev_err(smi->dev, "unable to register MDIO bus %s\n",
                        smi->slave_mii_bus->id);
-               of_node_put(mdio_np);
+               goto err_put_node;
        }
 
        return 0;
+
+err_put_node:
+       of_node_put(mdio_np);
+
+       return ret;
 }
 
 static int realtek_smi_probe(struct platform_device *pdev)
@@ -457,6 +463,8 @@ static int realtek_smi_remove(struct platform_device *pdev)
        struct realtek_smi *smi = dev_get_drvdata(&pdev->dev);
 
        dsa_unregister_switch(smi->ds);
+       if (smi->slave_mii_bus)
+               of_node_put(smi->slave_mii_bus->dev.of_node);
        gpiod_set_value(smi->reset, 1);
 
        return 0;
index 4f11f98347edecd95632b3bc875f8c7df51685c9..1827ef1f6d5580c76ea31124ef9bb4102ad46248 100644 (file)
@@ -2059,7 +2059,7 @@ static inline void ace_tx_int(struct net_device *dev,
                if (skb) {
                        dev->stats.tx_packets++;
                        dev->stats.tx_bytes += skb->len;
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                        info->skb = NULL;
                }
 
index 0fb986ba32905a5dac78c926333c9765ec4678de..0ae723f75341710a5347f061985a5fd3bbc2a862 100644 (file)
@@ -145,7 +145,8 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv)
                        & 0xffff;
 
        if (inuse) { /* Tx FIFO is not empty */
-               ready = priv->tx_prod - priv->tx_cons - inuse - 1;
+               ready = max_t(int,
+                             priv->tx_prod - priv->tx_cons - inuse - 1, 0);
        } else {
                /* Check for buffered last packet */
                status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status));
index 02921d877c08a7a93556db45a116d78ed2c485cd..aa1d1f5339d2a4b78ee2092d0c9683e1262e2581 100644 (file)
@@ -714,8 +714,10 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
 
                phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
                                     priv->phy_iface);
-               if (IS_ERR(phydev))
+               if (IS_ERR(phydev)) {
                        netdev_err(dev, "Could not attach to PHY\n");
+                       phydev = NULL;
+               }
 
        } else {
                int ret;
index a70bb1bb90e7d89dc75f6f3dcc4f1455484057bc..a6eacf2099c3027c1e11c36fba99779808e64823 100644 (file)
@@ -2663,11 +2663,6 @@ static int ena_restore_device(struct ena_adapter *adapter)
                goto err_device_destroy;
        }
 
-       clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
-       /* Make sure we don't have a race with AENQ Links state handler */
-       if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
-               netif_carrier_on(adapter->netdev);
-
        rc = ena_enable_msix_and_set_admin_interrupts(adapter,
                                                      adapter->num_queues);
        if (rc) {
@@ -2684,6 +2679,11 @@ static int ena_restore_device(struct ena_adapter *adapter)
        }
 
        set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
+
+       clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
+       if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
+               netif_carrier_on(adapter->netdev);
+
        mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
        dev_err(&pdev->dev,
                "Device reset completed successfully, Driver info: %s\n",
index dc8b6173d8d8224a5485480dec81c4f6526d94f0..63870072cbbd47ed3ec2c4426ba1210236d9ccab 100644 (file)
@@ -45,7 +45,7 @@
 
 #define DRV_MODULE_VER_MAJOR   2
 #define DRV_MODULE_VER_MINOR   0
-#define DRV_MODULE_VER_SUBMINOR 2
+#define DRV_MODULE_VER_SUBMINOR 3
 
 #define DRV_MODULE_NAME                "ena"
 #ifndef DRV_MODULE_VERSION
index a90080f12e67cd07e26ed60b5d0f12cc29741f41..e548c0ae2e00049d55c400b9bde74f5a7e7f10c8 100644 (file)
@@ -666,7 +666,7 @@ static int amd8111e_tx(struct net_device *dev)
                        pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
                                        lp->tx_skbuff[tx_index]->len,
                                        PCI_DMA_TODEVICE);
-                       dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
+                       dev_consume_skb_irq(lp->tx_skbuff[tx_index]);
                        lp->tx_skbuff[tx_index] = NULL;
                        lp->tx_dma_addr[tx_index] = 0;
                }
index d272dc6984ac6ef3f61743a16912c13552c35b2f..b40d4377cc71d798e4cd1f8680a3620b90c65b0c 100644 (file)
 #define MAC_MDIOSCAR_PA_WIDTH          5
 #define MAC_MDIOSCAR_RA_INDEX          0
 #define MAC_MDIOSCAR_RA_WIDTH          16
-#define MAC_MDIOSCAR_REG_INDEX         0
-#define MAC_MDIOSCAR_REG_WIDTH         21
 #define MAC_MDIOSCCDR_BUSY_INDEX       22
 #define MAC_MDIOSCCDR_BUSY_WIDTH       1
 #define MAC_MDIOSCCDR_CMD_INDEX                16
index 1e929a1e4ca78145f5c8214e5562c740472bfc97..4666084eda16a318a4042b81c2d3a03cb7664a19 100644 (file)
@@ -1284,6 +1284,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
        }
 }
 
+static unsigned int xgbe_create_mdio_sca(int port, int reg)
+{
+       unsigned int mdio_sca, da;
+
+       da = (reg & MII_ADDR_C45) ? reg >> 16 : 0;
+
+       mdio_sca = 0;
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da);
+
+       return mdio_sca;
+}
+
 static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
                                   int reg, u16 val)
 {
@@ -1291,9 +1305,7 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
        reinit_completion(&pdata->mdio_complete);
 
-       mdio_sca = 0;
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+       mdio_sca = xgbe_create_mdio_sca(addr, reg);
        XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
        mdio_sccd = 0;
@@ -1317,9 +1329,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
        reinit_completion(&pdata->mdio_complete);
 
-       mdio_sca = 0;
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+       mdio_sca = xgbe_create_mdio_sca(addr, reg);
        XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
        mdio_sccd = 0;
index 6a8e2567f2bdef5e4a7fa3685de97354c67ed280..4d3855ceb50051a74f7668c0913b1ff8e562880a 100644 (file)
@@ -777,7 +777,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
 
                if (bp->tx_bufs[bp->tx_empty]) {
                        ++dev->stats.tx_packets;
-                       dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
+                       dev_consume_skb_irq(bp->tx_bufs[bp->tx_empty]);
                }
                bp->tx_bufs[bp->tx_empty] = NULL;
                bp->tx_fullup = 0;
index f44808959ff38b475f1a492e565c216502b1d65f..97ab0dd255522bf7b931af63526684145f20c40e 100644 (file)
@@ -638,7 +638,7 @@ static void b44_tx(struct b44 *bp)
                bytes_compl += skb->len;
                pkts_compl++;
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
 
        netdev_completed_queue(bp->dev, pkts_compl, bytes_compl);
@@ -1012,7 +1012,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
 
                skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
-               dev_kfree_skb_any(skb);
+               dev_consume_skb_any(skb);
                skb = bounce_skb;
        }
 
index f9521d0274b75fdaa52a72a5850ae2e285c03c25..28c9b0bdf2f6cff3fc5cfeed3d8ef0beed1dfb60 100644 (file)
@@ -520,7 +520,6 @@ static void bcm_sysport_get_wol(struct net_device *dev,
                                struct ethtool_wolinfo *wol)
 {
        struct bcm_sysport_priv *priv = netdev_priv(dev);
-       u32 reg;
 
        wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
        wol->wolopts = priv->wolopts;
@@ -528,11 +527,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
        if (!(priv->wolopts & WAKE_MAGICSECURE))
                return;
 
-       /* Return the programmed SecureOn password */
-       reg = umac_readl(priv, UMAC_PSW_MS);
-       put_unaligned_be16(reg, &wol->sopass[0]);
-       reg = umac_readl(priv, UMAC_PSW_LS);
-       put_unaligned_be32(reg, &wol->sopass[2]);
+       memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
 }
 
 static int bcm_sysport_set_wol(struct net_device *dev,
@@ -548,13 +543,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
        if (wol->wolopts & ~supported)
                return -EINVAL;
 
-       /* Program the SecureOn password */
-       if (wol->wolopts & WAKE_MAGICSECURE) {
-               umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
-                           UMAC_PSW_MS);
-               umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
-                           UMAC_PSW_LS);
-       }
+       if (wol->wolopts & WAKE_MAGICSECURE)
+               memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
 
        /* Flag the device and relevant IRQ as wakeup capable */
        if (wol->wolopts) {
@@ -2649,13 +2639,18 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
        unsigned int index, i = 0;
        u32 reg;
 
-       /* Password has already been programmed */
        reg = umac_readl(priv, UMAC_MPD_CTRL);
        if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE))
                reg |= MPD_EN;
        reg &= ~PSW_EN;
-       if (priv->wolopts & WAKE_MAGICSECURE)
+       if (priv->wolopts & WAKE_MAGICSECURE) {
+               /* Program the SecureOn password */
+               umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
+                           UMAC_PSW_MS);
+               umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
+                           UMAC_PSW_LS);
                reg |= PSW_EN;
+       }
        umac_writel(priv, reg, UMAC_MPD_CTRL);
 
        if (priv->wolopts & WAKE_FILTER) {
index 0887e63566499b4bee2ac1041315cc6c790c3019..0b192fea9c5d113542b9b2124d214b89844539aa 100644 (file)
@@ -12,6 +12,7 @@
 #define __BCM_SYSPORT_H
 
 #include <linux/bitmap.h>
+#include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/net_dim.h>
 
@@ -778,6 +779,7 @@ struct bcm_sysport_priv {
        unsigned int            crc_fwd:1;
        u16                     rev;
        u32                     wolopts;
+       u8                      sopass[SOPASS_MAX];
        unsigned int            wol_irq_disabled:1;
 
        /* MIB related fields */
index 4ab6eb3baefc38fa44872240887f66752e167d87..8bc7e495b027083942e6963c56bed62a25fd6f5d 100644 (file)
@@ -4973,12 +4973,18 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
                struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
                u32 map_idx = ring->map_idx;
+               unsigned int vector;
 
+               vector = bp->irq_tbl[map_idx].vector;
+               disable_irq_nosync(vector);
                rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
-               if (rc)
+               if (rc) {
+                       enable_irq(vector);
                        goto err_out;
+               }
                bnxt_set_db(bp, &cpr->cp_db, type, map_idx, ring->fw_ring_id);
                bnxt_db_nq(bp, &cpr->cp_db, cpr->cp_raw_cons);
+               enable_irq(vector);
                bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id;
 
                if (!i) {
@@ -5601,7 +5607,8 @@ static int bnxt_hwrm_check_pf_rings(struct bnxt *bp, int tx_rings, int rx_rings,
                         FUNC_CFG_REQ_FLAGS_STAT_CTX_ASSETS_TEST |
                         FUNC_CFG_REQ_FLAGS_VNIC_ASSETS_TEST;
                if (bp->flags & BNXT_FLAG_CHIP_P5)
-                       flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST;
+                       flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST |
+                                FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST;
                else
                        flags |= FUNC_CFG_REQ_FLAGS_RING_GRP_ASSETS_TEST;
        }
@@ -6221,9 +6228,12 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp,
                        rmem->pg_tbl_map = ctx_pg->ctx_dma_arr[i];
                        rmem->depth = 1;
                        rmem->nr_pages = MAX_CTX_PAGES;
-                       if (i == (nr_tbls - 1))
-                               rmem->nr_pages = ctx_pg->nr_pages %
-                                                MAX_CTX_PAGES;
+                       if (i == (nr_tbls - 1)) {
+                               int rem = ctx_pg->nr_pages % MAX_CTX_PAGES;
+
+                               if (rem)
+                                       rmem->nr_pages = rem;
+                       }
                        rc = bnxt_alloc_ctx_mem_blk(bp, pg_tbl);
                        if (rc)
                                break;
index f1aaac8e626862f05d629f4c52e2f3d782cc9a73..0a0995894ddb5d7a3cd100fea8a52d424bf1875b 100644 (file)
@@ -386,8 +386,8 @@ struct hwrm_err_output {
 #define HWRM_VERSION_MAJOR 1
 #define HWRM_VERSION_MINOR 10
 #define HWRM_VERSION_UPDATE 0
-#define HWRM_VERSION_RSVD 33
-#define HWRM_VERSION_STR "1.10.0.33"
+#define HWRM_VERSION_RSVD 35
+#define HWRM_VERSION_STR "1.10.0.35"
 
 /* hwrm_ver_get_input (size:192b/24B) */
 struct hwrm_ver_get_input {
@@ -1184,6 +1184,7 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_FLAGS_L2_CTX_ASSETS_TEST             0x100000UL
        #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE              0x200000UL
        #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC          0x400000UL
+       #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST                 0x800000UL
        __le32  enables;
        #define FUNC_CFG_REQ_ENABLES_MTU                     0x1UL
        #define FUNC_CFG_REQ_ENABLES_MRU                     0x2UL
index 5db9f4158e62a24469220170de442d5b5ab15052..134ae2862efab5d91ecfd04ebea9c0d373de2bf4 100644 (file)
@@ -1288,7 +1288,7 @@ static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
                 * for transmits, we just free buffers.
                 */
 
-               dev_kfree_skb_irq(sb);
+               dev_consume_skb_irq(sb);
 
                /*
                 * .. and advance to the next buffer.
index 3d45f4c92cf6e5d3f091ae654e5312165956d19f..9bbaad9f3d6326cdd113e48faa0d0e091bcde04c 100644 (file)
 #define MACB_CAPS_JUMBO                                0x00000020
 #define MACB_CAPS_GEM_HAS_PTP                  0x00000040
 #define MACB_CAPS_BD_RD_PREFETCH               0x00000080
+#define MACB_CAPS_NEEDS_RSTONUBR               0x00000100
 #define MACB_CAPS_FIFO_MODE                    0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE       0x20000000
 #define MACB_CAPS_SG_DISABLED                  0x40000000
@@ -1214,6 +1215,8 @@ struct macb {
 
        int     rx_bd_rd_prefetch;
        int     tx_bd_rd_prefetch;
+
+       u32     rx_intr_mask;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
index b126926ef7f57a0ad2f4a379c8d3a16e7c0f1051..2b2882615e8b7659b49977baf51ffdbdc003fa60 100644 (file)
@@ -56,8 +56,7 @@
 /* level of occupied TX descriptors under which we wake up TX process */
 #define MACB_TX_WAKEUP_THRESH(bp)      (3 * (bp)->tx_ring_size / 4)
 
-#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
-                                | MACB_BIT(ISR_ROVR))
+#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR))
 #define MACB_TX_ERR_FLAGS      (MACB_BIT(ISR_TUND)                     \
                                        | MACB_BIT(ISR_RLE)             \
                                        | MACB_BIT(TXERR))
@@ -1270,7 +1269,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
                        napi_reschedule(napi);
                } else {
-                       queue_writel(queue, IER, MACB_RX_INT_FLAGS);
+                       queue_writel(queue, IER, bp->rx_intr_mask);
                }
        }
 
@@ -1288,7 +1287,7 @@ static void macb_hresp_error_task(unsigned long data)
        u32 ctrl;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
+               queue_writel(queue, IDR, bp->rx_intr_mask |
                                         MACB_TX_INT_FLAGS |
                                         MACB_BIT(HRESP));
        }
@@ -1318,7 +1317,7 @@ static void macb_hresp_error_task(unsigned long data)
 
                /* Enable interrupts */
                queue_writel(queue, IER,
-                            MACB_RX_INT_FLAGS |
+                            bp->rx_intr_mask |
                             MACB_TX_INT_FLAGS |
                             MACB_BIT(HRESP));
        }
@@ -1372,14 +1371,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                            (unsigned int)(queue - bp->queues),
                            (unsigned long)status);
 
-               if (status & MACB_RX_INT_FLAGS) {
+               if (status & bp->rx_intr_mask) {
                        /* There's no point taking any more interrupts
                         * until we have processed the buffers. The
                         * scheduling call may fail if the poll routine
                         * is already scheduled, so disable interrupts
                         * now.
                         */
-                       queue_writel(queue, IDR, MACB_RX_INT_FLAGS);
+                       queue_writel(queue, IDR, bp->rx_intr_mask);
                        if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
 
@@ -1412,8 +1411,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                /* There is a hardware issue under heavy load where DMA can
                 * stop, this causes endless "used buffer descriptor read"
                 * interrupts but it can be cleared by re-enabling RX. See
-                * the at91 manual, section 41.3.1 or the Zynq manual
-                * section 16.7.4 for details.
+                * the at91rm9200 manual, section 41.3.1 or the Zynq manual
+                * section 16.7.4 for details. RXUBR is only enabled for
+                * these two versions.
                 */
                if (status & MACB_BIT(RXUBR)) {
                        ctrl = macb_readl(bp, NCR);
@@ -1738,12 +1738,8 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                *skb = nskb;
        }
 
-       if (padlen) {
-               if (padlen >= ETH_FCS_LEN)
-                       skb_put_zero(*skb, padlen - ETH_FCS_LEN);
-               else
-                       skb_trim(*skb, ETH_FCS_LEN - padlen);
-       }
+       if (padlen > ETH_FCS_LEN)
+               skb_put_zero(*skb, padlen - ETH_FCS_LEN);
 
 add_fcs:
        /* set FCS to packet */
@@ -2263,7 +2259,7 @@ static void macb_init_hw(struct macb *bp)
 
                /* Enable interrupts */
                queue_writel(queue, IER,
-                            MACB_RX_INT_FLAGS |
+                            bp->rx_intr_mask |
                             MACB_TX_INT_FLAGS |
                             MACB_BIT(HRESP));
        }
@@ -3911,6 +3907,7 @@ static const struct macb_config sama5d4_config = {
 };
 
 static const struct macb_config emac_config = {
+       .caps = MACB_CAPS_NEEDS_RSTONUBR,
        .clk_init = at91ether_clk_init,
        .init = at91ether_init,
 };
@@ -3932,7 +3929,8 @@ static const struct macb_config zynqmp_config = {
 };
 
 static const struct macb_config zynq_config = {
-       .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF,
+       .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF |
+               MACB_CAPS_NEEDS_RSTONUBR,
        .dma_burst_length = 16,
        .clk_init = macb_clk_init,
        .init = macb_init,
@@ -4087,6 +4085,10 @@ static int macb_probe(struct platform_device *pdev)
                                                macb_dma_desc_get_size(bp);
        }
 
+       bp->rx_intr_mask = MACB_RX_INT_FLAGS;
+       if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
+               bp->rx_intr_mask |= MACB_BIT(RXUBR);
+
        mac = of_get_mac_address(np);
        if (mac) {
                ether_addr_copy(bp->dev->dev_addr, mac);
index 5f03199a3acf28940d78e515820d7af51e3cee4b..05f4a3b21e29ac79c367a4c770cef051b8d422fc 100644 (file)
@@ -54,7 +54,6 @@ config CAVIUM_PTP
        tristate "Cavium PTP coprocessor as PTP clock"
        depends on 64BIT && PCI
        imply PTP_1588_CLOCK
-       default y
        ---help---
          This driver adds support for the Precision Time Protocol Clocks and
          Timestamping coprocessor (PTP) found on Cavium processors.
index 85f22c28668054b4475701cdc3c4b99314b089f0..89db739b781910e8b482b1b24b7a99e0dd322df7 100644 (file)
@@ -2381,7 +2381,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
                                        lro_add_page(adap, qs, fl,
                                                     G_RSPD_LEN(len),
                                                     flags & F_RSPD_EOP);
-                                        goto next_fl;
+                                       goto next_fl;
                                }
 
                                skb = get_packet_pg(adap, fl, q,
@@ -3214,11 +3214,13 @@ void t3_start_sge_timers(struct adapter *adap)
        for (i = 0; i < SGE_QSETS; ++i) {
                struct sge_qset *q = &adap->sge.qs[i];
 
-       if (q->tx_reclaim_timer.function)
-               mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+               if (q->tx_reclaim_timer.function)
+                       mod_timer(&q->tx_reclaim_timer,
+                                 jiffies + TX_RECLAIM_PERIOD);
 
-       if (q->rx_reclaim_timer.function)
-               mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
+               if (q->rx_reclaim_timer.function)
+                       mod_timer(&q->rx_reclaim_timer,
+                                 jiffies + RX_RECLAIM_PERIOD);
        }
 }
 
index 080918af773cd1285accf3a08c95d8bd8391166b..0a9f2c5966242d472a3131c94c5085cfdb33aaab 100644 (file)
@@ -1082,7 +1082,7 @@ int t3_check_fw_version(struct adapter *adapter)
                CH_WARN(adapter, "found newer FW version(%u.%u), "
                        "driver compiled for version %u.%u\n", major, minor,
                        FW_VERSION_MAJOR, FW_VERSION_MINOR);
-                       return 0;
+               return 0;
        }
        return -EINVAL;
 }
@@ -3619,7 +3619,7 @@ int t3_reset_adapter(struct adapter *adapter)
 
 static int init_parity(struct adapter *adap)
 {
-               int i, err, addr;
+       int i, err, addr;
 
        if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
                return -EBUSY;
@@ -3806,6 +3806,6 @@ int t3_replay_prep_adapter(struct adapter *adapter)
                p->phy.ops->power_down(&p->phy, 1);
        }
 
-return 0;
+       return 0;
 }
 
index 9f9d6cae39d555057ba63ac6ee874d0884c0c51d..58a039c3224adfca8efc182c129617c0ae3d36e1 100644 (file)
@@ -378,10 +378,10 @@ static void cxgb4_init_ptp_timer(struct adapter *adapter)
        int err;
 
        memset(&c, 0, sizeof(c));
-               c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
-                                            FW_CMD_REQUEST_F |
-                                            FW_CMD_WRITE_F |
-                                            FW_PTP_CMD_PORTID_V(0));
+       c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
+                                    FW_CMD_REQUEST_F |
+                                    FW_CMD_WRITE_F |
+                                    FW_PTP_CMD_PORTID_V(0));
        c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
        c.u.scmd.sc = FW_PTP_SC_INIT_TIMER;
 
index 9a6065a3fa46cd68baafaa8be568249effe1bb3b..c041f44324db1d0e3cb16acd4b06925f6c481dcf 100644 (file)
@@ -78,7 +78,7 @@ static void free_msix_idx_in_bmap(struct adapter *adap, unsigned int msix_idx)
        unsigned long flags;
 
        spin_lock_irqsave(&bmap->lock, flags);
-        __clear_bit(msix_idx, bmap->msix_bmap);
+       __clear_bit(msix_idx, bmap->msix_bmap);
        spin_unlock_irqrestore(&bmap->lock, flags);
 }
 
index e8c34292a0ec578285f233207c2eb874851b1681..2b03f6187a24ec1e88669c2e4e8fbe4bf4077cfc 100644 (file)
@@ -3794,7 +3794,7 @@ int t4_load_phy_fw(struct adapter *adap,
        /* If we have version number support, then check to see if the adapter
         * already has up-to-date PHY firmware loaded.
         */
-        if (phy_fw_version) {
+       if (phy_fw_version) {
                new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size);
                ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver);
                if (ret < 0)
index 60641e202534109f3d1341607b6c4d413b75f65b..9a7f70db20c7f67da8608f65b5e9c98efbce2412 100644 (file)
@@ -1434,7 +1434,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
                 * csum is correct or is zero.
                 */
                if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
-                   tcp_udp_csum_ok && ipv4_csum_ok && outer_csum_ok) {
+                   tcp_udp_csum_ok && outer_csum_ok &&
+                   (ipv4_csum_ok || ipv6)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        skb->csum_level = encap;
                }
index 13430f75496cc3e2b981b02adb3b32275578c3ce..f1a2da15dd0a6f00718eb68fb1eb82214c2c484d 100644 (file)
@@ -585,7 +585,7 @@ static void de_tx (struct de_private *de)
                                netif_dbg(de, tx_done, de->dev,
                                          "tx done, slot %d\n", tx_tail);
                        }
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                }
 
 next:
index f53090cde041d2ac37f75e5f406b401fef25f08b..dfebc30c4841211990b7888d61b01780e31f44aa 100644 (file)
@@ -2051,6 +2051,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        bool nonlinear = skb_is_nonlinear(skb);
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa_percpu_priv *percpu_priv;
+       struct netdev_queue *txq;
        struct dpaa_priv *priv;
        struct qm_fd fd;
        int offset = 0;
@@ -2100,6 +2101,11 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        if (unlikely(err < 0))
                goto skb_to_fd_failed;
 
+       txq = netdev_get_tx_queue(net_dev, queue_mapping);
+
+       /* LLTX requires to do our own update of trans_start */
+       txq->trans_start = jiffies;
+
        if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
                fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
index 809a155eb193c7021734392956373c89323fd5aa..f6d244c663fd5d8f7a9524455c96798c9ac30663 100644 (file)
@@ -9,8 +9,9 @@ config FSL_DPAA2_ETH
 
 config FSL_DPAA2_PTP_CLOCK
        tristate "Freescale DPAA2 PTP Clock"
-       depends on FSL_DPAA2_ETH && POSIX_TIMERS
-       select PTP_1588_CLOCK
+       depends on FSL_DPAA2_ETH
+       imply PTP_1588_CLOCK
+       default y
        help
          This driver adds support for using the DPAA2 1588 timer module
          as a PTP clock.
index ae0f88bce9aa6edca13e5cba73b5aba8814097ff..697c2427f2b70c06c87dd00ae23d4e0b06d4fc3d 100644 (file)
@@ -2098,6 +2098,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev)
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
        defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
        defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST)
+static __u32 fec_enet_register_version = 2;
 static u32 fec_enet_register_offset[] = {
        FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0,
        FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL,
@@ -2128,6 +2129,7 @@ static u32 fec_enet_register_offset[] = {
        IEEE_R_FDXFC, IEEE_R_OCTETS_OK
 };
 #else
+static __u32 fec_enet_register_version = 1;
 static u32 fec_enet_register_offset[] = {
        FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0,
        FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0,
@@ -2149,6 +2151,8 @@ static void fec_enet_get_regs(struct net_device *ndev,
        u32 *buf = (u32 *)regbuf;
        u32 i, off;
 
+       regs->version = fec_enet_register_version;
+
        memset(buf, 0, regs->len);
 
        for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) {
@@ -3467,7 +3471,7 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_clk_ipg;
 
-       fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
+       fep->reg_phy = devm_regulator_get_optional(&pdev->dev, "phy");
        if (!IS_ERR(fep->reg_phy)) {
                ret = regulator_enable(fep->reg_phy);
                if (ret) {
index b90bab72efdb3b3d4370bc5616ff0e8609b85cfd..c1968b3ecec87cf8fcd807c4f34d0be4cc6e27e8 100644 (file)
@@ -369,7 +369,7 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
                dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len,
                                 DMA_TO_DEVICE);
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
        spin_unlock(&priv->lock);
 
index c3d539e209ed26a4ee3f022c45be85394a1ef398..eb3e65e8868f9f65047ab24e8094f56e307bb64b 100644 (file)
@@ -1879,6 +1879,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
        u16 i, j;
        u8 __iomem *bd;
 
+       netdev_reset_queue(ugeth->ndev);
+
        ug_info = ugeth->ug_info;
        uf_info = &ug_info->uf_info;
 
index ad1779fc410e64b668bf9bdf5dc037eb46a737fa..a78bfafd212c836b832a65bdaa62cc15259897c1 100644 (file)
@@ -147,12 +147,10 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
        struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
        int i;
 
-       vf_cb->mac_cb    = NULL;
-
-       kfree(vf_cb);
-
        for (i = 0; i < handle->q_num; i++)
                hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
+
+       kfree(vf_cb);
 }
 
 static int hns_ae_wait_flow_down(struct hnae_handle *handle)
index 3b9e74be5fbd27309fb00e1d36195f619c6a8ac6..b8155f5e71b41aee8c4e3b7e8cab151aac766ffb 100644 (file)
@@ -3081,6 +3081,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
        dsaf_dev = dev_get_drvdata(&pdev->dev);
        if (!dsaf_dev) {
                dev_err(&pdev->dev, "dsaf_dev is NULL\n");
+               put_device(&pdev->dev);
                return -ENODEV;
        }
 
@@ -3088,6 +3089,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
        if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
                dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n",
                        dsaf_dev->ae_dev.name);
+               put_device(&pdev->dev);
                return -ENODEV;
        }
 
index 5748d3f722f68ce4127c706dcba41ed71b66f4c8..60e7d7ae3787c280d9b21319a1493ccc5d570de8 100644 (file)
@@ -1170,6 +1170,13 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
        if (!h->phy_dev)
                return 0;
 
+       ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
+       linkmode_and(phy_dev->supported, phy_dev->supported, supported);
+       linkmode_copy(phy_dev->advertising, phy_dev->supported);
+
+       if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
+               phy_dev->autoneg = false;
+
        if (h->phy_if != PHY_INTERFACE_MODE_XGMII) {
                phy_dev->dev_flags = 0;
 
@@ -1181,16 +1188,6 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
        if (unlikely(ret))
                return -ENODEV;
 
-       ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
-       linkmode_and(phy_dev->supported, phy_dev->supported, supported);
-       linkmode_copy(phy_dev->advertising, phy_dev->supported);
-
-       if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
-               phy_dev->autoneg = false;
-
-       if (h->phy_if == PHY_INTERFACE_MODE_SGMII)
-               phy_stop(phy_dev);
-
        return 0;
 }
 
@@ -2421,6 +2418,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 out_notify_fail:
        (void)cancel_work_sync(&priv->service_task);
 out_read_prop_fail:
+       /* safe for ACPI FW */
+       of_node_put(to_of_node(priv->fwnode));
        free_netdev(ndev);
        return ret;
 }
@@ -2450,6 +2449,9 @@ static int hns_nic_dev_remove(struct platform_device *pdev)
        set_bit(NIC_STATE_REMOVING, &priv->state);
        (void)cancel_work_sync(&priv->service_task);
 
+       /* safe for ACPI FW */
+       of_node_put(to_of_node(priv->fwnode));
+
        free_netdev(ndev);
        return 0;
 }
index 8e9b95871d30810de0e7a12c028ffeecaff0def5..ce15d2350db948ec91c199153170715edb10674a 100644 (file)
@@ -1157,16 +1157,18 @@ static int hns_get_regs_len(struct net_device *net_dev)
  */
 static int hns_nic_nway_reset(struct net_device *netdev)
 {
-       int ret = 0;
        struct phy_device *phy = netdev->phydev;
 
-       if (netif_running(netdev)) {
-               /* if autoneg is disabled, don't restart auto-negotiation */
-               if (phy && phy->autoneg == AUTONEG_ENABLE)
-                       ret = genphy_restart_aneg(phy);
-       }
+       if (!netif_running(netdev))
+               return 0;
 
-       return ret;
+       if (!phy)
+               return -EOPNOTSUPP;
+
+       if (phy->autoneg != AUTONEG_ENABLE)
+               return -EINVAL;
+
+       return genphy_restart_aneg(phy);
 }
 
 static u32
index 017e08452d8c0b2ae9b1117e182b099aa36c0447..baf5cc251f3299499f3fc03ee17513aa740110f6 100644 (file)
@@ -321,7 +321,7 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
                }
 
                hns_mdio_cmd_write(mdio_dev, is_c45,
-                                  MDIO_C45_WRITE_ADDR, phy_id, devad);
+                                  MDIO_C45_READ, phy_id, devad);
        }
 
        /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
index d719668a6684aa5f9a8b93b8a991a08b28cb004a..92929750f83250c53e8815aaec3a89ede1c3fdb0 100644 (file)
@@ -1310,7 +1310,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
                                                dev->stats.tx_aborted_errors++;
                                }
 
-                               dev_kfree_skb_irq(skb);
+                               dev_consume_skb_irq(skb);
 
                                tx_cmd->cmd.command = 0; /* Mark free */
                                break;
index 098d8764c0ea96ed2c270e287672cccb7b720c45..dd71d5db727471d0047608a39d12dc78f3a8848a 100644 (file)
@@ -1313,7 +1313,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
        unsigned long lpar_rc;
        u16 mss = 0;
 
-restart_poll:
        while (frames_processed < budget) {
                if (!ibmveth_rxq_pending_buffer(adapter))
                        break;
@@ -1401,7 +1400,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
                    napi_reschedule(napi)) {
                        lpar_rc = h_vio_signal(adapter->vdev->unit_address,
                                               VIO_IRQ_DISABLE);
-                       goto restart_poll;
                }
        }
 
index 31fb76ee9d826ff34810735f5196f0c23cb070aa..a1246e89aad4685f0c9e8a48429cec573b97d500 100644 (file)
@@ -159,7 +159,7 @@ config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
        depends on PCI
        select MDIO
-       select MDIO_DEVICE
+       select PHYLIB
        imply PTP_1588_CLOCK
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
index fe1592ae87690bd3c22e82527d5dc50c0197d820..ca54e268d157bd9afb7ab23854a8ae52ff260215 100644 (file)
@@ -515,7 +515,7 @@ struct igb_adapter {
        /* OS defined structs */
        struct pci_dev *pdev;
 
-       struct mutex stats64_lock;
+       spinlock_t stats64_lock;
        struct rtnl_link_stats64 stats64;
 
        /* structs defined in e1000_hw.h */
index 7426060b678fd3075bef3812ff5b9aa9c1653aaa..c5767106824521a2e78374310cbe5f15ecc4d125 100644 (file)
@@ -2295,7 +2295,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
        int i, j;
        char *p;
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
 
        for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
@@ -2338,7 +2338,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
                } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
                i += IGB_RX_QUEUE_STATS_LEN;
        }
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 }
 
 static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
index 87bdf1604ae2c5933e18827a0a7d5ad02942b936..7137e7f9c7f3c7d17a6123e7a83234f58a886e82 100644 (file)
@@ -2203,9 +2203,9 @@ void igb_down(struct igb_adapter *adapter)
        del_timer_sync(&adapter->phy_info_timer);
 
        /* record the stats before reset*/
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
@@ -3840,7 +3840,7 @@ static int igb_sw_init(struct igb_adapter *adapter)
        adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
        spin_lock_init(&adapter->nfc_lock);
-       mutex_init(&adapter->stats64_lock);
+       spin_lock_init(&adapter->stats64_lock);
 #ifdef CONFIG_PCI_IOV
        switch (hw->mac.type) {
        case e1000_82576:
@@ -5406,9 +5406,9 @@ static void igb_watchdog_task(struct work_struct *work)
                }
        }
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igb_ring *tx_ring = adapter->tx_ring[i];
@@ -6235,10 +6235,10 @@ static void igb_get_stats64(struct net_device *netdev,
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
        memcpy(stats, &adapter->stats64, sizeof(*stats));
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 }
 
 /**
index 742f0c1f60df785eabe83ff5ab18746526100e2a..6d55e3d0b7ea20f3f85aeda976e8f2f6733bc09a 100644 (file)
@@ -825,7 +825,7 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!cgx->cgx_cmd_workq) {
                dev_err(dev, "alloc workqueue failed for cgx cmd");
                err = -ENOMEM;
-               goto err_release_regions;
+               goto err_free_irq_vectors;
        }
 
        list_add(&cgx->cgx_list, &cgx_list);
@@ -841,6 +841,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 err_release_lmac:
        cgx_lmac_exit(cgx);
        list_del(&cgx->cgx_list);
+err_free_irq_vectors:
+       pci_free_irq_vectors(pdev);
 err_release_regions:
        pci_release_regions(pdev);
 err_disable_device:
index 04fd1f135011f1a068bbc79991af0d05a7c56583..654ac534b10e3e8e04911b618d5fd1cb6fb5c8c8 100644 (file)
@@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        memset(p, 0, regs->len);
        memcpy_fromio(p, io, B3_RAM_ADDR);
 
-       memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-                     regs->len - B3_RI_WTO_R1);
+       if (regs->len > B3_RI_WTO_R1) {
+               memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+                             regs->len - B3_RI_WTO_R1);
+       }
 }
 
 /* Wake on Lan only supported on Yukon chips with rev 1 or above */
index fe9653fa8aea4bc43d2c4a525dd10d183b73ff98..49f926b7a91cffa90e07d08850632ba1d340722d 100644 (file)
@@ -258,11 +258,6 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
-       if (dev->phydev->link)
-               netif_carrier_on(dev);
-       else
-               netif_carrier_off(dev);
-
        if (!of_phy_is_fixed_link(mac->of_node))
                phy_print_status(dev->phydev);
 }
@@ -347,17 +342,6 @@ static int mtk_phy_connect(struct net_device *dev)
        if (mtk_phy_connect_node(eth, mac, np))
                goto err_phy;
 
-       dev->phydev->autoneg = AUTONEG_ENABLE;
-       dev->phydev->speed = 0;
-       dev->phydev->duplex = 0;
-
-       phy_set_max_speed(dev->phydev, SPEED_1000);
-       phy_support_asym_pause(dev->phydev);
-       linkmode_copy(dev->phydev->advertising, dev->phydev->supported);
-       linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
-                        dev->phydev->advertising);
-       phy_start_aneg(dev->phydev);
-
        of_node_put(np);
 
        return 0;
index db909b6069b5076208dbae35bd9358676c050ed5..65f8a4b6ed0c45e59e206ea8a907275ae2177b9e 100644 (file)
@@ -306,14 +306,16 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
 
        if (entries_per_copy < entries) {
                for (i = 0; i < entries / entries_per_copy; i++) {
-                       err = copy_to_user(buf, init_ents, PAGE_SIZE);
+                       err = copy_to_user((void __user *)buf, init_ents, PAGE_SIZE) ?
+                               -EFAULT : 0;
                        if (err)
                                goto out;
 
                        buf += PAGE_SIZE;
                }
        } else {
-               err = copy_to_user(buf, init_ents, entries * cqe_size);
+               err = copy_to_user((void __user *)buf, init_ents, entries * cqe_size) ?
+                       -EFAULT : 0;
        }
 
 out:
index 9a0881cb7f51d54fb5dff8f9ed9884cd5f3b867f..6c01314e87b09716ca076cbe4a91621b9e474fba 100644 (file)
@@ -617,6 +617,8 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
 }
 #endif
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 /* We reach this function only after checking that any of
  * the (IPv4 | IPv6) bits are set in cqe->status.
  */
@@ -624,9 +626,20 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
                      netdev_features_t dev_features)
 {
        __wsum hw_checksum = 0;
+       void *hdr;
+
+       /* CQE csum doesn't cover padding octets in short ethernet
+        * frames. And the pad field is appended prior to calculating
+        * and appending the FCS field.
+        *
+        * Detecting these padded frames requires to verify and parse
+        * IP headers, so we simply force all those small frames to skip
+        * checksum complete.
+        */
+       if (short_frame(skb->len))
+               return -EINVAL;
 
-       void *hdr = (u8 *)va + sizeof(struct ethhdr);
-
+       hdr = (u8 *)va + sizeof(struct ethhdr);
        hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
 
        if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
@@ -819,6 +832,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                skb_record_rx_queue(skb, cq_ring);
 
                if (likely(dev->features & NETIF_F_RXCSUM)) {
+                       /* TODO: For IP non TCP/UDP packets when csum complete is
+                        * not an option (not supported or any other reason) we can
+                        * actually check cqe IPOK status bit and report
+                        * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE
+                        */
                        if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
                                                       MLX4_CQE_STATUS_UDP)) &&
                            (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
index 7df728f1e5b526809d6db486a80e9feb841b598c..6e501af0e5322d648adf3938f9ac0e4d2a2d6360 100644 (file)
@@ -2067,9 +2067,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 {
        struct mlx4_cmd_mailbox *mailbox;
        __be32 *outbox;
+       u64 qword_field;
        u32 dword_field;
-       int err;
+       u16 word_field;
        u8 byte_field;
+       int err;
        static const u8 a0_dmfs_query_hw_steering[] =  {
                [0] = MLX4_STEERING_DMFS_A0_DEFAULT,
                [1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
@@ -2097,19 +2099,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 
        /* QPC/EEC/CQC/EQC/RDMARC attributes */
 
-       MLX4_GET(param->qpc_base,      outbox, INIT_HCA_QPC_BASE_OFFSET);
-       MLX4_GET(param->log_num_qps,   outbox, INIT_HCA_LOG_QP_OFFSET);
-       MLX4_GET(param->srqc_base,     outbox, INIT_HCA_SRQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_srqs,  outbox, INIT_HCA_LOG_SRQ_OFFSET);
-       MLX4_GET(param->cqc_base,      outbox, INIT_HCA_CQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_cqs,   outbox, INIT_HCA_LOG_CQ_OFFSET);
-       MLX4_GET(param->altc_base,     outbox, INIT_HCA_ALTC_BASE_OFFSET);
-       MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
-       MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
-       MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
-       MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
-       MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
+       MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
+       param->qpc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
+       param->log_num_qps = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
+       param->srqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
+       param->log_num_srqs = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
+       param->cqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
+       param->log_num_cqs = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
+       param->altc_base = qword_field;
+       MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
+       param->auxc_base = qword_field;
+       MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
+       param->eqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
+       param->log_num_eqs = byte_field & 0x1f;
+       MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
+       param->num_sys_eqs = word_field & 0xfff;
+       MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
+       param->rdmarc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
+       param->log_rd_per_qp = byte_field & 0x7;
 
        MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
        if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
@@ -2128,22 +2143,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        /* steering attributes */
        if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
-               MLX4_GET(param->log_mc_entry_sz, outbox,
-                        INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
-               MLX4_GET(param->log_mc_table_sz, outbox,
-                        INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
-               MLX4_GET(byte_field, outbox,
-                        INIT_HCA_FS_A0_OFFSET);
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
+               param->log_mc_entry_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
+               param->log_mc_table_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
                param->dmfs_high_steer_mode =
                        a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
        } else {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
-               MLX4_GET(param->log_mc_entry_sz, outbox,
-                        INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
-               MLX4_GET(param->log_mc_hash_sz,  outbox,
-                        INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-               MLX4_GET(param->log_mc_table_sz, outbox,
-                        INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+               MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
+               param->log_mc_entry_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field,  outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+               param->log_mc_hash_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+               param->log_mc_table_sz = byte_field & 0x1f;
        }
 
        /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
@@ -2167,15 +2181,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        /* TPT attributes */
 
        MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
-       MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
-       MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+       MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
+       param->mw_enabled = byte_field >> 7;
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+       param->log_mpt_sz = byte_field & 0x3f;
        MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
        MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
 
        /* UAR attributes */
 
        MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
-       MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+       param->log_uar_sz = byte_field & 0xf;
 
        /* phv_check enable */
        MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
index 4b4351141b94c7853e5519afc5bf48b8374cc196..d89a3da89e5aa0ee304481bd165a7179e52f72e9 100644 (file)
@@ -57,12 +57,12 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu
        int i;
 
        if (chunk->nsg > 0)
-               pci_unmap_sg(dev->persist->pdev, chunk->mem, chunk->npages,
-                            PCI_DMA_BIDIRECTIONAL);
+               dma_unmap_sg(&dev->persist->pdev->dev, chunk->sg, chunk->npages,
+                            DMA_BIDIRECTIONAL);
 
        for (i = 0; i < chunk->npages; ++i)
-               __free_pages(sg_page(&chunk->mem[i]),
-                            get_order(chunk->mem[i].length));
+               __free_pages(sg_page(&chunk->sg[i]),
+                            get_order(chunk->sg[i].length));
 }
 
 static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
@@ -71,9 +71,9 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *
 
        for (i = 0; i < chunk->npages; ++i)
                dma_free_coherent(&dev->persist->pdev->dev,
-                                 chunk->mem[i].length,
-                                 lowmem_page_address(sg_page(&chunk->mem[i])),
-                                 sg_dma_address(&chunk->mem[i]));
+                                 chunk->buf[i].size,
+                                 chunk->buf[i].addr,
+                                 chunk->buf[i].dma_addr);
 }
 
 void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent)
@@ -111,22 +111,21 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order,
        return 0;
 }
 
-static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
-                                   int order, gfp_t gfp_mask)
+static int mlx4_alloc_icm_coherent(struct device *dev, struct mlx4_icm_buf *buf,
+                                  int order, gfp_t gfp_mask)
 {
-       void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order,
-                                      &sg_dma_address(mem), gfp_mask);
-       if (!buf)
+       buf->addr = dma_alloc_coherent(dev, PAGE_SIZE << order,
+                                      &buf->dma_addr, gfp_mask);
+       if (!buf->addr)
                return -ENOMEM;
 
-       if (offset_in_page(buf)) {
-               dma_free_coherent(dev, PAGE_SIZE << order,
-                                 buf, sg_dma_address(mem));
+       if (offset_in_page(buf->addr)) {
+               dma_free_coherent(dev, PAGE_SIZE << order, buf->addr,
+                                 buf->dma_addr);
                return -ENOMEM;
        }
 
-       sg_set_buf(mem, buf, PAGE_SIZE << order);
-       sg_dma_len(mem) = PAGE_SIZE << order;
+       buf->size = PAGE_SIZE << order;
        return 0;
 }
 
@@ -159,21 +158,21 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
 
        while (npages > 0) {
                if (!chunk) {
-                       chunk = kmalloc_node(sizeof(*chunk),
+                       chunk = kzalloc_node(sizeof(*chunk),
                                             gfp_mask & ~(__GFP_HIGHMEM |
                                                          __GFP_NOWARN),
                                             dev->numa_node);
                        if (!chunk) {
-                               chunk = kmalloc(sizeof(*chunk),
+                               chunk = kzalloc(sizeof(*chunk),
                                                gfp_mask & ~(__GFP_HIGHMEM |
                                                             __GFP_NOWARN));
                                if (!chunk)
                                        goto fail;
                        }
+                       chunk->coherent = coherent;
 
-                       sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN);
-                       chunk->npages = 0;
-                       chunk->nsg    = 0;
+                       if (!coherent)
+                               sg_init_table(chunk->sg, MLX4_ICM_CHUNK_LEN);
                        list_add_tail(&chunk->list, &icm->chunk_list);
                }
 
@@ -186,10 +185,10 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
 
                if (coherent)
                        ret = mlx4_alloc_icm_coherent(&dev->persist->pdev->dev,
-                                                     &chunk->mem[chunk->npages],
-                                                     cur_order, mask);
+                                               &chunk->buf[chunk->npages],
+                                               cur_order, mask);
                else
-                       ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages],
+                       ret = mlx4_alloc_icm_pages(&chunk->sg[chunk->npages],
                                                   cur_order, mask,
                                                   dev->numa_node);
 
@@ -205,9 +204,9 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
                if (coherent)
                        ++chunk->nsg;
                else if (chunk->npages == MLX4_ICM_CHUNK_LEN) {
-                       chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
-                                               chunk->npages,
-                                               PCI_DMA_BIDIRECTIONAL);
+                       chunk->nsg = dma_map_sg(&dev->persist->pdev->dev,
+                                               chunk->sg, chunk->npages,
+                                               DMA_BIDIRECTIONAL);
 
                        if (chunk->nsg <= 0)
                                goto fail;
@@ -220,9 +219,8 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
        }
 
        if (!coherent && chunk) {
-               chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
-                                       chunk->npages,
-                                       PCI_DMA_BIDIRECTIONAL);
+               chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg,
+                                       chunk->npages, DMA_BIDIRECTIONAL);
 
                if (chunk->nsg <= 0)
                        goto fail;
@@ -320,7 +318,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
        u64 idx;
        struct mlx4_icm_chunk *chunk;
        struct mlx4_icm *icm;
-       struct page *page = NULL;
+       void *addr = NULL;
 
        if (!table->lowmem)
                return NULL;
@@ -336,28 +334,49 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
 
        list_for_each_entry(chunk, &icm->chunk_list, list) {
                for (i = 0; i < chunk->npages; ++i) {
+                       dma_addr_t dma_addr;
+                       size_t len;
+
+                       if (table->coherent) {
+                               len = chunk->buf[i].size;
+                               dma_addr = chunk->buf[i].dma_addr;
+                               addr = chunk->buf[i].addr;
+                       } else {
+                               struct page *page;
+
+                               len = sg_dma_len(&chunk->sg[i]);
+                               dma_addr = sg_dma_address(&chunk->sg[i]);
+
+                               /* XXX: we should never do this for highmem
+                                * allocation.  This function either needs
+                                * to be split, or the kernel virtual address
+                                * return needs to be made optional.
+                                */
+                               page = sg_page(&chunk->sg[i]);
+                               addr = lowmem_page_address(page);
+                       }
+
                        if (dma_handle && dma_offset >= 0) {
-                               if (sg_dma_len(&chunk->mem[i]) > dma_offset)
-                                       *dma_handle = sg_dma_address(&chunk->mem[i]) +
-                                               dma_offset;
-                               dma_offset -= sg_dma_len(&chunk->mem[i]);
+                               if (len > dma_offset)
+                                       *dma_handle = dma_addr + dma_offset;
+                               dma_offset -= len;
                        }
+
                        /*
                         * DMA mapping can merge pages but not split them,
                         * so if we found the page, dma_handle has already
                         * been assigned to.
                         */
-                       if (chunk->mem[i].length > offset) {
-                               page = sg_page(&chunk->mem[i]);
+                       if (len > offset)
                                goto out;
-                       }
-                       offset -= chunk->mem[i].length;
+                       offset -= len;
                }
        }
 
+       addr = NULL;
 out:
        mutex_unlock(&table->mutex);
-       return page ? lowmem_page_address(page) + offset : NULL;
+       return addr ? addr + offset : NULL;
 }
 
 int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
index c9169a490557cc28a865ef98cbe0676fd3999d33..d199874b1c074cafd7a740e6806761c279e476cd 100644 (file)
@@ -47,11 +47,21 @@ enum {
        MLX4_ICM_PAGE_SIZE      = 1 << MLX4_ICM_PAGE_SHIFT,
 };
 
+struct mlx4_icm_buf {
+       void                    *addr;
+       size_t                  size;
+       dma_addr_t              dma_addr;
+};
+
 struct mlx4_icm_chunk {
        struct list_head        list;
        int                     npages;
        int                     nsg;
-       struct scatterlist      mem[MLX4_ICM_CHUNK_LEN];
+       bool                    coherent;
+       union {
+               struct scatterlist      sg[MLX4_ICM_CHUNK_LEN];
+               struct mlx4_icm_buf     buf[MLX4_ICM_CHUNK_LEN];
+       };
 };
 
 struct mlx4_icm {
@@ -114,12 +124,18 @@ static inline void mlx4_icm_next(struct mlx4_icm_iter *iter)
 
 static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter)
 {
-       return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
+       if (iter->chunk->coherent)
+               return iter->chunk->buf[iter->page_idx].dma_addr;
+       else
+               return sg_dma_address(&iter->chunk->sg[iter->page_idx]);
 }
 
 static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter)
 {
-       return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
+       if (iter->chunk->coherent)
+               return iter->chunk->buf[iter->page_idx].size;
+       else
+               return sg_dma_len(&iter->chunk->sg[iter->page_idx]);
 }
 
 int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
index 3e0fa8a8077b0c9199f408a40182854b8970309a..e267ff93e8a8f7e816c9eeb88c449dcbb536c058 100644 (file)
@@ -1583,6 +1583,24 @@ void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
        spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 }
 
+void mlx5_cmd_flush(struct mlx5_core_dev *dev)
+{
+       struct mlx5_cmd *cmd = &dev->cmd;
+       int i;
+
+       for (i = 0; i < cmd->max_reg_cmds; i++)
+               while (down_trylock(&cmd->sem))
+                       mlx5_cmd_trigger_completions(dev);
+
+       while (down_trylock(&cmd->pages_sem))
+               mlx5_cmd_trigger_completions(dev);
+
+       /* Unlock cmdif */
+       up(&cmd->pages_sem);
+       for (i = 0; i < cmd->max_reg_cmds; i++)
+               up(&cmd->sem);
+}
+
 static int status_to_err(u8 status)
 {
        return status ? -1 : 0; /* TBD more meaningful codes */
index 8fa8fdd30b8509f73a27fe4d31b094dfceda5e5d..448a92561567fc03b42702fd0c68aae5c8422bd6 100644 (file)
@@ -657,6 +657,7 @@ struct mlx5e_channel_stats {
 enum {
        MLX5E_STATE_OPENED,
        MLX5E_STATE_DESTROYING,
+       MLX5E_STATE_XDP_TX_ENABLED,
 };
 
 struct mlx5e_rqt {
index 046948ead152a4874458aed4b1909be78652842a..f3c7ab6faea505202d48d1b0bd862db010e87e99 100644 (file)
@@ -256,6 +256,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
+       e->route_dev = route_dev;
 
        /* It's important to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -369,6 +370,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
+       e->route_dev = route_dev;
 
        /* It's importent to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -612,16 +614,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
                       struct mlx5_flow_spec *spec,
                       struct tc_cls_flower_offload *f,
                       void *headers_c,
-                      void *headers_v)
+                      void *headers_v, u8 *match_level)
 {
        int tunnel_type;
        int err = 0;
 
        tunnel_type = mlx5e_tc_tun_get_type(filter_dev);
        if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) {
+               *match_level = MLX5_MATCH_L4;
                err = mlx5e_tc_tun_parse_vxlan(priv, spec, f,
                                               headers_c, headers_v);
        } else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) {
+               *match_level = MLX5_MATCH_L3;
                err = mlx5e_tc_tun_parse_gretap(priv, spec, f,
                                                headers_c, headers_v);
        } else {
index 706ce7bf15e7f19f88ac4fe6afe7375ff5445c13..b63f15de899d08b8af045f61407ba290a3440255 100644 (file)
@@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
                       struct mlx5_flow_spec *spec,
                       struct tc_cls_flower_offload *f,
                       void *headers_c,
-                      void *headers_v);
+                      void *headers_v, u8 *match_level);
 
 #endif //__MLX5_EN_TC_TUNNEL_H__
index 3740177eed092f60a7b07f20b7199b81254b0d90..03b2a9f9c5895af92bcefad0b3525757aa0191c1 100644 (file)
@@ -365,7 +365,8 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
        int sq_num;
        int i;
 
-       if (unlikely(!test_bit(MLX5E_STATE_OPENED, &priv->state)))
+       /* this flag is sufficient, no need to test internal sq state */
+       if (unlikely(!mlx5e_xdp_tx_is_enabled(priv)))
                return -ENETDOWN;
 
        if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
@@ -378,9 +379,6 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
 
        sq = &priv->channels.c[sq_num]->xdpsq;
 
-       if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
-               return -ENETDOWN;
-
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
                struct mlx5e_xdp_info xdpi;
index 3a67cb3cd1799c13d2deffdbbe9eb20315c2bcbe..ee27a7c8cd87d5121361f22344b53a21a7fb408b 100644 (file)
@@ -50,6 +50,23 @@ void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq);
 int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
                   u32 flags);
 
+static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
+{
+       set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
+static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
+{
+       clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+       /* let other device's napi(s) see our new state */
+       synchronize_rcu();
+}
+
+static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
+{
+       return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
 {
        if (sq->doorbell_cseg) {
index c9df081337186ced2d951ec84ab40f364b82d945..47233b9a4f810f7df7eefa560ec145ac021be8d9 100644 (file)
@@ -354,9 +354,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
 
        new_channels.params = priv->channels.params;
        new_channels.params.num_channels = count;
-       if (!netif_is_rxfh_configured(priv->netdev))
-               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-                                             MLX5E_INDIR_RQT_SIZE, count);
 
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                priv->channels.params = new_channels.params;
@@ -372,6 +369,10 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
        if (arfs_enabled)
                mlx5e_arfs_disable(priv);
 
+       if (!netif_is_rxfh_configured(priv->netdev))
+               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
+                                             MLX5E_INDIR_RQT_SIZE, count);
+
        /* Switch to new channels, set new parameters and close old ones */
        mlx5e_switch_priv_channels(priv, &new_channels, NULL);
 
@@ -844,9 +845,12 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
                                             Autoneg);
 
-       if (get_fec_supported_advertised(mdev, link_ksettings))
+       err = get_fec_supported_advertised(mdev, link_ksettings);
+       if (err) {
                netdev_dbg(priv->netdev, "%s: FEC caps query failed: %d\n",
                           __func__, err);
+               err = 0; /* don't fail caps query because of FEC error */
+       }
 
        if (!an_disable_admin)
                ethtool_link_ksettings_add_link_mode(link_ksettings,
index 8cfd2ec7c0a209afe424eca2a7be3301cf79223f..93e50ccd44c30749f3dc2a070fdedf2628bd313d 100644 (file)
@@ -950,7 +950,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c,
        if (params->rx_dim_enabled)
                __set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
 
-       if (params->pflags & MLX5E_PFLAG_RX_NO_CSUM_COMPLETE)
+       if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_NO_CSUM_COMPLETE))
                __set_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state);
 
        return 0;
@@ -2938,6 +2938,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 
        mlx5e_build_tx2sq_maps(priv);
        mlx5e_activate_channels(&priv->channels);
+       mlx5e_xdp_tx_enable(priv);
        netif_tx_start_all_queues(priv->netdev);
 
        if (mlx5e_is_vport_rep(priv))
@@ -2959,6 +2960,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
         */
        netif_tx_stop_all_queues(priv->netdev);
        netif_tx_disable(priv->netdev);
+       mlx5e_xdp_tx_disable(priv);
        mlx5e_deactivate_channels(&priv->channels);
 }
 
index 96cc0c6a4014d1529d5ce12f4f98b78ec6cab816..ef9e472daffb0c6be75ae0eb9473d56f0dd34bd5 100644 (file)
@@ -58,7 +58,8 @@ struct mlx5e_rep_indr_block_priv {
        struct list_head list;
 };
 
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev);
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+                                           struct net_device *netdev);
 
 static void mlx5e_rep_get_drvinfo(struct net_device *dev,
                                  struct ethtool_drvinfo *drvinfo)
@@ -179,6 +180,7 @@ static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
 
                        s->tx_packets           += sq_stats->packets;
                        s->tx_bytes             += sq_stats->bytes;
+                       s->tx_queue_dropped     += sq_stats->dropped;
                }
        }
 }
@@ -594,6 +596,10 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
        if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
                ether_addr_copy(e->h_dest, ha);
                ether_addr_copy(eth->h_dest, ha);
+               /* Update the encap source mac, in case that we delete
+                * the flows when encap source mac changed.
+                */
+               ether_addr_copy(eth->h_source, e->route_dev->dev_addr);
 
                mlx5e_tc_encap_flows_add(priv, e);
        }
@@ -663,7 +669,7 @@ static void mlx5e_rep_indr_clean_block_privs(struct mlx5e_rep_priv *rpriv)
        struct list_head *head = &rpriv->uplink_priv.tc_indr_block_priv_list;
 
        list_for_each_entry_safe(cb_priv, temp, head, list) {
-               mlx5e_rep_indr_unregister_block(cb_priv->netdev);
+               mlx5e_rep_indr_unregister_block(rpriv, cb_priv->netdev);
                kfree(cb_priv);
        }
 }
@@ -735,7 +741,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 
                err = tcf_block_cb_register(f->block,
                                            mlx5e_rep_indr_setup_block_cb,
-                                           netdev, indr_priv, f->extack);
+                                           indr_priv, indr_priv, f->extack);
                if (err) {
                        list_del(&indr_priv->list);
                        kfree(indr_priv);
@@ -743,14 +749,15 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 
                return err;
        case TC_BLOCK_UNBIND:
+               indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
+               if (!indr_priv)
+                       return -ENOENT;
+
                tcf_block_cb_unregister(f->block,
                                        mlx5e_rep_indr_setup_block_cb,
-                                       netdev);
-               indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
-               if (indr_priv) {
-                       list_del(&indr_priv->list);
-                       kfree(indr_priv);
-               }
+                                       indr_priv);
+               list_del(&indr_priv->list);
+               kfree(indr_priv);
 
                return 0;
        default:
@@ -779,7 +786,7 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
 
        err = __tc_indr_block_cb_register(netdev, rpriv,
                                          mlx5e_rep_indr_setup_tc_cb,
-                                         netdev);
+                                         rpriv);
        if (err) {
                struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
 
@@ -789,10 +796,11 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
        return err;
 }
 
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev)
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+                                           struct net_device *netdev)
 {
        __tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb,
-                                     netdev);
+                                     rpriv);
 }
 
 static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
@@ -811,7 +819,7 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
                mlx5e_rep_indr_register_block(rpriv, netdev);
                break;
        case NETDEV_UNREGISTER:
-               mlx5e_rep_indr_unregister_block(netdev);
+               mlx5e_rep_indr_unregister_block(rpriv, netdev);
                break;
        }
        return NOTIFY_OK;
@@ -1122,9 +1130,17 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct mlx5_eswitch_rep *rep = rpriv->rep;
-       int ret;
+       int ret, pf_num;
+
+       ret = mlx5_lag_get_pf_num(priv->mdev, &pf_num);
+       if (ret)
+               return ret;
+
+       if (rep->vport == FDB_UPLINK_VPORT)
+               ret = snprintf(buf, len, "p%d", pf_num);
+       else
+               ret = snprintf(buf, len, "pf%dvf%d", pf_num, rep->vport - 1);
 
-       ret = snprintf(buf, len, "%d", rep->vport - 1);
        if (ret >= len)
                return -EOPNOTSUPP;
 
@@ -1281,6 +1297,18 @@ static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr)
        return 0;
 }
 
+static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
+                                       __be16 vlan_proto)
+{
+       netdev_warn_once(dev, "legacy vf vlan setting isn't supported in switchdev mode\n");
+
+       if (vlan != 0)
+               return -EOPNOTSUPP;
+
+       /* allow setting 0-vid for compatibility with libvirt */
+       return 0;
+}
+
 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
        .switchdev_port_attr_get        = mlx5e_attr_get,
 };
@@ -1315,6 +1343,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
        .ndo_set_vf_rate         = mlx5e_set_vf_rate,
        .ndo_get_vf_config       = mlx5e_get_vf_config,
        .ndo_get_vf_stats        = mlx5e_get_vf_stats,
+       .ndo_set_vf_vlan         = mlx5e_uplink_rep_set_vf_vlan,
 };
 
 bool mlx5e_eswitch_rep(struct net_device *netdev)
index edd722824697f42c45a7bf57c9c6c510d202bfea..36eafc877e6bf576e8dbb831bcfd27dd8f73d0aa 100644 (file)
@@ -148,6 +148,7 @@ struct mlx5e_encap_entry {
        unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
 
        struct net_device *out_dev;
+       struct net_device *route_dev;
        int tunnel_type;
        int tunnel_hlen;
        int reformat_type;
index 1d0bb5ff8c260b2aca71368681aad88aa4e627bf..f86e4804e83e2a0f1ce3ab57129db61cfe52ff2f 100644 (file)
@@ -732,6 +732,8 @@ static u8 get_ip_proto(struct sk_buff *skb, int network_depth, __be16 proto)
                                            ((struct ipv6hdr *)ip_p)->nexthdr;
 }
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 static inline void mlx5e_handle_csum(struct net_device *netdev,
                                     struct mlx5_cqe64 *cqe,
                                     struct mlx5e_rq *rq,
@@ -754,6 +756,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
        if (unlikely(test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state)))
                goto csum_unnecessary;
 
+       /* CQE csum doesn't cover padding octets in short ethernet
+        * frames. And the pad field is appended prior to calculating
+        * and appending the FCS field.
+        *
+        * Detecting these padded frames requires to verify and parse
+        * IP headers, so we simply force all those small frames to be
+        * CHECKSUM_UNNECESSARY even if they are not padded.
+        */
+       if (short_frame(skb->len))
+               goto csum_unnecessary;
+
        if (likely(is_last_ethertype_ip(skb, &network_depth, &proto))) {
                if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP))
                        goto csum_unnecessary;
index cae6c6d489847629a45dce371cec4bc252c28372..b5c1b039375ae28c82540fa519051853addde7a1 100644 (file)
@@ -128,6 +128,7 @@ struct mlx5e_tc_flow_parse_attr {
        struct net_device *filter_dev;
        struct mlx5_flow_spec spec;
        int num_mod_hdr_actions;
+       int max_mod_hdr_actions;
        void *mod_hdr_actions;
        int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
 };
@@ -1302,7 +1303,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
 static int parse_tunnel_attr(struct mlx5e_priv *priv,
                             struct mlx5_flow_spec *spec,
                             struct tc_cls_flower_offload *f,
-                            struct net_device *filter_dev)
+                            struct net_device *filter_dev, u8 *match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1317,7 +1318,7 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
        int err = 0;
 
        err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
-                                headers_c, headers_v);
+                                headers_c, headers_v, match_level);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "failed to parse tunnel attributes");
@@ -1426,7 +1427,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
                              struct tc_cls_flower_offload *f,
                              struct net_device *filter_dev,
-                             u8 *match_level)
+                             u8 *match_level, u8 *tunnel_match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1477,7 +1478,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                switch (key->addr_type) {
                case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
                case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
-                       if (parse_tunnel_attr(priv, spec, f, filter_dev))
+                       if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
                                return -EOPNOTSUPP;
                        break;
                default:
@@ -1826,11 +1827,11 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
        struct mlx5_core_dev *dev = priv->mdev;
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
        struct mlx5_eswitch_rep *rep;
-       u8 match_level;
        int err;
 
-       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level);
+       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
 
        if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
                rep = rpriv->rep;
@@ -1846,10 +1847,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
                }
        }
 
-       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
                flow->esw_attr->match_level = match_level;
-       else
+               flow->esw_attr->tunnel_match_level = tunnel_match_level;
+       } else {
                flow->nic_attr->match_level = match_level;
+       }
 
        return err;
 }
@@ -1934,9 +1937,9 @@ static struct mlx5_fields fields[] = {
        OFFLOAD(UDP_DPORT, 2, udp.dest,   0),
 };
 
-/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at
- * max from the SW pedit action. On success, it says how many HW actions were
- * actually parsed.
+/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
+ * max from the SW pedit action. On success, attr->num_mod_hdr_actions
+ * says how many HW actions were actually parsed.
  */
 static int offload_pedit_fields(struct pedit_headers *masks,
                                struct pedit_headers *vals,
@@ -1960,9 +1963,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
        add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
 
        action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
-       action = parse_attr->mod_hdr_actions;
-       max_actions = parse_attr->num_mod_hdr_actions;
-       nactions = 0;
+       action = parse_attr->mod_hdr_actions +
+                parse_attr->num_mod_hdr_actions * action_size;
+
+       max_actions = parse_attr->max_mod_hdr_actions;
+       nactions = parse_attr->num_mod_hdr_actions;
 
        for (i = 0; i < ARRAY_SIZE(fields); i++) {
                f = &fields[i];
@@ -2073,7 +2078,7 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
        if (!parse_attr->mod_hdr_actions)
                return -ENOMEM;
 
-       parse_attr->num_mod_hdr_actions = max_actions;
+       parse_attr->max_mod_hdr_actions = max_actions;
        return 0;
 }
 
@@ -2119,9 +2124,11 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
                        goto out_err;
        }
 
-       err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
-       if (err)
-               goto out_err;
+       if (!parse_attr->mod_hdr_actions) {
+               err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
+               if (err)
+                       goto out_err;
+       }
 
        err = offload_pedit_fields(masks, vals, parse_attr, extack);
        if (err < 0)
@@ -2179,6 +2186,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv,
 
 static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
                                          struct tcf_exts *exts,
+                                         u32 actions,
                                          struct netlink_ext_ack *extack)
 {
        const struct tc_action *a;
@@ -2188,7 +2196,11 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
        u16 ethertype;
        int nkeys, i;
 
-       headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+       if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+               headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers);
+       else
+               headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+
        ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
 
        /* for non-IP we only re-write MACs, so we're okay */
@@ -2245,7 +2257,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
 
        if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                return modify_header_match_supported(&parse_attr->spec, exts,
-                                                    extack);
+                                                    actions, extack);
 
        return true;
 }
index 598ad7e4d5c97872c17fe4ae8387e82a2555c96e..0e55cd1f2e984a4b57b12046a16f1db48efd7824 100644 (file)
@@ -387,8 +387,14 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
        num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
        contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
        if (unlikely(contig_wqebbs_room < num_wqebbs)) {
+#ifdef CONFIG_MLX5_EN_IPSEC
+               struct mlx5_wqe_eth_seg cur_eth = wqe->eth;
+#endif
                mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
                mlx5e_sq_fetch_wqe(sq, &wqe, &pi);
+#ifdef CONFIG_MLX5_EN_IPSEC
+               wqe->eth = cur_eth;
+#endif
        }
 
        /* fill wqe */
index a44ea7b8561494c14f3207aef7604810ca4edb5f..5b492b67f4e1b972e4bda62085beca54a618f9db 100644 (file)
@@ -1134,13 +1134,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
        int err = 0;
        u8 *smac_v;
 
-       if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) {
-               mlx5_core_warn(esw->dev,
-                              "vport[%d] configure ingress rules failed, illegal mac with spoofchk\n",
-                              vport->vport);
-               return -EPERM;
-       }
-
        esw_vport_cleanup_ingress_rules(esw, vport);
 
        if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
@@ -1728,7 +1721,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        int vport_num;
        int err;
 
-       if (!MLX5_ESWITCH_MANAGER(dev))
+       if (!MLX5_VPORT_MANAGER(dev))
                return 0;
 
        esw_info(dev,
@@ -1797,7 +1790,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 
 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
 {
-       if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev))
+       if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
                return;
 
        esw_info(esw->dev, "cleanup\n");
@@ -1827,13 +1820,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
        mutex_lock(&esw->state_lock);
        evport = &esw->vports[vport];
 
-       if (evport->info.spoofchk && !is_valid_ether_addr(mac)) {
+       if (evport->info.spoofchk && !is_valid_ether_addr(mac))
                mlx5_core_warn(esw->dev,
-                              "MAC invalidation is not allowed when spoofchk is on, vport(%d)\n",
+                              "Set invalid MAC while spoofchk is on, vport(%d)\n",
                               vport);
-               err = -EPERM;
-               goto unlock;
-       }
 
        err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
        if (err) {
@@ -1979,6 +1969,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
        evport = &esw->vports[vport];
        pschk = evport->info.spoofchk;
        evport->info.spoofchk = spoofchk;
+       if (pschk && !is_valid_ether_addr(evport->info.mac))
+               mlx5_core_warn(esw->dev,
+                              "Spoofchk in set while MAC is invalid, vport(%d)\n",
+                              evport->vport);
        if (evport->enabled && esw->mode == SRIOV_LEGACY)
                err = esw_vport_ingress_config(esw, evport);
        if (err)
index 9c89eea9b2c331752922fdf4b0b382b2f50c99e5..748ff178a1d66be5c55b3c1e3756d555eb3268c6 100644 (file)
@@ -312,6 +312,7 @@ struct mlx5_esw_flow_attr {
        } dests[MLX5_MAX_FLOW_FWD_VPORTS];
        u32     mod_hdr_id;
        u8      match_level;
+       u8      tunnel_match_level;
        struct mlx5_fc *counter;
        u32     chain;
        u16     prio;
index 53065b6ae59376089764fb5cb72f61de7f395c7d..d4e6fe5b9300c69d9ca219e79b1df3dbee1cd891 100644 (file)
@@ -160,14 +160,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                MLX5_SET_TO_ONES(fte_match_set_misc, misc,
                                 source_eswitch_owner_vhca_id);
 
-       if (attr->match_level == MLX5_MATCH_NONE)
-               spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
-       else
-               spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
-                                             MLX5_MATCH_MISC_PARAMETERS;
-
-       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
-               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
+               if (attr->tunnel_match_level != MLX5_MATCH_NONE)
+                       spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+               if (attr->match_level != MLX5_MATCH_NONE)
+                       spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+       } else if (attr->match_level != MLX5_MATCH_NONE) {
+               spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+       }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                flow_act.modify_id = attr->mod_hdr_id;
index fbc42b7252a9129dda4ce44e9eefe26c1273a778..503035469d2d8e9f62d3d45d2aa2f2db94ad17fb 100644 (file)
@@ -211,11 +211,10 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
        enum port_module_event_status_type module_status;
        enum port_module_event_error_type error_type;
        struct mlx5_eqe_port_module *module_event_eqe;
-       const char *status_str, *error_str;
+       const char *status_str;
        u8 module_num;
 
        module_event_eqe = &eqe->data.port_module;
-       module_num = module_event_eqe->module;
        module_status = module_event_eqe->module_status &
                        PORT_MODULE_EVENT_MODULE_STATUS_MASK;
        error_type = module_event_eqe->error_type &
@@ -223,25 +222,27 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
 
        if (module_status < MLX5_MODULE_STATUS_NUM)
                events->pme_stats.status_counters[module_status]++;
-       status_str = mlx5_pme_status_to_string(module_status);
 
-       if (module_status == MLX5_MODULE_STATUS_ERROR) {
+       if (module_status == MLX5_MODULE_STATUS_ERROR)
                if (error_type < MLX5_MODULE_EVENT_ERROR_NUM)
                        events->pme_stats.error_counters[error_type]++;
-               error_str = mlx5_pme_error_to_string(error_type);
-       }
 
        if (!printk_ratelimit())
                return NOTIFY_OK;
 
-       if (module_status == MLX5_MODULE_STATUS_ERROR)
+       module_num = module_event_eqe->module;
+       status_str = mlx5_pme_status_to_string(module_status);
+       if (module_status == MLX5_MODULE_STATUS_ERROR) {
+               const char *error_str = mlx5_pme_error_to_string(error_type);
+
                mlx5_core_err(events->dev,
                              "Port module event[error]: module %u, %s, %s\n",
                              module_num, status_str, error_str);
-       else
+       } else {
                mlx5_core_info(events->dev,
                               "Port module event: module %u, %s\n",
                               module_num, status_str);
+       }
 
        return NOTIFY_OK;
 }
index 196c07383082f9fe479e930ea4f4a3229c561c43..cb9fa3430c5358678a6a7b719ed0d22e8d2eb15e 100644 (file)
@@ -103,7 +103,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
        mlx5_core_err(dev, "start\n");
        if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) {
                dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
-               mlx5_cmd_trigger_completions(dev);
+               mlx5_cmd_flush(dev);
        }
 
        mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1);
index 3a6baed722d855498254d0970b48fdfb16b784d3..2d223385dc81925e1dbe267f3e54c2b76a7daf19 100644 (file)
@@ -616,6 +616,27 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
        }
 }
 
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num)
+{
+       struct mlx5_lag *ldev;
+       int n;
+
+       ldev = mlx5_lag_dev_get(dev);
+       if (!ldev) {
+               mlx5_core_warn(dev, "no lag device, can't get pf num\n");
+               return -EINVAL;
+       }
+
+       for (n = 0; n < MLX5_MAX_PORTS; n++)
+               if (ldev->pf[n].dev == dev) {
+                       *pf_num = n;
+                       return 0;
+               }
+
+       mlx5_core_warn(dev, "wasn't able to locate pf in the lag device\n");
+       return -EINVAL;
+}
+
 /* Must be called with intf_mutex held */
 void mlx5_lag_remove(struct mlx5_core_dev *dev)
 {
index c68dcea5985b9f7fed1ac71e23d978f43446a42f..4fdac020b795a9025554f4b3e327f9b85453e154 100644 (file)
@@ -126,6 +126,7 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
                             struct ptp_system_timestamp *sts);
 
 void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev);
+void mlx5_cmd_flush(struct mlx5_core_dev *dev);
 int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev);
 void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev);
 
@@ -187,6 +188,8 @@ static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev)
                    MLX5_CAP_GEN(dev, lag_master);
 }
 
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num);
+
 void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol);
 void mlx5_lag_update(struct mlx5_core_dev *dev);
 
index 388f205a497f0ba703c26b73ea05be1b591ad7b7..370ca94b677586728541bec1099acd2ef6dc227a 100644 (file)
@@ -44,14 +44,15 @@ static struct mlx5_core_rsc_common *
 mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn)
 {
        struct mlx5_core_rsc_common *common;
+       unsigned long flags;
 
-       spin_lock(&table->lock);
+       spin_lock_irqsave(&table->lock, flags);
 
        common = radix_tree_lookup(&table->tree, rsn);
        if (common)
                atomic_inc(&common->refcount);
 
-       spin_unlock(&table->lock);
+       spin_unlock_irqrestore(&table->lock, flags);
 
        return common;
 }
index 080ddd1942ec26f4bb7654600286af7ceeeae7a8..b9a25aed5d116c246316b60e464de54a4626657c 100644 (file)
@@ -78,6 +78,7 @@ config MLXSW_SPECTRUM
        depends on IPV6 || IPV6=n
        depends on NET_IPGRE || NET_IPGRE=n
        depends on IPV6_GRE || IPV6_GRE=n
+       depends on VXLAN || VXLAN=n
        select GENERIC_ALLOCATOR
        select PARMAN
        select OBJAGG
index 66b8098c6fd2e24414ee91395fb8132a6aeb9131..a2321fe8d6a0f22fc57afca9ede1932befb54fad 100644 (file)
@@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
                u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
                u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe);
                u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe);
+               char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
+
+               memcpy(ncqe, cqe, q->elem_size);
+               mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
 
                if (sendq) {
                        struct mlxsw_pci_queue *sdq;
 
                        sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
                        mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
-                                                wqe_counter, cqe);
+                                                wqe_counter, ncqe);
                        q->u.cq.comp_sdq_count++;
                } else {
                        struct mlxsw_pci_queue *rdq;
 
                        rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
                        mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
-                                                wqe_counter, q->u.cq.v, cqe);
+                                                wqe_counter, q->u.cq.v, ncqe);
                        q->u.cq.comp_rdq_count++;
                }
                if (++items == credits)
                        break;
        }
-       if (items) {
-               mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
+       if (items)
                mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
-       }
 }
 
 static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)
@@ -1365,10 +1367,10 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
                u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
 
                if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
-                       break;
+                       return 0;
                cond_resched();
        } while (time_before(jiffies, end));
-       return 0;
+       return -EBUSY;
 }
 
 static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
index bb99f6d41fe0b99cca74eafc2c956e5f14ef20bf..ffee38e36ce8995348f776bbdbb8e4601b36b223 100644 (file)
@@ -27,7 +27,7 @@
 
 #define MLXSW_PCI_SW_RESET                     0xF0010
 #define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       5000
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       13000
 #define MLXSW_PCI_SW_RESET_WAIT_MSECS          100
 #define MLXSW_PCI_FW_READY                     0xA1844
 #define MLXSW_PCI_FW_READY_MASK                        0xFFFF
@@ -53,6 +53,7 @@
 #define MLXSW_PCI_WQE_SIZE     32 /* 32 bytes per element */
 #define MLXSW_PCI_CQE01_SIZE   16 /* 16 bytes per element */
 #define MLXSW_PCI_CQE2_SIZE    32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE
 #define MLXSW_PCI_EQE_SIZE     16 /* 16 bytes per element */
 #define MLXSW_PCI_WQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
 #define MLXSW_PCI_CQE01_COUNT  (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE)
index eed1045e4d9661754be226d78b6289e868616364..32519c93df174c99d1a768209a4cb92ecdde5df3 100644 (file)
@@ -5005,12 +5005,15 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
                                                           lower_dev,
                                                           upper_dev);
                } else if (netif_is_lag_master(upper_dev)) {
-                       if (info->linking)
+                       if (info->linking) {
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
                                                             upper_dev);
-                       else
+                       } else {
+                               mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port,
+                                                           false);
                                mlxsw_sp_port_lag_leave(mlxsw_sp_port,
                                                        upper_dev);
+                       }
                } else if (netif_is_ovs_master(upper_dev)) {
                        if (info->linking)
                                err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
index b0f2d8e8ded0f3b5f8ee46f6459ab5080b320d3e..ac222833a5cff65560e9e584c84ef3ff382aef3f 100644 (file)
@@ -72,7 +72,15 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
        act_set = mlxsw_afa_block_first_set(rulei->act_block);
        mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
 
-       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+       err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+       if (err)
+               goto err_ptce2_write;
+
+       return 0;
+
+err_ptce2_write:
+       cregion->ops->entry_remove(cregion, centry);
+       return err;
 }
 
 static void
index 1c19feefa5f20120468b2c104f6f1e375d3ee3e7..2941967e1cc5032ce8f5a7c529270d867eca9b29 100644 (file)
@@ -1022,7 +1022,6 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
 {
        struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask;
 
-       ASSERT_RTNL();
        objagg_obj_put(aregion->erp_table->objagg, objagg_obj);
 }
 
@@ -1054,7 +1053,6 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
        const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj);
        unsigned int erp_bank;
 
-       ASSERT_RTNL();
        if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table))
                return;
 
index 055cc6943b348dd8a883a79b23762b04b1a217a4..9d9aa28684af7a798c366a12b55b7463bc1341c1 100644 (file)
@@ -997,8 +997,8 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
        .type                   = MLXSW_SP_FID_TYPE_DUMMY,
        .fid_size               = sizeof(struct mlxsw_sp_fid),
-       .start_index            = MLXSW_SP_RFID_BASE - 1,
-       .end_index              = MLXSW_SP_RFID_BASE - 1,
+       .start_index            = VLAN_N_VID - 1,
+       .end_index              = VLAN_N_VID - 1,
        .ops                    = &mlxsw_sp_fid_dummy_ops,
 };
 
index 0a31fff2516e500f634a2e75385f275083f7f24e..fb1c48c698f26c504903d06b36b89ed8fcef13c1 100644 (file)
@@ -816,14 +816,14 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
        ops = nve->nve_ops_arr[params->type];
 
        if (!ops->can_offload(nve, params->dev, extack))
-               return -EOPNOTSUPP;
+               return -EINVAL;
 
        memset(&config, 0, sizeof(config));
        ops->nve_config(nve, params->dev, &config);
        if (nve->num_nve_tunnels &&
            memcmp(&config, &nve->config, sizeof(config))) {
                NL_SET_ERR_MSG_MOD(extack, "Conflicting NVE tunnels configuration");
-               return -EOPNOTSUPP;
+               return -EINVAL;
        }
 
        err = mlxsw_sp_nve_tunnel_init(mlxsw_sp, &config);
index 1bd2c6e15f8d0b68ca46c826939ec325a87bd044..c772109b638d622943301d9135458b2d8e8a389f 100644 (file)
@@ -1078,8 +1078,7 @@ static int
 mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port,
                              u16 vid, bool is_untagged, bool is_pvid,
-                             struct netlink_ext_ack *extack,
-                             struct switchdev_trans *trans)
+                             struct netlink_ext_ack *extack)
 {
        u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
@@ -1095,9 +1094,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
            mlxsw_sp_port_vlan->bridge_port != bridge_port)
                return -EEXIST;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        if (!mlxsw_sp_port_vlan) {
                mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
                                                               vid);
@@ -1188,6 +1184,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                return err;
        }
 
+       if (switchdev_trans_ph_commit(trans))
+               return 0;
+
        bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
        if (WARN_ON(!bridge_port))
                return -EINVAL;
@@ -1200,7 +1199,7 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
 
                err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
                                                    vid, flag_untagged,
-                                                   flag_pvid, extack, trans);
+                                                   flag_pvid, extack);
                if (err)
                        return err;
        }
@@ -1234,7 +1233,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
 {
        return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
-                        MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+                        MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG;
 }
 
 static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
@@ -1291,7 +1290,7 @@ static int mlxsw_sp_port_fdb_tunnel_uc_op(struct mlxsw_sp *mlxsw_sp,
 static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                     const char *mac, u16 fid, bool adding,
                                     enum mlxsw_reg_sfd_rec_action action,
-                                    bool dynamic)
+                                    enum mlxsw_reg_sfd_rec_policy policy)
 {
        char *sfd_pl;
        u8 num_rec;
@@ -1302,8 +1301,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                return -ENOMEM;
 
        mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
-       mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
-                             mac, fid, action, local_port);
+       mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port);
        num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
        if (err)
@@ -1322,7 +1320,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                   bool dynamic)
 {
        return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
-                                        MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
+                                        MLXSW_REG_SFD_REC_ACTION_NOP,
+                                        mlxsw_sp_sfd_rec_policy(dynamic));
 }
 
 int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
@@ -1330,7 +1329,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
 {
        return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
                                         MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
-                                        false);
+                                        MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY);
 }
 
 static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
@@ -1808,7 +1807,7 @@ static void
 mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port, u16 vid)
 {
-       u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : vid;
+       u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid;
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
 
        mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
@@ -3207,7 +3206,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
                                  struct mlxsw_sp_bridge_device *bridge_device,
                                  const struct net_device *vxlan_dev, u16 vid,
                                  bool flag_untagged, bool flag_pvid,
-                                 struct switchdev_trans *trans,
                                  struct netlink_ext_ack *extack)
 {
        struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
@@ -3225,9 +3223,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
            mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid))
                return -EINVAL;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        if (!netif_running(vxlan_dev))
                return 0;
 
@@ -3345,6 +3340,9 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
 
        port_obj_info->handled = true;
 
+       if (switchdev_trans_ph_commit(trans))
+               return 0;
+
        bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
        if (!bridge_device)
                return -EINVAL;
@@ -3358,8 +3356,7 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
                err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device,
                                                        vxlan_dev, vid,
                                                        flag_untagged,
-                                                       flag_pvid, trans,
-                                                       extack);
+                                                       flag_pvid, extack);
                if (err)
                        return err;
        }
index 20c9377e99cb227f863c3a113014496450b4f1cb..310807ef328bd5b59f72f9d202227fbe21b3f413 100644 (file)
@@ -962,13 +962,10 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
 
                memset(&ksettings, 0, sizeof(ksettings));
                phy_ethtool_get_link_ksettings(netdev, &ksettings);
-               local_advertisement = phy_read(phydev, MII_ADVERTISE);
-               if (local_advertisement < 0)
-                       return;
-
-               remote_advertisement = phy_read(phydev, MII_LPA);
-               if (remote_advertisement < 0)
-                       return;
+               local_advertisement =
+                       linkmode_adv_to_mii_adv_t(phydev->advertising);
+               remote_advertisement =
+                       linkmode_adv_to_mii_adv_t(phydev->lp_advertising);
 
                lan743x_phy_update_flowcontrol(adapter,
                                               ksettings.base.duplex,
index 24a90163775e169eea28140aec8f6d3f4585758d..2d8a77cc156baf4f882505cd483a8bad48caecfa 100644 (file)
@@ -53,7 +53,7 @@
 extern const struct qed_common_ops qed_common_ops_pass;
 
 #define QED_MAJOR_VERSION              8
-#define QED_MINOR_VERSION              33
+#define QED_MINOR_VERSION              37
 #define QED_REVISION_VERSION           0
 #define QED_ENGINEERING_VERSION                20
 
index 8f655142194576a6fe5e484ab28701a2956b36a0..2ecaaaa4469a67f7f4846cdba46b691b8f1a2c6f 100644 (file)
@@ -795,19 +795,19 @@ static void qed_init_qm_pq(struct qed_hwfn *p_hwfn,
 
 /* get pq index according to PQ_FLAGS */
 static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
-                                          u32 pq_flags)
+                                          unsigned long pq_flags)
 {
        struct qed_qm_info *qm_info = &p_hwfn->qm_info;
 
        /* Can't have multiple flags set here */
-       if (bitmap_weight((unsigned long *)&pq_flags,
+       if (bitmap_weight(&pq_flags,
                          sizeof(pq_flags) * BITS_PER_BYTE) > 1) {
-               DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags);
+               DP_ERR(p_hwfn, "requested multiple pq flags 0x%lx\n", pq_flags);
                goto err;
        }
 
        if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) {
-               DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags);
+               DP_ERR(p_hwfn, "pq flag 0x%lx is not set\n", pq_flags);
                goto err;
        }
 
index 67c02ea939062dea70ae6e806546fd8266dd08cf..58be1c4c66684797b79e4bf5d1ca834fe2d61f9d 100644 (file)
@@ -609,6 +609,10 @@ qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn,
                          (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) &&
                           !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
 
+               SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL,
+                         (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) &&
+                          !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)));
+
                SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL,
                          !!(accept_filter & QED_ACCEPT_BCAST));
 
@@ -744,6 +748,11 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
                return rc;
        }
 
+       if (p_params->update_ctl_frame_check) {
+               p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en;
+               p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en;
+       }
+
        /* Update mcast bins for VFs, PF doesn't use this functionality */
        qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params);
 
@@ -2207,7 +2216,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                        u16 num_queues = 0;
 
                        /* Since the feature controls only queue-zones,
-                        * make sure we have the contexts [rx, tx, xdp] to
+                        * make sure we have the contexts [rx, xdp, tcs] to
                         * match.
                         */
                        for_each_hwfn(cdev, i) {
@@ -2217,7 +2226,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                                u16 cids;
 
                                cids = hwfn->pf_params.eth_pf_params.num_cons;
-                               num_queues += min_t(u16, l2_queues, cids / 3);
+                               cids /= (2 + info->num_tc);
+                               num_queues += min_t(u16, l2_queues, cids);
                        }
 
                        /* queues might theoretically be >256, but interrupts'
@@ -2688,7 +2698,8 @@ static int qed_configure_filter_rx_mode(struct qed_dev *cdev,
        if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) {
                accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
                                                 QED_ACCEPT_MCAST_UNMATCHED;
-               accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
+               accept_flags.tx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
+                                                QED_ACCEPT_MCAST_UNMATCHED;
        } else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) {
                accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
                accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
@@ -2860,7 +2871,8 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle)
        p_hwfn = p_cid->p_owner;
        rc = qed_get_queue_coalesce(p_hwfn, coal, handle);
        if (rc)
-               DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n");
+               DP_VERBOSE(cdev, QED_MSG_DEBUG,
+                          "Unable to read queue coalescing\n");
 
        return rc;
 }
index 8d80f1095d171c85b7d010bb5297a58a1961808d..7127d5aaac4223de0a2758478bb54e8e642c9430 100644 (file)
@@ -219,6 +219,9 @@ struct qed_sp_vport_update_params {
        struct qed_rss_params           *rss_params;
        struct qed_filter_accept_flags  accept_flags;
        struct qed_sge_tpa_params       *sge_tpa_params;
+       u8                              update_ctl_frame_check;
+       u8                              mac_chk_en;
+       u8                              ethtype_chk_en;
 };
 
 int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
index 90afd514ffe18351aee5da16560a549cadf5d06e..b5f419b71287513635cdf83a35458292ad361a12 100644 (file)
@@ -1619,6 +1619,10 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
        cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain);
        rx_prod.bd_prod = cpu_to_le16(bd_prod);
        rx_prod.cqe_prod = cpu_to_le16(cq_prod);
+
+       /* Make sure chain element is updated before ringing the doorbell */
+       dma_wmb();
+
        DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
 }
 
@@ -2447,19 +2451,24 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
 {
        struct qed_ll2_tx_pkt_info pkt;
        const skb_frag_t *frag;
+       u8 flags = 0, nr_frags;
        int rc = -EINVAL, i;
        dma_addr_t mapping;
        u16 vlan = 0;
-       u8 flags = 0;
 
        if (unlikely(skb->ip_summed != CHECKSUM_NONE)) {
                DP_INFO(cdev, "Cannot transmit a checksummed packet\n");
                return -EINVAL;
        }
 
-       if (1 + skb_shinfo(skb)->nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
+       /* Cache number of fragments from SKB since SKB may be freed by
+        * the completion routine after calling qed_ll2_prepare_tx_packet()
+        */
+       nr_frags = skb_shinfo(skb)->nr_frags;
+
+       if (1 + nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
                DP_ERR(cdev, "Cannot transmit a packet with %d fragments\n",
-                      1 + skb_shinfo(skb)->nr_frags);
+                      1 + nr_frags);
                return -EINVAL;
        }
 
@@ -2481,7 +2490,7 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
        }
 
        memset(&pkt, 0, sizeof(pkt));
-       pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags;
+       pkt.num_of_bds = 1 + nr_frags;
        pkt.vlan = vlan;
        pkt.bd_flags = flags;
        pkt.tx_dest = QED_LL2_TX_DEST_NW;
@@ -2492,12 +2501,17 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
            test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags))
                pkt.remove_stag = true;
 
+       /* qed_ll2_prepare_tx_packet() may actually send the packet if
+        * there are no fragments in the skb and subsequently the completion
+        * routine may run and free the SKB, so no dereferencing the SKB
+        * beyond this point unless skb has any fragments.
+        */
        rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle,
                                       &pkt, 1);
        if (rc)
                goto err;
 
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+       for (i = 0; i < nr_frags; i++) {
                frag = &skb_shinfo(skb)->frags[i];
 
                mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,
index 4179c9013fc65fea92c132c927cdaf5bc5637fe4..96ab77ae6af59f4e0268393cd85c3494039b273e 100644 (file)
@@ -382,6 +382,7 @@ void qed_consq_setup(struct qed_hwfn *p_hwfn);
  * @param p_hwfn
  */
 void qed_consq_free(struct qed_hwfn *p_hwfn);
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn);
 
 /**
  * @file
index 888274fa208bc768b2ab9db2514407573bfab2e1..5a495fda9e9dd4f34ef7ec4b6dbf4dc0ebe6c6db 100644 (file)
@@ -604,6 +604,9 @@ int qed_sp_pf_update_stag(struct qed_hwfn *p_hwfn)
 
        p_ent->ramrod.pf_update.update_mf_vlan_flag = true;
        p_ent->ramrod.pf_update.mf_vlan = cpu_to_le16(p_hwfn->hw_info.ovlan);
+       if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))
+               p_ent->ramrod.pf_update.mf_vlan |=
+                       cpu_to_le16(((u16)p_hwfn->ufp_info.tc << 13));
 
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
index eb88bbc6b1931adfa1c5d5760739fa0702e90dee..ba64ff9bedbd2078ce543abdf045056a5f5e4ce3 100644 (file)
@@ -397,6 +397,11 @@ int qed_eq_completion(struct qed_hwfn *p_hwfn, void *cookie)
 
        qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain));
 
+       /* Attempt to post pending requests */
+       spin_lock_bh(&p_hwfn->p_spq->lock);
+       rc = qed_spq_pend_post(p_hwfn);
+       spin_unlock_bh(&p_hwfn->p_spq->lock);
+
        return rc;
 }
 
@@ -767,7 +772,7 @@ static int qed_spq_post_list(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
-static int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
 {
        struct qed_spq *p_spq = p_hwfn->p_spq;
        struct qed_spq_entry *p_ent = NULL;
@@ -905,7 +910,6 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
        struct qed_spq_entry    *p_ent = NULL;
        struct qed_spq_entry    *tmp;
        struct qed_spq_entry    *found = NULL;
-       int                     rc;
 
        if (!p_hwfn)
                return -EINVAL;
@@ -963,12 +967,7 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
                 */
                qed_spq_return_entry(p_hwfn, found);
 
-       /* Attempt to post pending requests */
-       spin_lock_bh(&p_spq->lock);
-       rc = qed_spq_pend_post(p_hwfn);
-       spin_unlock_bh(&p_spq->lock);
-
-       return rc;
+       return 0;
 }
 
 int qed_consq_alloc(struct qed_hwfn *p_hwfn)
index ca6290fa0f30940265ca1590de148c94eb2cf18e..71a7af134dd8e74622a8cecb99d04628a7683069 100644 (file)
@@ -1969,7 +1969,9 @@ static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn,
        params.vport_id = vf->vport_id;
        params.max_buffers_per_cqe = start->max_buffers_per_cqe;
        params.mtu = vf->mtu;
-       params.check_mac = true;
+
+       /* Non trusted VFs should enable control frame filtering */
+       params.check_mac = !vf->p_vf_info.is_trusted_configured;
 
        rc = qed_sp_eth_vport_start(p_hwfn, &params);
        if (rc) {
@@ -5130,6 +5132,9 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
                params.opaque_fid = vf->opaque_fid;
                params.vport_id = vf->vport_id;
 
+               params.update_ctl_frame_check = 1;
+               params.mac_chk_en = !vf_info->is_trusted_configured;
+
                if (vf_info->rx_accept_mode & mask) {
                        flags->update_rx_mode_config = 1;
                        flags->rx_accept_filter = vf_info->rx_accept_mode;
@@ -5147,7 +5152,8 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
                }
 
                if (flags->update_rx_mode_config ||
-                   flags->update_tx_mode_config)
+                   flags->update_tx_mode_config ||
+                   params.update_ctl_frame_check)
                        qed_sp_vport_update(hwfn, &params,
                                            QED_SPQ_MODE_EBLOCK, NULL);
        }
index b6cccf44bf409bc626e9089c3c9c40eaa98827b2..5dda547772c1363e9373f2d81ef72c6644936b85 100644 (file)
@@ -261,6 +261,7 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
        struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp;
        struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
        struct vf_pf_resc_request *p_resc;
+       u8 retry_cnt = VF_ACQUIRE_THRESH;
        bool resources_acquired = false;
        struct vfpf_acquire_tlv *req;
        int rc = 0, attempts = 0;
@@ -314,6 +315,15 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
 
                /* send acquire request */
                rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
+
+               /* Re-try acquire in case of vf-pf hw channel timeout */
+               if (retry_cnt && rc == -EBUSY) {
+                       DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+                                  "VF retrying to acquire due to VPC timeout\n");
+                       retry_cnt--;
+                       continue;
+               }
+
                if (rc)
                        goto exit;
 
index 613249d1e967d5310df16de8576f3a4d9c317521..730997b1374733575c95e8f2168393398f17ee72 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/tc_act/tc_gact.h>
 
 #define QEDE_MAJOR_VERSION             8
-#define QEDE_MINOR_VERSION             33
+#define QEDE_MINOR_VERSION             37
 #define QEDE_REVISION_VERSION          0
 #define QEDE_ENGINEERING_VERSION       20
 #define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \
@@ -494,6 +494,9 @@ struct qede_reload_args {
 
 /* Datapath functions definition */
 netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     struct net_device *sb_dev,
+                     select_queue_fallback_t fallback);
 netdev_features_t qede_features_check(struct sk_buff *skb,
                                      struct net_device *dev,
                                      netdev_features_t features);
index bdf816fe5a16cf8c5d1cdf4b72812e49e3a6d688..31b046e24565f38dbdb117ec6cd0f69430419c45 100644 (file)
@@ -1695,6 +1695,19 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     struct net_device *sb_dev,
+                     select_queue_fallback_t fallback)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       int total_txq;
+
+       total_txq = QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc;
+
+       return QEDE_TSS_COUNT(edev) ?
+               fallback(dev, skb, NULL) % total_txq :  0;
+}
+
 /* 8B udp header + 8B base tunnel header + 32B option length */
 #define QEDE_MAX_TUN_HDR_LEN 48
 
index 5a74fcbdbc2b59fde83468f2d6538296fa35d2c6..9790f26d17c4a9eb00bba41afec3d2ab994da9bf 100644 (file)
@@ -631,6 +631,7 @@ static const struct net_device_ops qede_netdev_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -666,6 +667,7 @@ static const struct net_device_ops qede_netdev_vf_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -684,6 +686,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
index 44f6e4873aadd16b35ae34c3561393fc010a698b..4f910c4f67b0e223ede96dffe2391e918cc42b62 100644 (file)
@@ -691,7 +691,7 @@ static void cp_tx (struct cp_private *cp)
                        }
                        bytes_compl += skb->len;
                        pkts_compl++;
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                }
 
                cp->tx_skb[tx_tail] = NULL;
index 298930d39b7945aa216aa17418d032473b8b4e0e..6e36b88ca7c9c296fa5306e3376835f4259a7760 100644 (file)
@@ -205,6 +205,8 @@ enum cfg_version {
 };
 
 static const struct pci_device_id rtl8169_pci_tbl[] = {
+       { PCI_VDEVICE(REALTEK,  0x2502), RTL_CFG_1 },
+       { PCI_VDEVICE(REALTEK,  0x2600), RTL_CFG_1 },
        { PCI_VDEVICE(REALTEK,  0x8129), RTL_CFG_0 },
        { PCI_VDEVICE(REALTEK,  0x8136), RTL_CFG_2 },
        { PCI_VDEVICE(REALTEK,  0x8161), RTL_CFG_1 },
@@ -706,6 +708,7 @@ module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_SOFTDEP("pre: realtek");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(FIRMWARE_8168D_1);
 MODULE_FIRMWARE(FIRMWARE_8168D_2);
@@ -1283,11 +1286,13 @@ static u16 rtl_get_events(struct rtl8169_private *tp)
 static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
 {
        RTL_W16(tp, IntrStatus, bits);
+       mmiowb();
 }
 
 static void rtl_irq_disable(struct rtl8169_private *tp)
 {
        RTL_W16(tp, IntrMask, 0);
+       mmiowb();
 }
 
 #define RTL_EVENT_NAPI_RX      (RxOK | RxErr)
@@ -1679,11 +1684,13 @@ static bool rtl8169_reset_counters(struct rtl8169_private *tp)
 
 static bool rtl8169_update_counters(struct rtl8169_private *tp)
 {
+       u8 val = RTL_R8(tp, ChipCmd);
+
        /*
         * Some chips are unable to dump tally counters when the receiver
-        * is disabled.
+        * is disabled. If 0xff chip may be in a PCI power-save state.
         */
-       if ((RTL_R8(tp, ChipCmd) & CmdRxEnb) == 0)
+       if (!(val & CmdRxEnb) || val == 0xff)
                return true;
 
        return rtl8169_do_counters(tp, CounterDump);
@@ -6067,7 +6074,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
        struct device *d = tp_to_dev(tp);
        dma_addr_t mapping;
        u32 opts[2], len;
-       bool stop_queue;
        int frags;
 
        if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) {
@@ -6109,6 +6115,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 
        txd->opts2 = cpu_to_le32(opts[1]);
 
+       netdev_sent_queue(dev, skb->len);
+
        skb_tx_timestamp(skb);
 
        /* Force memory writes to complete before releasing descriptor */
@@ -6121,14 +6129,16 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 
        tp->cur_tx += frags + 1;
 
-       stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS);
-       if (unlikely(stop_queue))
-               netif_stop_queue(dev);
+       RTL_W8(tp, TxPoll, NPQ);
 
-       if (__netdev_sent_queue(dev, skb->len, skb->xmit_more))
-               RTL_W8(tp, TxPoll, NPQ);
+       mmiowb();
 
-       if (unlikely(stop_queue)) {
+       if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) {
+               /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
+                * not miss a ring update when it notices a stopped queue.
+                */
+               smp_wmb();
+               netif_stop_queue(dev);
                /* Sync with rtl_tx:
                 * - publish queue status and cur_tx ring index (write barrier)
                 * - refresh dirty_tx ring index (read barrier).
@@ -6478,7 +6488,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
 
        if (work_done < budget) {
                napi_complete_done(napi, work_done);
+
                rtl_irq_enable(tp);
+               mmiowb();
        }
 
        return work_done;
index ffc1ada4e6da3408a0d13867618a7e735fd5c8df..d28c8f9ca55ba31bacbd0f96e0538616621da14f 100644 (file)
@@ -343,7 +343,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
        int i;
 
        priv->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : ndev->mtu) +
-               ETH_HLEN + VLAN_HLEN;
+               ETH_HLEN + VLAN_HLEN + sizeof(__sum16);
 
        /* Allocate RX and TX skb rings */
        priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
@@ -524,13 +524,15 @@ static void ravb_rx_csum(struct sk_buff *skb)
 {
        u8 *hw_csum;
 
-       /* The hardware checksum is 2 bytes appended to packet data */
-       if (unlikely(skb->len < 2))
+       /* The hardware checksum is contained in sizeof(__sum16) (2) bytes
+        * appended to packet data
+        */
+       if (unlikely(skb->len < sizeof(__sum16)))
                return;
-       hw_csum = skb_tail_pointer(skb) - 2;
+       hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
        skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
        skb->ip_summed = CHECKSUM_COMPLETE;
-       skb_trim(skb, skb->len - 2);
+       skb_trim(skb, skb->len - sizeof(__sum16));
 }
 
 /* Packet receive function for Ethernet AVB */
index b6a50058bb8db90b0f8c459469b3cc058692efdc..c08034154a9ae6e8707daa73e1977cfae306da81 100644 (file)
@@ -6046,22 +6046,25 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = {
        { NVRAM_PARTITION_TYPE_EXPANSION_UEFI,     0,    0, "sfc_uefi" },
        { NVRAM_PARTITION_TYPE_STATUS,             0,    0, "sfc_status" }
 };
+#define EF10_NVRAM_PARTITION_COUNT     ARRAY_SIZE(efx_ef10_nvram_types)
 
 static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
                                        struct efx_mcdi_mtd_partition *part,
-                                       unsigned int type)
+                                       unsigned int type,
+                                       unsigned long *found)
 {
        MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
        MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_METADATA_OUT_LENMAX);
        const struct efx_ef10_nvram_type_info *info;
        size_t size, erase_size, outlen;
+       int type_idx = 0;
        bool protected;
        int rc;
 
-       for (info = efx_ef10_nvram_types; ; info++) {
-               if (info ==
-                   efx_ef10_nvram_types + ARRAY_SIZE(efx_ef10_nvram_types))
+       for (type_idx = 0; ; type_idx++) {
+               if (type_idx == EF10_NVRAM_PARTITION_COUNT)
                        return -ENODEV;
+               info = efx_ef10_nvram_types + type_idx;
                if ((type & ~info->type_mask) == info->type)
                        break;
        }
@@ -6074,6 +6077,13 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
        if (protected)
                return -ENODEV; /* hide it */
 
+       /* If we've already exposed a partition of this type, hide this
+        * duplicate.  All operations on MTDs are keyed by the type anyway,
+        * so we can't act on the duplicate.
+        */
+       if (__test_and_set_bit(type_idx, found))
+               return -EEXIST;
+
        part->nvram_type = type;
 
        MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
@@ -6105,6 +6115,7 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
 static int efx_ef10_mtd_probe(struct efx_nic *efx)
 {
        MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
+       DECLARE_BITMAP(found, EF10_NVRAM_PARTITION_COUNT) = { 0 };
        struct efx_mcdi_mtd_partition *parts;
        size_t outlen, n_parts_total, i, n_parts;
        unsigned int type;
@@ -6133,11 +6144,13 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx)
        for (i = 0; i < n_parts_total; i++) {
                type = MCDI_ARRAY_DWORD(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID,
                                        i);
-               rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type);
-               if (rc == 0)
-                       n_parts++;
-               else if (rc != -ENODEV)
+               rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type,
+                                                 found);
+               if (rc == -EEXIST || rc == -ENODEV)
+                       continue;
+               if (rc)
                        goto fail;
+               n_parts++;
        }
 
        rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
index 15c62c160953308b3f4018e8bd7973dee9fa59cd..be47d864f8b9b045ef5b0f7a9e68d097bae15c1c 100644 (file)
@@ -1037,7 +1037,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
                skb = ep->tx_skbuff[entry];
                pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
                ep->tx_skbuff[entry] = NULL;
        }
 
index 7b923362ee5509d6fdedc9c15d09cd760182fab2..3b174eae77c10f3b9da3aa9d89d850535233a87c 100644 (file)
@@ -1342,8 +1342,10 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
        }
 
        ret = phy_power_on(bsp_priv, true);
-       if (ret)
+       if (ret) {
+               gmac_clk_enable(bsp_priv, false);
                return ret;
+       }
 
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
index 6c5092e7771cde12e65abb4a497c76c943d512c0..c5e25580a43fa59e926ed0f78ae6830826b1438a 100644 (file)
@@ -263,6 +263,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
                                  struct stmmac_extra_stats *x, u32 chan)
 {
        u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
+       u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
        int ret = 0;
 
        /* ABNORMAL interrupts */
@@ -282,8 +283,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
                x->normal_irq_n++;
 
                if (likely(intr_status & XGMAC_RI)) {
-                       u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
-                       if (likely(value & XGMAC_RIE)) {
+                       if (likely(intr_en & XGMAC_RIE)) {
                                x->rx_normal_irq_n++;
                                ret |= handle_rx;
                        }
@@ -295,7 +295,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
        }
 
        /* Clear interrupts */
-       writel(~0x0, ioaddr + XGMAC_DMA_CH_STATUS(chan));
+       writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan));
 
        return ret;
 }
index d1f61c25d82bc8e25c1026bd20105614a73a1b05..5d85742a2be0b62189ce83dbc0de40714f6eb34c 100644 (file)
@@ -721,8 +721,11 @@ static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
 {
        unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
 
-       if (!clk)
-               return 0;
+       if (!clk) {
+               clk = priv->plat->clk_ref_rate;
+               if (!clk)
+                       return 0;
+       }
 
        return (usec * (clk / 1000000)) / 256;
 }
@@ -731,8 +734,11 @@ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
 {
        unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
 
-       if (!clk)
-               return 0;
+       if (!clk) {
+               clk = priv->plat->clk_ref_rate;
+               if (!clk)
+                       return 0;
+       }
 
        return (riwt * 256) / (clk / 1000000);
 }
index 0c4ab3444cc381ab4b55a988b4b85cda9455efb4..685d20472358ec88f04f8a333913465fbdde5cb7 100644 (file)
@@ -3023,10 +3023,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q = &priv->tx_queue[queue];
 
+       if (priv->tx_path_in_lpi_mode)
+               stmmac_disable_eee_mode(priv);
+
        /* Manage oversized TCP frames for GMAC4 device */
        if (skb_is_gso(skb) && priv->tso) {
-               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+                       /*
+                        * There is no way to determine the number of TSO
+                        * capable Queues. Let's use always the Queue 0
+                        * because if TSO is supported then at least this
+                        * one will be capable.
+                        */
+                       skb_set_queue_mapping(skb, 0);
+
                        return stmmac_tso_xmit(skb, dev);
+               }
        }
 
        if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
@@ -3041,9 +3053,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       if (priv->tx_path_in_lpi_mode)
-               stmmac_disable_eee_mode(priv);
-
        entry = tx_q->cur_tx;
        first_entry = entry;
        WARN_ON(tx_q->tx_skbuff[first_entry]);
@@ -3517,27 +3526,28 @@ static int stmmac_napi_poll(struct napi_struct *napi, int budget)
        struct stmmac_channel *ch =
                container_of(napi, struct stmmac_channel, napi);
        struct stmmac_priv *priv = ch->priv_data;
-       int work_done = 0, work_rem = budget;
+       int work_done, rx_done = 0, tx_done = 0;
        u32 chan = ch->index;
 
        priv->xstats.napi_poll++;
 
-       if (ch->has_tx) {
-               int done = stmmac_tx_clean(priv, work_rem, chan);
+       if (ch->has_tx)
+               tx_done = stmmac_tx_clean(priv, budget, chan);
+       if (ch->has_rx)
+               rx_done = stmmac_rx(priv, budget, chan);
 
-               work_done += done;
-               work_rem -= done;
-       }
+       work_done = max(rx_done, tx_done);
+       work_done = min(work_done, budget);
 
-       if (ch->has_rx) {
-               int done = stmmac_rx(priv, work_rem, chan);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
+               int stat;
 
-               work_done += done;
-               work_rem -= done;
-       }
-
-       if (work_done < budget && napi_complete_done(napi, work_done))
                stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+               stat = stmmac_dma_interrupt_status(priv, priv->ioaddr,
+                                                  &priv->xstats, chan);
+               if (stat && napi_reschedule(napi))
+                       stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+       }
 
        return work_done;
 }
@@ -4160,6 +4170,18 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
                        return ret;
        }
 
+       /* Rx Watchdog is available in the COREs newer than the 3.40.
+        * In some case, for example on bugged HW this feature
+        * has to be disable and this can be done by passing the
+        * riwt_off field from the platform.
+        */
+       if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
+           (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
+               priv->use_riwt = 1;
+               dev_info(priv->device,
+                        "Enable RX Mitigation via HW Watchdog Timer\n");
+       }
+
        return 0;
 }
 
@@ -4292,18 +4314,6 @@ int stmmac_dvr_probe(struct device *device,
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
-       /* Rx Watchdog is available in the COREs newer than the 3.40.
-        * In some case, for example on bugged HW this feature
-        * has to be disable and this can be done by passing the
-        * riwt_off field from the platform.
-        */
-       if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
-           (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
-               priv->use_riwt = 1;
-               dev_info(priv->device,
-                        "Enable RX Mitigation via HW Watchdog Timer\n");
-       }
-
        /* Setup channels NAPI */
        maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
 
index c54a50dbd5ac264faa439550f949a981cb0440ae..d819e8eaba1225dc5e9b188e42636721cc66a4c0 100644 (file)
@@ -299,7 +299,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
  */
 static void stmmac_pci_remove(struct pci_dev *pdev)
 {
+       int i;
+
        stmmac_dvr_remove(&pdev->dev);
+
+       for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+               if (pci_resource_len(pdev, i) == 0)
+                       continue;
+               pcim_iounmap_regions(pdev, BIT(i));
+               break;
+       }
+
        pci_disable_device(pdev);
 }
 
index 531294f4978bc42bbb0e3cb0177b1312a33bef61..58ea18af9813ab950b1252cde08d626abe61c30e 100644 (file)
@@ -301,6 +301,8 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
        /* Queue 0 is not AVB capable */
        if (queue <= 0 || queue >= tx_queues_count)
                return -EINVAL;
+       if (!priv->dma_cap.av)
+               return -EOPNOTSUPP;
        if (priv->speed != SPEED_100 && priv->speed != SPEED_1000)
                return -EOPNOTSUPP;
 
index 9020b084b953880466cdf9c0354ee8208b987873..6fc05c106afc6fcef6e8f8855cdcbc588c33fea1 100644 (file)
@@ -1,22 +1,9 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
  *
  * Copyright (C) 2004 Sun Microsystems Inc.
  * Copyright (C) 2003 Adrian Sun (asun@darksunrising.com)
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
  * This driver uses the sungem driver (c) David Miller
  * (davem@redhat.com) as its basis.
  *
@@ -1911,7 +1898,7 @@ static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
                cp->net_stats[ring].tx_packets++;
                cp->net_stats[ring].tx_bytes += skb->len;
                spin_unlock(&cp->stat_lock[ring]);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
        cp->tx_old[ring] = entry;
 
index 13f3860496a861d3d2f9716fabd93add43b74f6c..ae5f05f03f8804e14616cc1c040b462d43b7351f 100644 (file)
@@ -1,23 +1,10 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
 /* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
  * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
  *
  * Copyright (C) 2004 Sun Microsystems Inc.
  * Copyright (c) 2003 Adrian Sun (asun@darksunrising.com)
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
  * vendor id: 0x108E (Sun Microsystems, Inc.)
  * device id: 0xabba (Cassini)
  * revision ids: 0x01 = Cassini
index 720b7ac77f3b3c08e428faaf16ba4cbae1b76275..e9b757b03b564377079d22af1b60580584811744 100644 (file)
@@ -781,7 +781,7 @@ static void bigmac_tx(struct bigmac *bp)
 
                DTX(("skb(%p) ", skb));
                bp->tx_skbs[elem] = NULL;
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
 
                elem = NEXT_TX(elem);
        }
index ff641cf30a4e1306baa5573bf5e7f464eaa5e729..d007dfeba5c356d7da3b9c211840d791dd34059d 100644 (file)
@@ -1962,7 +1962,7 @@ static void happy_meal_tx(struct happy_meal *hp)
                        this = &txbase[elem];
                }
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
                dev->stats.tx_packets++;
        }
        hp->tx_old = elem;
index dc966ddb6d815038b487f2edd05279e9397c30e7..b24c11187017d88b75ca9686603d5d32d7039e97 100644 (file)
@@ -1739,7 +1739,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv)
                tx_level -= db->rptr->len;      /* '-' koz len is negative */
 
                /* now should come skb pointer - free it */
-               dev_kfree_skb_irq(db->rptr->addr.skb);
+               dev_consume_skb_irq(db->rptr->addr.skb);
                bdx_tx_db_inc_rptr(db);
        }
 
index 810dfc7de1f9125763af49ad0a2c6070901f7313..e2d47b24a86922284ab508af8eb4bebfde2893e4 100644 (file)
@@ -608,7 +608,7 @@ static void cpmac_end_xmit(struct net_device *dev, int queue)
                        netdev_dbg(dev, "sent 0x%p, len=%d\n",
                                   desc->skb, desc->skb->len);
 
-               dev_kfree_skb_irq(desc->skb);
+               dev_consume_skb_irq(desc->skb);
                desc->skb = NULL;
                if (__netif_subqueue_stopped(dev, queue))
                        netif_wake_subqueue(dev, queue);
index 82412691ee66bf13b488db6d61072f239d27d9c3..27f6cf140845fb357a2880757e343c1ab024d14d 100644 (file)
@@ -1740,7 +1740,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
                dma_unmap_single(vptr->dev, tdinfo->skb_dma[i],
                                 le16_to_cpu(pktlen), DMA_TO_DEVICE);
        }
-       dev_kfree_skb_irq(skb);
+       dev_consume_skb_irq(skb);
        tdinfo->skb = NULL;
 }
 
index 38ac8ef41f5fca9e1b9dcf10c63cb5ea65d6eb47..56b7791911bfc3b32d87922ca45632202e7963a4 100644 (file)
@@ -3512,7 +3512,7 @@ static int dfx_xmt_done(DFX_board_t *bp)
                                 bp->descr_block_virt->xmt_data[comp].long_1,
                                 p_xmt_drv_descr->p_skb->len,
                                 DMA_TO_DEVICE);
-               dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
+               dev_consume_skb_irq(p_xmt_drv_descr->p_skb);
 
                /*
                 * Move to start of next packet by updating completion index
index 58bbba8582b0960de94296ccbbed9c074b12aed0..3377ac66a34748bf03c5875410f808562794ed18 100644 (file)
@@ -1512,9 +1512,13 @@ static void geneve_link_config(struct net_device *dev,
        }
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6: {
-               struct rt6_info *rt = rt6_lookup(geneve->net,
-                                                &info->key.u.ipv6.dst, NULL, 0,
-                                                NULL, 0);
+               struct rt6_info *rt;
+
+               if (!__in6_dev_get(dev))
+                       break;
+
+               rt = rt6_lookup(geneve->net, &info->key.u.ipv6.dst, NULL, 0,
+                               NULL, 0);
 
                if (rt && rt->dst.dev)
                        ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
index ef6f766f6389380894d855494d371035fc26325e..e859ae2e42d5a152a567de048e898eeafa99fcb5 100644 (file)
@@ -144,6 +144,8 @@ struct hv_netvsc_packet {
        u32 total_data_buflen;
 };
 
+#define NETVSC_HASH_KEYLEN 40
+
 struct netvsc_device_info {
        unsigned char mac_adr[ETH_ALEN];
        u32  num_chn;
@@ -151,6 +153,8 @@ struct netvsc_device_info {
        u32  recv_sections;
        u32  send_section_size;
        u32  recv_section_size;
+
+       u8 rss_key[NETVSC_HASH_KEYLEN];
 };
 
 enum rndis_device_state {
@@ -160,8 +164,6 @@ enum rndis_device_state {
        RNDIS_DEV_DATAINITIALIZED,
 };
 
-#define NETVSC_HASH_KEYLEN 40
-
 struct rndis_device {
        struct net_device *ndev;
 
@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net,
 void netvsc_channel_cb(void *context);
 int netvsc_poll(struct napi_struct *napi, int budget);
 
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
+int rndis_set_subchannel(struct net_device *ndev,
+                        struct netvsc_device *nvdev,
+                        struct netvsc_device_info *dev_info);
 int rndis_filter_open(struct netvsc_device *nvdev);
 int rndis_filter_close(struct netvsc_device *nvdev);
 struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type {
 
 enum rndis_per_pkt_info_interal_type {
        RNDIS_PKTINFO_ID = 1,
-       /* Add more memebers here */
+       /* Add more members here */
 
        RNDIS_PKTINFO_MAX
 };
index 922054c1d5448bf6406742c52a94a7bc4226575c..813d195bbd57fed2ef96ea708b637ca8197be458 100644 (file)
@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)
 
        rdev = nvdev->extension;
        if (rdev) {
-               ret = rndis_set_subchannel(rdev->ndev, nvdev);
+               ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
                if (ret == 0) {
                        netif_device_attach(rdev->ndev);
                } else {
@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context)
        prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);
 
        if (napi_schedule_prep(&nvchan->napi)) {
-               /* disable interupts from host */
+               /* disable interrupts from host */
                hv_begin_read(rbi);
 
                __napi_schedule_irqoff(&nvchan->napi);
index 91ed15ea58835c6704838c69ada7b5b0c98b6715..256adbd044f5ea138154c0a9126aacdaf1aafcb4 100644 (file)
@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
 {
        int j = 0;
 
-       /* Deal with compund pages by ignoring unused part
+       /* Deal with compound pages by ignoring unused part
         * of the page.
         */
        page += (offset >> PAGE_SHIFT);
@@ -858,6 +858,39 @@ static void netvsc_get_channels(struct net_device *net,
        }
 }
 
+/* Alloc struct netvsc_device_info, and initialize it from either existing
+ * struct netvsc_device, or from default values.
+ */
+static struct netvsc_device_info *netvsc_devinfo_get
+                       (struct netvsc_device *nvdev)
+{
+       struct netvsc_device_info *dev_info;
+
+       dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC);
+
+       if (!dev_info)
+               return NULL;
+
+       if (nvdev) {
+               dev_info->num_chn = nvdev->num_chn;
+               dev_info->send_sections = nvdev->send_section_cnt;
+               dev_info->send_section_size = nvdev->send_section_size;
+               dev_info->recv_sections = nvdev->recv_section_cnt;
+               dev_info->recv_section_size = nvdev->recv_section_size;
+
+               memcpy(dev_info->rss_key, nvdev->extension->rss_key,
+                      NETVSC_HASH_KEYLEN);
+       } else {
+               dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
+               dev_info->send_sections = NETVSC_DEFAULT_TX;
+               dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE;
+               dev_info->recv_sections = NETVSC_DEFAULT_RX;
+               dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE;
+       }
+
+       return dev_info;
+}
+
 static int netvsc_detach(struct net_device *ndev,
                         struct netvsc_device *nvdev)
 {
@@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev,
                return PTR_ERR(nvdev);
 
        if (nvdev->num_chn > 1) {
-               ret = rndis_set_subchannel(ndev, nvdev);
+               ret = rndis_set_subchannel(ndev, nvdev, dev_info);
 
                /* if unavailable, just proceed with one queue */
                if (ret) {
@@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net,
        struct net_device_context *net_device_ctx = netdev_priv(net);
        struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
        unsigned int orig, count = channels->combined_count;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        int ret;
 
        /* We do not support separate count for rx, tx, or other */
@@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net,
 
        orig = nvdev->num_chn;
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = count;
-       device_info.send_sections = nvdev->send_section_cnt;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = nvdev->recv_section_cnt;
-       device_info.recv_section_size = nvdev->recv_section_size;
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
+       device_info->num_chn = count;
 
        ret = netvsc_detach(net, nvdev);
        if (ret)
-               return ret;
+               goto out;
 
-       ret = netvsc_attach(net, &device_info);
+       ret = netvsc_attach(net, device_info);
        if (ret) {
-               device_info.num_chn = orig;
-               if (netvsc_attach(net, &device_info))
+               device_info->num_chn = orig;
+               if (netvsc_attach(net, device_info))
                        netdev_err(net, "restoring channel setting failed\n");
        }
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -1048,48 +1083,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
        struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
        int orig_mtu = ndev->mtu;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        int ret = 0;
 
        if (!nvdev || nvdev->destroy)
                return -ENODEV;
 
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
        /* Change MTU of underlying VF netdev first. */
        if (vf_netdev) {
                ret = dev_set_mtu(vf_netdev, mtu);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = nvdev->num_chn;
-       device_info.send_sections = nvdev->send_section_cnt;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = nvdev->recv_section_cnt;
-       device_info.recv_section_size = nvdev->recv_section_size;
-
        ret = netvsc_detach(ndev, nvdev);
        if (ret)
                goto rollback_vf;
 
        ndev->mtu = mtu;
 
-       ret = netvsc_attach(ndev, &device_info);
-       if (ret)
-               goto rollback;
-
-       return 0;
+       ret = netvsc_attach(ndev, device_info);
+       if (!ret)
+               goto out;
 
-rollback:
        /* Attempt rollback to original MTU */
        ndev->mtu = orig_mtu;
 
-       if (netvsc_attach(ndev, &device_info))
+       if (netvsc_attach(ndev, device_info))
                netdev_err(ndev, "restoring mtu failed\n");
 rollback_vf:
        if (vf_netdev)
                dev_set_mtu(vf_netdev, orig_mtu);
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
 {
        struct net_device_context *ndevctx = netdev_priv(ndev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        struct ethtool_ringparam orig;
        u32 new_tx, new_rx;
        int ret = 0;
@@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
            new_rx == orig.rx_pending)
                return 0;        /* no change */
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = nvdev->num_chn;
-       device_info.send_sections = new_tx;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = new_rx;
-       device_info.recv_section_size = nvdev->recv_section_size;
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
+       device_info->send_sections = new_tx;
+       device_info->recv_sections = new_rx;
 
        ret = netvsc_detach(ndev, nvdev);
        if (ret)
-               return ret;
+               goto out;
 
-       ret = netvsc_attach(ndev, &device_info);
+       ret = netvsc_attach(ndev, device_info);
        if (ret) {
-               device_info.send_sections = orig.tx_pending;
-               device_info.recv_sections = orig.rx_pending;
+               device_info->send_sections = orig.tx_pending;
+               device_info->recv_sections = orig.rx_pending;
 
-               if (netvsc_attach(ndev, &device_info))
+               if (netvsc_attach(ndev, device_info))
                        netdev_err(ndev, "restoring ringparam failed");
        }
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
        if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
                return NOTIFY_DONE;
 
-       /* if syntihetic interface is a different namespace,
+       /* if synthetic interface is a different namespace,
         * then move the VF to that namespace; join will be
         * done again in that context.
         */
@@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev,
 {
        struct net_device *net = NULL;
        struct net_device_context *net_device_ctx;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info = NULL;
        struct netvsc_device *nvdev;
        int ret = -ENOMEM;
 
@@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev,
        netif_set_real_num_rx_queues(net, 1);
 
        /* Notify the netvsc driver of the new device */
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = VRSS_CHANNEL_DEFAULT;
-       device_info.send_sections = NETVSC_DEFAULT_TX;
-       device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
-       device_info.recv_sections = NETVSC_DEFAULT_RX;
-       device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;
-
-       nvdev = rndis_filter_device_add(dev, &device_info);
+       device_info = netvsc_devinfo_get(NULL);
+
+       if (!device_info) {
+               ret = -ENOMEM;
+               goto devinfo_failed;
+       }
+
+       nvdev = rndis_filter_device_add(dev, device_info);
        if (IS_ERR(nvdev)) {
                ret = PTR_ERR(nvdev);
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
                goto rndis_failed;
        }
 
-       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+       memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN);
 
        /* We must get rtnl lock before scheduling nvdev->subchan_work,
         * otherwise netvsc_subchan_work() can get rtnl lock first and wait
@@ -2236,7 +2271,7 @@ static int netvsc_probe(struct hv_device *dev,
         * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
         * -> ... -> device_add() -> ... -> __device_attach() can't get
         * the device lock, so all the subchannels can't be processed --
-        * finally netvsc_subchan_work() hangs for ever.
+        * finally netvsc_subchan_work() hangs forever.
         */
        rtnl_lock();
 
@@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev,
 
        list_add(&net_device_ctx->list, &netvsc_dev_list);
        rtnl_unlock();
+
+       kfree(device_info);
        return 0;
 
 register_failed:
        rtnl_unlock();
        rndis_filter_device_remove(dev, nvdev);
 rndis_failed:
+       kfree(device_info);
+devinfo_failed:
        free_percpu(net_device_ctx->vf_stats);
 no_stats:
        hv_set_drvdata(dev, NULL);
index 8b537a049c1e5960c2f3f31c3afc59b4b4ef19e0..73b60592de06ca5e9dc6a2c5bc9db8a34ec88cbf 100644 (file)
@@ -774,8 +774,8 @@ rndis_filter_set_offload_params(struct net_device *ndev,
        return ret;
 }
 
-int rndis_filter_set_rss_param(struct rndis_device *rdev,
-                              const u8 *rss_key)
+static int rndis_set_rss_param_msg(struct rndis_device *rdev,
+                                  const u8 *rss_key, u16 flag)
 {
        struct net_device *ndev = rdev->ndev;
        struct rndis_request *request;
@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
        rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
        rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
        rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
-       rssp->flag = 0;
+       rssp->flag = flag;
        rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
                         NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
                         NDIS_HASH_TCP_IPV6;
@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
 
        wait_for_completion(&request->wait_event);
        set_complete = &request->response_msg.msg.set_complete;
-       if (set_complete->status == RNDIS_STATUS_SUCCESS)
-               memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
-       else {
+       if (set_complete->status == RNDIS_STATUS_SUCCESS) {
+               if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
+                   !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
+                       memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
+
+       } else {
                netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
                           set_complete->status);
                ret = -EINVAL;
@@ -842,6 +845,16 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
        return ret;
 }
 
+int rndis_filter_set_rss_param(struct rndis_device *rdev,
+                              const u8 *rss_key)
+{
+       /* Disable RSS before change */
+       rndis_set_rss_param_msg(rdev, rss_key,
+                               NDIS_RSS_PARAM_FLAG_DISABLE_RSS);
+
+       return rndis_set_rss_param_msg(rdev, rss_key, 0);
+}
+
 static int rndis_filter_query_device_link_status(struct rndis_device *dev,
                                                 struct netvsc_device *net_device)
 {
@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
  * This breaks overlap of processing the host message for the
  * new primary channel with the initialization of sub-channels.
  */
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
+int rndis_set_subchannel(struct net_device *ndev,
+                        struct netvsc_device *nvdev,
+                        struct netvsc_device_info *dev_info)
 {
        struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
        struct net_device_context *ndev_ctx = netdev_priv(ndev);
@@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
        wait_event(nvdev->subchan_open,
                   atomic_read(&nvdev->open_chn) == nvdev->num_chn);
 
-       /* ignore failues from setting rss parameters, still have channels */
-       rndis_filter_set_rss_param(rdev, netvsc_hash_key);
+       /* ignore failures from setting rss parameters, still have channels */
+       if (dev_info)
+               rndis_filter_set_rss_param(rdev, dev_info->rss_key);
+       else
+               rndis_filter_set_rss_param(rdev, netvsc_hash_key);
 
        netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
        netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
index 44de81e5f140fba3f6efd3c02932c2c8346f67b8..c589f5ae75bb552f53b39eed367594bc3d420165 100644 (file)
@@ -905,9 +905,9 @@ mcr20a_irq_clean_complete(void *context)
                }
                break;
        case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_SEQIRQ):
-                       /* rx is starting */
-                       dev_dbg(printdev(lp), "RX is starting\n");
-                       mcr20a_handle_rx(lp);
+               /* rx is starting */
+               dev_dbg(printdev(lp), "RX is starting\n");
+               mcr20a_handle_rx(lp);
                break;
        case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_TXIRQ | DAR_IRQSTS1_SEQIRQ):
                if (lp->is_tx) {
index 19bdde60680c29a1e58a3192a5367e0a18eba6c4..7cdac77d0c68527630b89c2eaff874582200d93a 100644 (file)
@@ -100,12 +100,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
                        err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
                        if (!err) {
                                mdev->l3mdev_ops = &ipvl_l3mdev_ops;
-                               mdev->priv_flags |= IFF_L3MDEV_MASTER;
+                               mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
                        } else
                                goto fail;
                } else if (port->mode == IPVLAN_MODE_L3S) {
                        /* Old mode was L3S */
-                       mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
+                       mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
                        ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
                        mdev->l3mdev_ops = NULL;
                }
@@ -167,7 +167,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
        struct sk_buff *skb;
 
        if (port->mode == IPVLAN_MODE_L3S) {
-               dev->priv_flags &= ~IFF_L3MDEV_MASTER;
+               dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
                ipvlan_unregister_nf_hook(dev_net(dev));
                dev->l3mdev_ops = NULL;
        }
index fc726ce4c164efaa30e713529f217a40c548a9ec..6d067176320fe845e5ef5804044c55614b5392fd 100644 (file)
@@ -337,7 +337,7 @@ static void macvlan_process_broadcast(struct work_struct *w)
 
                if (src)
                        dev_put(src->dev);
-               kfree_skb(skb);
+               consume_skb(skb);
        }
 }
 
index 8ebe7f5484aee02af92d47a4e286d970adcc73b9..f14ba5366b911e7791472f9d1cbabaae8b6fb622 100644 (file)
@@ -1,13 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /* Driver for Asix PHYs
  *
  * Author: Michael Schmitz <schmitzmic@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 1b350183bffbd20732f0b6a3495a5d16e3758aa3..a271239748f2dde163a42167105d1cf60a553db4 100644 (file)
@@ -197,6 +197,7 @@ static struct phy_driver bcm87xx_driver[] = {
        .phy_id         = PHY_ID_BCM8706,
        .phy_id_mask    = 0xffffffff,
        .name           = "Broadcom BCM8706",
+       .features       = PHY_10GBIT_FEC_FEATURES,
        .config_init    = bcm87xx_config_init,
        .config_aneg    = bcm87xx_config_aneg,
        .read_status    = bcm87xx_read_status,
@@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[] = {
        .phy_id         = PHY_ID_BCM8727,
        .phy_id_mask    = 0xffffffff,
        .name           = "Broadcom BCM8727",
+       .features       = PHY_10GBIT_FEC_FEATURES,
        .config_init    = bcm87xx_config_init,
        .config_aneg    = bcm87xx_config_aneg,
        .read_status    = bcm87xx_read_status,
index 8022cd317f62bca6338a7b66ab190e410d1fe5e1..1a4d04afb7f047110441781d65973376f6f58a2c 100644 (file)
@@ -88,6 +88,7 @@ static struct phy_driver cortina_driver[] = {
        .phy_id         = PHY_ID_CS4340,
        .phy_id_mask    = 0xffffffff,
        .name           = "Cortina CS4340",
+       .features       = PHY_10GBIT_FEATURES,
        .config_init    = gen10g_config_init,
        .config_aneg    = gen10g_config_aneg,
        .read_status    = cortina_read_status,
index 18b41bc345ab90856aa0ad17912fb7b8a3421f46..6e8807212aa342228ad5edb63b5bee4cc6cadd81 100644 (file)
@@ -898,14 +898,14 @@ static void decode_txts(struct dp83640_private *dp83640,
                        struct phy_txts *phy_txts)
 {
        struct skb_shared_hwtstamps shhwtstamps;
+       struct dp83640_skb_info *skb_info;
        struct sk_buff *skb;
-       u64 ns;
        u8 overflow;
+       u64 ns;
 
        /* We must already have the skb that triggered this. */
-
+again:
        skb = skb_dequeue(&dp83640->tx_queue);
-
        if (!skb) {
                pr_debug("have timestamp but tx_queue empty\n");
                return;
@@ -920,6 +920,11 @@ static void decode_txts(struct dp83640_private *dp83640,
                }
                return;
        }
+       skb_info = (struct dp83640_skb_info *)skb->cb;
+       if (time_after(jiffies, skb_info->tmo)) {
+               kfree_skb(skb);
+               goto again;
+       }
 
        ns = phy2txts(phy_txts);
        memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -1472,6 +1477,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
 static void dp83640_txtstamp(struct phy_device *phydev,
                             struct sk_buff *skb, int type)
 {
+       struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
        struct dp83640_private *dp83640 = phydev->priv;
 
        switch (dp83640->hwts_tx_en) {
@@ -1484,6 +1490,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
                /* fall through */
        case HWTSTAMP_TX_ON:
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
                skb_queue_tail(&dp83640->tx_queue, skb);
                break;
 
index a9c7c7f41b0cdd3b058c6e805dfe4d063ad9b58d..abb7876a87762d6631d88894f1423c00c313d0a9 100644 (file)
@@ -847,7 +847,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
 
        /* SGMII-to-Copper mode initialization */
        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
-
                /* Select page 18 */
                err = marvell_set_page(phydev, 18);
                if (err < 0)
@@ -870,21 +869,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
                err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
                if (err < 0)
                        return err;
-
-               /* There appears to be a bug in the 88e1512 when used in
-                * SGMII to copper mode, where the AN advertisement register
-                * clears the pause bits each time a negotiation occurs.
-                * This means we can never be truely sure what was advertised,
-                * so disable Pause support.
-                */
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-                                  phydev->supported);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-                                  phydev->supported);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-                                  phydev->advertising);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-                                  phydev->advertising);
        }
 
        return m88e1318_config_init(phydev);
@@ -1046,6 +1030,39 @@ static int m88e1145_config_init(struct phy_device *phydev)
        return 0;
 }
 
+/* The VOD can be out of specification on link up. Poke an
+ * undocumented register, in an undocumented page, with a magic value
+ * to fix this.
+ */
+static int m88e6390_errata(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_write(phydev, MII_BMCR,
+                       BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX);
+       if (err)
+               return err;
+
+       usleep_range(300, 400);
+
+       err = phy_write_paged(phydev, 0xf8, 0x08, 0x36);
+       if (err)
+               return err;
+
+       return genphy_soft_reset(phydev);
+}
+
+static int m88e6390_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       err = m88e6390_errata(phydev);
+       if (err)
+               return err;
+
+       return m88e1510_config_aneg(phydev);
+}
+
 /**
  * fiber_lpa_mod_linkmode_lpa_t
  * @advertising: the linkmode advertisement settings
@@ -1402,7 +1419,7 @@ static int m88e1318_set_wol(struct phy_device *phydev,
                 * before enabling it if !phy_interrupt_is_valid()
                 */
                if (!phy_interrupt_is_valid(phydev))
-                       phy_read(phydev, MII_M1011_IEVENT);
+                       __phy_read(phydev, MII_M1011_IEVENT);
 
                /* Enable the WOL interrupt */
                err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0,
@@ -2283,7 +2300,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .probe = m88e6390_probe,
                .config_init = &marvell_config_init,
-               .config_aneg = &m88e1510_config_aneg,
+               .config_aneg = &m88e6390_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
index b03fedd6c1d847164857d218fa1cb99ca987aebf..287f3ccf1da1deb649f2852ec8ed73ff573bd219 100644 (file)
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Hisilicon Fast Ethernet MDIO Bus Driver
  *
  * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
@@ -163,4 +151,4 @@ module_platform_driver(hisi_femac_mdio_driver);
 
 MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver");
 MODULE_AUTHOR("Dongpo Li <lidongpo@hisilicon.com>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index 2e59a8419b17e9db4adb298d510d1038b9de604e..66b9cfe692fc707be1acb6a3f87dbfc996566c6a 100644 (file)
@@ -390,6 +390,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
        if (IS_ERR(gpiod)) {
                dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
                        bus->id);
+               device_del(&bus->dev);
                return PTR_ERR(gpiod);
        } else  if (gpiod) {
                bus->reset_gpiod = gpiod;
index b03bcf2c388aee4fa2b9d0bfa22f573e2689d824..3ddaf959569733a9e2e0ba3204b5b1db90f0cf20 100644 (file)
@@ -233,6 +233,7 @@ static struct phy_driver meson_gxl_phy[] = {
                .name           = "Meson GXL Internal PHY",
                .features       = PHY_BASIC_FEATURES,
                .flags          = PHY_IS_INTERNAL,
+               .soft_reset     = genphy_soft_reset,
                .config_init    = meson_gxl_config_init,
                .aneg_done      = genphy_aneg_done,
                .read_status    = meson_gxl_read_status,
index c33384710d26e03230562d1b0754b490dc0a45fc..b1f959935f50ceba9d23850e01d56f4f16d28e63 100644 (file)
@@ -1070,6 +1070,7 @@ static struct phy_driver ksphy_driver[] = {
        .driver_data    = &ksz9021_type,
        .probe          = kszphy_probe,
        .config_init    = ksz9031_config_init,
+       .soft_reset     = genphy_soft_reset,
        .read_status    = ksz9031_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = kszphy_config_intr,
@@ -1098,6 +1099,7 @@ static struct phy_driver ksphy_driver[] = {
        .phy_id         = PHY_ID_KSZ8873MLL,
        .phy_id_mask    = MICREL_PHY_ID_MASK,
        .name           = "Micrel KSZ8873MLL Switch",
+       .features       = PHY_BASIC_FEATURES,
        .config_init    = kszphy_config_init,
        .config_aneg    = ksz8873mll_config_aneg,
        .read_status    = ksz8873mll_read_status,
index d33e7b3caf03cb9af913f56dc47d732fe9b96a69..c5675df5fc6f8d4a377da8f08f6811bcffc36bf0 100644 (file)
@@ -543,13 +543,6 @@ int phy_start_aneg(struct phy_device *phydev)
 
        mutex_lock(&phydev->lock);
 
-       if (!__phy_is_started(phydev)) {
-               WARN(1, "called from state %s\n",
-                    phy_state_to_str(phydev->state));
-               err = -EBUSY;
-               goto out_unlock;
-       }
-
        if (AUTONEG_DISABLE == phydev->autoneg)
                phy_sanitize_settings(phydev);
 
@@ -560,11 +553,13 @@ int phy_start_aneg(struct phy_device *phydev)
        if (err < 0)
                goto out_unlock;
 
-       if (phydev->autoneg == AUTONEG_ENABLE) {
-               err = phy_check_link_status(phydev);
-       } else {
-               phydev->state = PHY_FORCING;
-               phydev->link_timeout = PHY_FORCE_TIMEOUT;
+       if (phy_is_started(phydev)) {
+               if (phydev->autoneg == AUTONEG_ENABLE) {
+                       err = phy_check_link_status(phydev);
+               } else {
+                       phydev->state = PHY_FORCING;
+                       phydev->link_timeout = PHY_FORCE_TIMEOUT;
+               }
        }
 
 out_unlock:
@@ -714,7 +709,7 @@ void phy_stop_machine(struct phy_device *phydev)
        cancel_delayed_work_sync(&phydev->state_queue);
 
        mutex_lock(&phydev->lock);
-       if (__phy_is_started(phydev))
+       if (phy_is_started(phydev))
                phydev->state = PHY_UP;
        mutex_unlock(&phydev->lock);
 }
@@ -767,9 +762,6 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
 {
        struct phy_device *phydev = phy_dat;
 
-       if (!phy_is_started(phydev))
-               return IRQ_NONE;                /* It can't be ours.  */
-
        if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev))
                return IRQ_NONE;
 
@@ -847,15 +839,14 @@ EXPORT_SYMBOL(phy_stop_interrupts);
  */
 void phy_stop(struct phy_device *phydev)
 {
-       mutex_lock(&phydev->lock);
-
-       if (!__phy_is_started(phydev)) {
+       if (!phy_is_started(phydev)) {
                WARN(1, "called from state %s\n",
                     phy_state_to_str(phydev->state));
-               mutex_unlock(&phydev->lock);
                return;
        }
 
+       mutex_lock(&phydev->lock);
+
        if (phy_interrupt_is_valid(phydev))
                phy_disable_interrupts(phydev);
 
@@ -994,8 +985,10 @@ void phy_state_machine(struct work_struct *work)
         * state machine would be pointless and possibly error prone when
         * called from phy_disconnect() synchronously.
         */
+       mutex_lock(&phydev->lock);
        if (phy_polling_mode(phydev) && phy_is_started(phydev))
                phy_queue_state_machine(phydev, PHY_STATE_TIME);
+       mutex_unlock(&phydev->lock);
 }
 
 /**
index 51990002d495e65eb857490d4f23d75788bf86e1..46c86725a693a84084f03b12cbf807661b78e65f 100644 (file)
@@ -61,6 +61,9 @@ EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features);
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_10gbit_features);
 
+__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features);
+
 static const int phy_basic_ports_array[] = {
        ETHTOOL_LINK_MODE_Autoneg_BIT,
        ETHTOOL_LINK_MODE_TP_BIT,
@@ -109,6 +112,11 @@ const int phy_10gbit_features_array[1] = {
 };
 EXPORT_SYMBOL_GPL(phy_10gbit_features_array);
 
+const int phy_10gbit_fec_features_array[1] = {
+       ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+};
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features_array);
+
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_10gbit_full_features);
 
@@ -191,6 +199,10 @@ static void features_init(void)
        linkmode_set_bit_array(phy_10gbit_full_features_array,
                               ARRAY_SIZE(phy_10gbit_full_features_array),
                               phy_10gbit_full_features);
+       /* 10G FEC only */
+       linkmode_set_bit_array(phy_10gbit_fec_features_array,
+                              ARRAY_SIZE(phy_10gbit_fec_features_array),
+                              phy_10gbit_fec_features);
 }
 
 void phy_device_free(struct phy_device *phydev)
@@ -2243,6 +2255,11 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
 {
        int retval;
 
+       if (WARN_ON(!new_driver->features)) {
+               pr_err("%s: Driver features are missing\n", new_driver->name);
+               return -EINVAL;
+       }
+
        new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY;
        new_driver->mdiodrv.driver.name = new_driver->name;
        new_driver->mdiodrv.driver.bus = &mdio_bus_type;
index e7becc7379d74899c5d007bc0e7789aeb953fc6e..938803237d7fa54ed70e7118bfe4d5b2dfbf0c47 100644 (file)
@@ -474,6 +474,17 @@ static void phylink_run_resolve(struct phylink *pl)
                queue_work(system_power_efficient_wq, &pl->resolve);
 }
 
+static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
+{
+       unsigned long state = pl->phylink_disable_state;
+
+       set_bit(bit, &pl->phylink_disable_state);
+       if (state == 0) {
+               queue_work(system_power_efficient_wq, &pl->resolve);
+               flush_work(&pl->resolve);
+       }
+}
+
 static void phylink_fixed_poll(struct timer_list *t)
 {
        struct phylink *pl = container_of(t, struct phylink, link_poll);
@@ -924,9 +935,7 @@ void phylink_stop(struct phylink *pl)
        if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
                del_timer_sync(&pl->link_poll);
 
-       set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
-       queue_work(system_power_efficient_wq, &pl->resolve);
-       flush_work(&pl->resolve);
+       phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
@@ -1632,9 +1641,7 @@ static void phylink_sfp_link_down(void *upstream)
 
        ASSERT_RTNL();
 
-       set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
-       queue_work(system_power_efficient_wq, &pl->resolve);
-       flush_work(&pl->resolve);
+       phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
 }
 
 static void phylink_sfp_link_up(void *upstream)
index f1da70b9b55ffa6107a372611e3ea34ad9d321c7..95abf7072f3226ecb02897d372b71b2bd8d082e3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /**
  * drivers/net/phy/rockchip.c
  *
@@ -6,12 +7,6 @@
  * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
  *
  * David Wu <david.wu@rock-chips.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
  */
 
 #include <linux/ethtool.h>
@@ -229,4 +224,4 @@ MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
 
 MODULE_AUTHOR("David Wu <david.wu@rock-chips.com>");
 MODULE_DESCRIPTION("Rockchip Ethernet PHY driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index ad9db652874dc737d0a76f16b9af4c56749d60fc..fef701bfad62e67e3349d8f1cca24b440af1aceb 100644 (file)
@@ -347,6 +347,7 @@ static int sfp_register_bus(struct sfp_bus *bus)
                                return ret;
                }
        }
+       bus->socket_ops->attach(bus->sfp);
        if (bus->started)
                bus->socket_ops->start(bus->sfp);
        bus->netdev->sfp_bus = bus;
@@ -362,6 +363,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
        if (bus->registered) {
                if (bus->started)
                        bus->socket_ops->stop(bus->sfp);
+               bus->socket_ops->detach(bus->sfp);
                if (bus->phydev && ops && ops->disconnect_phy)
                        ops->disconnect_phy(bus->upstream);
        }
index fd8bb998ae52d946ca5b29172a4553176addc726..68c8fbf099f87c3205b15908b520c2a57fc94c7a 100644 (file)
@@ -184,6 +184,7 @@ struct sfp {
 
        struct gpio_desc *gpio[GPIO_MAX];
 
+       bool attached;
        unsigned int state;
        struct delayed_work poll;
        struct delayed_work timeout;
@@ -1475,7 +1476,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
         */
        switch (sfp->sm_mod_state) {
        default:
-               if (event == SFP_E_INSERT) {
+               if (event == SFP_E_INSERT && sfp->attached) {
                        sfp_module_tx_disable(sfp);
                        sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
                }
@@ -1607,6 +1608,19 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
        mutex_unlock(&sfp->sm_mutex);
 }
 
+static void sfp_attach(struct sfp *sfp)
+{
+       sfp->attached = true;
+       if (sfp->state & SFP_F_PRESENT)
+               sfp_sm_event(sfp, SFP_E_INSERT);
+}
+
+static void sfp_detach(struct sfp *sfp)
+{
+       sfp->attached = false;
+       sfp_sm_event(sfp, SFP_E_REMOVE);
+}
+
 static void sfp_start(struct sfp *sfp)
 {
        sfp_sm_event(sfp, SFP_E_DEV_UP);
@@ -1667,6 +1681,8 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee,
 }
 
 static const struct sfp_socket_ops sfp_module_ops = {
+       .attach = sfp_attach,
+       .detach = sfp_detach,
        .start = sfp_start,
        .stop = sfp_stop,
        .module_info = sfp_module_info,
@@ -1834,10 +1850,6 @@ static int sfp_probe(struct platform_device *pdev)
        dev_info(sfp->dev, "Host maximum power %u.%uW\n",
                 sfp->max_power_mW / 1000, (sfp->max_power_mW / 100) % 10);
 
-       sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
-       if (!sfp->sfp_bus)
-               return -ENOMEM;
-
        /* Get the initial state, and always signal TX disable,
         * since the network interface will not be up.
         */
@@ -1848,10 +1860,6 @@ static int sfp_probe(struct platform_device *pdev)
                sfp->state |= SFP_F_RATE_SELECT;
        sfp_set_state(sfp, sfp->state);
        sfp_module_tx_disable(sfp);
-       rtnl_lock();
-       if (sfp->state & SFP_F_PRESENT)
-               sfp_sm_event(sfp, SFP_E_INSERT);
-       rtnl_unlock();
 
        for (i = 0; i < GPIO_MAX; i++) {
                if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
@@ -1884,6 +1892,10 @@ static int sfp_probe(struct platform_device *pdev)
                dev_warn(sfp->dev,
                         "No tx_disable pin: SFP modules will always be emitting.\n");
 
+       sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
+       if (!sfp->sfp_bus)
+               return -ENOMEM;
+
        return 0;
 }
 
index 31b0acf337e27f985e4d3d44800bdb4652bb31f7..64f54b0bbd8c4d2518898ce211aca5ea794479e4 100644 (file)
@@ -7,6 +7,8 @@
 struct sfp;
 
 struct sfp_socket_ops {
+       void (*attach)(struct sfp *sfp);
+       void (*detach)(struct sfp *sfp);
        void (*start)(struct sfp *sfp);
        void (*stop)(struct sfp *sfp);
        int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
index 22f3bdd8206cff3c7eb9cda24d585314ecaa3a0d..91247182bc527464549e22498d4350cad4cfd121 100644 (file)
@@ -80,6 +80,7 @@ static struct phy_driver teranetics_driver[] = {
        .phy_id         = PHY_ID_TN2020,
        .phy_id_mask    = 0xffffffff,
        .name           = "Teranetics TN2020",
+       .features       = PHY_10GBIT_FEATURES,
        .soft_reset     = gen10g_no_soft_reset,
        .aneg_done      = teranetics_aneg_done,
        .config_init    = gen10g_config_init,
index 62dc564b251d5e0c2019035355aa17426471cc8e..f22639f0116a4268644e4e8af911d5791b21962f 100644 (file)
@@ -445,6 +445,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
        if (pskb_trim_rcsum(skb, len))
                goto drop;
 
+       ph = pppoe_hdr(skb);
        pn = pppoe_pernet(dev_net(dev));
 
        /* Note that get_item does a sock_hold(), so sk_pppox(po)
index afd9d25d19924dcf5b343d23917d4cd6dc878d9b..958f1cf67282d46fbc379930a333d2d47a295709 100644 (file)
@@ -256,17 +256,6 @@ static void __team_option_inst_mark_removed_port(struct team *team,
        }
 }
 
-static bool __team_option_inst_tmp_find(const struct list_head *opts,
-                                       const struct team_option_inst *needle)
-{
-       struct team_option_inst *opt_inst;
-
-       list_for_each_entry(opt_inst, opts, tmp_list)
-               if (opt_inst == needle)
-                       return true;
-       return false;
-}
-
 static int __team_options_register(struct team *team,
                                   const struct team_option *option,
                                   size_t option_count)
@@ -2460,7 +2449,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
        int err = 0;
        int i;
        struct nlattr *nl_option;
-       LIST_HEAD(opt_inst_list);
 
        rtnl_lock();
 
@@ -2480,6 +2468,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1];
                struct nlattr *attr;
                struct nlattr *attr_data;
+               LIST_HEAD(opt_inst_list);
                enum team_option_type opt_type;
                int opt_port_ifindex = 0; /* != 0 for per-port options */
                u32 opt_array_index = 0;
@@ -2584,23 +2573,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                        if (err)
                                goto team_put;
                        opt_inst->changed = true;
-
-                       /* dumb/evil user-space can send us duplicate opt,
-                        * keep only the last one
-                        */
-                       if (__team_option_inst_tmp_find(&opt_inst_list,
-                                                       opt_inst))
-                               continue;
-
                        list_add(&opt_inst->tmp_list, &opt_inst_list);
                }
                if (!opt_found) {
                        err = -ENOENT;
                        goto team_put;
                }
-       }
 
-       err = team_nl_send_event_options_get(team, &opt_inst_list);
+               err = team_nl_send_event_options_get(team, &opt_inst_list);
+               if (err)
+                       break;
+       }
 
 team_put:
        team_nl_team_put(team);
index a4fdad47559462fbd049a89f880cc3fb33d1151d..fed298c0cb393e126243c84b44006b94192a1c5e 100644 (file)
@@ -856,10 +856,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
                err = 0;
        }
 
-       rcu_assign_pointer(tfile->tun, tun);
-       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
-       tun->numqueues++;
-
        if (tfile->detached) {
                tun_enable_queue(tfile);
        } else {
@@ -870,12 +866,18 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
        if (rtnl_dereference(tun->xdp_prog))
                sock_set_flag(&tfile->sk, SOCK_XDP);
 
-       tun_set_real_num_queues(tun);
-
        /* device is allowed to go away first, so no need to hold extra
         * refcnt.
         */
 
+       /* Publish tfile->tun and tun->tfiles only after we've fully
+        * initialized tfile; otherwise we risk using half-initialized
+        * object.
+        */
+       rcu_assign_pointer(tfile->tun, tun);
+       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+       tun->numqueues++;
+       tun_set_real_num_queues(tun);
 out:
        return err;
 }
index 57f1c94fca0ba0e96383c70676e45682d8862c11..820a2fe7d027733eb1c9ccc54aa504a4088a6600 100644 (file)
@@ -1287,6 +1287,20 @@ static const struct driver_info asix112_info = {
 
 #undef ASIX112_DESC
 
+static const struct driver_info trendnet_info = {
+       .description    = "USB-C 3.1 to 5GBASE-T Ethernet Adapter",
+       .bind           = aqc111_bind,
+       .unbind         = aqc111_unbind,
+       .status         = aqc111_status,
+       .link_reset     = aqc111_link_reset,
+       .reset          = aqc111_reset,
+       .stop           = aqc111_stop,
+       .flags          = FLAG_ETHER | FLAG_FRAMING_AX |
+                         FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+       .rx_fixup       = aqc111_rx_fixup,
+       .tx_fixup       = aqc111_tx_fixup,
+};
+
 static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
@@ -1440,6 +1454,7 @@ static const struct usb_device_id products[] = {
        {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
        {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)},
        {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)},
+       {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)},
        { },/* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
index b654f05b2ccd0b85c88cd42d52dc7c4fea44b868..3d93993e74da09abfa63252247c680be069401d3 100644 (file)
@@ -739,8 +739,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
        chipcode &= AX_CHIPCODE_MASK;
 
-       (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
-                                           ax88772a_hw_reset(dev, 0);
+       ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
+                                                 ax88772a_hw_reset(dev, 0);
+
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Failed to reset AX88772: %d\n", ret);
+               return ret;
+       }
 
        /* Read PHYID register *AFTER* the PHY was reset properly */
        phyid = asix_get_phyid(dev);
index b3b3c05903a1b3a863d2d4db43d20354133ff4f0..5512a1038721459a727326bb8823e16c0886b7f1 100644 (file)
@@ -179,10 +179,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
         * probed with) and a slave/data interface; union
         * descriptors sort this all out.
         */
-       info->control = usb_ifnum_to_if(dev->udev,
-       info->u->bMasterInterface0);
-       info->data = usb_ifnum_to_if(dev->udev,
-               info->u->bSlaveInterface0);
+       info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
+       info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
        if (!info->control || !info->data) {
                dev_dbg(&intf->dev,
                        "master #%u/%p slave #%u/%p\n",
@@ -216,18 +214,16 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        /* a data interface altsetting does the real i/o */
        d = &info->data->cur_altsetting->desc;
        if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
-               dev_dbg(&intf->dev, "slave class %u\n",
-                       d->bInterfaceClass);
+               dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass);
                goto bad_desc;
        }
 skip:
-       if (    rndis &&
-               header.usb_cdc_acm_descriptor &&
-               header.usb_cdc_acm_descriptor->bmCapabilities) {
-                       dev_dbg(&intf->dev,
-                               "ACM capabilities %02x, not really RNDIS?\n",
-                               header.usb_cdc_acm_descriptor->bmCapabilities);
-                       goto bad_desc;
+       if (rndis && header.usb_cdc_acm_descriptor &&
+           header.usb_cdc_acm_descriptor->bmCapabilities) {
+               dev_dbg(&intf->dev,
+                       "ACM capabilities %02x, not really RNDIS?\n",
+                       header.usb_cdc_acm_descriptor->bmCapabilities);
+               goto bad_desc;
        }
 
        if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
@@ -238,7 +234,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        }
 
        if (header.usb_cdc_mdlm_desc &&
-               memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
+           memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
                dev_dbg(&intf->dev, "GUID doesn't match\n");
                goto bad_desc;
        }
@@ -302,7 +298,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
                struct usb_endpoint_descriptor  *desc;
 
-               dev->status = &info->control->cur_altsetting->endpoint [0];
+               dev->status = &info->control->cur_altsetting->endpoint[0];
                desc = &dev->status->desc;
                if (!usb_endpoint_is_int_in(desc) ||
                    (le16_to_cpu(desc->wMaxPacketSize)
@@ -847,6 +843,14 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* USB-C 3.1 to 5GBASE-T Ethernet Adapter (based on AQC111U) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0xe05a, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
index 774e1ff01c9a9e3e3297360cc46d199ee9c90f40..735ad838e2ba86ab689c549d4a89e5ca54fecd95 100644 (file)
@@ -123,6 +123,7 @@ static void qmimux_setup(struct net_device *dev)
        dev->addr_len        = 0;
        dev->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
        dev->netdev_ops      = &qmimux_netdev_ops;
+       dev->mtu             = 1500;
        dev->needs_free_netdev = true;
 }
 
index 0237250860467f296cb3ab8bb916b17f353bdf2f..4cfceb789eea803c07b8971673451cec9a535636 100644 (file)
@@ -57,6 +57,8 @@ module_param(napi_tx, bool, 0644);
 #define VIRTIO_XDP_TX          BIT(0)
 #define VIRTIO_XDP_REDIR       BIT(1)
 
+#define VIRTIO_XDP_FLAG        BIT(0)
+
 /* RX packet size EWMA. The average packet size is used to determine the packet
  * buffer size when refilling RX rings. As the entire RX ring may be refilled
  * at once, the weight is chosen so that the EWMA will be insensitive to short-
@@ -252,6 +254,21 @@ struct padded_vnet_hdr {
        char padding[4];
 };
 
+static bool is_xdp_frame(void *ptr)
+{
+       return (unsigned long)ptr & VIRTIO_XDP_FLAG;
+}
+
+static void *xdp_to_ptr(struct xdp_frame *ptr)
+{
+       return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG);
+}
+
+static struct xdp_frame *ptr_to_xdp(void *ptr)
+{
+       return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
+}
+
 /* Converting between virtqueue no. and kernel tx/rx queue no.
  * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
  */
@@ -462,7 +479,8 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
 
        sg_init_one(sq->sg, xdpf->data, xdpf->len);
 
-       err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdpf, GFP_ATOMIC);
+       err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp_to_ptr(xdpf),
+                                  GFP_ATOMIC);
        if (unlikely(err))
                return -ENOSPC; /* Caller handle free/refcnt */
 
@@ -482,36 +500,47 @@ static int virtnet_xdp_xmit(struct net_device *dev,
 {
        struct virtnet_info *vi = netdev_priv(dev);
        struct receive_queue *rq = vi->rq;
-       struct xdp_frame *xdpf_sent;
        struct bpf_prog *xdp_prog;
        struct send_queue *sq;
        unsigned int len;
+       int packets = 0;
+       int bytes = 0;
        int drops = 0;
        int kicks = 0;
        int ret, err;
+       void *ptr;
        int i;
 
-       sq = virtnet_xdp_sq(vi);
-
-       if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
-               ret = -EINVAL;
-               drops = n;
-               goto out;
-       }
-
        /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
         * indicate XDP resources have been successfully allocated.
         */
        xdp_prog = rcu_dereference(rq->xdp_prog);
-       if (!xdp_prog) {
-               ret = -ENXIO;
+       if (!xdp_prog)
+               return -ENXIO;
+
+       sq = virtnet_xdp_sq(vi);
+
+       if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
+               ret = -EINVAL;
                drops = n;
                goto out;
        }
 
        /* Free up any pending old buffers before queueing new ones. */
-       while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
-               xdp_return_frame(xdpf_sent);
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(is_xdp_frame(ptr))) {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
+
+                       bytes += frame->len;
+                       xdp_return_frame(frame);
+               } else {
+                       struct sk_buff *skb = ptr;
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, false);
+               }
+               packets++;
+       }
 
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
@@ -530,6 +559,8 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        }
 out:
        u64_stats_update_begin(&sq->stats.syncp);
+       sq->stats.bytes += bytes;
+       sq->stats.packets += packets;
        sq->stats.xdp_tx += n;
        sq->stats.xdp_tx_drops += drops;
        sq->stats.kicks += kicks;
@@ -1330,20 +1361,28 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
        return stats.packets;
 }
 
-static void free_old_xmit_skbs(struct send_queue *sq)
+static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
 {
-       struct sk_buff *skb;
        unsigned int len;
        unsigned int packets = 0;
        unsigned int bytes = 0;
+       void *ptr;
 
-       while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-               pr_debug("Sent skb %p\n", skb);
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(!is_xdp_frame(ptr))) {
+                       struct sk_buff *skb = ptr;
 
-               bytes += skb->len;
-               packets++;
+                       pr_debug("Sent skb %p\n", skb);
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, in_napi);
+               } else {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
 
-               dev_consume_skb_any(skb);
+                       bytes += frame->len;
+                       xdp_return_frame(frame);
+               }
+               packets++;
        }
 
        /* Avoid overhead when no packets have been processed
@@ -1358,6 +1397,16 @@ static void free_old_xmit_skbs(struct send_queue *sq)
        u64_stats_update_end(&sq->stats.syncp);
 }
 
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+{
+       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+               return false;
+       else if (q < vi->curr_queue_pairs)
+               return true;
+       else
+               return false;
+}
+
 static void virtnet_poll_cleantx(struct receive_queue *rq)
 {
        struct virtnet_info *vi = rq->vq->vdev->priv;
@@ -1365,11 +1414,11 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
        struct send_queue *sq = &vi->sq[index];
        struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index);
 
-       if (!sq->napi.weight)
+       if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
                return;
 
        if (__netif_tx_trylock(txq)) {
-               free_old_xmit_skbs(sq);
+               free_old_xmit_skbs(sq, true);
                __netif_tx_unlock(txq);
        }
 
@@ -1442,10 +1491,18 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
 {
        struct send_queue *sq = container_of(napi, struct send_queue, napi);
        struct virtnet_info *vi = sq->vq->vdev->priv;
-       struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
+       unsigned int index = vq2txq(sq->vq);
+       struct netdev_queue *txq;
 
+       if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
+               /* We don't need to enable cb for XDP */
+               napi_complete_done(napi, 0);
+               return 0;
+       }
+
+       txq = netdev_get_tx_queue(vi->dev, index);
        __netif_tx_lock(txq, raw_smp_processor_id());
-       free_old_xmit_skbs(sq);
+       free_old_xmit_skbs(sq, true);
        __netif_tx_unlock(txq);
 
        virtqueue_napi_complete(napi, sq->vq, 0);
@@ -1514,7 +1571,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
        bool use_napi = sq->napi.weight;
 
        /* Free up any pending old buffers before queueing new ones. */
-       free_old_xmit_skbs(sq);
+       free_old_xmit_skbs(sq, false);
 
        if (use_napi && kick)
                virtqueue_enable_cb_delayed(sq->vq);
@@ -1557,7 +1614,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
                if (!use_napi &&
                    unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
-                       free_old_xmit_skbs(sq);
+                       free_old_xmit_skbs(sq, false);
                        if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
                                netif_start_subqueue(dev, qnum);
                                virtqueue_disable_cb(sq->vq);
@@ -2395,6 +2452,10 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                return -ENOMEM;
        }
 
+       old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
+       if (!prog && !old_prog)
+               return 0;
+
        if (prog) {
                prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
                if (IS_ERR(prog))
@@ -2402,36 +2463,62 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
        }
 
        /* Make sure NAPI is not using any XDP TX queues for RX. */
-       if (netif_running(dev))
-               for (i = 0; i < vi->max_queue_pairs; i++)
+       if (netif_running(dev)) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
                        napi_disable(&vi->rq[i].napi);
+                       virtnet_napi_tx_disable(&vi->sq[i].napi);
+               }
+       }
+
+       if (!prog) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+                       if (i == 0)
+                               virtnet_restore_guest_offloads(vi);
+               }
+               synchronize_net();
+       }
 
-       netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
        err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
        if (err)
                goto err;
+       netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
        vi->xdp_queue_pairs = xdp_qp;
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
-               rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
-               if (i == 0) {
-                       if (!old_prog)
+       if (prog) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+                       if (i == 0 && !old_prog)
                                virtnet_clear_guest_offloads(vi);
-                       if (!prog)
-                               virtnet_restore_guest_offloads(vi);
                }
+       }
+
+       for (i = 0; i < vi->max_queue_pairs; i++) {
                if (old_prog)
                        bpf_prog_put(old_prog);
-               if (netif_running(dev))
+               if (netif_running(dev)) {
                        virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+                                              &vi->sq[i].napi);
+               }
        }
 
        return 0;
 
 err:
-       for (i = 0; i < vi->max_queue_pairs; i++)
-               virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+       if (!prog) {
+               virtnet_clear_guest_offloads(vi);
+               for (i = 0; i < vi->max_queue_pairs; i++)
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
+       }
+
+       if (netif_running(dev)) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+                                              &vi->sq[i].napi);
+               }
+       }
        if (prog)
                bpf_prog_sub(prog, vi->max_queue_pairs - 1);
        return err;
@@ -2613,16 +2700,6 @@ static void free_receive_page_frags(struct virtnet_info *vi)
                        put_page(vi->rq[i].alloc_frag.page);
 }
 
-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
-{
-       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
-               return false;
-       else if (q < vi->curr_queue_pairs)
-               return true;
-       else
-               return false;
-}
-
 static void free_unused_bufs(struct virtnet_info *vi)
 {
        void *buf;
@@ -2631,10 +2708,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
        for (i = 0; i < vi->max_queue_pairs; i++) {
                struct virtqueue *vq = vi->sq[i].vq;
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-                       if (!is_xdp_raw_buffer_queue(vi, i))
+                       if (!is_xdp_frame(buf))
                                dev_kfree_skb(buf);
                        else
-                               put_page(virt_to_head_page(buf));
+                               xdp_return_frame(ptr_to_xdp(buf));
                }
        }
 
index 5209ee9aac47846367d7f469a7e69d08c030087e..2aae11feff0c22c1b073a6a119fc6c311cbe1691 100644 (file)
@@ -2219,7 +2219,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
        struct pcpu_sw_netstats *tx_stats, *rx_stats;
        union vxlan_addr loopback;
        union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
-       struct net_device *dev = skb->dev;
+       struct net_device *dev;
        int len = skb->len;
 
        tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
@@ -2239,9 +2239,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 #endif
        }
 
+       rcu_read_lock();
+       dev = skb->dev;
+       if (unlikely(!(dev->flags & IFF_UP))) {
+               kfree_skb(skb);
+               goto drop;
+       }
+
        if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
-               vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0,
-                           vni);
+               vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
 
        u64_stats_update_begin(&tx_stats->syncp);
        tx_stats->tx_packets++;
@@ -2254,8 +2260,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                rx_stats->rx_bytes += len;
                u64_stats_update_end(&rx_stats->syncp);
        } else {
+drop:
                dev->stats.rx_dropped++;
        }
+       rcu_read_unlock();
 }
 
 static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
index c0b0f525c87ca81c52ba66e0563288c558a7605c..27decf8ae840b95e3b8568a7d4f94cb8805e9093 100644 (file)
@@ -1575,7 +1575,7 @@ static void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
                                        dev->stats.tx_packets++;
                                        dev->stats.tx_bytes += skb->len;
                                }
-                               dev_kfree_skb_irq(skb);
+                               dev_consume_skb_irq(skb);
                                dpriv->tx_skbuff[cur] = NULL;
                                ++dpriv->tx_dirty;
                        } else {
index be64854281981b33a085bdf31bad0407a199bb3a..a08f04c3f64410c9ca8d78ff62802ac1c417be40 100644 (file)
@@ -482,7 +482,7 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv)
                memset(priv->tx_buffer +
                       (be32_to_cpu(bd->buf) - priv->dma_tx_addr),
                       0, skb->len);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
 
                priv->tx_skbuff[priv->skb_dirtytx] = NULL;
                priv->skb_dirtytx =
@@ -1056,6 +1056,54 @@ static const struct net_device_ops uhdlc_ops = {
        .ndo_tx_timeout = uhdlc_tx_timeout,
 };
 
+static int hdlc_map_iomem(char *name, int init_flag, void __iomem **ptr)
+{
+       struct device_node *np;
+       struct platform_device *pdev;
+       struct resource *res;
+       static int siram_init_flag;
+       int ret = 0;
+
+       np = of_find_compatible_node(NULL, NULL, name);
+       if (!np)
+               return -EINVAL;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev) {
+               pr_err("%pOFn: failed to lookup pdev\n", np);
+               of_node_put(np);
+               return -EINVAL;
+       }
+
+       of_node_put(np);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -EINVAL;
+               goto error_put_device;
+       }
+       *ptr = ioremap(res->start, resource_size(res));
+       if (!*ptr) {
+               ret = -ENOMEM;
+               goto error_put_device;
+       }
+
+       /* We've remapped the addresses, and we don't need the device any
+        * more, so we should release it.
+        */
+       put_device(&pdev->dev);
+
+       if (init_flag && siram_init_flag == 0) {
+               memset_io(*ptr, 0, resource_size(res));
+               siram_init_flag = 1;
+       }
+       return  0;
+
+error_put_device:
+       put_device(&pdev->dev);
+
+       return ret;
+}
+
 static int ucc_hdlc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1150,6 +1198,15 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
                ret = ucc_of_parse_tdm(np, utdm, ut_info);
                if (ret)
                        goto free_utdm;
+
+               ret = hdlc_map_iomem("fsl,t1040-qe-si", 0,
+                                    (void __iomem **)&utdm->si_regs);
+               if (ret)
+                       goto free_utdm;
+               ret = hdlc_map_iomem("fsl,t1040-qe-siram", 1,
+                                    (void __iomem **)&utdm->siram);
+               if (ret)
+                       goto unmap_si_regs;
        }
 
        if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask))
@@ -1158,7 +1215,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
        ret = uhdlc_init(uhdlc_priv);
        if (ret) {
                dev_err(&pdev->dev, "Failed to init uhdlc\n");
-               goto free_utdm;
+               goto undo_uhdlc_init;
        }
 
        dev = alloc_hdlcdev(uhdlc_priv);
@@ -1187,6 +1244,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
 free_dev:
        free_netdev(dev);
 undo_uhdlc_init:
+       iounmap(utdm->siram);
+unmap_si_regs:
+       iounmap(utdm->si_regs);
 free_utdm:
        if (uhdlc_priv->tsa)
                kfree(utdm);
index 399b501f3c3c19d73f6183ad3a5ad692fefc86ff..e8891f5fc83ada175eebe0bd389ea0e7494ba5b9 100644 (file)
@@ -548,7 +548,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
        {
                .id = WCN3990_HW_1_0_DEV_VERSION,
                .dev_id = 0,
-               .bus = ATH10K_BUS_PCI,
+               .bus = ATH10K_BUS_SNOC,
                .name = "wcn3990 hw1.0",
                .continuous_frag_desc = true,
                .tx_chain_mask = 0x7,
index 491ca3c8b43cb745c7ea0beed63e6097fbc96a64..83d5bceea08f75c0f37b65f873600ba1c7eb0b79 100644 (file)
@@ -1,6 +1,6 @@
 config IWLWIFI
        tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
-       depends on PCI && HAS_IOMEM
+       depends on PCI && HAS_IOMEM && CFG80211
        select FW_LOADER
        ---help---
          Select to build the driver supporting the:
@@ -47,6 +47,7 @@ if IWLWIFI
 config IWLWIFI_LEDS
        bool
        depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
+       depends on IWLMVM || IWLDVM
        select LEDS_TRIGGERS
        select MAC80211_LEDS
        default y
index 3a4b8786f7ea92d4286135c2070fe5a9158691dd..320edcac469985308ea96a7883dcdf86367d83ae 100644 (file)
@@ -2761,6 +2761,11 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                                        BIT(NL80211_CHAN_WIDTH_160);
        }
 
+       if (!n_limits) {
+               err = -EINVAL;
+               goto failed_hw;
+       }
+
        data->if_combination.n_limits = n_limits;
        data->if_combination.max_interfaces = 2048;
        data->if_combination.limits = data->if_limits;
index 497e762978cca5fa6b48cb78939d16dc740a0f26..b2cabce1d74d78e97666200194724ea8c6852981 100644 (file)
@@ -212,24 +212,24 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
        mt76x02_add_rate_power_offset(t, delta);
 }
 
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
+void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp)
 {
        struct mt76x0_chan_map {
                u8 chan;
                u8 offset;
        } chan_map[] = {
-               {   2,  0 }, {   4,  1 }, {   6,  2 }, {   8,  3 },
-               {  10,  4 }, {  12,  5 }, {  14,  6 }, {  38,  0 },
-               {  44,  1 }, {  48,  2 }, {  54,  3 }, {  60,  4 },
-               {  64,  5 }, { 102,  6 }, { 108,  7 }, { 112,  8 },
-               { 118,  9 }, { 124, 10 }, { 128, 11 }, { 134, 12 },
-               { 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 },
-               { 167, 17 }, { 171, 18 }, { 173, 19 },
+               {   2,  0 }, {   4,  2 }, {   6,  4 }, {   8,  6 },
+               {  10,  8 }, {  12, 10 }, {  14, 12 }, {  38,  0 },
+               {  44,  2 }, {  48,  4 }, {  54,  6 }, {  60,  8 },
+               {  64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 },
+               { 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 },
+               { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
+               { 167, 34 }, { 171, 36 }, { 175, 38 },
        };
        struct ieee80211_channel *chan = dev->mt76.chandef.chan;
        u8 offset, addr;
+       int i, idx = 0;
        u16 data;
-       int i;
 
        if (mt76x0_tssi_enabled(dev)) {
                s8 target_power;
@@ -239,14 +239,14 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
                else
                        data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
                target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
-               info[0] = target_power + mt76x0_get_delta(dev);
-               info[1] = 0;
+               *tp = target_power + mt76x0_get_delta(dev);
 
                return;
        }
 
        for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
-               if (chan_map[i].chan <= chan->hw_value) {
+               if (chan->hw_value <= chan_map[i].chan) {
+                       idx = (chan->hw_value == chan_map[i].chan);
                        offset = chan_map[i].offset;
                        break;
                }
@@ -258,13 +258,16 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
                addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
        } else {
                switch (chan->hw_value) {
+               case 42:
+                       offset = 2;
+                       break;
                case 58:
                        offset = 8;
                        break;
                case 106:
                        offset = 14;
                        break;
-               case 112:
+               case 122:
                        offset = 20;
                        break;
                case 155:
@@ -277,14 +280,9 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
        }
 
        data = mt76x02_eeprom_get(dev, addr);
-
-       info[0] = data;
-       if (!info[0] || info[0] > 0x3f)
-               info[0] = 5;
-
-       info[1] = data >> 8;
-       if (!info[1] || info[1] > 0x3f)
-               info[1] = 5;
+       *tp = data >> (8 * idx);
+       if (*tp < 0 || *tp > 0x3f)
+               *tp = 5;
 }
 
 static int mt76x0_check_eeprom(struct mt76x02_dev *dev)
index ee9ade9f3c8bf1394dce37618613e07d0400c08d..42b259f90b6d3f6f8ce8ef76bd97f061f7c584bf 100644 (file)
@@ -26,7 +26,7 @@ struct mt76x02_dev;
 int mt76x0_eeprom_init(struct mt76x02_dev *dev);
 void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
 void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev);
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info);
+void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp);
 
 static inline s8 s6_to_s8(u32 val)
 {
index 1eb1a802ed20d2a8744fa6496c4857c43a762046..b6166703ad763742475a4cfdf80bcc1f0479cd27 100644 (file)
@@ -845,17 +845,17 @@ static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
 void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
 {
        struct mt76_rate_power *t = &dev->mt76.rate_power;
-       u8 info[2];
+       s8 info;
 
        mt76x0_get_tx_power_per_rate(dev);
-       mt76x0_get_power_info(dev, info);
+       mt76x0_get_power_info(dev, &info);
 
-       mt76x02_add_rate_power_offset(t, info[0]);
+       mt76x02_add_rate_power_offset(t, info);
        mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
        dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
-       mt76x02_add_rate_power_offset(t, -info[0]);
+       mt76x02_add_rate_power_offset(t, -info);
 
-       mt76x02_phy_set_txpower(dev, info[0], info[1]);
+       mt76x02_phy_set_txpower(dev, info, info);
 }
 
 void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
index bd10165d7eec5b4d28c22d06e7a3abad79ade277..4d4b077011497b140fa56d2ac74159bdb8dcc25d 100644 (file)
@@ -164,6 +164,12 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
        }
 
        sdio_claim_host(func);
+       /*
+        * To guarantee that the SDIO card is power cycled, as required to make
+        * the FW programming to succeed, let's do a brute force HW reset.
+        */
+       mmc_hw_reset(card->host);
+
        sdio_enable_func(func);
        sdio_release_host(func);
 
@@ -174,20 +180,13 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
 {
        struct sdio_func *func = dev_to_sdio_func(glue->dev);
        struct mmc_card *card = func->card;
-       int error;
 
        sdio_claim_host(func);
        sdio_disable_func(func);
        sdio_release_host(func);
 
        /* Let runtime PM know the card is powered off */
-       error = pm_runtime_put(&card->dev);
-       if (error < 0 && error != -EBUSY) {
-               dev_err(&card->dev, "%s failed: %i\n", __func__, error);
-
-               return error;
-       }
-
+       pm_runtime_put(&card->dev);
        return 0;
 }
 
index 64b218699656f5a02a70ea1357868d96793d8e49..3a93e4d9828bb5355934a4b06a6bf157188cfeaa 100644 (file)
@@ -530,8 +530,10 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
        SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
        dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL);
 
-       if (!dev->ieee80211_ptr)
+       if (!dev->ieee80211_ptr) {
+               err = -ENOMEM;
                goto remove_handler;
+       }
 
        dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
        dev->ieee80211_ptr->wiphy = common_wiphy;
index 0cf58cabc9eda43aed6a006a88b4f18fc88daa18..3cf50274fadb023b485fa613954b5b51af83240f 100644 (file)
@@ -26,6 +26,12 @@ static int nvdimm_probe(struct device *dev)
        struct nvdimm_drvdata *ndd;
        int rc;
 
+       rc = nvdimm_security_setup_events(dev);
+       if (rc < 0) {
+               dev_err(dev, "security event setup failed: %d\n", rc);
+               return rc;
+       }
+
        rc = nvdimm_check_config_data(dev);
        if (rc) {
                /* not required for non-aliased nvdimm, ex. NVDIMM-N */
index 4890310df87440a3fcd459de19d563e026c0922d..efe412a6b5b916220a1313a7ac194ce10f5232ca 100644 (file)
@@ -578,13 +578,25 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(__nvdimm_create);
 
-int nvdimm_security_setup_events(struct nvdimm *nvdimm)
+static void shutdown_security_notify(void *data)
 {
-       nvdimm->sec.overwrite_state = sysfs_get_dirent(nvdimm->dev.kobj.sd,
-                       "security");
+       struct nvdimm *nvdimm = data;
+
+       sysfs_put(nvdimm->sec.overwrite_state);
+}
+
+int nvdimm_security_setup_events(struct device *dev)
+{
+       struct nvdimm *nvdimm = to_nvdimm(dev);
+
+       if (nvdimm->sec.state < 0 || !nvdimm->sec.ops
+                       || !nvdimm->sec.ops->overwrite)
+               return 0;
+       nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security");
        if (!nvdimm->sec.overwrite_state)
-               return -ENODEV;
-       return 0;
+               return -ENOMEM;
+
+       return devm_add_action_or_reset(dev, shutdown_security_notify, nvdimm);
 }
 EXPORT_SYMBOL_GPL(nvdimm_security_setup_events);
 
index 2b2cf4e554d3b06074d70de3a2134fe84dbc77d5..e5ffd5733540955b43826614d5e92d8a72d953b9 100644 (file)
@@ -54,12 +54,12 @@ struct nvdimm {
 };
 
 static inline enum nvdimm_security_state nvdimm_security_state(
-               struct nvdimm *nvdimm, bool master)
+               struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype)
 {
        if (!nvdimm->sec.ops)
                return -ENXIO;
 
-       return nvdimm->sec.ops->state(nvdimm, master);
+       return nvdimm->sec.ops->state(nvdimm, ptype);
 }
 int nvdimm_security_freeze(struct nvdimm *nvdimm);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
index cfde992684e7db07de208b94b0f4b382e59701d3..379bf4305e6159a2568940df7cb06f07f774b55c 100644 (file)
@@ -250,6 +250,7 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
 void nvdimm_set_aliasing(struct device *dev);
 void nvdimm_set_locked(struct device *dev);
 void nvdimm_clear_locked(struct device *dev);
+int nvdimm_security_setup_events(struct device *dev);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
 int nvdimm_security_unlock(struct device *dev);
 #else
index 150e49723c15af38167f3d6aa6a3ddb9a745ed4b..6a9dd68c0f4feb673e57ebbaba1bfe967832b1ba 100644 (file)
@@ -1253,6 +1253,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
         * effects say only one namespace is affected.
         */
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
+               mutex_lock(&ctrl->scan_lock);
                nvme_start_freeze(ctrl);
                nvme_wait_freeze(ctrl);
        }
@@ -1281,8 +1282,10 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
         */
        if (effects & NVME_CMD_EFFECTS_LBCC)
                nvme_update_formats(ctrl);
-       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK))
+       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                nvme_unfreeze(ctrl);
+               mutex_unlock(&ctrl->scan_lock);
+       }
        if (effects & NVME_CMD_EFFECTS_CCC)
                nvme_init_identify(ctrl);
        if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
@@ -3401,6 +3404,7 @@ static void nvme_scan_work(struct work_struct *work)
        if (nvme_identify_ctrl(ctrl, &id))
                return;
 
+       mutex_lock(&ctrl->scan_lock);
        nn = le32_to_cpu(id->nn);
        if (ctrl->vs >= NVME_VS(1, 1, 0) &&
            !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
@@ -3409,6 +3413,7 @@ static void nvme_scan_work(struct work_struct *work)
        }
        nvme_scan_ns_sequential(ctrl, nn);
 out_free_id:
+       mutex_unlock(&ctrl->scan_lock);
        kfree(id);
        down_write(&ctrl->namespaces_rwsem);
        list_sort(NULL, &ctrl->namespaces, ns_cmp);
@@ -3652,6 +3657,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 
        ctrl->state = NVME_CTRL_NEW;
        spin_lock_init(&ctrl->lock);
+       mutex_init(&ctrl->scan_lock);
        INIT_LIST_HEAD(&ctrl->namespaces);
        init_rwsem(&ctrl->namespaces_rwsem);
        ctrl->dev = dev;
index df4b3a6db51bfdf8307e38da3cd568209266f0a5..b9fff3b8ed1b1dd180b50de141bbc3d2af73a485 100644 (file)
@@ -545,8 +545,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
        ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
                ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc);
-       if (!(ctrl->anacap & (1 << 6)))
-               ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
+       ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
 
        if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
                dev_err(ctrl->device,
index ab961bdeea89ad5e3c6d2f0be0480ca23083bd7c..c4a1bb41abf0041e41e18a40db2dc4280be0aab4 100644 (file)
@@ -154,6 +154,7 @@ struct nvme_ctrl {
        enum nvme_ctrl_state state;
        bool identified;
        spinlock_t lock;
+       struct mutex scan_lock;
        const struct nvme_ctrl_ops *ops;
        struct request_queue *admin_q;
        struct request_queue *connect_q;
index deb1a66bf117a8896d2aeb0d13a9b2453657a49f..7fee665ec45e80675a44b9e478193a92516d43af 100644 (file)
@@ -2041,14 +2041,18 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
        return ret;
 }
 
+/* irq_queues covers admin queue */
 static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
 {
        unsigned int this_w_queues = write_queues;
 
+       WARN_ON(!irq_queues);
+
        /*
-        * Setup read/write queue split
+        * Setup read/write queue split, assign admin queue one independent
+        * irq vector if irq_queues is > 1.
         */
-       if (irq_queues == 1) {
+       if (irq_queues <= 2) {
                dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
                dev->io_queues[HCTX_TYPE_READ] = 0;
                return;
@@ -2056,21 +2060,21 @@ static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
 
        /*
         * If 'write_queues' is set, ensure it leaves room for at least
-        * one read queue
+        * one read queue and one admin queue
         */
        if (this_w_queues >= irq_queues)
-               this_w_queues = irq_queues - 1;
+               this_w_queues = irq_queues - 2;
 
        /*
         * If 'write_queues' is set to zero, reads and writes will share
         * a queue set.
         */
        if (!this_w_queues) {
-               dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues;
+               dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues - 1;
                dev->io_queues[HCTX_TYPE_READ] = 0;
        } else {
                dev->io_queues[HCTX_TYPE_DEFAULT] = this_w_queues;
-               dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues;
+               dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues - 1;
        }
 }
 
@@ -2095,7 +2099,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                this_p_queues = nr_io_queues - 1;
                irq_queues = 1;
        } else {
-               irq_queues = nr_io_queues - this_p_queues;
+               irq_queues = nr_io_queues - this_p_queues + 1;
        }
        dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
 
@@ -2115,8 +2119,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                 * If we got a failure and we're down to asking for just
                 * 1 + 1 queues, just ask for a single vector. We'll share
                 * that between the single IO queue and the admin queue.
+                * Otherwise, we assign one independent vector to admin queue.
                 */
-               if (result >= 0 && irq_queues > 1)
+               if (irq_queues > 1)
                        irq_queues = irq_sets[0] + irq_sets[1] + 1;
 
                result = pci_alloc_irq_vectors_affinity(pdev, irq_queues,
@@ -2552,27 +2557,18 @@ static void nvme_reset_work(struct work_struct *work)
        if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
                nvme_dev_disable(dev, false);
 
-       /*
-        * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
-        * initializing procedure here.
-        */
-       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
-               dev_warn(dev->ctrl.device,
-                       "failed to mark controller CONNECTING\n");
-               goto out;
-       }
-
+       mutex_lock(&dev->shutdown_lock);
        result = nvme_pci_enable(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        result = nvme_pci_configure_admin_queue(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        result = nvme_alloc_admin_tags(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        /*
         * Limit the max command size to prevent iod->sg allocations going
@@ -2580,6 +2576,17 @@ static void nvme_reset_work(struct work_struct *work)
         */
        dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1;
        dev->ctrl.max_segments = NVME_MAX_SEGS;
+       mutex_unlock(&dev->shutdown_lock);
+
+       /*
+        * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
+        * initializing procedure here.
+        */
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
+               dev_warn(dev->ctrl.device,
+                       "failed to mark controller CONNECTING\n");
+               goto out;
+       }
 
        result = nvme_init_identify(&dev->ctrl);
        if (result)
@@ -2644,6 +2651,8 @@ static void nvme_reset_work(struct work_struct *work)
        nvme_start_ctrl(&dev->ctrl);
        return;
 
+ out_unlock:
+       mutex_unlock(&dev->shutdown_lock);
  out:
        nvme_remove_dead_ctrl(dev, result);
 }
index 0a2fd2949ad788b9f5daae0acf3d7d54b8a6ad18..52abc3a6de129cab702ee1ca488bf8946940657e 100644 (file)
@@ -119,6 +119,7 @@ struct nvme_rdma_ctrl {
 
        struct nvme_ctrl        ctrl;
        bool                    use_inline_data;
+       u32                     io_queues[HCTX_MAX_TYPES];
 };
 
 static inline struct nvme_rdma_ctrl *to_rdma_ctrl(struct nvme_ctrl *ctrl)
@@ -165,8 +166,8 @@ static inline int nvme_rdma_queue_idx(struct nvme_rdma_queue *queue)
 static bool nvme_rdma_poll_queue(struct nvme_rdma_queue *queue)
 {
        return nvme_rdma_queue_idx(queue) >
-               queue->ctrl->ctrl.opts->nr_io_queues +
-               queue->ctrl->ctrl.opts->nr_write_queues;
+               queue->ctrl->io_queues[HCTX_TYPE_DEFAULT] +
+               queue->ctrl->io_queues[HCTX_TYPE_READ];
 }
 
 static inline size_t nvme_rdma_inline_data_size(struct nvme_rdma_queue *queue)
@@ -661,8 +662,21 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
        nr_io_queues = min_t(unsigned int, nr_io_queues,
                                ibdev->num_comp_vectors);
 
-       nr_io_queues += min(opts->nr_write_queues, num_online_cpus());
-       nr_io_queues += min(opts->nr_poll_queues, num_online_cpus());
+       if (opts->nr_write_queues) {
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] =
+                               min(opts->nr_write_queues, nr_io_queues);
+               nr_io_queues += ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       } else {
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] = nr_io_queues;
+       }
+
+       ctrl->io_queues[HCTX_TYPE_READ] = nr_io_queues;
+
+       if (opts->nr_poll_queues) {
+               ctrl->io_queues[HCTX_TYPE_POLL] =
+                       min(opts->nr_poll_queues, num_online_cpus());
+               nr_io_queues += ctrl->io_queues[HCTX_TYPE_POLL];
+       }
 
        ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
        if (ret)
@@ -1689,18 +1703,28 @@ static enum blk_eh_timer_return
 nvme_rdma_timeout(struct request *rq, bool reserved)
 {
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+       struct nvme_rdma_queue *queue = req->queue;
+       struct nvme_rdma_ctrl *ctrl = queue->ctrl;
 
-       dev_warn(req->queue->ctrl->ctrl.device,
-                "I/O %d QID %d timeout, reset controller\n",
-                rq->tag, nvme_rdma_queue_idx(req->queue));
+       dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n",
+                rq->tag, nvme_rdma_queue_idx(queue));
 
-       /* queue error recovery */
-       nvme_rdma_error_recovery(req->queue->ctrl);
+       if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
+               /*
+                * Teardown immediately if controller times out while starting
+                * or we are already started error recovery. all outstanding
+                * requests are completed on shutdown, so we return BLK_EH_DONE.
+                */
+               flush_work(&ctrl->err_work);
+               nvme_rdma_teardown_io_queues(ctrl, false);
+               nvme_rdma_teardown_admin_queue(ctrl, false);
+               return BLK_EH_DONE;
+       }
 
-       /* fail with DNR on cmd timeout */
-       nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+       dev_warn(ctrl->ctrl.device, "starting error recovery\n");
+       nvme_rdma_error_recovery(ctrl);
 
-       return BLK_EH_DONE;
+       return BLK_EH_RESET_TIMER;
 }
 
 static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
@@ -1779,17 +1803,15 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
        struct nvme_rdma_ctrl *ctrl = set->driver_data;
 
        set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
-       set->map[HCTX_TYPE_READ].nr_queues = ctrl->ctrl.opts->nr_io_queues;
+       set->map[HCTX_TYPE_DEFAULT].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       set->map[HCTX_TYPE_READ].nr_queues = ctrl->io_queues[HCTX_TYPE_READ];
        if (ctrl->ctrl.opts->nr_write_queues) {
                /* separate read/write queues */
-               set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                               ctrl->ctrl.opts->nr_write_queues;
                set->map[HCTX_TYPE_READ].queue_offset =
-                               ctrl->ctrl.opts->nr_write_queues;
+                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
        } else {
                /* mixed read/write queues */
-               set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                               ctrl->ctrl.opts->nr_io_queues;
                set->map[HCTX_TYPE_READ].queue_offset = 0;
        }
        blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_DEFAULT],
@@ -1799,12 +1821,12 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
 
        if (ctrl->ctrl.opts->nr_poll_queues) {
                set->map[HCTX_TYPE_POLL].nr_queues =
-                               ctrl->ctrl.opts->nr_poll_queues;
+                               ctrl->io_queues[HCTX_TYPE_POLL];
                set->map[HCTX_TYPE_POLL].queue_offset =
-                               ctrl->ctrl.opts->nr_io_queues;
+                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
                if (ctrl->ctrl.opts->nr_write_queues)
                        set->map[HCTX_TYPE_POLL].queue_offset +=
-                               ctrl->ctrl.opts->nr_write_queues;
+                               ctrl->io_queues[HCTX_TYPE_READ];
                blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
        }
        return 0;
index 265a0543b381c318f792e5088d8b2f1549cd9556..5f0a004252422f970c2f90ced7a01e4f92dd0041 100644 (file)
@@ -1948,20 +1948,23 @@ nvme_tcp_timeout(struct request *rq, bool reserved)
        struct nvme_tcp_ctrl *ctrl = req->queue->ctrl;
        struct nvme_tcp_cmd_pdu *pdu = req->pdu;
 
-       dev_dbg(ctrl->ctrl.device,
+       dev_warn(ctrl->ctrl.device,
                "queue %d: timeout request %#x type %d\n",
-               nvme_tcp_queue_id(req->queue), rq->tag,
-               pdu->hdr.type);
+               nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type);
 
        if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
-               union nvme_result res = {};
-
-               nvme_req(rq)->flags |= NVME_REQ_CANCELLED;
-               nvme_end_request(rq, cpu_to_le16(NVME_SC_ABORT_REQ), res);
+               /*
+                * Teardown immediately if controller times out while starting
+                * or we are already started error recovery. all outstanding
+                * requests are completed on shutdown, so we return BLK_EH_DONE.
+                */
+               flush_work(&ctrl->err_work);
+               nvme_tcp_teardown_io_queues(&ctrl->ctrl, false);
+               nvme_tcp_teardown_admin_queue(&ctrl->ctrl, false);
                return BLK_EH_DONE;
        }
 
-       /* queue error recovery */
+       dev_warn(ctrl->ctrl.device, "starting error recovery\n");
        nvme_tcp_error_recovery(&ctrl->ctrl);
 
        return BLK_EH_RESET_TIMER;
index a8d23eb80192024e2fe101f91fa58d222a17b698..a884e3a0e8afee4cf0d6bf3b8a8848d1f659c7c0 100644 (file)
@@ -139,6 +139,10 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_qp_event(struct ib_event *event, void *priv);
 static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue);
+static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev,
+                               struct nvmet_rdma_rsp *r);
+static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
+                               struct nvmet_rdma_rsp *r);
 
 static const struct nvmet_fabrics_ops nvmet_rdma_ops;
 
@@ -182,9 +186,17 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
        spin_unlock_irqrestore(&queue->rsps_lock, flags);
 
        if (unlikely(!rsp)) {
-               rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
+               int ret;
+
+               rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
                if (unlikely(!rsp))
                        return NULL;
+               ret = nvmet_rdma_alloc_rsp(queue->dev, rsp);
+               if (unlikely(ret)) {
+                       kfree(rsp);
+                       return NULL;
+               }
+
                rsp->allocated = true;
        }
 
@@ -197,6 +209,7 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
        unsigned long flags;
 
        if (unlikely(rsp->allocated)) {
+               nvmet_rdma_free_rsp(rsp->queue->dev, rsp);
                kfree(rsp);
                return;
        }
index 44b37b202e39853a215483028e36e4942087a870..ad0df786fe933794c2c2a158a03d2ab5fffbfd37 100644 (file)
@@ -1089,7 +1089,7 @@ static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue)
 
 static int nvmet_tcp_try_recv_one(struct nvmet_tcp_queue *queue)
 {
-       int result;
+       int result = 0;
 
        if (unlikely(queue->rcv_state == NVMET_TCP_RECV_ERR))
                return 0;
index a09c1c3cf831e70f1dc12102558aa1143c69138b..49b16f76d78e88ffd37a0374003aca9b0530bdc1 100644 (file)
@@ -207,11 +207,8 @@ static void __of_attach_node(struct device_node *np)
 
        if (!of_node_check_flag(np, OF_OVERLAY)) {
                np->name = __of_get_property(np, "name", NULL);
-               np->type = __of_get_property(np, "device_type", NULL);
                if (!np->name)
                        np->name = "<NULL>";
-               if (!np->type)
-                       np->type = "<NULL>";
 
                phandle = __of_get_property(np, "phandle", &sz);
                if (!phandle)
index 7099c652c6a5b367349a28648e57b8f9eca3f222..9cc1461aac7dd0a6d073571111bdad94f9902655 100644 (file)
@@ -314,12 +314,8 @@ static bool populate_node(const void *blob,
        populate_properties(blob, offset, mem, np, pathp, dryrun);
        if (!dryrun) {
                np->name = of_get_property(np, "name", NULL);
-               np->type = of_get_property(np, "device_type", NULL);
-
                if (!np->name)
                        np->name = "<NULL>";
-               if (!np->type)
-                       np->type = "<NULL>";
        }
 
        *pnp = np;
index 2b5ac43a5690019b3d0ce30a918083ce5acb7040..c423e94baf0f02ba6aee663273a229502eb952cb 100644 (file)
@@ -423,12 +423,9 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
 
                tchild->parent = target->np;
                tchild->name = __of_get_property(node, "name", NULL);
-               tchild->type = __of_get_property(node, "device_type", NULL);
 
                if (!tchild->name)
                        tchild->name = "<NULL>";
-               if (!tchild->type)
-                       tchild->type = "<NULL>";
 
                /* ignore obsolete "linux,phandle" */
                phandle = __of_get_property(node, "phandle", &size);
index d3185063d369c5c0c42f85162aaaae2cb74e0654..7eda43c66c916198b1c2d8fc5043fcb1edaede7a 100644 (file)
@@ -155,7 +155,6 @@ static struct device_node * __init of_pdt_create_node(phandle node,
        dp->parent = parent;
 
        dp->name = of_pdt_get_one_property(node, "name");
-       dp->type = of_pdt_get_one_property(node, "device_type");
        dp->phandle = node;
 
        dp->properties = of_pdt_build_prop_list(node);
index 08430031bd2861cb1d21218a54f2bb1c6949540d..8631efa1daa152efa428b483d355d3a99d96963e 100644 (file)
@@ -806,6 +806,7 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
 
        if (!of_device_is_available(remote)) {
                pr_debug("not available for remote node\n");
+               of_node_put(remote);
                return NULL;
        }
 
index 4310c7a4212eb1402b3e2eff10a717b7da26ea16..2ab92409210afc0cc8cf54da3bef2392abd7d5c3 100644 (file)
@@ -21,13 +21,14 @@ menuconfig PCI
          support for PCI-X and the foundations for PCI Express support.
          Say 'Y' here unless you know what you are doing.
 
+if PCI
+
 config PCI_DOMAINS
        bool
        depends on PCI
 
 config PCI_DOMAINS_GENERIC
        bool
-       depends on PCI
        select PCI_DOMAINS
 
 config PCI_SYSCALL
@@ -37,7 +38,6 @@ source "drivers/pci/pcie/Kconfig"
 
 config PCI_MSI
        bool "Message Signaled Interrupts (MSI and MSI-X)"
-       depends on PCI
        select GENERIC_MSI_IRQ
        help
           This allows device drivers to enable MSI (Message Signaled
@@ -59,7 +59,6 @@ config PCI_MSI_IRQ_DOMAIN
 config PCI_QUIRKS
        default y
        bool "Enable PCI quirk workarounds" if EXPERT
-       depends on PCI
        help
          This enables workarounds for various PCI chipset bugs/quirks.
          Disable this only if your target machine is unaffected by PCI
@@ -67,7 +66,7 @@ config PCI_QUIRKS
 
 config PCI_DEBUG
        bool "PCI Debugging"
-       depends on PCI && DEBUG_KERNEL
+       depends on DEBUG_KERNEL
        help
          Say Y here if you want the PCI core to produce a bunch of debug
          messages to the system log.  Select this if you are having a
@@ -77,7 +76,6 @@ config PCI_DEBUG
 
 config PCI_REALLOC_ENABLE_AUTO
        bool "Enable PCI resource re-allocation detection"
-       depends on PCI
        depends on PCI_IOV
        help
          Say Y here if you want the PCI core to detect if PCI resource
@@ -90,7 +88,6 @@ config PCI_REALLOC_ENABLE_AUTO
 
 config PCI_STUB
        tristate "PCI Stub driver"
-       depends on PCI
        help
          Say Y or M here if you want be able to reserve a PCI device
          when it is going to be assigned to a guest operating system.
@@ -99,7 +96,6 @@ config PCI_STUB
 
 config PCI_PF_STUB
        tristate "PCI PF Stub driver"
-       depends on PCI
        depends on PCI_IOV
        help
          Say Y or M here if you want to enable support for devices that
@@ -111,7 +107,7 @@ config PCI_PF_STUB
 
 config XEN_PCIDEV_FRONTEND
         tristate "Xen PCI Frontend"
-        depends on PCI && X86 && XEN
+        depends on X86 && XEN
         select PCI_XEN
        select XEN_XENBUS_FRONTEND
         default y
@@ -133,7 +129,6 @@ config PCI_BRIDGE_EMUL
 
 config PCI_IOV
        bool "PCI IOV support"
-       depends on PCI
        select PCI_ATS
        help
          I/O Virtualization is a PCI feature supported by some devices
@@ -144,7 +139,6 @@ config PCI_IOV
 
 config PCI_PRI
        bool "PCI PRI support"
-       depends on PCI
        select PCI_ATS
        help
          PRI is the PCI Page Request Interface. It allows PCI devices that are
@@ -154,7 +148,6 @@ config PCI_PRI
 
 config PCI_PASID
        bool "PCI PASID support"
-       depends on PCI
        select PCI_ATS
        help
          Process Address Space Identifiers (PASIDs) can be used by PCI devices
@@ -167,7 +160,7 @@ config PCI_PASID
 
 config PCI_P2PDMA
        bool "PCI peer-to-peer transfer support"
-       depends on PCI && ZONE_DEVICE
+       depends on ZONE_DEVICE
        select GENERIC_ALLOCATOR
        help
          EnableÑ• drivers to do PCI peer-to-peer transactions to and from
@@ -184,12 +177,11 @@ config PCI_P2PDMA
 
 config PCI_LABEL
        def_bool y if (DMI || ACPI)
-       depends on PCI
        select NLS
 
 config PCI_HYPERV
         tristate "Hyper-V PCI Frontend"
-        depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+        depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
         help
           The PCI device frontend driver allows the kernel to import arbitrary
           PCI devices from a PCI backend to support PCI driver domains.
@@ -198,3 +190,5 @@ source "drivers/pci/hotplug/Kconfig"
 source "drivers/pci/controller/Kconfig"
 source "drivers/pci/endpoint/Kconfig"
 source "drivers/pci/switch/Kconfig"
+
+endif
index 52e47dac028f7c43c7dde99945b2961b22554016..80f843030e363e872cfb228879361a3d5c500575 100644 (file)
@@ -310,6 +310,9 @@ static int imx6_pcie_attach_pd(struct device *dev)
        imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie");
        if (IS_ERR(imx6_pcie->pd_pcie))
                return PTR_ERR(imx6_pcie->pd_pcie);
+       /* Do nothing when power domain missing */
+       if (!imx6_pcie->pd_pcie)
+               return 0;
        link = device_link_add(dev, imx6_pcie->pd_pcie,
                        DL_FLAG_STATELESS |
                        DL_FLAG_PM_RUNTIME |
@@ -323,13 +326,13 @@ static int imx6_pcie_attach_pd(struct device *dev)
        if (IS_ERR(imx6_pcie->pd_pcie_phy))
                return PTR_ERR(imx6_pcie->pd_pcie_phy);
 
-       device_link_add(dev, imx6_pcie->pd_pcie_phy,
+       link = device_link_add(dev, imx6_pcie->pd_pcie_phy,
                        DL_FLAG_STATELESS |
                        DL_FLAG_PM_RUNTIME |
                        DL_FLAG_RPM_ACTIVE);
-       if (IS_ERR(link)) {
-               dev_err(dev, "Failed to add device_link to pcie_phy pd: %ld\n", PTR_ERR(link));
-               return PTR_ERR(link);
+       if (!link) {
+               dev_err(dev, "Failed to add device_link to pcie_phy pd.\n");
+               return -EINVAL;
        }
 
        return 0;
index b171b6bc15c84c9fbef3ee20d992c2f526beeef3..0c389a30ef5d371135ff80adba6396a08f5a69c8 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/resource.h>
 #include <linux/of_pci.h>
 #include <linux/of_irq.h>
-#include <linux/gpio/consumer.h>
 
 #include "pcie-designware.h"
 
@@ -30,7 +29,6 @@ struct armada8k_pcie {
        struct dw_pcie *pci;
        struct clk *clk;
        struct clk *clk_reg;
-       struct gpio_desc *reset_gpio;
 };
 
 #define PCIE_VENDOR_REGS_OFFSET                0x8000
@@ -139,12 +137,6 @@ static int armada8k_pcie_host_init(struct pcie_port *pp)
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
 
-       if (pcie->reset_gpio) {
-               /* assert and then deassert the reset signal */
-               gpiod_set_value_cansleep(pcie->reset_gpio, 1);
-               msleep(100);
-               gpiod_set_value_cansleep(pcie->reset_gpio, 0);
-       }
        dw_pcie_setup_rc(pp);
        armada8k_pcie_establish_link(pcie);
 
@@ -257,14 +249,6 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
                goto fail_clkreg;
        }
 
-       /* Get reset gpio signal and hold asserted (logically high) */
-       pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-                                                  GPIOD_OUT_HIGH);
-       if (IS_ERR(pcie->reset_gpio)) {
-               ret = PTR_ERR(pcie->reset_gpio);
-               goto fail_clkreg;
-       }
-
        platform_set_drvdata(pdev, pcie);
 
        ret = armada8k_add_pcie_port(pcie, pdev);
index 7a1c8a09efa579595c3239aa562fba4a97fa8e56..4c0b47867258c554f91fd0b86e89d30630130b86 100644 (file)
@@ -1168,7 +1168,8 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                                   const struct irq_affinity *affd)
 {
        static const struct irq_affinity msi_default_affd;
-       int vecs = -ENOSPC;
+       int msix_vecs = -ENOSPC;
+       int msi_vecs = -ENOSPC;
 
        if (flags & PCI_IRQ_AFFINITY) {
                if (!affd)
@@ -1179,16 +1180,17 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
        }
 
        if (flags & PCI_IRQ_MSIX) {
-               vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
-                               affd);
-               if (vecs > 0)
-                       return vecs;
+               msix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs,
+                                                   max_vecs, affd);
+               if (msix_vecs > 0)
+                       return msix_vecs;
        }
 
        if (flags & PCI_IRQ_MSI) {
-               vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);
-               if (vecs > 0)
-                       return vecs;
+               msi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs,
+                                                 affd);
+               if (msi_vecs > 0)
+                       return msi_vecs;
        }
 
        /* use legacy irq if allowed */
@@ -1199,7 +1201,9 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                }
        }
 
-       return vecs;
+       if (msix_vecs == -ENOSPC)
+               return -ENOSPC;
+       return msi_vecs;
 }
 EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
 
index c9d8e3c837de785d7960897f511328e1399239ae..c25acace7d9149c38877e83f6ead2481a7635b7d 100644 (file)
@@ -6195,7 +6195,8 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "pcie_scan_all", 13)) {
                                pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
                        } else if (!strncmp(str, "disable_acs_redir=", 18)) {
-                               disable_acs_redir_param = str + 18;
+                               disable_acs_redir_param =
+                                       kstrdup(str + 18, GFP_KERNEL);
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
index b0a413f3f7cabbdc0ccf5f0f9b06c137c5144cc8..e2a879e93d8680dc596aa9ff6ba946bdcd0dcf13 100644 (file)
@@ -639,8 +639,9 @@ static void quirk_synopsys_haps(struct pci_dev *pdev)
                break;
        }
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
-                        quirk_synopsys_haps);
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
+                              PCI_CLASS_SERIAL_USB_XHCI, 0,
+                              quirk_synopsys_haps);
 
 /*
  * Let's make the southbridge information explicit instead of having to
index 6fd6e07ab345f6813c8285038206dad2ff3c1726..09a77e556ecebfa9c7b318e88a5fdaadb6a41747 100644 (file)
@@ -31,7 +31,7 @@ static int ath79_usb_phy_power_on(struct phy *phy)
 
        err = reset_control_deassert(priv->reset);
        if (err && priv->no_suspend_override)
-               reset_control_assert(priv->no_suspend_override);
+               reset_control_deassert(priv->no_suspend_override);
 
        return err;
 }
@@ -69,7 +69,7 @@ static int ath79_usb_phy_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->reset = devm_reset_control_get(&pdev->dev, "usb-phy");
+       priv->reset = devm_reset_control_get(&pdev->dev, "phy");
        if (IS_ERR(priv->reset))
                return PTR_ERR(priv->reset);
 
index f137e010776463d03e59f02a33a96002070d628d..c4709ed7fb0e72b78b58cb871c63aecf93189e03 100644 (file)
@@ -82,6 +82,7 @@ config PHY_TI_GMII_SEL
        default y if TI_CPSW=y
        depends on TI_CPSW || COMPILE_TEST
        select GENERIC_PHY
+       select REGMAP
        default m
        help
          This driver supports configuring of the TI CPSW Port mode depending on
index 77fdaa5519772f55df8deafccbee86a8304b17a0..a52c5bb350333ec14951c32b11f741dd9287db80 100644 (file)
@@ -204,11 +204,11 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev,
 
        if (args->args_count < 1)
                return ERR_PTR(-EINVAL);
+       if (!priv || !priv->if_phys)
+               return ERR_PTR(-ENODEV);
        if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) &&
            args->args_count < 2)
                return ERR_PTR(-EINVAL);
-       if (!priv || !priv->if_phys)
-               return ERR_PTR(-ENODEV);
        if (phy_id > priv->soc_data->num_ports)
                return ERR_PTR(-EINVAL);
        if (phy_id != priv->if_phys[phy_id - 1].id)
index 05044e323ea5529d15d001337fcad75f089abe23..03ec7a5d9d0bd8014382cad9f316071828bc7f63 100644 (file)
@@ -1513,7 +1513,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1521,7 +1521,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1529,7 +1529,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1537,7 +1537,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {}
index 1817786ab6aa164384c90c96ade5bc2fc1830102..a005cbccb4f7d527d79533a5e6df16979ec21f8e 100644 (file)
@@ -45,12 +45,14 @@ config PINCTRL_MT2701
 config PINCTRL_MT7623
        bool "Mediatek MT7623 pin control with generic binding"
        depends on MACH_MT7623 || COMPILE_TEST
+       depends on OF
        default MACH_MT7623
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT7629
        bool "Mediatek MT7629 pin control"
        depends on MACH_MT7629 || COMPILE_TEST
+       depends on OF
        default MACH_MT7629
        select PINCTRL_MTK_MOORE
 
@@ -92,6 +94,7 @@ config PINCTRL_MT6797
 
 config PINCTRL_MT7622
        bool "MediaTek MT7622 pin control"
+       depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_MOORE
index b03481ef99a13ab63dc8ba188113fcccfe50be78..98905d4a79ca93b52935dc438b4797bb4fc86f78 100644 (file)
@@ -832,8 +832,13 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 
        case MCP_TYPE_S18:
+               one_regmap_config =
+                       devm_kmemdup(dev, &mcp23x17_regmap,
+                               sizeof(struct regmap_config), GFP_KERNEL);
+               if (!one_regmap_config)
+                       return -ENOMEM;
                mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
-                                              &mcp23x17_regmap);
+                                              one_regmap_config);
                mcp->reg_shift = 1;
                mcp->chip.ngpio = 16;
                mcp->chip.label = "mcp23s18";
index aa8b58125568ddcd90d64a76db5e414920e00873..ef4268cc62275057016846703cca8de58f8386f6 100644 (file)
@@ -588,7 +588,7 @@ static const unsigned int h6_irq_bank_map[] = { 1, 5, 6, 7 };
 static const struct sunxi_pinctrl_desc h6_pinctrl_data = {
        .pins = h6_pins,
        .npins = ARRAY_SIZE(h6_pins),
-       .irq_banks = 3,
+       .irq_banks = 4,
        .irq_bank_map = h6_irq_bank_map,
        .irq_read_needs_mux = true,
 };
index 5d9184d18c16058fbd0f6e7dd4854c3cc5b8e827..0e7fa69e93dfd32aa74182d90ac07a517f1a32db 100644 (file)
@@ -698,26 +698,24 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        unsigned short bank = offset / PINS_PER_BANK;
-       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
-       struct regulator *reg;
+       unsigned short bank_offset = bank - pctl->desc->pin_base /
+                                           PINS_PER_BANK;
+       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
+       struct regulator *reg = s_reg->regulator;
+       char supply[16];
        int ret;
 
-       reg = s_reg->regulator;
-       if (!reg) {
-               char supply[16];
-
-               snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
-               reg = regulator_get(pctl->dev, supply);
-               if (IS_ERR(reg)) {
-                       dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
-                               'A' + bank);
-                       return PTR_ERR(reg);
-               }
-
-               s_reg->regulator = reg;
-               refcount_set(&s_reg->refcount, 1);
-       } else {
+       if (reg) {
                refcount_inc(&s_reg->refcount);
+               return 0;
+       }
+
+       snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
+       reg = regulator_get(pctl->dev, supply);
+       if (IS_ERR(reg)) {
+               dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
+                       'A' + bank);
+               return PTR_ERR(reg);
        }
 
        ret = regulator_enable(reg);
@@ -727,13 +725,13 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
                goto out;
        }
 
+       s_reg->regulator = reg;
+       refcount_set(&s_reg->refcount, 1);
+
        return 0;
 
 out:
-       if (refcount_dec_and_test(&s_reg->refcount)) {
-               regulator_put(s_reg->regulator);
-               s_reg->regulator = NULL;
-       }
+       regulator_put(s_reg->regulator);
 
        return ret;
 }
@@ -742,7 +740,9 @@ static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        unsigned short bank = offset / PINS_PER_BANK;
-       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
+       unsigned short bank_offset = bank - pctl->desc->pin_base /
+                                           PINS_PER_BANK;
+       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
 
        if (!refcount_dec_and_test(&s_reg->refcount))
                return 0;
index e340d2a24b44e3874246d78c7fb3b4f0c413882c..034c0317c8d61694c39e8afc127e34dbe5e4c931 100644 (file)
@@ -136,7 +136,7 @@ struct sunxi_pinctrl {
        struct gpio_chip                *chip;
        const struct sunxi_pinctrl_desc *desc;
        struct device                   *dev;
-       struct sunxi_pinctrl_regulator  regulators[12];
+       struct sunxi_pinctrl_regulator  regulators[9];
        struct irq_domain               *domain;
        struct sunxi_pinctrl_function   *functions;
        unsigned                        nfunctions;
index e3b62c2ee8d18bff0bed82836440e552bca78930..b5e9db85e8813c71d9e57cfd33d45a83a1d21512 100644 (file)
@@ -905,6 +905,7 @@ config TOSHIBA_WMI
 config ACPI_CMPC
        tristate "CMPC Laptop Extras"
        depends on ACPI && INPUT
+       depends on BACKLIGHT_LCD_SUPPORT
        depends on RFKILL || RFKILL=n
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -1009,7 +1010,7 @@ config INTEL_MFLD_THERMAL
 
 config INTEL_IPS
        tristate "Intel Intelligent Power Sharing"
-       depends on ACPI
+       depends on ACPI && PCI
        ---help---
          Intel Calpella platforms support dynamic power sharing between the
          CPU and GPU, maximizing performance in a given TDP.  This driver,
@@ -1128,6 +1129,7 @@ config INTEL_OAKTRAIL
 config SAMSUNG_Q10
        tristate "Samsung Q10 Extras"
        depends on ACPI
+       depends on BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
        ---help---
          This driver provides support for backlight control on Samsung Q10
@@ -1135,7 +1137,7 @@ config SAMSUNG_Q10
 
 config APPLE_GMUX
        tristate "Apple Gmux Driver"
-       depends on ACPI
+       depends on ACPI && PCI
        depends on PNP
        depends on BACKLIGHT_CLASS_DEVICE
        depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE
@@ -1174,7 +1176,7 @@ config INTEL_SMARTCONNECT
 
 config INTEL_PMC_IPC
        tristate "Intel PMC IPC Driver"
-       depends on ACPI
+       depends on ACPI && PCI
        ---help---
        This driver provides support for PMC control on some Intel platforms.
        The PMC is an ARC processor which defines IPC commands for communication
index 797fab33bb983913d50864ce7c6a792a6c3a6f95..7cbea796652aca1ef537d9cdc68b645d340f73ee 100644 (file)
@@ -224,7 +224,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                        extoff = NULL;
                        break;
                }
-               if (extoff->n_samples > PTP_MAX_SAMPLES) {
+               if (extoff->n_samples > PTP_MAX_SAMPLES
+                   || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) {
                        err = -EINVAL;
                        break;
                }
index 183fc42a510a73e5f41c1c8221bea032bbbfbc81..2d7cd344f3bffbc3b5960078c86f77b79d32743b 100644 (file)
@@ -153,10 +153,15 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
                                 const bool * ctx,
                                 struct irq_affinity *desc)
 {
-       int i, ret;
+       int i, ret, queue_idx = 0;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
                                    ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
index 4e7b55a14b1a46d40920fde48460fa2400c46f84..6e294b4d3635fe399586f05045297646d9c8c574 100644 (file)
@@ -4469,6 +4469,14 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
                usrparm.psf_data &= 0x7fffffffULL;
                usrparm.rssd_result &= 0x7fffffffULL;
        }
+       /* at least 2 bytes are accessed and should be allocated */
+       if (usrparm.psf_data_len < 2) {
+               DBF_DEV_EVENT(DBF_WARNING, device,
+                             "Symmetrix ioctl invalid data length %d",
+                             usrparm.psf_data_len);
+               rc = -EINVAL;
+               goto out;
+       }
        /* alloc I/O data area */
        psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
        rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
index 194ffd5c8580401a13eefb3f85e61fdba2d5e7e6..039b2074db7e5d39a88aeed516630e62dfc05e4e 100644 (file)
@@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
 
 static void __ref sclp_cpu_change_notify(struct work_struct *work)
 {
+       lock_device_hotplug();
        smp_rescan_cpus();
+       unlock_device_hotplug();
 }
 
 static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
index 48ea0004a56da0dfe51c4251f0af62d0b4679a83..5a699746c357e4090a96812d9770844b6757ef07 100644 (file)
@@ -248,7 +248,8 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr)
 static inline int ap_test_config_card_id(unsigned int id)
 {
        if (!ap_configuration)  /* QCI not supported */
-               return 1;
+               /* only ids 0...3F may be probed */
+               return id < 0x40 ? 1 : 0;
        return ap_test_config(ap_configuration->apm, id);
 }
 
index 0ee026947f209941ace51b0ff8a476885e46b048..122059ecad848e372ead33052e08f6abac3102d7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/hashtable.h>
 #include <linux/ip.h>
 #include <linux/refcount.h>
+#include <linux/workqueue.h>
 
 #include <net/ipv6.h>
 #include <net/if_inet6.h>
@@ -789,6 +790,7 @@ struct qeth_card {
        struct qeth_seqno seqno;
        struct qeth_card_options options;
 
+       struct workqueue_struct *event_wq;
        wait_queue_head_t wait_q;
        spinlock_t mclock;
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -962,7 +964,6 @@ extern const struct attribute_group *qeth_osn_attr_groups[];
 extern const struct attribute_group qeth_device_attr_group;
 extern const struct attribute_group qeth_device_blkt_group;
 extern const struct device_type qeth_generic_devtype;
-extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
 const char *qeth_get_cardname_short(struct qeth_card *);
index e63e03143ca7fa2f6995c7a24dbef9c981c7f41c..89f912213e6261ca945837afb31f0b0abb52efc0 100644 (file)
@@ -74,8 +74,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
 static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
 static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
 
-struct workqueue_struct *qeth_wq;
-EXPORT_SYMBOL_GPL(qeth_wq);
+static struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *card)
 {
@@ -566,6 +565,7 @@ static int __qeth_issue_next_read(struct qeth_card *card)
                QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
                                 rc, CARD_DEVID(card));
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                card->read_or_write_problem = 1;
                qeth_schedule_recovery(card);
                wake_up(&card->wait_q);
@@ -1127,6 +1127,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
                rc = qeth_get_problem(card, cdev, irb);
                if (rc) {
                        card->read_or_write_problem = 1;
+                       if (iob)
+                               qeth_release_buffer(iob->channel, iob);
                        qeth_clear_ipacmd_list(card);
                        qeth_schedule_recovery(card);
                        goto out;
@@ -1466,6 +1468,10 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
        CARD_RDEV(card) = gdev->cdev[0];
        CARD_WDEV(card) = gdev->cdev[1];
        CARD_DDEV(card) = gdev->cdev[2];
+
+       card->event_wq = alloc_ordered_workqueue("%s", 0, dev_name(&gdev->dev));
+       if (!card->event_wq)
+               goto out_wq;
        if (qeth_setup_channel(&card->read, true))
                goto out_ip;
        if (qeth_setup_channel(&card->write, true))
@@ -1481,6 +1487,8 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
 out_channel:
        qeth_clean_channel(&card->read);
 out_ip:
+       destroy_workqueue(card->event_wq);
+out_wq:
        dev_set_drvdata(&gdev->dev, NULL);
        kfree(card);
 out:
@@ -1809,6 +1817,7 @@ static int qeth_idx_activate_get_answer(struct qeth_card *card,
                QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
                QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                wake_up(&card->wait_q);
                return rc;
        }
@@ -1878,6 +1887,7 @@ static int qeth_idx_activate_channel(struct qeth_card *card,
                        rc);
                QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                wake_up(&card->wait_q);
                return rc;
        }
@@ -2058,6 +2068,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        }
        reply = qeth_alloc_reply(card);
        if (!reply) {
+               qeth_release_buffer(channel, iob);
                return -ENOMEM;
        }
        reply->callback = reply_cb;
@@ -2389,11 +2400,12 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
        return 0;
 }
 
-static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
+static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
 {
        if (!q)
                return;
 
+       qeth_clear_outq_buffers(q, 1);
        qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
        kfree(q);
 }
@@ -2467,10 +2479,8 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
                card->qdio.out_qs[i]->bufs[j] = NULL;
        }
 out_freeoutq:
-       while (i > 0) {
-               qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
-               qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-       }
+       while (i > 0)
+               qeth_free_output_queue(card->qdio.out_qs[--i]);
        kfree(card->qdio.out_qs);
        card->qdio.out_qs = NULL;
 out_freepool:
@@ -2503,10 +2513,8 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
        qeth_free_buffer_pool(card);
        /* free outbound qdio_qs */
        if (card->qdio.out_qs) {
-               for (i = 0; i < card->qdio.no_out_queues; ++i) {
-                       qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-                       qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
-               }
+               for (i = 0; i < card->qdio.no_out_queues; i++)
+                       qeth_free_output_queue(card->qdio.out_qs[i]);
                kfree(card->qdio.out_qs);
                card->qdio.out_qs = NULL;
        }
@@ -5028,6 +5036,7 @@ static void qeth_core_free_card(struct qeth_card *card)
        qeth_clean_channel(&card->read);
        qeth_clean_channel(&card->write);
        qeth_clean_channel(&card->data);
+       destroy_workqueue(card->event_wq);
        qeth_free_qdio_buffers(card);
        unregister_service_level(&card->qeth_service_level);
        dev_set_drvdata(&card->gdev->dev, NULL);
index f108d4b44605805b3430a7fc7890340645b92146..a43de2f9bcac4abc253e9421398fd9546753428e 100644 (file)
@@ -369,6 +369,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
+
+       flush_workqueue(card->event_wq);
 }
 
 static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -801,6 +803,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 
        if (cgdev->state == CCWGROUP_ONLINE)
                qeth_l2_set_offline(cgdev);
+
+       cancel_work_sync(&card->close_dev_work);
        if (qeth_netdev_is_registered(card->dev))
                unregister_netdev(card->dev);
 }
@@ -1434,7 +1438,7 @@ static void qeth_bridge_state_change(struct qeth_card *card,
        data->card = card;
        memcpy(&data->qports, qports,
                        sizeof(struct qeth_sbp_state_change) + extrasize);
-       queue_work(qeth_wq, &data->worker);
+       queue_work(card->event_wq, &data->worker);
 }
 
 struct qeth_bridge_host_data {
@@ -1506,7 +1510,7 @@ static void qeth_bridge_host_event(struct qeth_card *card,
        data->card = card;
        memcpy(&data->hostevs, hostevs,
                        sizeof(struct qeth_ipacmd_addr_change) + extrasize);
-       queue_work(qeth_wq, &data->worker);
+       queue_work(card->event_wq, &data->worker);
 }
 
 /* SETBRIDGEPORT support; sending commands */
index 42a7cdc59b76af1a8e220f4097a16702a950cab9..df34bff4ac31ba18c62380c6e13a312fdc1d8213 100644 (file)
@@ -1433,6 +1433,8 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
+
+       flush_workqueue(card->event_wq);
 }
 
 /*
@@ -2338,6 +2340,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
        if (cgdev->state == CCWGROUP_ONLINE)
                qeth_l3_set_offline(cgdev);
 
+       cancel_work_sync(&card->close_dev_work);
        if (qeth_netdev_is_registered(card->dev))
                unregister_netdev(card->dev);
        qeth_l3_clear_ip_htable(card, 0);
index 9cf30d124b9efbb469277b02d3b098425b07ea8e..e390f8c6d5f390f3bc7ba8fa61b061f5dac701fb 100644 (file)
@@ -403,7 +403,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
                goto failed;
 
        /* report size limit per scatter-gather segment */
-       adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
        adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
        adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
index 00acc7144bbc919f1198fd3c5aca064c855ac949..f4f6a07c52220234fb0e865ca3f0d87a2d2fdbe0 100644 (file)
@@ -428,6 +428,8 @@ static struct scsi_host_template zfcp_scsi_host_template = {
        .max_sectors             = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
                                     * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
                                   /* GCD, adjusted later */
+       /* report size limit per scatter-gather segment */
+       .max_segment_size        = ZFCP_QDIO_SBALE_LEN,
        .dma_boundary            = ZFCP_QDIO_SBALE_LEN - 1,
        .shost_attrs             = zfcp_sysfs_shost_attrs,
        .sdev_attrs              = zfcp_sysfs_sdev_attrs,
index fc9dbad476c0ca4ee96bda0ed0074f1c18538f40..ae1d56da671dfe9eab824e379d7d482b639dacf2 100644 (file)
@@ -635,7 +635,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
        unsigned long *indicatorp = NULL;
-       int ret, i;
+       int ret, i, queue_idx = 0;
        struct ccw1 *ccw;
 
        ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
@@ -643,8 +643,14 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return -ENOMEM;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i],
-                                            ctx ? ctx[i] : false, ccw);
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, callbacks[i],
+                                            names[i], ctx ? ctx[i] : false,
+                                            ccw);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
                        vqs[i] = NULL;
index 128d658d472a92c7ea476f788c133d27652356c4..16957d7ac414d5000f85614c799fddf63ae69739 100644 (file)
@@ -295,7 +295,7 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        if(tpnt->sdev_attrs == NULL)
                tpnt->sdev_attrs = NCR_700_dev_attrs;
 
-       memory = dma_alloc_attrs(hostdata->dev, TOTAL_MEM_SIZE, &pScript,
+       memory = dma_alloc_attrs(dev, TOTAL_MEM_SIZE, &pScript,
                                 GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
        if(memory == NULL) {
                printk(KERN_ERR "53c700: Failed to allocate memory for driver, detaching\n");
index 634ddb90e7aae6010eb3c6f231e68d343d17ab90..7e56a11836c18c30d4c1d430a3978277e0121e5b 100644 (file)
@@ -1747,11 +1747,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                shost->max_sectors = (shost->sg_tablesize * 8) + 112;
        }
 
-       error = dma_set_max_seg_size(&pdev->dev,
-               (aac->adapter_info.options & AAC_OPT_NEW_COMM) ?
-                       (shost->max_sectors << 9) : 65536);
-       if (error)
-               goto out_deinit;
+       if (aac->adapter_info.options & AAC_OPT_NEW_COMM)
+               shost->max_segment_size = shost->max_sectors << 9;
+       else
+               shost->max_segment_size = 65536;
 
        /*
         * Firmware printf works only with older firmware.
index f83f79b07b508de2b8f76dbcb481f9c9027bd0b9..07efcb9b5b943109bea84daf60fc223263b8d376 100644 (file)
@@ -280,7 +280,7 @@ static ssize_t asd_show_dev_rev(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        asd_dev_rev[asd_ha->revision_id]);
 }
-static DEVICE_ATTR(revision, S_IRUGO, asd_show_dev_rev, NULL);
+static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL);
 
 static ssize_t asd_show_dev_bios_build(struct device *dev,
                                       struct device_attribute *attr,char *buf)
@@ -477,7 +477,7 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 {
        int err;
 
-       err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        if (err)
                return err;
 
@@ -499,13 +499,13 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 err_biosb:
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
 err_rev:
-       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        return err;
 }
 
 static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
 {
-       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
index 350257c13a5bac433f1fdfbfcdc12dc6698587cb..bc9f2a2365f4d4514aa744c591a7f5f84139ff78 100644 (file)
@@ -240,6 +240,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
                return NULL;
        }
 
+       cmgr->hba = hba;
        cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list),
                                  GFP_KERNEL);
        if (!cmgr->free_list) {
@@ -256,7 +257,6 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
                goto mem_err;
        }
 
-       cmgr->hba = hba;
        cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
 
        for (i = 0; i < arr_sz; i++)  {
@@ -295,7 +295,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
 
        /* Allocate pool of io_bdts - one for each bnx2fc_cmd */
        mem_size = num_ios * sizeof(struct io_bdt *);
-       cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL);
+       cmgr->io_bdt_pool = kzalloc(mem_size, GFP_KERNEL);
        if (!cmgr->io_bdt_pool) {
                printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n");
                goto mem_err;
index 8a004036e3d72a666d3f49e22ee83539f165ba75..9bd2bd8dc2be24692c8ad72b13a1243721a5284c 100644 (file)
@@ -594,12 +594,12 @@ csio_vport_create(struct fc_vport *fc_vport, bool disable)
        }
 
        fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+       ln->fc_vport = fc_vport;
 
        if (csio_fcoe_alloc_vnp(hw, ln))
                goto error;
 
        *(struct csio_lnode **)fc_vport->dd_data = ln;
-       ln->fc_vport = fc_vport;
        if (!fc_vport->node_name)
                fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
        if (!fc_vport->port_name)
index 8a20411699d9ed73900ab65685d1f6d552068372..75e1273a44b3e0f629c51ac5e20cf9ec63b27bbe 100644 (file)
@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm,
 }
 
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
-                                      unsigned int tid, int pg_idx, bool reply)
+                               unsigned int tid, int pg_idx)
 {
        struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
                                        GFP_KERNEL);
@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
        req = (struct cpl_set_tcb_field *)skb->head;
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply = V_NO_REPLY(reply ? 0 : 1);
+       req->reply = V_NO_REPLY(1);
        req->cpu_idx = 0;
        req->word = htons(31);
        req->mask = cpu_to_be64(0xF0000000);
@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
  * @tid: connection id
  * @hcrc: header digest enabled
  * @dcrc: data digest enabled
- * @reply: request reply from h/w
  * set up the iscsi digest settings for a connection identified by tid
  */
 static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
-                            int hcrc, int dcrc, int reply)
+                                int hcrc, int dcrc)
 {
        struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
                                        GFP_KERNEL);
@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply = V_NO_REPLY(reply ? 0 : 1);
+       req->reply = V_NO_REPLY(1);
        req->cpu_idx = 0;
        req->word = htons(31);
        req->mask = cpu_to_be64(0x0F000000);
index 49f8028ac52418015cb0a6e064ceb2e3e81353cd..d26f50af00eadea888263ffa7d7b6bdb07895cec 100644 (file)
@@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
        struct cxgbi_sock *csk;
 
        csk = lookup_tid(t, tid);
-       if (!csk)
+       if (!csk) {
                pr_err("can't find conn. for tid %u.\n", tid);
+               return;
+       }
 
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p,%u,%lx,%u, status 0x%x.\n",
                csk, csk->state, csk->flags, csk->tid, rpl->status);
 
-       if (rpl->status != CPL_ERR_NONE)
+       if (rpl->status != CPL_ERR_NONE) {
                pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
                        csk, tid, rpl->status);
+               csk->err = -EINVAL;
+       }
+
+       complete(&csk->cmpl);
 
        __kfree_skb(skb);
 }
@@ -1983,7 +1989,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk,
 }
 
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
-                               int pg_idx, bool reply)
+                               int pg_idx)
 {
        struct sk_buff *skb;
        struct cpl_set_tcb_field *req;
@@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        INIT_TP_WR(req, csk->tid);
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
-       req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+       req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
        req->word_cookie = htons(0);
        req->mask = cpu_to_be64(0x3 << 8);
        req->val = cpu_to_be64(pg_idx << 8);
@@ -2008,12 +2014,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
 
+       reinit_completion(&csk->cmpl);
        cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
-       return 0;
+       wait_for_completion(&csk->cmpl);
+
+       return csk->err;
 }
 
 static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
-                                int hcrc, int dcrc, int reply)
+                                int hcrc, int dcrc)
 {
        struct sk_buff *skb;
        struct cpl_set_tcb_field *req;
@@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        INIT_TP_WR(req, tid);
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+       req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
        req->word_cookie = htons(0);
        req->mask = cpu_to_be64(0x3 << 4);
        req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
@@ -2041,8 +2050,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
 
+       reinit_completion(&csk->cmpl);
        cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
-       return 0;
+       wait_for_completion(&csk->cmpl);
+
+       return csk->err;
 }
 
 static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev)
index 75f876409fb9d8344adf36f48a4a288da5b7c8ed..245742557c03646677a120c5feb5213931e06e31 100644 (file)
@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
        skb_queue_head_init(&csk->receive_queue);
        skb_queue_head_init(&csk->write_queue);
        timer_setup(&csk->retry_timer, NULL, 0);
+       init_completion(&csk->cmpl);
        rwlock_init(&csk->callback_lock);
        csk->cdev = cdev;
        csk->flags = 0;
@@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
                if (!err && conn->hdrdgst_en)
                        err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
                                                        conn->hdrdgst_en,
-                                                       conn->datadgst_en, 0);
+                                                       conn->datadgst_en);
                break;
        case ISCSI_PARAM_DATADGST_EN:
                err = iscsi_set_param(cls_conn, param, buf, buflen);
                if (!err && conn->datadgst_en)
                        err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
                                                        conn->hdrdgst_en,
-                                                       conn->datadgst_en, 0);
+                                                       conn->datadgst_en);
                break;
        case ISCSI_PARAM_MAX_R2T:
                return iscsi_tcp_set_max_r2t(conn, buf);
@@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
 
        ppm = csk->cdev->cdev2ppm(csk->cdev);
        err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
-                                            ppm->tformat.pgsz_idx_dflt, 0);
+                                            ppm->tformat.pgsz_idx_dflt);
        if (err < 0)
                return err;
 
index 5d5d8b50d8426fbc12e9befc511def952963b087..1917ff57651d7dfbda250d369b36381b2dda740c 100644 (file)
@@ -149,6 +149,7 @@ struct cxgbi_sock {
        struct sk_buff_head receive_queue;
        struct sk_buff_head write_queue;
        struct timer_list retry_timer;
+       struct completion cmpl;
        int err;
        rwlock_t callback_lock;
        void *user_data;
@@ -490,9 +491,9 @@ struct cxgbi_device {
                                  struct cxgbi_ppm *,
                                  struct cxgbi_task_tag_info *);
        int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
-                               unsigned int, int, int, int);
+                                   unsigned int, int, int);
        int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
-                               unsigned int, int, bool);
+                                  unsigned int, int);
 
        void (*csk_release_offload_resources)(struct cxgbi_sock *);
        int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
index bfa13e3b191c7aa026af76279a8acc1a708db703..c8bad2c093b8b88f6495f0af61b836f9395b3b1a 100644 (file)
@@ -3687,6 +3687,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
        host->max_cmd_len = CXLFLASH_MAX_CDB_LEN;
 
        cfg = shost_priv(host);
+       cfg->state = STATE_PROBING;
        cfg->host = host;
        rc = alloc_mem(cfg);
        if (rc) {
@@ -3775,6 +3776,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
        return rc;
 
 out_remove:
+       cfg->state = STATE_PROBED;
        cxlflash_remove(pdev);
        goto out;
 }
index e2420a810e994b771db36fe7b0fa522e29e16ea8..c92b3822c40823fa283711746a8f4da9a527f539 100644 (file)
@@ -2507,6 +2507,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                sha->sas_port[i] = &hisi_hba->port[i].sas_port;
        }
 
+       if (hisi_hba->prot_mask) {
+               dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
+                        prot_mask);
+               scsi_host_set_prot(hisi_hba->shost, prot_mask);
+       }
+
        rc = scsi_add_host(shost, dev);
        if (rc)
                goto err_out_ha;
@@ -2519,12 +2525,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                goto err_out_register_ha;
 
-       if (hisi_hba->prot_mask) {
-               dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
-                        prot_mask);
-               scsi_host_set_prot(hisi_hba->shost, prot_mask);
-       }
-
        scsi_scan_host(shost);
 
        return 0;
index 68b90c4f79a31b2f1a106e76b45ab24130365092..1727d0c71b1235e153b7565cff1e5a29ead37b4b 100644 (file)
@@ -576,6 +576,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
        shost->max_lun = ~0;
        shost->max_cmd_len = MAX_COMMAND_SIZE;
 
+       /* turn on DIF support */
+       scsi_host_set_prot(shost,
+                          SHOST_DIF_TYPE1_PROTECTION |
+                          SHOST_DIF_TYPE2_PROTECTION |
+                          SHOST_DIF_TYPE3_PROTECTION);
+       scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+
        err = scsi_add_host(shost, &pdev->dev);
        if (err)
                goto err_shost;
@@ -663,13 +670,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                        goto err_host_alloc;
                }
                pci_info->hosts[i] = h;
-
-               /* turn on DIF support */
-               scsi_host_set_prot(to_shost(h),
-                                  SHOST_DIF_TYPE1_PROTECTION |
-                                  SHOST_DIF_TYPE2_PROTECTION |
-                                  SHOST_DIF_TYPE3_PROTECTION);
-               scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
        }
 
        err = isci_setup_interrupts(pdev);
index be83590ed9559636549d90d794d74483d141ec89..ff943f477d6f00bfce6e33c5bcede9c7c9711d47 100644 (file)
@@ -1726,14 +1726,14 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
            fc_frame_payload_op(fp) != ELS_LS_ACC) {
                FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        flp = fc_frame_payload_get(fp, sizeof(*flp));
        if (!flp) {
                FC_LPORT_DBG(lport, "FLOGI bad response\n");
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        mfs = ntohs(flp->fl_csp.sp_bb_data) &
@@ -1743,7 +1743,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
                FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
                             "lport->mfs:%hu\n", mfs, lport->mfs);
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        if (mfs <= lport->mfs) {
index 9192a1d9dec6260f12348835a977d3e1f03f36f7..dfba4921b265a0fa7fdf2409295483a68c5e181c 100644 (file)
@@ -184,7 +184,6 @@ void fc_rport_destroy(struct kref *kref)
        struct fc_rport_priv *rdata;
 
        rdata = container_of(kref, struct fc_rport_priv, kref);
-       WARN_ON(!list_empty(&rdata->peers));
        kfree_rcu(rdata, rcu);
 }
 EXPORT_SYMBOL(fc_rport_destroy);
index 4c66b19e61996a80c6440211e78086a1b4257c10..8c9f7904222888251a010eb3ab392f4e78a25f34 100644 (file)
@@ -297,7 +297,8 @@ lpfc_nvme_localport_delete(struct nvme_fc_local_port *localport)
                         lport);
 
        /* release any threads waiting for the unreg to complete */
-       complete(&lport->lport_unreg_done);
+       if (lport->vport->localport)
+               complete(lport->lport_unreg_cmp);
 }
 
 /* lpfc_nvme_remoteport_delete
@@ -2545,7 +2546,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
  */
 void
 lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
-                          struct lpfc_nvme_lport *lport)
+                          struct lpfc_nvme_lport *lport,
+                          struct completion *lport_unreg_cmp)
 {
 #if (IS_ENABLED(CONFIG_NVME_FC))
        u32 wait_tmo;
@@ -2557,8 +2559,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
         */
        wait_tmo = msecs_to_jiffies(LPFC_NVME_WAIT_TMO * 1000);
        while (true) {
-               ret = wait_for_completion_timeout(&lport->lport_unreg_done,
-                                                 wait_tmo);
+               ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo);
                if (unlikely(!ret)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
                                         "6176 Lport %p Localport %p wait "
@@ -2592,12 +2593,12 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        struct lpfc_nvme_lport *lport;
        struct lpfc_nvme_ctrl_stat *cstat;
        int ret;
+       DECLARE_COMPLETION_ONSTACK(lport_unreg_cmp);
 
        if (vport->nvmei_support == 0)
                return;
 
        localport = vport->localport;
-       vport->localport = NULL;
        lport = (struct lpfc_nvme_lport *)localport->private;
        cstat = lport->cstat;
 
@@ -2608,13 +2609,14 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        /* lport's rport list is clear.  Unregister
         * lport and release resources.
         */
-       init_completion(&lport->lport_unreg_done);
+       lport->lport_unreg_cmp = &lport_unreg_cmp;
        ret = nvme_fc_unregister_localport(localport);
 
        /* Wait for completion.  This either blocks
         * indefinitely or succeeds
         */
-       lpfc_nvme_lport_unreg_wait(vport, lport);
+       lpfc_nvme_lport_unreg_wait(vport, lport, &lport_unreg_cmp);
+       vport->localport = NULL;
        kfree(cstat);
 
        /* Regardless of the unregister upcall response, clear
index cfd4719be25c3d3eb35ae4ae5ea7e56d357d0d21..b234d02989942ba65f0a87db0aab71c9c1b7cbb2 100644 (file)
@@ -50,7 +50,7 @@ struct lpfc_nvme_ctrl_stat {
 /* Declare nvme-based local and remote port definitions. */
 struct lpfc_nvme_lport {
        struct lpfc_vport *vport;
-       struct completion lport_unreg_done;
+       struct completion *lport_unreg_cmp;
        /* Add stats counters here */
        struct lpfc_nvme_ctrl_stat *cstat;
        atomic_t fc4NvmeLsRequests;
index 6245f442d784bed3056de8c0830cd9e687b59a6a..95fee83090eb7bf03fa2f9ea2263e06b761e6ede 100644 (file)
@@ -1003,7 +1003,8 @@ lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
        struct lpfc_nvmet_tgtport *tport = targetport->private;
 
        /* release any threads waiting for the unreg to complete */
-       complete(&tport->tport_unreg_done);
+       if (tport->phba->targetport)
+               complete(tport->tport_unreg_cmp);
 }
 
 static void
@@ -1692,6 +1693,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
        struct lpfc_nvmet_tgtport *tgtp;
        struct lpfc_queue *wq;
        uint32_t qidx;
+       DECLARE_COMPLETION_ONSTACK(tport_unreg_cmp);
 
        if (phba->nvmet_support == 0)
                return;
@@ -1701,9 +1703,9 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
                        wq = phba->sli4_hba.nvme_wq[qidx];
                        lpfc_nvmet_wqfull_flush(phba, wq, NULL);
                }
-               init_completion(&tgtp->tport_unreg_done);
+               tgtp->tport_unreg_cmp = &tport_unreg_cmp;
                nvmet_fc_unregister_targetport(phba->targetport);
-               wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
+               wait_for_completion_timeout(&tport_unreg_cmp, 5);
                lpfc_nvmet_cleanup_io_context(phba);
        }
        phba->targetport = NULL;
index 1aaff63f1f419209b08cdfa0c6e7141a2018854d..0ec1082ce7ef62dd503ce8086cbc47a56a5b9ec5 100644 (file)
@@ -34,7 +34,7 @@
 /* Used for NVME Target */
 struct lpfc_nvmet_tgtport {
        struct lpfc_hba *phba;
-       struct completion tport_unreg_done;
+       struct completion *tport_unreg_cmp;
 
        /* Stats counters - lpfc_nvmet_unsol_ls_buffer */
        atomic_t rcv_ls_req_in;
index 12fd74761ae00f3760d9833ad85647dde994cd5b..2242e9b3ca128d0e0d57e928f672cd674fe8feba 100644 (file)
@@ -9407,6 +9407,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                cmnd = CMD_XMIT_SEQUENCE64_CR;
                if (phba->link_flag & LS_LOOPBACK_MODE)
                        bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
+               /* fall through */
        case CMD_XMIT_SEQUENCE64_CR:
                /* word3 iocb=io_tag32 wqe=reserved */
                wqe->xmit_sequence.rsvd3 = 0;
@@ -13528,6 +13529,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "2537 Receive Frame Truncated!!\n");
+               /* fall through */
        case FC_STATUS_RQ_SUCCESS:
                spin_lock_irqsave(&phba->hbalock, iflags);
                lpfc_sli4_rq_release(hrq, drq);
@@ -13937,7 +13939,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "6126 Receive Frame Truncated!!\n");
-               /* Drop thru */
+               /* fall through */
        case FC_STATUS_RQ_SUCCESS:
                spin_lock_irqsave(&phba->hbalock, iflags);
                lpfc_sli4_rq_release(hrq, drq);
@@ -14849,7 +14851,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
                                eq->entry_count);
                if (eq->entry_count < 256)
                        return -EINVAL;
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 256:
                bf_set(lpfc_eq_context_count, &eq_create->u.request.context,
                       LPFC_EQ_CNT_256);
@@ -14980,7 +14982,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
                               LPFC_CQ_CNT_WORD7);
                        break;
                }
-               /* Fall Thru */
+               /* fall through */
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0361 Unsupported CQ count: "
@@ -14991,7 +14993,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
                        status = -EINVAL;
                        goto out;
                }
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 256:
                bf_set(lpfc_cq_context_count, &cq_create->u.request.context,
                       LPFC_CQ_CNT_256);
@@ -15151,7 +15153,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                                               LPFC_CQ_CNT_WORD7);
                                        break;
                                }
-                               /* Fall Thru */
+                               /* fall through */
                        default:
                                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                                "3118 Bad CQ count. (%d)\n",
@@ -15160,7 +15162,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                                        status = -EINVAL;
                                        goto out;
                                }
-                               /* otherwise default to smallest (drop thru) */
+                               /* fall through - otherwise default to smallest */
                        case 256:
                                bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
                                       &cq_set->u.request, LPFC_CQ_CNT_256);
@@ -15432,7 +15434,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
                        status = -EINVAL;
                        goto out;
                }
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 16:
                bf_set(lpfc_mq_context_ring_size,
                       &mq_create_ext->u.request.context,
@@ -15851,7 +15853,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                status = -EINVAL;
                                goto out;
                        }
-                       /* otherwise default to smallest count (drop through) */
+                       /* fall through - otherwise default to smallest count */
                case 512:
                        bf_set(lpfc_rq_context_rqe_count,
                               &rq_create->u.request.context,
@@ -15988,7 +15990,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                status = -EINVAL;
                                goto out;
                        }
-                       /* otherwise default to smallest count (drop through) */
+                       /* fall through - otherwise default to smallest count */
                case 512:
                        bf_set(lpfc_rq_context_rqe_count,
                               &rq_create->u.request.context,
index 7eaa400f63280e47f413f2371cbdd47d97e5f6a4..fcbff83c0097d2a0edd87a5f40239f745df144c8 100644 (file)
@@ -6236,7 +6236,7 @@ megasas_set_dma_mask(struct megasas_instance *instance)
                instance->consistent_mask_64bit = true;
 
        dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n",
-                ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "63" : "32"),
+                ((*pdev->dev.dma_mask == DMA_BIT_MASK(63)) ? "63" : "32"),
                 (instance->consistent_mask_64bit ? "63" : "32"));
 
        return 0;
index a9a25f0eaf6f0316ecf19604ab554f75ad0a06ed..647f48a28f8567c71a09e9787a8f721aaae62470 100644 (file)
@@ -175,7 +175,8 @@ megasas_clear_intr_fusion(struct megasas_instance *instance)
        /*
         * Check if it is our interrupt
         */
-       status = readl(&regs->outbound_intr_status);
+       status = megasas_readl(instance,
+                              &regs->outbound_intr_status);
 
        if (status & 1) {
                writel(status, &regs->outbound_intr_status);
index 4c5a3d23e010a9f629c6188f458d695c2e11edac..084f2fcced0aeb49fd987a63b02dd78fd4566b47 100644 (file)
@@ -657,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
                if (dev->dev_type == SAS_SATA_DEV) {
                        pm8001_device->attached_phy =
                                dev->rphy->identify.phy_identifier;
-                               flag = 1; /* directly sata*/
+                       flag = 1; /* directly sata */
                }
        } /*register this device to HBA*/
        PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
index 4da660c1c4318efbabddffe969cb98190cd0b36d..6d6d6013e35b82a5131ac07647cda5b48e2a737a 100644 (file)
@@ -953,6 +953,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
 
        qedi_ep = ep->dd_data;
        if (qedi_ep->state == EP_STATE_IDLE ||
+           qedi_ep->state == EP_STATE_OFLDCONN_NONE ||
            qedi_ep->state == EP_STATE_OFLDCONN_FAILED)
                return -1;
 
@@ -1035,6 +1036,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
 
        switch (qedi_ep->state) {
        case EP_STATE_OFLDCONN_START:
+       case EP_STATE_OFLDCONN_NONE:
                goto ep_release_conn;
        case EP_STATE_OFLDCONN_FAILED:
                        break;
@@ -1225,6 +1227,7 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
 
        if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
                QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
+               qedi_ep->state = EP_STATE_OFLDCONN_NONE;
                ret = -EIO;
                goto set_path_exit;
        }
index 11260776212fa42cdcb6c481c728fe06be956065..892d70d545537320e6b742ca099e0e1583bcb64a 100644 (file)
@@ -59,6 +59,7 @@ enum {
        EP_STATE_OFLDCONN_FAILED        = 0x2000,
        EP_STATE_CONNECT_FAILED         = 0x4000,
        EP_STATE_DISCONN_TIMEDOUT       = 0x8000,
+       EP_STATE_OFLDCONN_NONE          = 0x10000,
 };
 
 struct qedi_conn;
index a414f51302b755669301f86408b52d28443665ed..6856dfdfa47383d5e41141cccdc3826f2b7fd7bf 100644 (file)
@@ -4248,7 +4248,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->devnum = devnum;    /* specifies microcode load address */
 
 #ifdef QLA_64BIT_PTR
-       if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
+       if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) {
                if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32))) {
                        printk(KERN_WARNING "scsi(%li): Unable to set a "
                               "suitable DMA mask - aborting\n", ha->host_no);
index 26b93c563f924fc67b523e5b0476415c0b5c1047..d1fc4958222a47276f8866c0092e03b5fb4bab40 100644 (file)
@@ -4394,6 +4394,8 @@ typedef struct scsi_qla_host {
        uint16_t        n2n_id;
        struct list_head gpnid_list;
        struct fab_scan scan;
+
+       unsigned int irq_offset;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
index aeeb0144bd5595ae3491b96349e505545d35fbe0..8d1acc802a6741ef38efd09c5f5382d413a4b011 100644 (file)
@@ -1785,13 +1785,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 
                /* Issue Marker IOCB */
                qla2x00_marker(vha, vha->hw->req_q_map[0],
-                   vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
+                   vha->hw->rsp_q_map[0], fcport->loop_id, lun,
                    flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
        }
 
 done_free_sp:
        sp->free(sp);
-       sp->fcport->flags &= ~FCF_ASYNC_SENT;
+       fcport->flags &= ~FCF_ASYNC_SENT;
 done:
        return rval;
 }
index 30d3090842f856d27fb32f23e051832d8eb7b500..8507c43b918cfa29a4027f6f6621ee4212598e75 100644 (file)
@@ -3446,6 +3446,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                            "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
                }
        }
+       vha->irq_offset = desc.pre_vectors;
        ha->msix_entries = kcalloc(ha->msix_count,
                                   sizeof(struct qla_msix_entry),
                                   GFP_KERNEL);
index ea69dafc97749e34be377c658c314cbfdc58bf94..c6ef83d0d99b893ccd5976da44dfc5e93218dd1b 100644 (file)
@@ -6939,7 +6939,7 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost)
        if (USER_CTRL_IRQ(vha->hw))
                rc = blk_mq_map_queues(qmap);
        else
-               rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0);
+               rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, vha->irq_offset);
        return rc;
 }
 
index cfdfcda28072f6dd4595f0212ba325b674f42950..a77bfb2242489b76842ab3ba3fbc138774b0c5dc 100644 (file)
@@ -7232,6 +7232,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
 
        rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,
                                           fw_ddb_entry);
+       if (rc)
+               goto free_sess;
 
        ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
                   __func__, fnode_sess->dev.kobj.name);
index 661512bec3ac683fc2c718e3c1b8675221fb1cdf..e27f4df2402170e9b04012c4b6feceb9be196309 100644 (file)
@@ -62,7 +62,7 @@
 
 /* make sure inq_product_rev string corresponds to this version */
 #define SDEBUG_VERSION "0188"  /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20180128";
+static const char *sdebug_version_date = "20190125";
 
 #define MY_NAME "scsi_debug"
 
@@ -735,7 +735,7 @@ static inline bool scsi_debug_lbp(void)
                (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
 }
 
-static void *fake_store(unsigned long long lba)
+static void *lba2fake_store(unsigned long long lba)
 {
        lba = do_div(lba, sdebug_store_sectors);
 
@@ -2514,8 +2514,8 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
        return ret;
 }
 
-/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
- * arr into fake_store(lba,num) and return true. If comparison fails then
+/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of
+ * arr into lba2fake_store(lba,num) and return true. If comparison fails then
  * return false. */
 static bool comp_write_worker(u64 lba, u32 num, const u8 *arr)
 {
@@ -2643,7 +2643,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
                if (sdt->app_tag == cpu_to_be16(0xffff))
                        continue;
 
-               ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
+               ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba);
                if (ret) {
                        dif_errors++;
                        return ret;
@@ -3261,10 +3261,12 @@ static int resp_write_scat(struct scsi_cmnd *scp,
 static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
                           u32 ei_lba, bool unmap, bool ndob)
 {
+       int ret;
        unsigned long iflags;
        unsigned long long i;
-       int ret;
-       u64 lba_off;
+       u32 lb_size = sdebug_sector_size;
+       u64 block, lbaa;
+       u8 *fs1p;
 
        ret = check_device_access_params(scp, lba, num);
        if (ret)
@@ -3276,31 +3278,30 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
                unmap_region(lba, num);
                goto out;
        }
-
-       lba_off = lba * sdebug_sector_size;
+       lbaa = lba;
+       block = do_div(lbaa, sdebug_store_sectors);
        /* if ndob then zero 1 logical block, else fetch 1 logical block */
+       fs1p = fake_storep + (block * lb_size);
        if (ndob) {
-               memset(fake_storep + lba_off, 0, sdebug_sector_size);
+               memset(fs1p, 0, lb_size);
                ret = 0;
        } else
-               ret = fetch_to_dev_buffer(scp, fake_storep + lba_off,
-                                         sdebug_sector_size);
+               ret = fetch_to_dev_buffer(scp, fs1p, lb_size);
 
        if (-1 == ret) {
                write_unlock_irqrestore(&atomic_rw, iflags);
                return DID_ERROR << 16;
-       } else if (sdebug_verbose && !ndob && (ret < sdebug_sector_size))
+       } else if (sdebug_verbose && !ndob && (ret < lb_size))
                sdev_printk(KERN_INFO, scp->device,
                            "%s: %s: lb size=%u, IO sent=%d bytes\n",
-                           my_name, "write same",
-                           sdebug_sector_size, ret);
+                           my_name, "write same", lb_size, ret);
 
        /* Copy first sector to remaining blocks */
-       for (i = 1 ; i < num ; i++)
-               memcpy(fake_storep + ((lba + i) * sdebug_sector_size),
-                      fake_storep + lba_off,
-                      sdebug_sector_size);
-
+       for (i = 1 ; i < num ; i++) {
+               lbaa = lba + i;
+               block = do_div(lbaa, sdebug_store_sectors);
+               memmove(fake_storep + (block * lb_size), fs1p, lb_size);
+       }
        if (scsi_debug_lbp())
                map_region(lba, num);
 out:
index b13cc9288ba0d9db3fab88849a5fe4a86f6537ff..6d65ac584eba0178846b3b0fc6526f6c10ec8863 100644 (file)
@@ -1842,8 +1842,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
        blk_queue_segment_boundary(q, shost->dma_boundary);
        dma_set_seg_boundary(dev, shost->dma_boundary);
 
-       blk_queue_max_segment_size(q,
-               min(shost->max_segment_size, dma_get_max_seg_size(dev)));
+       blk_queue_max_segment_size(q, shost->max_segment_size);
+       dma_set_max_seg_size(dev, shost->max_segment_size);
 
        /*
         * Set a reasonable default alignment:  The larger of 32-byte (dword),
index a2b4179bfdf7bc91d518fe8bbe415e4176fd7e5e..7639df91b1108495d9af0ba9b8133d51450e759d 100644 (file)
@@ -80,8 +80,22 @@ static int scsi_dev_type_resume(struct device *dev,
 
        if (err == 0) {
                pm_runtime_disable(dev);
-               pm_runtime_set_active(dev);
+               err = pm_runtime_set_active(dev);
                pm_runtime_enable(dev);
+
+               /*
+                * Forcibly set runtime PM status of request queue to "active"
+                * to make sure we can again get requests from the queue
+                * (see also blk_pm_peek_request()).
+                *
+                * The resume hook will correct runtime PM status of the disk.
+                */
+               if (!err && scsi_is_sdev_device(dev)) {
+                       struct scsi_device *sdev = to_scsi_device(dev);
+
+                       if (sdev->request_queue->dev)
+                               blk_set_runtime_active(sdev->request_queue);
+               }
        }
 
        return err;
@@ -140,16 +154,6 @@ static int scsi_bus_resume_common(struct device *dev,
        else
                fn = NULL;
 
-       /*
-        * Forcibly set runtime PM status of request queue to "active" to
-        * make sure we can again get requests from the queue (see also
-        * blk_pm_peek_request()).
-        *
-        * The resume hook will correct runtime PM status of the disk.
-        */
-       if (scsi_is_sdev_device(dev) && pm_runtime_suspended(dev))
-               blk_set_runtime_active(to_scsi_device(dev)->request_queue);
-
        if (fn) {
                async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
 
index a1a44f52e0e8414202a46437a64b937604318e9b..5464d467e23ea120aee77659aaa68692634c3603 100644 (file)
@@ -206,6 +206,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
        sp = buffer_data[0] & 0x80 ? 1 : 0;
        buffer_data[0] &= ~0x80;
 
+       /*
+        * Ensure WP, DPOFUA, and RESERVED fields are cleared in
+        * received mode parameter buffer before doing MODE SELECT.
+        */
+       data.device_specific = 0;
+
        if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
                             SD_MAX_RETRIES, &data, &sshdr)) {
                if (scsi_sense_valid(&sshdr))
@@ -2945,9 +2951,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
        if (rot == 1) {
                blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
                blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
-       } else {
-               blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
-               blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
        }
 
        if (sdkp->device->type == TYPE_ZBC) {
@@ -3084,6 +3087,15 @@ static int sd_revalidate_disk(struct gendisk *disk)
        if (sdkp->media_present) {
                sd_read_capacity(sdkp, buffer);
 
+               /*
+                * set the default to rotational.  All non-rotational devices
+                * support the block characteristics VPD page, which will
+                * cause this to be updated correctly and any device which
+                * doesn't support it should be treated as rotational.
+                */
+               blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+               blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
+
                if (scsi_device_supports_vpd(sdp)) {
                        sd_read_block_provisioning(sdkp);
                        sd_read_block_limits(sdkp);
index 83365b29a4d8ed515b1381166b5b438ddb60c363..fff86940388bab1315c000b241a5456b297cd418 100644 (file)
@@ -462,12 +462,16 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
        sdkp->device->use_10_for_rw = 0;
 
        /*
-        * If something changed, revalidate the disk zone bitmaps once we have
-        * the capacity, that is on the second revalidate execution during disk
-        * scan and always during normal revalidate.
+        * Revalidate the disk zone bitmaps once the block device capacity is
+        * set on the second revalidate execution during disk scan and if
+        * something changed when executing a normal revalidate.
         */
-       if (sdkp->first_scan)
+       if (sdkp->first_scan) {
+               sdkp->zone_blocks = zone_blocks;
+               sdkp->nr_zones = nr_zones;
                return 0;
+       }
+
        if (sdkp->zone_blocks != zone_blocks ||
            sdkp->nr_zones != nr_zones ||
            disk->queue->nr_zones != nr_zones) {
index 7bde6c809442347dce9c35b1b81f58268afedf4c..f564af8949e8694673043e506b3b5a9fbdcf7c3c 100644 (file)
@@ -323,7 +323,7 @@ static inline void pqi_device_remove_start(struct pqi_scsi_dev *device)
 static inline bool pqi_device_in_remove(struct pqi_ctrl_info *ctrl_info,
                                        struct pqi_scsi_dev *device)
 {
-       return device->in_remove & !ctrl_info->in_shutdown;
+       return device->in_remove && !ctrl_info->in_shutdown;
 }
 
 static inline void pqi_schedule_rescan_worker_with_delay(
index dd65fea07687dd2611b58cc000ef2b2646a16ff6..6d176815e6cee04ab7ff653d26926893ab8e3c96 100644 (file)
@@ -195,7 +195,7 @@ enum ufs_desc_def_size {
        QUERY_DESC_CONFIGURATION_DEF_SIZE       = 0x90,
        QUERY_DESC_UNIT_DEF_SIZE                = 0x23,
        QUERY_DESC_INTERCONNECT_DEF_SIZE        = 0x06,
-       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x44,
+       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x48,
        QUERY_DESC_POWER_DEF_SIZE               = 0x62,
        QUERY_DESC_HEALTH_DEF_SIZE              = 0x25,
 };
index 9ba7671b84f8798d190295a51baf5751e1229843..2ddf24466a62e39e351bd90e4f7d24edfad5791f 100644 (file)
 int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
                     const char *prefix)
 {
-       u8 *regs;
+       u32 *regs;
+       size_t pos;
+
+       if (offset % 4 != 0 || len % 4 != 0) /* keep readl happy */
+               return -EINVAL;
 
        regs = kzalloc(len, GFP_KERNEL);
        if (!regs)
                return -ENOMEM;
 
-       memcpy_fromio(regs, hba->mmio_base + offset, len);
+       for (pos = 0; pos < len; pos += 4)
+               regs[pos / 4] = ufshcd_readl(hba, offset + pos);
+
        ufshcd_hex_dump(prefix, regs, len);
        kfree(regs);
 
@@ -8001,6 +8007,8 @@ int ufshcd_system_resume(struct ufs_hba *hba)
        trace_ufshcd_system_resume(dev_name(hba->dev), ret,
                ktime_to_us(ktime_sub(ktime_get(), start)),
                hba->curr_dev_pwr_mode, hba->uic_link_state);
+       if (!ret)
+               hba->is_sys_suspended = false;
        return ret;
 }
 EXPORT_SYMBOL(ufshcd_system_resume);
index 52c153cd795a8c471b48eb570fa87e5613244c2e..636f83f781f5abf85546d9a754b67baab09d0831 100644 (file)
@@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work);
 static irqreturn_t portal_isr(int irq, void *ptr)
 {
        struct qman_portal *p = ptr;
-
-       u32 clear = QM_DQAVAIL_MASK | p->irq_sources;
        u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources;
+       u32 clear = 0;
 
        if (unlikely(!is))
                return IRQ_NONE;
 
        /* DQRR-handling if it's interrupt-driven */
-       if (is & QM_PIRQ_DQRI)
+       if (is & QM_PIRQ_DQRI) {
                __poll_portal_fast(p, QMAN_POLL_LIMIT);
+               clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI;
+       }
        /* Handling of anything else that's interrupt-driven */
-       clear |= __poll_portal_slow(p, is);
+       clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW;
        qm_out(&p->p, QM_REG_ISR, clear);
        return IRQ_HANDLED;
 }
index f78c34647ca2da8e653ed86d6b893bd39aa53534..76480df195a878322fe86a883f55e50c3b7108bd 100644 (file)
@@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
        const char *sprop;
        int ret = 0;
        u32 val;
-       struct resource *res;
-       struct device_node *np2;
-       static int siram_init_flag;
-       struct platform_device *pdev;
 
        sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
        if (sprop) {
@@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
        utdm->siram_entry_id = val;
 
        set_si_param(utdm, ut_info);
-
-       np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si");
-       if (!np2)
-               return -EINVAL;
-
-       pdev = of_find_device_by_node(np2);
-       if (!pdev) {
-               pr_err("%pOFn: failed to lookup pdev\n", np2);
-               of_node_put(np2);
-               return -EINVAL;
-       }
-
-       of_node_put(np2);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       utdm->si_regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(utdm->si_regs)) {
-               ret = PTR_ERR(utdm->si_regs);
-               goto err_miss_siram_property;
-       }
-
-       np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram");
-       if (!np2) {
-               ret = -EINVAL;
-               goto err_miss_siram_property;
-       }
-
-       pdev = of_find_device_by_node(np2);
-       if (!pdev) {
-               ret = -EINVAL;
-               pr_err("%pOFn: failed to lookup pdev\n", np2);
-               of_node_put(np2);
-               goto err_miss_siram_property;
-       }
-
-       of_node_put(np2);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       utdm->siram = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(utdm->siram)) {
-               ret = PTR_ERR(utdm->siram);
-               goto err_miss_siram_property;
-       }
-
-       if (siram_init_flag == 0) {
-               memset_io(utdm->siram, 0,  resource_size(res));
-               siram_init_flag = 1;
-       }
-
-       return ret;
-
-err_miss_siram_property:
-       devm_iounmap(&pdev->dev, utdm->si_regs);
        return ret;
 }
 EXPORT_SYMBOL(ucc_of_parse_tdm);
index a0802de8c3a1dbf54c4bca70d56535ac632026c7..6f5afab7c1a1b8e9ae63222412b163c25c643bfe 100644 (file)
@@ -248,10 +248,10 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf,
        struct ion_dma_buf_attachment *a = attachment->priv;
        struct ion_buffer *buffer = dmabuf->priv;
 
-       free_duped_table(a->table);
        mutex_lock(&buffer->lock);
        list_del(&a->list);
        mutex_unlock(&buffer->lock);
+       free_duped_table(a->table);
 
        kfree(a);
 }
index 2848fa71a33d2c51f1fe7f6e615419125aac9924..d6248eecf123bdc5ad123ac1fd7b5821b9a22e24 100644 (file)
@@ -170,7 +170,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
                return -ENODEV;
 
        priv->last_link = 0;
-       phy_start_aneg(phydev);
+       phy_start(phydev);
 
        return 0;
 no_phy:
index 28cbd6b3d26c39e09f5b8586756f22d83fd9b97a..dfee6985efa6126cb652fc96bad1bfd352aa764c 100644 (file)
@@ -35,6 +35,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
        {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
        {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+       {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
        {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
        {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
index bcc8dfa8e67287b80bd68ae6134133c5b0aac26c..9efb4dcb9d3a8f1d32544b3c8e9b5694da14a63d 100644 (file)
@@ -850,18 +850,18 @@ enum ieee80211_state {
 #define IP_FMT "%pI4"
 #define IP_ARG(x) (x)
 
-extern __inline int is_multicast_mac_addr(const u8 *addr)
+static inline int is_multicast_mac_addr(const u8 *addr)
 {
         return ((addr[0] != 0xff) && (0x01 & addr[0]));
 }
 
-extern __inline int is_broadcast_mac_addr(const u8 *addr)
+static inline int is_broadcast_mac_addr(const u8 *addr)
 {
        return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
                (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
 }
 
-extern __inline int is_zero_mac_addr(const u8 *addr)
+static inline int is_zero_mac_addr(const u8 *addr)
 {
        return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) &&   \
                (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
index c92bbd05516e5561172049207429f4d6ce548d3d..005de0024dd405086e6fa79fa5c1abf6c8d6ac83 100644 (file)
@@ -265,7 +265,8 @@ static void spk_ttyio_send_xchar(char ch)
                return;
        }
 
-       speakup_tty->ops->send_xchar(speakup_tty, ch);
+       if (speakup_tty->ops->send_xchar)
+               speakup_tty->ops->send_xchar(speakup_tty, ch);
        mutex_unlock(&speakup_tty_mutex);
 }
 
@@ -277,7 +278,8 @@ static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
                return;
        }
 
-       speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+       if (speakup_tty->ops->tiocmset)
+               speakup_tty->ops->tiocmset(speakup_tty, set, clear);
        mutex_unlock(&speakup_tty_mutex);
 }
 
index 9e17ec651bdec040d73f21ceff6685054e6ec337..53f5a1cb4636eb2e195bcb19c84d94588502abc5 100644 (file)
@@ -446,6 +446,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
 static inline void
 remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event)
 {
+       event->fired = 1;
        event->armed = 0;
        wake_up_all(wq);
 }
index 70c854d939cee222cda5e66618b6a30aca589999..3d0badc34825f27fb34addab44eec4c4e264455a 100644 (file)
@@ -36,7 +36,7 @@ struct wilc_op_mode {
 struct wilc_reg_frame {
        bool reg;
        u8 reg_id;
-       __le32 frame_type;
+       __le16 frame_type;
 } __packed;
 
 struct wilc_drv_handler {
@@ -1744,7 +1744,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
                                              ARRAY_SIZE(wid_list),
                                              wilc_get_vif_idx(vif));
-               kfree(gtk_key);
        } else if (mode == WILC_STATION_MODE) {
                struct wid wid;
 
@@ -1754,9 +1753,9 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                wid.val = (u8 *)gtk_key;
                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
                                              wilc_get_vif_idx(vif));
-               kfree(gtk_key);
        }
 
+       kfree(gtk_key);
        return result;
 }
 
index 3c5e9e030cadcff05cde6f37dc3c63ec5fc6f2b4..489e5a5038f8d10bc786162f7b92106c72b1e764 100644 (file)
@@ -1252,21 +1252,22 @@ static u32 init_chip(struct net_device *dev)
                ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, &reg);
                if (!ret) {
                        netdev_err(dev, "fail read reg 0x1118\n");
-                       return ret;
+                       goto release;
                }
                reg |= BIT(0);
                ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg);
                if (!ret) {
                        netdev_err(dev, "fail write reg 0x1118\n");
-                       return ret;
+                       goto release;
                }
                ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71);
                if (!ret) {
                        netdev_err(dev, "fail write reg 0xc0000\n");
-                       return ret;
+                       goto release;
                }
        }
 
+release:
        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 
        return ret;
index 984941e036c80c2e5962ee66c439e9bcaa2c19d7..bd15a564fe246c462a8c04628c52cfb9bf66b80b 100644 (file)
@@ -714,7 +714,7 @@ static int __init iscsi_target_init_module(void)
                        sizeof(struct iscsi_queue_req),
                        __alignof__(struct iscsi_queue_req), 0, NULL);
        if (!lio_qr_cache) {
-               pr_err("nable to kmem_cache_create() for"
+               pr_err("Unable to kmem_cache_create() for"
                                " lio_qr_cache\n");
                goto bitmap_out;
        }
index 72016d0dfca5dcc68483f6bfa1cc90adea2b2480..8e7fffbb880291e494dc8074e1fbdaa884426fea 100644 (file)
@@ -852,6 +852,12 @@ static ssize_t pi_prot_type_store(struct config_item *item,
        return count;
 }
 
+/* always zero, but attr needs to remain RW to avoid userspace breakage */
+static ssize_t pi_prot_format_show(struct config_item *item, char *page)
+{
+       return snprintf(page, PAGE_SIZE, "0\n");
+}
+
 static ssize_t pi_prot_format_store(struct config_item *item,
                const char *page, size_t count)
 {
@@ -1132,7 +1138,7 @@ CONFIGFS_ATTR(, emulate_3pc);
 CONFIGFS_ATTR(, emulate_pr);
 CONFIGFS_ATTR(, pi_prot_type);
 CONFIGFS_ATTR_RO(, hw_pi_prot_type);
-CONFIGFS_ATTR_WO(, pi_prot_format);
+CONFIGFS_ATTR(, pi_prot_format);
 CONFIGFS_ATTR(, pi_prot_verify);
 CONFIGFS_ATTR(, enforce_pr_isids);
 CONFIGFS_ATTR(, is_nonrot);
index 1e6d24943565f7825171ae578aaf2f70fb58f944..5831e0eecea120f9157cb566311839b9273755ce 100644 (file)
@@ -148,7 +148,7 @@ struct tcmu_dev {
        size_t ring_size;
 
        struct mutex cmdr_lock;
-       struct list_head cmdr_queue;
+       struct list_head qfull_queue;
 
        uint32_t dbi_max;
        uint32_t dbi_thresh;
@@ -159,6 +159,7 @@ struct tcmu_dev {
 
        struct timer_list cmd_timer;
        unsigned int cmd_time_out;
+       struct list_head inflight_queue;
 
        struct timer_list qfull_timer;
        int qfull_time_out;
@@ -179,7 +180,7 @@ struct tcmu_dev {
 struct tcmu_cmd {
        struct se_cmd *se_cmd;
        struct tcmu_dev *tcmu_dev;
-       struct list_head cmdr_queue_entry;
+       struct list_head queue_entry;
 
        uint16_t cmd_id;
 
@@ -192,6 +193,7 @@ struct tcmu_cmd {
        unsigned long deadline;
 
 #define TCMU_CMD_BIT_EXPIRED 0
+#define TCMU_CMD_BIT_INFLIGHT 1
        unsigned long flags;
 };
 /*
@@ -586,7 +588,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
        if (!tcmu_cmd)
                return NULL;
 
-       INIT_LIST_HEAD(&tcmu_cmd->cmdr_queue_entry);
+       INIT_LIST_HEAD(&tcmu_cmd->queue_entry);
        tcmu_cmd->se_cmd = se_cmd;
        tcmu_cmd->tcmu_dev = udev;
 
@@ -915,11 +917,13 @@ static int tcmu_setup_cmd_timer(struct tcmu_cmd *tcmu_cmd, unsigned int tmo,
                return 0;
 
        tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo));
-       mod_timer(timer, tcmu_cmd->deadline);
+       if (!timer_pending(timer))
+               mod_timer(timer, tcmu_cmd->deadline);
+
        return 0;
 }
 
-static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
+static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd)
 {
        struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
        unsigned int tmo;
@@ -942,7 +946,7 @@ static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
        if (ret)
                return ret;
 
-       list_add_tail(&tcmu_cmd->cmdr_queue_entry, &udev->cmdr_queue);
+       list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue);
        pr_debug("adding cmd %u on dev %s to ring space wait queue\n",
                 tcmu_cmd->cmd_id, udev->name);
        return 0;
@@ -999,7 +1003,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
        base_command_size = tcmu_cmd_get_base_cmd_size(tcmu_cmd->dbi_cnt);
        command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
 
-       if (!list_empty(&udev->cmdr_queue))
+       if (!list_empty(&udev->qfull_queue))
                goto queue;
 
        mb = udev->mb_addr;
@@ -1096,13 +1100,16 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
        UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
        tcmu_flush_dcache_range(mb, sizeof(*mb));
 
+       list_add_tail(&tcmu_cmd->queue_entry, &udev->inflight_queue);
+       set_bit(TCMU_CMD_BIT_INFLIGHT, &tcmu_cmd->flags);
+
        /* TODO: only if FLUSH and FUA? */
        uio_event_notify(&udev->uio_info);
 
        return 0;
 
 queue:
-       if (add_to_cmdr_queue(tcmu_cmd)) {
+       if (add_to_qfull_queue(tcmu_cmd)) {
                *scsi_err = TCM_OUT_OF_RESOURCES;
                return -1;
        }
@@ -1145,6 +1152,8 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
                goto out;
 
+       list_del_init(&cmd->queue_entry);
+
        tcmu_cmd_reset_dbi_cur(cmd);
 
        if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
@@ -1194,9 +1203,29 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        tcmu_free_cmd(cmd);
 }
 
+static void tcmu_set_next_deadline(struct list_head *queue,
+                                  struct timer_list *timer)
+{
+       struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
+       unsigned long deadline = 0;
+
+       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, queue, queue_entry) {
+               if (!time_after(jiffies, tcmu_cmd->deadline)) {
+                       deadline = tcmu_cmd->deadline;
+                       break;
+               }
+       }
+
+       if (deadline)
+               mod_timer(timer, deadline);
+       else
+               del_timer(timer);
+}
+
 static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
 {
        struct tcmu_mailbox *mb;
+       struct tcmu_cmd *cmd;
        int handled = 0;
 
        if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
@@ -1210,7 +1239,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
        while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) {
 
                struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned;
-               struct tcmu_cmd *cmd;
 
                tcmu_flush_dcache_range(entry, sizeof(*entry));
 
@@ -1243,7 +1271,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                /* no more pending commands */
                del_timer(&udev->cmd_timer);
 
-               if (list_empty(&udev->cmdr_queue)) {
+               if (list_empty(&udev->qfull_queue)) {
                        /*
                         * no more pending or waiting commands so try to
                         * reclaim blocks if needed.
@@ -1252,6 +1280,8 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                            tcmu_global_max_blocks)
                                schedule_delayed_work(&tcmu_unmap_work, 0);
                }
+       } else if (udev->cmd_time_out) {
+               tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
        }
 
        return handled;
@@ -1271,7 +1301,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
        if (!time_after(jiffies, cmd->deadline))
                return 0;
 
-       is_running = list_empty(&cmd->cmdr_queue_entry);
+       is_running = test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags);
        se_cmd = cmd->se_cmd;
 
        if (is_running) {
@@ -1287,9 +1317,9 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
                 * target_complete_cmd will translate this to LUN COMM FAILURE
                 */
                scsi_status = SAM_STAT_CHECK_CONDITION;
+               list_del_init(&cmd->queue_entry);
        } else {
-               list_del_init(&cmd->cmdr_queue_entry);
-
+               list_del_init(&cmd->queue_entry);
                idr_remove(&udev->commands, id);
                tcmu_free_cmd(cmd);
                scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -1372,7 +1402,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
 
        INIT_LIST_HEAD(&udev->node);
        INIT_LIST_HEAD(&udev->timedout_entry);
-       INIT_LIST_HEAD(&udev->cmdr_queue);
+       INIT_LIST_HEAD(&udev->qfull_queue);
+       INIT_LIST_HEAD(&udev->inflight_queue);
        idr_init(&udev->commands);
 
        timer_setup(&udev->qfull_timer, tcmu_qfull_timedout, 0);
@@ -1383,7 +1414,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
        return &udev->se_dev;
 }
 
-static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
+static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
 {
        struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
        LIST_HEAD(cmds);
@@ -1391,15 +1422,15 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
        sense_reason_t scsi_ret;
        int ret;
 
-       if (list_empty(&udev->cmdr_queue))
+       if (list_empty(&udev->qfull_queue))
                return true;
 
        pr_debug("running %s's cmdr queue forcefail %d\n", udev->name, fail);
 
-       list_splice_init(&udev->cmdr_queue, &cmds);
+       list_splice_init(&udev->qfull_queue, &cmds);
 
-       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, cmdr_queue_entry) {
-               list_del_init(&tcmu_cmd->cmdr_queue_entry);
+       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, queue_entry) {
+               list_del_init(&tcmu_cmd->queue_entry);
 
                pr_debug("removing cmd %u on dev %s from queue\n",
                         tcmu_cmd->cmd_id, udev->name);
@@ -1437,14 +1468,13 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
                         * cmd was requeued, so just put all cmds back in
                         * the queue
                         */
-                       list_splice_tail(&cmds, &udev->cmdr_queue);
+                       list_splice_tail(&cmds, &udev->qfull_queue);
                        drained = false;
-                       goto done;
+                       break;
                }
        }
-       if (list_empty(&udev->cmdr_queue))
-               del_timer(&udev->qfull_timer);
-done:
+
+       tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
        return drained;
 }
 
@@ -1454,7 +1484,7 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
 
        mutex_lock(&udev->cmdr_lock);
        tcmu_handle_completions(udev);
-       run_cmdr_queue(udev, false);
+       run_qfull_queue(udev, false);
        mutex_unlock(&udev->cmdr_lock);
 
        return 0;
@@ -1982,7 +2012,7 @@ static void tcmu_block_dev(struct tcmu_dev *udev)
        /* complete IO that has executed successfully */
        tcmu_handle_completions(udev);
        /* fail IO waiting to be queued */
-       run_cmdr_queue(udev, true);
+       run_qfull_queue(udev, true);
 
 unlock:
        mutex_unlock(&udev->cmdr_lock);
@@ -1997,7 +2027,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
        mutex_lock(&udev->cmdr_lock);
 
        idr_for_each_entry(&udev->commands, cmd, i) {
-               if (!list_empty(&cmd->cmdr_queue_entry))
+               if (!test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags))
                        continue;
 
                pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
@@ -2006,6 +2036,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
 
                idr_remove(&udev->commands, i);
                if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+                       list_del_init(&cmd->queue_entry);
                        if (err_level == 1) {
                                /*
                                 * Userspace was not able to start the
@@ -2666,6 +2697,10 @@ static void check_timedout_devices(void)
 
                mutex_lock(&udev->cmdr_lock);
                idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
+
+               tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
+               tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
+
                mutex_unlock(&udev->cmdr_lock);
 
                spin_lock_bh(&timed_out_udevs_lock);
index dfd23245f778a3193903d582e015bd27a7f50ad3..6fff16113628743ae9a6b006799fb376abb39198 100644 (file)
@@ -774,7 +774,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
 
                cdev = __cpufreq_cooling_register(np, policy, capacitance);
                if (IS_ERR(cdev)) {
-                       pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
+                       pr_err("cpu_cooling: cpu%d failed to register as cooling device: %ld\n",
                               policy->cpu, PTR_ERR(cdev));
                        cdev = NULL;
                }
index 0582bd12a239d76b5924d9dec5b120a114b50dc2..0ca908d12750e85d46a7d9ca95f2f2402424135a 100644 (file)
@@ -4,7 +4,7 @@
 
 config INT340X_THERMAL
        tristate "ACPI INT340X thermal drivers"
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select THERMAL_GOV_USER_SPACE
        select ACPI_THERMAL_REL
        select ACPI_FAN
index 284cf2c5a8fd92db5bde9705e67d2510fe984731..8e1cf4d789be10df2413e1311bba63dde3545f43 100644 (file)
@@ -84,7 +84,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
        struct pci_dev *pci_dev; \
        struct platform_device *pdev; \
        struct proc_thermal_device *proc_dev; \
-\
+       \
+       if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
+               dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
+               return 0; \
+       } \
+       \
        if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
                pdev = to_platform_device(dev); \
                proc_dev = platform_get_drvdata(pdev); \
@@ -298,11 +303,6 @@ static int proc_thermal_add(struct device *dev,
        *priv = proc_priv;
 
        ret = proc_thermal_read_ppcc(proc_priv);
-       if (!ret) {
-               ret = sysfs_create_group(&dev->kobj,
-                                        &power_limit_attribute_group);
-
-       }
        if (ret)
                return ret;
 
@@ -316,8 +316,7 @@ static int proc_thermal_add(struct device *dev,
 
        proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
        if (IS_ERR(proc_priv->int340x_zone)) {
-               ret = PTR_ERR(proc_priv->int340x_zone);
-               goto remove_group;
+               return PTR_ERR(proc_priv->int340x_zone);
        } else
                ret = 0;
 
@@ -331,9 +330,6 @@ static int proc_thermal_add(struct device *dev,
 
 remove_zone:
        int340x_thermal_zone_remove(proc_priv->int340x_zone);
-remove_group:
-       sysfs_remove_group(&proc_priv->dev->kobj,
-                          &power_limit_attribute_group);
 
        return ret;
 }
@@ -364,7 +360,10 @@ static int int3401_add(struct platform_device *pdev)
        platform_set_drvdata(pdev, proc_priv);
        proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
 
-       return 0;
+       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
+
+       return sysfs_create_group(&pdev->dev.kobj,
+                                        &power_limit_attribute_group);
 }
 
 static int int3401_remove(struct platform_device *pdev)
@@ -423,7 +422,7 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                proc_priv->soc_dts = intel_soc_dts_iosf_init(
                                        INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
 
-               if (proc_priv->soc_dts && pdev->irq) {
+               if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
                        ret = pci_enable_msi(pdev);
                        if (!ret) {
                                ret = request_threaded_irq(pdev->irq, NULL,
@@ -441,7 +440,10 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                        dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
        }
 
-       return 0;
+       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
+
+       return sysfs_create_group(&pdev->dev.kobj,
+                                        &power_limit_attribute_group);
 }
 
 static void  proc_thermal_pci_remove(struct pci_dev *pdev)
index 4bfdb4a1e47d4fa1f7527c7cf16fd82872e8118a..2df059cc07e2fb76fbe2b23aa436f3878e84125a 100644 (file)
@@ -867,14 +867,14 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
 
        ret = of_property_read_u32(np, "polling-delay-passive", &prop);
        if (ret < 0) {
-               pr_err("missing polling-delay-passive property\n");
+               pr_err("%pOFn: missing polling-delay-passive property\n", np);
                goto free_tz;
        }
        tz->passive_delay = prop;
 
        ret = of_property_read_u32(np, "polling-delay", &prop);
        if (ret < 0) {
-               pr_err("missing polling-delay property\n");
+               pr_err("%pOFn: missing polling-delay property\n", np);
                goto free_tz;
        }
        tz->polling_delay = prop;
index 4164414d4c64b266dfce58772241cb009363f4c0..8bdf42bc8fc817c9a0ac1278d2e89aeb7377ba0e 100644 (file)
@@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
                                /* too large for caller's buffer */
                                ret = -EOVERFLOW;
                        } else {
+                               __set_current_state(TASK_RUNNING);
                                if (copy_to_user(buf, rbuf->buf, rbuf->count))
                                        ret = -EFAULT;
                                else
index 189ab1212d9aa80b219e01c131ddbbe6c4bec6d8..e441221e04b9aa67186bf6784236486d6f30cdce 100644 (file)
@@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 
                        ret = 0;
                }
-       }
 
-       /* Initialise interrupt backoff work if required */
-       if (up->overrun_backoff_time_ms > 0) {
-               uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
-               INIT_DELAYED_WORK(&uart->overrun_backoff,
-                                 serial_8250_overrun_backoff_work);
-       } else {
-               uart->overrun_backoff_time_ms = 0;
+               /* Initialise interrupt backoff work if required */
+               if (up->overrun_backoff_time_ms > 0) {
+                       uart->overrun_backoff_time_ms =
+                               up->overrun_backoff_time_ms;
+                       INIT_DELAYED_WORK(&uart->overrun_backoff,
+                                       serial_8250_overrun_backoff_work);
+               } else {
+                       uart->overrun_backoff_time_ms = 0;
+               }
        }
 
        mutex_unlock(&serial_mutex);
index e2c407656fa6c8045d33d43f9fa6d9ffe113fcb4..c1fdbc0b68401bf3b1030faf9a41321ae045013e 100644 (file)
@@ -357,6 +357,9 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
        if (dmacnt == 2) {
                data->dma = devm_kzalloc(&pdev->dev, sizeof(*data->dma),
                                         GFP_KERNEL);
+               if (!data->dma)
+                       return -ENOMEM;
+
                data->dma->fn = mtk8250_dma_filter;
                data->dma->rx_size = MTK_UART_RX_SIZE;
                data->dma->rxconf.src_maxburst = MTK_UART_RX_TRIGGER;
index f80a300b5d68f6e8ad61b7daf2544234da7e1662..48bd694a5fa1f825b2432ffc019975595bc5538b 100644 (file)
@@ -3420,6 +3420,11 @@ static int
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
        int num_iomem, num_port, first_port = -1, i;
+       int rc;
+
+       rc = serial_pci_is_class_communication(dev);
+       if (rc)
+               return rc;
 
        /*
         * Should we try to make guesses for multiport serial devices later?
@@ -3647,10 +3652,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 
        board = &pci_boards[ent->driver_data];
 
-       rc = serial_pci_is_class_communication(dev);
-       if (rc)
-               return rc;
-
        rc = serial_pci_is_blacklisted(dev);
        if (rc)
                return rc;
index e1a551aae3362f2805a9840179858d2a0d927452..ce81523c311314e9b5f0675e5d5c53231e965a4b 100644 (file)
 #include <linux/serial_core.h>
 #include <asm/sbi.h>
 
-static void sbi_console_write(struct console *con,
-                             const char *s, unsigned int n)
+static void sbi_putc(struct uart_port *port, int c)
 {
-       int i;
+       sbi_console_putchar(c);
+}
 
-       for (i = 0; i < n; ++i)
-               sbi_console_putchar(s[i]);
+static void sbi_console_write(struct console *con,
+                             const char *s, unsigned n)
+{
+       struct earlycon_device *dev = con->data;
+       uart_console_write(&dev->port, s, n, sbi_putc);
 }
 
 static int __init early_sbi_setup(struct earlycon_device *device,
index 241a48e5052c37106acc8f672c37834dd38a74c8..debdd1b9e01ae560d32065d89cb37d6115388879 100644 (file)
@@ -1697,7 +1697,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /* ask the core to calculate the divisor */
-       baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+       baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
index a72d6d9fb98340e6d283876a7f7b2f96c31479e0..38016609c7fa99b1726bcebe3ed04b1fd6a0c724 100644 (file)
@@ -225,7 +225,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
        unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
        u32 geni_ios;
 
-       if (uart_console(uport) || !uart_cts_enabled(uport)) {
+       if (uart_console(uport)) {
                mctrl |= TIOCM_CTS;
        } else {
                geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS);
@@ -241,7 +241,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
 {
        u32 uart_manual_rfr = 0;
 
-       if (uart_console(uport) || !uart_cts_enabled(uport))
+       if (uart_console(uport))
                return;
 
        if (!(mctrl & TIOCM_RTS))
index d4cca5bdaf1c60d40ba45b6c1815f2a6d98046af..556f50aa1b586ce9876d61ca35d95b0a4568b088 100644 (file)
@@ -130,6 +130,9 @@ static void uart_start(struct tty_struct *tty)
        struct uart_port *port;
        unsigned long flags;
 
+       if (!state)
+               return;
+
        port = uart_port_lock(state, flags);
        __uart_start(tty);
        uart_port_unlock(port, flags);
@@ -550,10 +553,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
        int ret = 0;
 
        circ = &state->xmit;
-       if (!circ->buf)
+       port = uart_port_lock(state, flags);
+       if (!circ->buf) {
+               uart_port_unlock(port, flags);
                return 0;
+       }
 
-       port = uart_port_lock(state, flags);
        if (port && uart_circ_chars_free(circ) != 0) {
                circ->buf[circ->head] = c;
                circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -586,11 +591,13 @@ static int uart_write(struct tty_struct *tty,
                return -EL3HLT;
        }
 
+       port = uart_port_lock(state, flags);
        circ = &state->xmit;
-       if (!circ->buf)
+       if (!circ->buf) {
+               uart_port_unlock(port, flags);
                return 0;
+       }
 
-       port = uart_port_lock(state, flags);
        while (port) {
                c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
                if (count < c)
@@ -723,6 +730,9 @@ static void uart_unthrottle(struct tty_struct *tty)
        upstat_t mask = UPSTAT_SYNC_FIFO;
        struct uart_port *port;
 
+       if (!state)
+               return;
+
        port = uart_port_ref(state);
        if (!port)
                return;
index 8df0fd8245203f8b5d77aa6f5f8666830ca47b01..64bbeb7d7e0c727e85fe8999ca56c3f03f5cee9f 100644 (file)
@@ -1921,7 +1921,7 @@ static int sci_request_irq(struct sci_port *port)
 
 static void sci_free_irq(struct sci_port *port)
 {
-       int i;
+       int i, j;
 
        /*
         * Intentionally in reverse order so we iterate over the muxed
@@ -1937,6 +1937,13 @@ static void sci_free_irq(struct sci_port *port)
                if (unlikely(irq < 0))
                        continue;
 
+               /* Check if already freed (irq was muxed) */
+               for (j = 0; j < i; j++)
+                       if (port->irqs[j] == irq)
+                               j = i + 1;
+               if (j > i)
+                       continue;
+
                free_irq(port->irqs[i], port);
                kfree(port->irqstr[i]);
 
index 23c6fd23842295de47b5ec328316e5de8c435b76..21ffcce16927164a279cb0afa8300d4430942910 100644 (file)
@@ -2189,7 +2189,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
        ld = tty_ldisc_ref_wait(tty);
        if (!ld)
                return -EIO;
-       ld->ops->receive_buf(tty, &ch, &mbz, 1);
+       if (ld->ops->receive_buf)
+               ld->ops->receive_buf(tty, &ch, &mbz, 1);
        tty_ldisc_deref(ld);
        return 0;
 }
index 41ec8e5010f30a544b82ca439cc5a481fe499b19..bba75560d11e2eca421638aef7a2a928c44878b3 100644 (file)
@@ -1272,6 +1272,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (con_is_visible(vc))
                update_screen(vc);
        vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
+       notify_update(vc);
        return err;
 }
 
@@ -2764,8 +2765,8 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
        con_flush(vc, draw_from, draw_to, &draw_x);
        vc_uniscr_debug_check(vc);
        console_conditional_schedule();
-       console_unlock();
        notify_update(vc);
+       console_unlock();
        return n;
 }
 
@@ -2884,8 +2885,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        unsigned char c;
        static DEFINE_SPINLOCK(printing_lock);
        const ushort *start;
-       ushort cnt = 0;
-       ushort myx;
+       ushort start_x, cnt;
        int kmsg_console;
 
        /* console busy or not yet initialized */
@@ -2898,10 +2898,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
                vc = vc_cons[kmsg_console - 1].d;
 
-       /* read `x' only after setting currcons properly (otherwise
-          the `x' macro will read the x of the foreground console). */
-       myx = vc->vc_x;
-
        if (!vc_cons_allocated(fg_console)) {
                /* impossible */
                /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
@@ -2916,53 +2912,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
                hide_cursor(vc);
 
        start = (ushort *)vc->vc_pos;
-
-       /* Contrived structure to try to emulate original need_wrap behaviour
-        * Problems caused when we have need_wrap set on '\n' character */
+       start_x = vc->vc_x;
+       cnt = 0;
        while (count--) {
                c = *b++;
                if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
-                       if (cnt > 0) {
-                               if (con_is_visible(vc))
-                                       vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
-                               vc->vc_x += cnt;
-                               if (vc->vc_need_wrap)
-                                       vc->vc_x--;
-                               cnt = 0;
-                       }
+                       if (cnt && con_is_visible(vc))
+                               vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
+                       cnt = 0;
                        if (c == 8) {           /* backspace */
                                bs(vc);
                                start = (ushort *)vc->vc_pos;
-                               myx = vc->vc_x;
+                               start_x = vc->vc_x;
                                continue;
                        }
                        if (c != 13)
                                lf(vc);
                        cr(vc);
                        start = (ushort *)vc->vc_pos;
-                       myx = vc->vc_x;
+                       start_x = vc->vc_x;
                        if (c == 10 || c == 13)
                                continue;
                }
+               vc_uniscr_putc(vc, c);
                scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
                notify_write(vc, c);
                cnt++;
-               if (myx == vc->vc_cols - 1) {
-                       vc->vc_need_wrap = 1;
-                       continue;
-               }
-               vc->vc_pos += 2;
-               myx++;
-       }
-       if (cnt > 0) {
-               if (con_is_visible(vc))
-                       vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
-               vc->vc_x += cnt;
-               if (vc->vc_x == vc->vc_cols) {
-                       vc->vc_x--;
+               if (vc->vc_x == vc->vc_cols - 1) {
                        vc->vc_need_wrap = 1;
+               } else {
+                       vc->vc_pos += 2;
+                       vc->vc_x++;
                }
        }
+       if (cnt && con_is_visible(vc))
+               vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
        set_cursor(vc);
        notify_update(vc);
 
index e81de9ca8729e2e7101ce0e6bcb8e15977377ff0..9b45aa422e696e96f6038aed9fadc6a1a1527956 100644 (file)
@@ -316,7 +316,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
        if (IS_ERR(data->usbmisc_data))
                return PTR_ERR(data->usbmisc_data);
 
-       if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) {
+       if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC)
+               && data->usbmisc_data) {
                pdata.flags |= CI_HDRC_IMX_IS_HSIC;
                data->usbmisc_data->hsic = 1;
                data->pinctrl = devm_pinctrl_get(dev);
index dc7f7fd71684cb7d7e2d0f3bc39f49f114618def..c12ac56606c3f681fe8cebe0357a8284ec405f25 100644 (file)
@@ -119,11 +119,6 @@ static const struct attribute_group ports_group = {
        .attrs = ports_attrs,
 };
 
-static const struct attribute_group *ports_groups[] = {
-       &ports_group,
-       NULL
-};
-
 /***************************************
  * Adding & removing ports
  ***************************************/
@@ -307,6 +302,7 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action,
 static int usbport_trig_activate(struct led_classdev *led_cdev)
 {
        struct usbport_trig_data *usbport_data;
+       int err;
 
        usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL);
        if (!usbport_data)
@@ -315,6 +311,9 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
 
        /* List of ports */
        INIT_LIST_HEAD(&usbport_data->ports);
+       err = sysfs_create_group(&led_cdev->dev->kobj, &ports_group);
+       if (err)
+               goto err_free;
        usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
        usbport_trig_update_count(usbport_data);
 
@@ -322,8 +321,11 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
        usbport_data->nb.notifier_call = usbport_trig_notify;
        led_set_trigger_data(led_cdev, usbport_data);
        usb_register_notify(&usbport_data->nb);
-
        return 0;
+
+err_free:
+       kfree(usbport_data);
+       return err;
 }
 
 static void usbport_trig_deactivate(struct led_classdev *led_cdev)
@@ -335,6 +337,8 @@ static void usbport_trig_deactivate(struct led_classdev *led_cdev)
                usbport_trig_remove_port(usbport_data, port);
        }
 
+       sysfs_remove_group(&led_cdev->dev->kobj, &ports_group);
+
        usb_unregister_notify(&usbport_data->nb);
 
        kfree(usbport_data);
@@ -344,7 +348,6 @@ static struct led_trigger usbport_led_trigger = {
        .name     = "usbport",
        .activate = usbport_trig_activate,
        .deactivate = usbport_trig_deactivate,
-       .groups = ports_groups,
 };
 
 static int __init usbport_trig_init(void)
index 68ad75a7460dd032cfbe8b5a007f3774f8a8cad6..55ef3cc2701b999aa93d9bca90cc979bfb1cc08a 100644 (file)
@@ -261,7 +261,7 @@ static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
 
        if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
                dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
-               dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
+               dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
                dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG);
        }
 }
index cb7fcd7c0ad84608bf80431176ade8583212a64d..c1e9ea621f41365137b898011442eb3ebb5a595d 100644 (file)
@@ -78,7 +78,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
        for (i = 0; i < exynos->num_clks; i++) {
                ret = clk_prepare_enable(exynos->clks[i]);
                if (ret) {
-                       while (--i > 0)
+                       while (i-- > 0)
                                clk_disable_unprepare(exynos->clks[i]);
                        return ret;
                }
@@ -223,7 +223,7 @@ static int dwc3_exynos_resume(struct device *dev)
        for (i = 0; i < exynos->num_clks; i++) {
                ret = clk_prepare_enable(exynos->clks[i]);
                if (ret) {
-                       while (--i > 0)
+                       while (i-- > 0)
                                clk_disable_unprepare(exynos->clks[i]);
                        return ret;
                }
index 07bd31bb2f8a0a6a70d3f4a9e94766abdf857bfe..6c9b76bcc2e173570b7fdae29769d4925b3c971d 100644 (file)
@@ -177,6 +177,7 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
        req->started = false;
        list_del(&req->list);
        req->remaining = 0;
+       req->needs_extra_trb = false;
 
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
@@ -1118,7 +1119,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
        unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
        unsigned int rem = length % maxp;
 
-       if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
+       if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
                struct dwc3     *dwc = dep->dwc;
                struct dwc3_trb *trb;
 
@@ -1984,6 +1985,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
 
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
+       dwc->link_state = DWC3_LINK_STATE_SS_DIS;
        dwc3_ep0_out_start(dwc);
 
        dwc3_gadget_enable_irq(dwc);
@@ -3379,6 +3381,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
        dwc3_disconnect_gadget(dwc);
        __dwc3_gadget_stop(dwc);
 
+       synchronize_irq(dwc->irq_gadget);
+
        return 0;
 }
 
index 9cdef108fb1b3da5581c99c8251903702b04c6a8..ed68a4860b7d8702e1a8fd9cca40b04b5065a4ce 100644 (file)
@@ -838,7 +838,7 @@ static struct usb_function *source_sink_alloc_func(
 
        ss = kzalloc(sizeof(*ss), GFP_KERNEL);
        if (!ss)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ss_opts =  container_of(fi, struct f_ss_opts, func_inst);
 
index 660878a195055b32568db74ca3716b9fbccbae12..b77f3126580ebb937986e7ced5b28739dd25dea4 100644 (file)
@@ -2083,7 +2083,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+       if (!(intcsr & (1 << NET2272_PCI_IRQ))) {
                spin_unlock(&dev->lock);
                return IRQ_NONE;
        }
index f26109eafdbfbc3633a9126c18f41cef27e26e01..66ec1fdf9fe7d9860c3c0d277391b430c516e339 100644 (file)
@@ -302,3 +302,4 @@ MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
 MODULE_AUTHOR("Neil Zhang <zhangwm@marvell.com>");
 MODULE_ALIAS("mv-ehci");
 MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, ehci_mv_dt_ids);
index eae8b1b1b45b864a545827b9c5403b88b8779f78..ffe462a657b15d8b592ac7801dc6f4be4629c86f 100644 (file)
@@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum)
        }
 
        if (request) {
-               u8      is_dma = 0;
-               bool    short_packet = false;
 
                trace_musb_req_tx(req);
 
                if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
-                       is_dma = 1;
                        csr |= MUSB_TXCSR_P_WZC_BITS;
                        csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
                                 MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
@@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
                 */
                if ((request->zero && request->length)
                        && (request->length % musb_ep->packet_sz == 0)
-                       && (request->actual == request->length))
-                               short_packet = true;
+                       && (request->actual == request->length)) {
 
-               if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) &&
-                       (is_dma && (!dma->desired_mode ||
-                               (request->actual &
-                                       (musb_ep->packet_sz - 1)))))
-                               short_packet = true;
-
-               if (short_packet) {
                        /*
                         * On DMA completion, FIFO may not be
                         * available yet...
index a688f7f87829f760c9fdee9008f6ca365e342dd3..5fc6825745f21bd6246d71b99fd98d7313396f01 100644 (file)
@@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                channel->status = MUSB_DMA_STATUS_FREE;
 
                                /* completed */
-                               if ((devctl & MUSB_DEVCTL_HM)
-                                       && (musb_channel->transmit)
-                                       && ((channel->desired_mode == 0)
-                                           || (channel->actual_len &
-                                           (musb_channel->max_packet_sz - 1)))
-                                   ) {
+                               if (musb_channel->transmit &&
+                                       (!channel->desired_mode ||
+                                       (channel->actual_len %
+                                           musb_channel->max_packet_sz))) {
                                        u8  epnum  = musb_channel->epnum;
                                        int offset = musb->io.ep_offset(epnum,
                                                                    MUSB_TXCSR);
@@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                         */
                                        musb_ep_select(mbase, epnum);
                                        txcsr = musb_readw(mbase, offset);
-                                       txcsr &= ~(MUSB_TXCSR_DMAENAB
+                                       if (channel->desired_mode == 1) {
+                                               txcsr &= ~(MUSB_TXCSR_DMAENAB
                                                        | MUSB_TXCSR_AUTOSET);
-                                       musb_writew(mbase, offset, txcsr);
-                                       /* Send out the packet */
-                                       txcsr &= ~MUSB_TXCSR_DMAMODE;
+                                               musb_writew(mbase, offset, txcsr);
+                                               /* Send out the packet */
+                                               txcsr &= ~MUSB_TXCSR_DMAMODE;
+                                               txcsr |= MUSB_TXCSR_DMAENAB;
+                                       }
                                        txcsr |=  MUSB_TXCSR_TXPKTRDY;
                                        musb_writew(mbase, offset, txcsr);
                                }
index d7312eed60882a7c356b0d6736c5df836d2dbaf0..91ea3083e7ad97793872fbb9459ab205fd9b5161 100644 (file)
@@ -21,7 +21,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM
+       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM=y && PM
        depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
        select USB_PHY
        help
index 27bdb72225272394d1d1001dc8d50e17c0186601..f5f0568d8533e111a6d1287d0ef39916005efbb3 100644 (file)
@@ -61,9 +61,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
-       if (ret)
-               return ret;
        am_phy->usb_phy_gen.phy.init = am335x_init;
        am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
 
@@ -82,7 +79,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
        device_set_wakeup_enable(dev, false);
        phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);
 
-       return 0;
+       return usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
index 1ab2a6191013e195d8c4d8f246222f85b064b9c0..77ef4c481f3ce42c7bcd24bd9c271ac64a46703f 100644 (file)
@@ -1783,6 +1783,10 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
        int result;
        u16 val;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        val = (mode << 8) | (priv->gpio_output << 4) | priv->gpio_value;
        result = usb_control_msg(serial->dev,
                                 usb_sndctrlpipe(serial->dev, 0),
@@ -1795,6 +1799,8 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
                        val, result);
        }
 
+       usb_autopm_put_interface(serial->interface);
+
        return result;
 }
 
@@ -1846,9 +1852,15 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
        unsigned char *buf;
        int result;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        buf = kmalloc(1, GFP_KERNEL);
-       if (!buf)
+       if (!buf) {
+               usb_autopm_put_interface(serial->interface);
                return -ENOMEM;
+       }
 
        result = usb_control_msg(serial->dev,
                                 usb_rcvctrlpipe(serial->dev, 0),
@@ -1863,6 +1875,7 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
        }
 
        kfree(buf);
+       usb_autopm_put_interface(serial->interface);
 
        return result;
 }
index 09e21e84fc4e03ed7db638c402bbfd66e02918ef..a68f1fb25b8a996cc2d601c5f72a02cafa1500ad 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa26msg.h
 
index dee454c4609a2a51a60169b41f3420b5937ddad7..a19f3fe5d98d346719185459d713aefd646119be 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa28msg.h
 
index 163b2dea2ec5ccd7fba706068031b69a134ad377..8c3970fdd868a407b87f9a80468e67f1ac7c2dff 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa49msg.h
 
index 20fa3e2f7187a4c84da1fd524eb67afd10e4532e..dcf502fdbb44430c29d2bfc6d1c40257ed483302 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa67msg.h
 
index 86708ecd87357095629d6f670938b2da30e456ac..c4ca0f631d20a9085294f67e1fe356e55a209b9b 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa90msg.h
 
index 98e7a5df0f6d8ffcbd28335fea51bb25f294eb1b..bb3f9aa4a9093fe4fcf6ebc192cf1d040d6dc8c3 100644 (file)
@@ -46,6 +46,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID),
index 4e2554d553620402ae8d3adf5e7f4eee96c90cff..559941ca884daf353cc022e41755fc9bc6d54567 100644 (file)
@@ -8,6 +8,7 @@
 
 #define PL2303_VENDOR_ID       0x067b
 #define PL2303_PRODUCT_ID      0x2303
+#define PL2303_PRODUCT_ID_TB           0x2304
 #define PL2303_PRODUCT_ID_RSAQ2                0x04bb
 #define PL2303_PRODUCT_ID_DCU11                0x1234
 #define PL2303_PRODUCT_ID_PHAROS       0xaaa0
@@ -20,6 +21,7 @@
 #define PL2303_PRODUCT_ID_MOTOROLA     0x0307
 #define PL2303_PRODUCT_ID_ZTEK         0xe1f1
 
+
 #define ATEN_VENDOR_ID         0x0557
 #define ATEN_VENDOR_ID2                0x0547
 #define ATEN_PRODUCT_ID                0x2008
index 4d0273508043de920cc4868eab9722deabf4ba40..edbbb13d6de6ee39285fef25268be3d08f4e3b0e 100644 (file)
@@ -85,7 +85,8 @@ DEVICE(moto_modem, MOTO_IDS);
 /* Motorola Tetra driver */
 #define MOTOROLA_TETRA_IDS()                   \
        { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
-       { USB_DEVICE(0x0cad, 0x9012) }  /* MTP6550 */
+       { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
+       { USB_DEVICE(0x0cad, 0x9016) }  /* TPG2200 */
 DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
 
 /* Novatel Wireless GPS driver */
index 4bc29b5866980ffa3486516670b4bf15812dd21a..f1c39a3c753434666b033e1ab47fb1033b5fd259 100644 (file)
@@ -2297,7 +2297,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
                                              pdo_pps_apdo_max_voltage(snk));
                port->pps_data.max_curr = min_pps_apdo_current(src, snk);
                port->pps_data.out_volt = min(port->pps_data.max_volt,
-                                             port->pps_data.out_volt);
+                                             max(port->pps_data.min_volt,
+                                                 port->pps_data.out_volt));
                port->pps_data.op_curr = min(port->pps_data.max_curr,
                                             port->pps_data.op_curr);
        }
diff --git a/drivers/usb/usbip/README b/drivers/usb/usbip/README
deleted file mode 100644 (file)
index 41a2cf2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-       - more discussion about the protocol
-       - testing
-       - review of the userspace interface
-       - document the protocol
-
-Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
index 4d13e510590e7b9a56ca8a57ef4a2737200f55ff..b2aa986ab9ed0572fb4fe71b41d1c2b8645d5de1 100644 (file)
@@ -1,13 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * VFIO PCI mmap/mmap_fault tracepoints
  *
  * Copyright (C) 2018 IBM Corp.  All rights reserved.
  *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #undef TRACE_SYSTEM
index 054a2cf9dd8e555a17b7eb11563a1750c7f01cd5..32f695ffe128085b0df8b8c0025e9b420868f6f8 100644 (file)
@@ -1,14 +1,10 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * VFIO PCI NVIDIA Whitherspoon GPU support a.k.a. NVLink2.
  *
  * Copyright (C) 2018 IBM Corp.  All rights reserved.
  *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Register an on-GPU RAM region for cacheable access.
  *
  * Derived from original vfio_pci_igd.c:
@@ -178,11 +174,11 @@ static int vfio_pci_nvgpu_add_capability(struct vfio_pci_device *vdev,
                struct vfio_pci_region *region, struct vfio_info_cap *caps)
 {
        struct vfio_pci_nvgpu_data *data = region->data;
-       struct vfio_region_info_cap_nvlink2_ssatgt cap = { 0 };
-
-       cap.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
-       cap.header.version = 1;
-       cap.tgt = data->gpu_tgt;
+       struct vfio_region_info_cap_nvlink2_ssatgt cap = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+               .header.version = 1,
+               .tgt = data->gpu_tgt
+       };
 
        return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
 }
@@ -365,18 +361,18 @@ static int vfio_pci_npu2_add_capability(struct vfio_pci_device *vdev,
                struct vfio_pci_region *region, struct vfio_info_cap *caps)
 {
        struct vfio_pci_npu2_data *data = region->data;
-       struct vfio_region_info_cap_nvlink2_ssatgt captgt = { 0 };
-       struct vfio_region_info_cap_nvlink2_lnkspd capspd = { 0 };
+       struct vfio_region_info_cap_nvlink2_ssatgt captgt = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+               .header.version = 1,
+               .tgt = data->gpu_tgt
+       };
+       struct vfio_region_info_cap_nvlink2_lnkspd capspd = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD,
+               .header.version = 1,
+               .link_speed = data->link_speed
+       };
        int ret;
 
-       captgt.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
-       captgt.header.version = 1;
-       captgt.tgt = data->gpu_tgt;
-
-       capspd.header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD;
-       capspd.header.version = 1;
-       capspd.link_speed = data->link_speed;
-
        ret = vfio_info_add_capability(caps, &captgt.header, sizeof(captgt));
        if (ret)
                return ret;
index 36f3d0f49e60c093a96f2a689b9fd0d8c6a24c53..df51a35cf537c96caf570d0ce06dbbc004b61af1 100644 (file)
@@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net)
                if (nvq->done_idx > VHOST_NET_BATCH)
                        vhost_net_signal_used(nvq);
                if (unlikely(vq_log))
-                       vhost_log_write(vq, vq_log, log, vhost_len);
+                       vhost_log_write(vq, vq_log, log, vhost_len,
+                                       vq->iov, in);
                total_len += vhost_len;
                if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
                        vhost_poll_queue(&vq->poll);
@@ -1336,7 +1337,8 @@ static int vhost_net_open(struct inode *inode, struct file *f)
                n->vqs[i].rx_ring = NULL;
                vhost_net_buf_init(&n->vqs[i].rxq);
        }
-       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
+       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX,
+                      UIO_MAXIOV + VHOST_NET_BATCH);
 
        vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev);
        vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
index 8e10ab436d1f13bbf38c8f15dcfcb06c4fc3ab46..23593cb23dd0229abdbbef2c7178d3ba487b383a 100644 (file)
@@ -1127,16 +1127,18 @@ vhost_scsi_send_tmf_reject(struct vhost_scsi *vs,
                           struct vhost_virtqueue *vq,
                           struct vhost_scsi_ctx *vc)
 {
-       struct virtio_scsi_ctrl_tmf_resp __user *resp;
        struct virtio_scsi_ctrl_tmf_resp rsp;
+       struct iov_iter iov_iter;
        int ret;
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));
        rsp.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
-       resp = vq->iov[vc->out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
+
+       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+       ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+       if (likely(ret == sizeof(rsp)))
                vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_tmf_resp\n");
@@ -1147,16 +1149,18 @@ vhost_scsi_send_an_resp(struct vhost_scsi *vs,
                        struct vhost_virtqueue *vq,
                        struct vhost_scsi_ctx *vc)
 {
-       struct virtio_scsi_ctrl_an_resp __user *resp;
        struct virtio_scsi_ctrl_an_resp rsp;
+       struct iov_iter iov_iter;
        int ret;
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));   /* event_actual = 0 */
        rsp.response = VIRTIO_SCSI_S_OK;
-       resp = vq->iov[vc->out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
+
+       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+       ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+       if (likely(ret == sizeof(rsp)))
                vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_an_resp\n");
@@ -1623,7 +1627,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
                vqs[i] = &vs->vqs[i].vq;
                vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
        }
-       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
+       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV);
 
        vhost_scsi_init_inflight(vs, NULL);
 
index 9f7942cbcbb22a9f09eb0dd4d052b8d0c562004d..24a129fcdd61b38bd8bb5045d22dd4ca0884a59f 100644 (file)
@@ -390,9 +390,9 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
                vq->indirect = kmalloc_array(UIO_MAXIOV,
                                             sizeof(*vq->indirect),
                                             GFP_KERNEL);
-               vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log),
+               vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log),
                                        GFP_KERNEL);
-               vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads),
+               vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads),
                                          GFP_KERNEL);
                if (!vq->indirect || !vq->log || !vq->heads)
                        goto err_nomem;
@@ -414,7 +414,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
 }
 
 void vhost_dev_init(struct vhost_dev *dev,
-                   struct vhost_virtqueue **vqs, int nvqs)
+                   struct vhost_virtqueue **vqs, int nvqs, int iov_limit)
 {
        struct vhost_virtqueue *vq;
        int i;
@@ -427,6 +427,7 @@ void vhost_dev_init(struct vhost_dev *dev,
        dev->iotlb = NULL;
        dev->mm = NULL;
        dev->worker = NULL;
+       dev->iov_limit = iov_limit;
        init_llist_head(&dev->work_list);
        init_waitqueue_head(&dev->wait);
        INIT_LIST_HEAD(&dev->read_list);
@@ -1034,8 +1035,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
        int type, ret;
 
        ret = copy_from_iter(&type, sizeof(type), from);
-       if (ret != sizeof(type))
+       if (ret != sizeof(type)) {
+               ret = -EINVAL;
                goto done;
+       }
 
        switch (type) {
        case VHOST_IOTLB_MSG:
@@ -1054,8 +1057,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
 
        iov_iter_advance(from, offset);
        ret = copy_from_iter(&msg, sizeof(msg), from);
-       if (ret != sizeof(msg))
+       if (ret != sizeof(msg)) {
+               ret = -EINVAL;
                goto done;
+       }
        if (vhost_process_iotlb_msg(dev, &msg)) {
                ret = -EFAULT;
                goto done;
@@ -1733,13 +1738,87 @@ static int log_write(void __user *log_base,
        return r;
 }
 
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+       struct vhost_umem *umem = vq->umem;
+       struct vhost_umem_node *u;
+       u64 start, end, l, min;
+       int r;
+       bool hit = false;
+
+       while (len) {
+               min = len;
+               /* More than one GPAs can be mapped into a single HVA. So
+                * iterate all possible umems here to be safe.
+                */
+               list_for_each_entry(u, &umem->umem_list, link) {
+                       if (u->userspace_addr > hva - 1 + len ||
+                           u->userspace_addr - 1 + u->size < hva)
+                               continue;
+                       start = max(u->userspace_addr, hva);
+                       end = min(u->userspace_addr - 1 + u->size,
+                                 hva - 1 + len);
+                       l = end - start + 1;
+                       r = log_write(vq->log_base,
+                                     u->start + start - u->userspace_addr,
+                                     l);
+                       if (r < 0)
+                               return r;
+                       hit = true;
+                       min = min(l, min);
+               }
+
+               if (!hit)
+                       return -EFAULT;
+
+               len -= min;
+               hva += min;
+       }
+
+       return 0;
+}
+
+static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
+{
+       struct iovec iov[64];
+       int i, ret;
+
+       if (!vq->iotlb)
+               return log_write(vq->log_base, vq->log_addr + used_offset, len);
+
+       ret = translate_desc(vq, (uintptr_t)vq->used + used_offset,
+                            len, iov, 64, VHOST_ACCESS_WO);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < ret; i++) {
+               ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+                                   iov[i].iov_len);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-                   unsigned int log_num, u64 len)
+                   unsigned int log_num, u64 len, struct iovec *iov, int count)
 {
        int i, r;
 
        /* Make sure data written is seen before log. */
        smp_wmb();
+
+       if (vq->iotlb) {
+               for (i = 0; i < count; i++) {
+                       r = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+                                         iov[i].iov_len);
+                       if (r < 0)
+                               return r;
+               }
+               return 0;
+       }
+
        for (i = 0; i < log_num; ++i) {
                u64 l = min(log[i].len, len);
                r = log_write(vq->log_base, log[i].addr, l);
@@ -1769,9 +1848,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
                smp_wmb();
                /* Log used flag write. */
                used = &vq->used->flags;
-               log_write(vq->log_base, vq->log_addr +
-                         (used - (void __user *)vq->used),
-                         sizeof vq->used->flags);
+               log_used(vq, (used - (void __user *)vq->used),
+                        sizeof vq->used->flags);
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
@@ -1789,9 +1867,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
                smp_wmb();
                /* Log avail event write */
                used = vhost_avail_event(vq);
-               log_write(vq->log_base, vq->log_addr +
-                         (used - (void __user *)vq->used),
-                         sizeof *vhost_avail_event(vq));
+               log_used(vq, (used - (void __user *)vq->used),
+                        sizeof *vhost_avail_event(vq));
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
@@ -2191,10 +2268,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
                /* Make sure data is seen before log. */
                smp_wmb();
                /* Log used ring entry write. */
-               log_write(vq->log_base,
-                         vq->log_addr +
-                          ((void __user *)used - (void __user *)vq->used),
-                         count * sizeof *used);
+               log_used(vq, ((void __user *)used - (void __user *)vq->used),
+                        count * sizeof *used);
        }
        old = vq->last_used_idx;
        new = (vq->last_used_idx += count);
@@ -2236,9 +2311,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
                /* Make sure used idx is seen before log. */
                smp_wmb();
                /* Log used index update. */
-               log_write(vq->log_base,
-                         vq->log_addr + offsetof(struct vring_used, idx),
-                         sizeof vq->used->idx);
+               log_used(vq, offsetof(struct vring_used, idx),
+                        sizeof vq->used->idx);
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
index 466ef75422916c020fcb26d27cf812bd99f99284..9490e7ddb3404891515908cb8e67d74563640ebd 100644 (file)
@@ -170,9 +170,11 @@ struct vhost_dev {
        struct list_head read_list;
        struct list_head pending_list;
        wait_queue_head_t wait;
+       int iov_limit;
 };
 
-void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
+void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
+                   int nvqs, int iov_limit);
 long vhost_dev_set_owner(struct vhost_dev *dev);
 bool vhost_dev_has_owner(struct vhost_dev *dev);
 long vhost_dev_check_owner(struct vhost_dev *);
@@ -205,7 +207,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
 bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-                   unsigned int log_num, u64 len);
+                   unsigned int log_num, u64 len,
+                   struct iovec *iov, int count);
 int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
 
 struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
index bc42d38ae031102615662afb68d06c80a86bd063..bb5fc0e9fbc2d7cbb9948afa207453694f092877 100644 (file)
@@ -531,7 +531,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
        vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
        vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
 
-       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs));
+       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV);
 
        file->private_data = vsock;
        spin_lock_init(&vsock->send_pkt_list_lock);
@@ -642,7 +642,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
                hash_del_rcu(&vsock->hash);
 
        vsock->guest_cid = guest_cid;
-       hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
+       hash_add_rcu(vhost_vsock_hash, &vsock->hash, vsock->guest_cid);
        mutex_unlock(&vhost_vsock_mutex);
 
        return 0;
index 6d8dc2c775205529a2a6f069e7c12439c12aa53d..51e0c4be08df3bc3c4434f4cfceba837ac8dc956 100644 (file)
@@ -174,7 +174,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
                return -ENODEV;
        }
        for_each_child_of_node(nproot, np) {
-               if (!of_node_cmp(np->name, name)) {
+               if (of_node_name_eq(np, name)) {
                        of_property_read_u32(np, "marvell,88pm860x-iset",
                                             &iset);
                        data->iset = PM8606_WLED_CURRENT(iset);
index f9ef0673a083cb63c776ca58631710e659329ee3..feb90764a8117d2818960267a608c270024a2e07 100644 (file)
@@ -30,6 +30,7 @@ struct pwm_bl_data {
        struct device           *dev;
        unsigned int            lth_brightness;
        unsigned int            *levels;
+       bool                    enabled;
        struct regulator        *power_supply;
        struct gpio_desc        *enable_gpio;
        unsigned int            scale;
@@ -50,7 +51,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
        int err;
 
        pwm_get_state(pb->pwm, &state);
-       if (state.enabled)
+       if (pb->enabled)
                return;
 
        err = regulator_enable(pb->power_supply);
@@ -65,6 +66,8 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
 
        if (pb->enable_gpio)
                gpiod_set_value_cansleep(pb->enable_gpio, 1);
+
+       pb->enabled = true;
 }
 
 static void pwm_backlight_power_off(struct pwm_bl_data *pb)
@@ -72,7 +75,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
        struct pwm_state state;
 
        pwm_get_state(pb->pwm, &state);
-       if (!state.enabled)
+       if (!pb->enabled)
                return;
 
        if (pb->enable_gpio)
@@ -86,6 +89,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
        pwm_apply_state(pb->pwm, &state);
 
        regulator_disable(pb->power_supply);
+       pb->enabled = false;
 }
 
 static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
@@ -268,6 +272,16 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
        memset(data, 0, sizeof(*data));
 
+       /*
+        * These values are optional and set as 0 by default, the out values
+        * are modified only if a valid u32 value can be decoded.
+        */
+       of_property_read_u32(node, "post-pwm-on-delay-ms",
+                            &data->post_pwm_on_delay);
+       of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
+
+       data->enable_gpio = -EINVAL;
+
        /*
         * Determine the number of brightness levels, if this property is not
         * set a default table of brightness levels will be used.
@@ -380,15 +394,6 @@ static int pwm_backlight_parse_dt(struct device *dev,
                data->max_brightness--;
        }
 
-       /*
-        * These values are optional and set as 0 by default, the out values
-        * are modified only if a valid u32 value can be decoded.
-        */
-       of_property_read_u32(node, "post-pwm-on-delay-ms",
-                            &data->post_pwm_on_delay);
-       of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
-
-       data->enable_gpio = -EINVAL;
        return 0;
 }
 
@@ -483,6 +488,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        pb->check_fb = data->check_fb;
        pb->exit = data->exit;
        pb->dev = &pdev->dev;
+       pb->enabled = false;
        pb->post_pwm_on_delay = data->post_pwm_on_delay;
        pb->pwm_off_delay = data->pwm_off_delay;
 
index 09731b2f6815f98651acba84cf9cc8d679f34f7a..c6b3bdbbdbc9e283d661eb960696681611575489 100644 (file)
@@ -271,6 +271,7 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
+       c->vc_origin = c->vc_visible_origin;
        vgacon_scrollback_cur->save = 0;
 
        if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
@@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        int start, end, count, soff;
 
        if (!lines) {
-               c->vc_visible_origin = c->vc_origin;
-               vga_set_mem_top(c);
+               vgacon_restore_screen(c);
                return;
        }
 
@@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        if (!vgacon_scrollback_cur->save) {
                vgacon_cursor(c, CM_ERASE);
                vgacon_save_screen(c);
+               c->vc_origin = (unsigned long)c->vc_screenbuf;
                vgacon_scrollback_cur->save = 1;
        }
 
@@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
                int copysize;
 
                int diff = c->vc_rows - count;
-               void *d = (void *) c->vc_origin;
+               void *d = (void *) c->vc_visible_origin;
                void *s = (void *) c->vc_screenbuf;
 
                count *= c->vc_size_row;
index 8976190b6c1ffbdecd5776100cbebb13cf879b11..bfa1360ec750491e2cc065ce8021a3f62495b71c 100644 (file)
@@ -510,6 +510,13 @@ static int __init fb_console_setup(char *this_opt)
                        continue;
                }
 #endif
+
+               if (!strncmp(options, "logo-pos:", 9)) {
+                       options += 9;
+                       if (!strcmp(options, "center"))
+                               fb_center_logo = true;
+                       continue;
+               }
        }
        return 1;
 }
index 558ed2ed31249d083ecb4e8d275415c48141be61..cb43a2258c5185ec8c8112eab30f6375cdf6c899 100644 (file)
@@ -53,6 +53,9 @@ EXPORT_SYMBOL(registered_fb);
 int num_registered_fb __read_mostly;
 EXPORT_SYMBOL(num_registered_fb);
 
+bool fb_center_logo __read_mostly;
+EXPORT_SYMBOL(fb_center_logo);
+
 static struct fb_info *get_fb_info(unsigned int idx)
 {
        struct fb_info *fb_info;
@@ -506,8 +509,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
                fb_set_logo(info, logo, logo_new, fb_logo.depth);
        }
 
-#ifdef CONFIG_FB_LOGO_CENTER
-       {
+       if (fb_center_logo) {
                int xres = info->var.xres;
                int yres = info->var.yres;
 
@@ -520,11 +522,11 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
                        --n;
                image.dx = (xres - n * (logo->width + 8) - 8) / 2;
                image.dy = y ?: (yres - logo->height) / 2;
+       } else {
+               image.dx = 0;
+               image.dy = y;
        }
-#else
-       image.dx = 0;
-       image.dy = y;
-#endif
+
        image.width = logo->width;
        image.height = logo->height;
 
@@ -684,9 +686,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
        }
 
        height = fb_logo.logo->height;
-#ifdef CONFIG_FB_LOGO_CENTER
-       height += (yres - fb_logo.logo->height) / 2;
-#endif
+       if (fb_center_logo)
+               height += (yres - fb_logo.logo->height) / 2;
 
        return fb_prepare_extra_logos(info, height, yres);
 }
index 31f769d67195b9d748fed8aafec7b43633dd1545..057d3cdef92e67963291f1a130cb3df700f4807a 100644 (file)
@@ -318,28 +318,28 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
 }
 
 static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
-                                   const char *name, unsigned long address)
+                                   unsigned long address)
 {
        struct offb_par *par = (struct offb_par *) info->par;
 
-       if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+       if (of_node_name_prefix(dp, "ATY,Rage128")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_r128;
-       } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
-                         || !strncmp(name, "ATY,RageM3p12A", 14))) {
+       } else if (of_node_name_prefix(dp, "ATY,RageM3pA") ||
+                  of_node_name_prefix(dp, "ATY,RageM3p12A")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_M3A;
-       } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+       } else if (of_node_name_prefix(dp, "ATY,RageM3pB")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_M3B;
-       } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+       } else if (of_node_name_prefix(dp, "ATY,Rage6")) {
                par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_radeon;
-       } else if (!strncmp(name, "ATY,", 4)) {
+       } else if (of_node_name_prefix(dp, "ATY,")) {
                unsigned long base = address & 0xff000000UL;
                par->cmap_adr =
                        ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
@@ -350,7 +350,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
                par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
                if (par->cmap_adr)
                        par->cmap_type = cmap_gxt2000;
-       } else if (dp && !strncmp(name, "vga,Display-", 12)) {
+       } else if (of_node_name_prefix(dp, "vga,Display-")) {
                /* Look for AVIVO initialized by SLOF */
                struct device_node *pciparent = of_get_parent(dp);
                const u32 *vid, *did;
@@ -438,7 +438,7 @@ static void __init offb_init_fb(const char *name,
 
        par->cmap_type = cmap_unknown;
        if (depth == 8)
-               offb_init_palette_hacks(info, dp, name, address);
+               offb_init_palette_hacks(info, dp, address);
        else
                fix->visual = FB_VISUAL_TRUECOLOR;
 
index 53f93616c671cd9e758d243fd3691662b98e0355..8e23160ec59f861e87e12d163849dfa4967a2b62 100644 (file)
@@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        int r = 0;
 
+       memset(&p, 0, sizeof(p));
+
        switch (cmd) {
        case OMAPFB_SYNC_GFX:
                DBG("ioctl SYNC_GFX\n");
index 1e972c4e88b1418de27cae80ebaeb41e853c411c..d1f6196c8b9a4b329bf5b73aa6222d3ef7d3647f 100644 (file)
@@ -10,15 +10,6 @@ menuconfig LOGO
 
 if LOGO
 
-config FB_LOGO_CENTER
-       bool "Center the logo"
-       depends on FB=y
-       help
-         When this option is selected, the bootup logo is centered both
-         horizontally and vertically. If more than one logo is displayed
-         due to multiple CPUs, the collected line of logos is centered
-         as a whole.
-
 config FB_LOGO_EXTRA
        bool
        depends on FB=y
index 728ecd1eea305a50b5a899de53ac873cb8bceca2..fb12fe205f86669b68a885c4e377e0342bb9ed85 100644 (file)
@@ -61,6 +61,10 @@ enum virtio_balloon_vq {
        VIRTIO_BALLOON_VQ_MAX
 };
 
+enum virtio_balloon_config_read {
+       VIRTIO_BALLOON_CONFIG_READ_CMD_ID = 0,
+};
+
 struct virtio_balloon {
        struct virtio_device *vdev;
        struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq;
@@ -77,14 +81,20 @@ struct virtio_balloon {
        /* Prevent updating balloon when it is being canceled. */
        spinlock_t stop_update_lock;
        bool stop_update;
+       /* Bitmap to indicate if reading the related config fields are needed */
+       unsigned long config_read_bitmap;
 
        /* The list of allocated free pages, waiting to be given back to mm */
        struct list_head free_page_list;
        spinlock_t free_page_list_lock;
        /* The number of free page blocks on the above list */
        unsigned long num_free_page_blocks;
-       /* The cmd id received from host */
-       u32 cmd_id_received;
+       /*
+        * The cmd id received from host.
+        * Read it via virtio_balloon_cmd_id_received to get the latest value
+        * sent from host.
+        */
+       u32 cmd_id_received_cache;
        /* The cmd id that is actively in use */
        __virtio32 cmd_id_active;
        /* Buffer to store the stop sign */
@@ -390,37 +400,31 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb,
        return num_returned;
 }
 
+static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
+{
+       if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
+               return;
+
+       /* No need to queue the work if the bit was already set. */
+       if (test_and_set_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+                            &vb->config_read_bitmap))
+               return;
+
+       queue_work(vb->balloon_wq, &vb->report_free_page_work);
+}
+
 static void virtballoon_changed(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb = vdev->priv;
        unsigned long flags;
-       s64 diff = towards_target(vb);
-
-       if (diff) {
-               spin_lock_irqsave(&vb->stop_update_lock, flags);
-               if (!vb->stop_update)
-                       queue_work(system_freezable_wq,
-                                  &vb->update_balloon_size_work);
-               spin_unlock_irqrestore(&vb->stop_update_lock, flags);
-       }
 
-       if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
-               virtio_cread(vdev, struct virtio_balloon_config,
-                            free_page_report_cmd_id, &vb->cmd_id_received);
-               if (vb->cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
-                       /* Pass ULONG_MAX to give back all the free pages */
-                       return_free_pages_to_mm(vb, ULONG_MAX);
-               } else if (vb->cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
-                          vb->cmd_id_received !=
-                          virtio32_to_cpu(vdev, vb->cmd_id_active)) {
-                       spin_lock_irqsave(&vb->stop_update_lock, flags);
-                       if (!vb->stop_update) {
-                               queue_work(vb->balloon_wq,
-                                          &vb->report_free_page_work);
-                       }
-                       spin_unlock_irqrestore(&vb->stop_update_lock, flags);
-               }
+       spin_lock_irqsave(&vb->stop_update_lock, flags);
+       if (!vb->stop_update) {
+               queue_work(system_freezable_wq,
+                          &vb->update_balloon_size_work);
+               virtio_balloon_queue_free_page_work(vb);
        }
+       spin_unlock_irqrestore(&vb->stop_update_lock, flags);
 }
 
 static void update_balloon_size(struct virtio_balloon *vb)
@@ -527,6 +531,17 @@ static int init_vqs(struct virtio_balloon *vb)
        return 0;
 }
 
+static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb)
+{
+       if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+                              &vb->config_read_bitmap))
+               virtio_cread(vb->vdev, struct virtio_balloon_config,
+                            free_page_report_cmd_id,
+                            &vb->cmd_id_received_cache);
+
+       return vb->cmd_id_received_cache;
+}
+
 static int send_cmd_id_start(struct virtio_balloon *vb)
 {
        struct scatterlist sg;
@@ -537,7 +552,8 @@ static int send_cmd_id_start(struct virtio_balloon *vb)
        while (virtqueue_get_buf(vq, &unused))
                ;
 
-       vb->cmd_id_active = cpu_to_virtio32(vb->vdev, vb->cmd_id_received);
+       vb->cmd_id_active = virtio32_to_cpu(vb->vdev,
+                                       virtio_balloon_cmd_id_received(vb));
        sg_init_one(&sg, &vb->cmd_id_active, sizeof(vb->cmd_id_active));
        err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_active, GFP_KERNEL);
        if (!err)
@@ -620,7 +636,8 @@ static int send_free_pages(struct virtio_balloon *vb)
                 * stop the reporting.
                 */
                cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active);
-               if (cmd_id_active != vb->cmd_id_received)
+               if (unlikely(cmd_id_active !=
+                            virtio_balloon_cmd_id_received(vb)))
                        break;
 
                /*
@@ -637,11 +654,9 @@ static int send_free_pages(struct virtio_balloon *vb)
        return 0;
 }
 
-static void report_free_page_func(struct work_struct *work)
+static void virtio_balloon_report_free_page(struct virtio_balloon *vb)
 {
        int err;
-       struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
-                                                report_free_page_work);
        struct device *dev = &vb->vdev->dev;
 
        /* Start by sending the received cmd id to host with an outbuf. */
@@ -659,6 +674,23 @@ static void report_free_page_func(struct work_struct *work)
                dev_err(dev, "Failed to send a stop id, err = %d\n", err);
 }
 
+static void report_free_page_func(struct work_struct *work)
+{
+       struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
+                                                report_free_page_work);
+       u32 cmd_id_received;
+
+       cmd_id_received = virtio_balloon_cmd_id_received(vb);
+       if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
+               /* Pass ULONG_MAX to give back all the free pages */
+               return_free_pages_to_mm(vb, ULONG_MAX);
+       } else if (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
+                  cmd_id_received !=
+                  virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) {
+               virtio_balloon_report_free_page(vb);
+       }
+}
+
 #ifdef CONFIG_BALLOON_COMPACTION
 /*
  * virtballoon_migratepage - perform the balloon page migration on behalf of
@@ -885,7 +917,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
                        goto out_del_vqs;
                }
                INIT_WORK(&vb->report_free_page_work, report_free_page_func);
-               vb->cmd_id_received = VIRTIO_BALLOON_CMD_ID_STOP;
+               vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP;
                vb->cmd_id_active = cpu_to_virtio32(vb->vdev,
                                                  VIRTIO_BALLOON_CMD_ID_STOP);
                vb->cmd_id_stop = cpu_to_virtio32(vb->vdev,
index 4cd9ea5c75be728b88a45df1d3d199c3d7801ab6..d9dd0f7892791047811c54d8a950c40660d0eaac 100644 (file)
@@ -468,7 +468,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
        unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
-       int i, err;
+       int i, err, queue_idx = 0;
 
        err = request_irq(irq, vm_interrupt, IRQF_SHARED,
                        dev_name(&vdev->dev), vm_dev);
@@ -476,7 +476,12 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return err;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i],
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        vm_del_vqs(vdev);
index 465a6f5142cc56500ddbc84bf9c6f37fce058bee..d0584c040c60f3a8f1a8b48004ec66074eebdcc8 100644 (file)
@@ -285,7 +285,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        u16 msix_vec;
-       int i, err, nvectors, allocated_vectors;
+       int i, err, nvectors, allocated_vectors, queue_idx = 0;
 
        vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
        if (!vp_dev->vqs)
@@ -321,7 +321,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
                        msix_vec = allocated_vectors++;
                else
                        msix_vec = VP_MSIX_VQ_VECTOR;
-               vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+               vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false,
                                     msix_vec);
                if (IS_ERR(vqs[i])) {
@@ -356,7 +356,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                const char * const names[], const bool *ctx)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-       int i, err;
+       int i, err, queue_idx = 0;
 
        vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
        if (!vp_dev->vqs)
@@ -374,7 +374,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                        vqs[i] = NULL;
                        continue;
                }
-               vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+               vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false,
                                     VIRTIO_MSI_NO_VECTOR);
                if (IS_ERR(vqs[i])) {
index cd7e755484e3be873cbcc73369a2ddadf1c4f376..a0b07c3312550463b689acf9aa8d524ac5ad7d89 100644 (file)
@@ -152,7 +152,12 @@ struct vring_virtqueue {
                /* Available for packed ring */
                struct {
                        /* Actual memory layout for this queue. */
-                       struct vring_packed vring;
+                       struct {
+                               unsigned int num;
+                               struct vring_packed_desc *desc;
+                               struct vring_packed_desc_event *driver;
+                               struct vring_packed_desc_event *device;
+                       } vring;
 
                        /* Driver ring wrap counter. */
                        bool avail_wrap_counter;
@@ -1609,6 +1614,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
                !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
+       if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+               vq->weak_barriers = false;
+
        vq->packed.ring_dma_addr = ring_dma_addr;
        vq->packed.driver_event_dma_addr = driver_event_dma_addr;
        vq->packed.device_event_dma_addr = device_event_dma_addr;
@@ -2079,6 +2087,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
                !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
+       if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+               vq->weak_barriers = false;
+
        vq->split.queue_dma_addr = 0;
        vq->split.queue_size_in_bytes = 0;
 
@@ -2213,6 +2224,8 @@ void vring_transport_features(struct virtio_device *vdev)
                        break;
                case VIRTIO_F_RING_PACKED:
                        break;
+               case VIRTIO_F_ORDER_PLATFORM:
+                       break;
                default:
                        /* We don't understand this bit. */
                        __virtio_clear_bit(vdev, i);
index 5c4a764717c4d09dcd7345180d622ef55c7124a4..81208cd3f4ecba3edc2dc6334b360cdd98a7f935 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/watchdog.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 
 #include <asm/mach-ralink/ralink_regs.h>
 
index 98967f0a7d10e239e51080e5489b656bbdff084b..db7c57d82cfdc0201b9a49272c3dbb44db5961a7 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/watchdog.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 
 #include <asm/mach-ralink/ralink_regs.h>
 
index 0d3a0fbbd7a5ddfcedc59a1ce16ec22b8830fba7..52941207a12aba71ea1694b23c1c5765d3a56b8b 100644 (file)
@@ -79,13 +79,13 @@ static int tqmx86_wdt_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (IS_ERR(res))
-               return PTR_ERR(res);
+       if (!res)
+               return -ENODEV;
 
        priv->io_base = devm_ioport_map(&pdev->dev, res->start,
                                        resource_size(res));
-       if (IS_ERR(priv->io_base))
-               return PTR_ERR(priv->io_base);
+       if (!priv->io_base)
+               return -ENOMEM;
 
        watchdog_set_drvdata(&priv->wdd, priv);
 
index 93194f3e75404f05655028531d5ae710a6d6db87..117e76b2f9391a1983a0c46b3276e7606412977e 100644 (file)
@@ -1650,7 +1650,7 @@ void xen_callback_vector(void)
                        xen_have_vector_callback = 0;
                        return;
                }
-               pr_info("Xen HVM callback vector for event delivery is enabled\n");
+               pr_info_once("Xen HVM callback vector for event delivery is enabled\n");
                alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
                                xen_hvm_callback_vector);
        }
index 2e5d845b5091478252dfb1ed17395cf9c5ce870a..7aa64d1b119c2c7b8c99efaae07bb65e1964db1f 100644 (file)
@@ -160,9 +160,10 @@ static void pvcalls_conn_back_read(void *opaque)
 
        /* write the data, then modify the indexes */
        virt_wmb();
-       if (ret < 0)
+       if (ret < 0) {
+               atomic_set(&map->read, 0);
                intf->in_error = ret;
-       else
+       else
                intf->in_prod = prod + ret;
        /* update the indexes, then notify the other end */
        virt_wmb();
@@ -282,13 +283,11 @@ static int pvcalls_back_socket(struct xenbus_device *dev,
 static void pvcalls_sk_state_change(struct sock *sock)
 {
        struct sock_mapping *map = sock->sk_user_data;
-       struct pvcalls_data_intf *intf;
 
        if (map == NULL)
                return;
 
-       intf = map->ring;
-       intf->in_error = -ENOTCONN;
+       atomic_inc(&map->read);
        notify_remote_via_irq(map->irq);
 }
 
index 77224d8f3e6fe6ee17cb06f81f20be18069422a9..8a249c95c19342059d9eb06dcf1aeb74f4936458 100644 (file)
 #define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE)
 #define PVCALLS_FRONT_MAX_SPIN 5000
 
+static struct proto pvcalls_proto = {
+       .name   = "PVCalls",
+       .owner  = THIS_MODULE,
+       .obj_size = sizeof(struct sock),
+};
+
 struct pvcalls_bedata {
        struct xen_pvcalls_front_ring ring;
        grant_ref_t ref;
@@ -335,6 +341,42 @@ int pvcalls_front_socket(struct socket *sock)
        return ret;
 }
 
+static void free_active_ring(struct sock_mapping *map)
+{
+       if (!map->active.ring)
+               return;
+
+       free_pages((unsigned long)map->active.data.in,
+                       map->active.ring->ring_order);
+       free_page((unsigned long)map->active.ring);
+}
+
+static int alloc_active_ring(struct sock_mapping *map)
+{
+       void *bytes;
+
+       map->active.ring = (struct pvcalls_data_intf *)
+               get_zeroed_page(GFP_KERNEL);
+       if (!map->active.ring)
+               goto out;
+
+       map->active.ring->ring_order = PVCALLS_RING_ORDER;
+       bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+                                       PVCALLS_RING_ORDER);
+       if (!bytes)
+               goto out;
+
+       map->active.data.in = bytes;
+       map->active.data.out = bytes +
+               XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
+
+       return 0;
+
+out:
+       free_active_ring(map);
+       return -ENOMEM;
+}
+
 static int create_active(struct sock_mapping *map, int *evtchn)
 {
        void *bytes;
@@ -343,15 +385,7 @@ static int create_active(struct sock_mapping *map, int *evtchn)
        *evtchn = -1;
        init_waitqueue_head(&map->active.inflight_conn_req);
 
-       map->active.ring = (struct pvcalls_data_intf *)
-               __get_free_page(GFP_KERNEL | __GFP_ZERO);
-       if (map->active.ring == NULL)
-               goto out_error;
-       map->active.ring->ring_order = PVCALLS_RING_ORDER;
-       bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                       PVCALLS_RING_ORDER);
-       if (bytes == NULL)
-               goto out_error;
+       bytes = map->active.data.in;
        for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
                map->active.ring->ref[i] = gnttab_grant_foreign_access(
                        pvcalls_front_dev->otherend_id,
@@ -361,10 +395,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
                pvcalls_front_dev->otherend_id,
                pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0);
 
-       map->active.data.in = bytes;
-       map->active.data.out = bytes +
-               XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
-
        ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn);
        if (ret)
                goto out_error;
@@ -385,8 +415,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
 out_error:
        if (*evtchn >= 0)
                xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
-       free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
-       free_page((unsigned long)map->active.ring);
        return ret;
 }
 
@@ -406,17 +434,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
                return PTR_ERR(map);
 
        bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+       ret = alloc_active_ring(map);
+       if (ret < 0) {
+               pvcalls_exit_sock(sock);
+               return ret;
+       }
 
        spin_lock(&bedata->socket_lock);
        ret = get_request(bedata, &req_id);
        if (ret < 0) {
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map);
                pvcalls_exit_sock(sock);
                return ret;
        }
        ret = create_active(map, &evtchn);
        if (ret < 0) {
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map);
                pvcalls_exit_sock(sock);
                return ret;
        }
@@ -469,8 +504,10 @@ static int __write_ring(struct pvcalls_data_intf *intf,
        virt_mb();
 
        size = pvcalls_queued(prod, cons, array_size);
-       if (size >= array_size)
+       if (size > array_size)
                return -EINVAL;
+       if (size == array_size)
+               return 0;
        if (len > array_size - size)
                len = array_size - size;
 
@@ -560,15 +597,13 @@ static int __read_ring(struct pvcalls_data_intf *intf,
        error = intf->in_error;
        /* get pointers before reading from the ring */
        virt_rmb();
-       if (error < 0)
-               return error;
 
        size = pvcalls_queued(prod, cons, array_size);
        masked_prod = pvcalls_mask(prod, array_size);
        masked_cons = pvcalls_mask(cons, array_size);
 
        if (size == 0)
-               return 0;
+               return error ?: size;
 
        if (len > size)
                len = size;
@@ -780,25 +815,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
                }
        }
 
-       spin_lock(&bedata->socket_lock);
-       ret = get_request(bedata, &req_id);
-       if (ret < 0) {
+       map2 = kzalloc(sizeof(*map2), GFP_KERNEL);
+       if (map2 == NULL) {
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
-               spin_unlock(&bedata->socket_lock);
+               pvcalls_exit_sock(sock);
+               return -ENOMEM;
+       }
+       ret = alloc_active_ring(map2);
+       if (ret < 0) {
+               clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+                               (void *)&map->passive.flags);
+               kfree(map2);
                pvcalls_exit_sock(sock);
                return ret;
        }
-       map2 = kzalloc(sizeof(*map2), GFP_ATOMIC);
-       if (map2 == NULL) {
+       spin_lock(&bedata->socket_lock);
+       ret = get_request(bedata, &req_id);
+       if (ret < 0) {
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map2);
+               kfree(map2);
                pvcalls_exit_sock(sock);
-               return -ENOMEM;
+               return ret;
        }
+
        ret = create_active(map2, &evtchn);
        if (ret < 0) {
+               free_active_ring(map2);
                kfree(map2);
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
@@ -839,7 +885,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
 
 received:
        map2->sock = newsock;
-       newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL);
+       newsock->sk = sk_alloc(sock_net(sock->sk), PF_INET, GFP_KERNEL, &pvcalls_proto, false);
        if (!newsock->sk) {
                bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
                map->passive.inflight_req_id = PVCALLS_INVALID_ID;
@@ -1032,8 +1078,8 @@ int pvcalls_front_release(struct socket *sock)
                spin_lock(&bedata->socket_lock);
                list_del(&map->list);
                spin_unlock(&bedata->socket_lock);
-               if (READ_ONCE(map->passive.inflight_req_id) !=
-                   PVCALLS_INVALID_ID) {
+               if (READ_ONCE(map->passive.inflight_req_id) != PVCALLS_INVALID_ID &&
+                       READ_ONCE(map->passive.inflight_req_id) != 0) {
                        pvcalls_front_free_map(bedata,
                                               map->passive.accept_map);
                }
index 989cf872b98c60398e9394528721de1811151e9a..bb7888429be6b98dec9cd7fcfd13f9827a515d05 100644 (file)
@@ -645,7 +645,7 @@ xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                     void *cpu_addr, dma_addr_t dma_addr, size_t size,
                     unsigned long attrs)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
        if (xen_get_dma_ops(dev)->mmap)
                return xen_get_dma_ops(dev)->mmap(dev, vma, cpu_addr,
                                                    dma_addr, size, attrs);
@@ -662,7 +662,7 @@ xen_swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
                        void *cpu_addr, dma_addr_t handle, size_t size,
                        unsigned long attrs)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
        if (xen_get_dma_ops(dev)->get_sgtable) {
 #if 0
        /*
index 0568fd98682109e0dd686d5097bf9fe2e40ecfe1..e432bd27a2e7b893bf8a1d2480cf2c7efdc17ab8 100644 (file)
@@ -208,7 +208,7 @@ void afs_lock_work(struct work_struct *work)
                /* The new front of the queue now owns the state variables. */
                next = list_entry(vnode->pending_locks.next,
                                  struct file_lock, fl_u.afs.link);
-               vnode->lock_key = afs_file_key(next->fl_file);
+               vnode->lock_key = key_get(afs_file_key(next->fl_file));
                vnode->lock_type = (next->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
                vnode->lock_state = AFS_VNODE_LOCK_WAITING_FOR_CB;
                goto again;
@@ -413,7 +413,7 @@ static void afs_dequeue_lock(struct afs_vnode *vnode, struct file_lock *fl)
        /* The new front of the queue now owns the state variables. */
        next = list_entry(vnode->pending_locks.next,
                          struct file_lock, fl_u.afs.link);
-       vnode->lock_key = afs_file_key(next->fl_file);
+       vnode->lock_key = key_get(afs_file_key(next->fl_file));
        vnode->lock_type = (next->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
        vnode->lock_state = AFS_VNODE_LOCK_WAITING_FOR_CB;
        afs_lock_may_be_available(vnode);
index 6b17d362041426967dd5fdc875a80c46d4e30742..1a4ce07fb406da8e3a4e0d12c6fda605636ccb47 100644 (file)
@@ -414,7 +414,6 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
        } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                valid = true;
        } else {
-               vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
                vnode->cb_v_break = vnode->volume->cb_v_break;
                valid = false;
        }
@@ -546,6 +545,8 @@ void afs_evict_inode(struct inode *inode)
 #endif
 
        afs_put_permits(rcu_access_pointer(vnode->permit_cache));
+       key_put(vnode->lock_key);
+       vnode->lock_key = NULL;
        _leave("");
 }
 
index 07bc10f076aacface0263e67f5dd994c61bdfa3a..d443e2bfa0946e5845ea65af121a5e34ea3f2270 100644 (file)
@@ -161,3 +161,14 @@ struct yfs_xdr_YFSStoreVolumeStatus {
        struct yfs_xdr_u64      max_quota;
        struct yfs_xdr_u64      file_quota;
 } __packed;
+
+enum yfs_lock_type {
+       yfs_LockNone            = -1,
+       yfs_LockRead            = 0,
+       yfs_LockWrite           = 1,
+       yfs_LockExtend          = 2,
+       yfs_LockRelease         = 3,
+       yfs_LockMandatoryRead   = 0x100,
+       yfs_LockMandatoryWrite  = 0x101,
+       yfs_LockMandatoryExtend = 0x102,
+};
index a7b44863d502e95cbb28a1f7ed2f2a17d7ba1043..2c588f9bbbda226ec64fa0670e9c92c700f259e6 100644 (file)
@@ -23,6 +23,7 @@ struct workqueue_struct *afs_async_calls;
 static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
 static long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
 static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
+static void afs_delete_async_call(struct work_struct *);
 static void afs_process_async_call(struct work_struct *);
 static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
 static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
@@ -203,20 +204,26 @@ void afs_put_call(struct afs_call *call)
        }
 }
 
+static struct afs_call *afs_get_call(struct afs_call *call,
+                                    enum afs_call_trace why)
+{
+       int u = atomic_inc_return(&call->usage);
+
+       trace_afs_call(call, why, u,
+                      atomic_read(&call->net->nr_outstanding_calls),
+                      __builtin_return_address(0));
+       return call;
+}
+
 /*
  * Queue the call for actual work.
  */
 static void afs_queue_call_work(struct afs_call *call)
 {
        if (call->type->work) {
-               int u = atomic_inc_return(&call->usage);
-
-               trace_afs_call(call, afs_call_trace_work, u,
-                              atomic_read(&call->net->nr_outstanding_calls),
-                              __builtin_return_address(0));
-
                INIT_WORK(&call->work, call->type->work);
 
+               afs_get_call(call, afs_call_trace_work);
                if (!queue_work(afs_wq, &call->work))
                        afs_put_call(call);
        }
@@ -398,6 +405,12 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
                }
        }
 
+       /* If the call is going to be asynchronous, we need an extra ref for
+        * the call to hold itself so the caller need not hang on to its ref.
+        */
+       if (call->async)
+               afs_get_call(call, afs_call_trace_get);
+
        /* create a call */
        rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
                                         (unsigned long)call,
@@ -438,15 +451,17 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
                        goto error_do_abort;
        }
 
-       /* at this point, an async call may no longer exist as it may have
-        * already completed */
-       if (call->async)
+       /* Note that at this point, we may have received the reply or an abort
+        * - and an asynchronous call may already have completed.
+        */
+       if (call->async) {
+               afs_put_call(call);
                return -EINPROGRESS;
+       }
 
        return afs_wait_for_call_to_complete(call, ac);
 
 error_do_abort:
-       call->state = AFS_CALL_COMPLETE;
        if (ret != -ECONNABORTED) {
                rxrpc_kernel_abort_call(call->net->socket, rxcall,
                                        RX_USER_ABORT, ret, "KSD");
@@ -463,8 +478,24 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
 error_kill_call:
        if (call->type->done)
                call->type->done(call);
-       afs_put_call(call);
+
+       /* We need to dispose of the extra ref we grabbed for an async call.
+        * The call, however, might be queued on afs_async_calls and we need to
+        * make sure we don't get any more notifications that might requeue it.
+        */
+       if (call->rxcall) {
+               rxrpc_kernel_end_call(call->net->socket, call->rxcall);
+               call->rxcall = NULL;
+       }
+       if (call->async) {
+               if (cancel_work_sync(&call->async_work))
+                       afs_put_call(call);
+               afs_put_call(call);
+       }
+
        ac->error = ret;
+       call->state = AFS_CALL_COMPLETE;
+       afs_put_call(call);
        _leave(" = %d", ret);
        return ret;
 }
index 95d0761cdb34ef3c0a214693651292ba08b2def1..155dc14caef93e515fa8c887895d52f0164ad6a7 100644 (file)
@@ -42,9 +42,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
                if (vldb->fs_mask[i] & type_mask)
                        nr_servers++;
 
-       slist = kzalloc(sizeof(struct afs_server_list) +
-                       sizeof(struct afs_server_entry) * nr_servers,
-                       GFP_KERNEL);
+       slist = kzalloc(struct_size(slist, servers, nr_servers), GFP_KERNEL);
        if (!slist)
                goto error;
 
index 12658c1363ae41951783049d56b3933f3f3fd43e..5aa57929e8c23559c41b8a875f3ea2db43a364dc 100644 (file)
@@ -803,7 +803,7 @@ int yfs_fs_create_file(struct afs_fs_cursor *fc,
        bp = xdr_encode_YFSFid(bp, &vnode->fid);
        bp = xdr_encode_string(bp, name, namesz);
        bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
-       bp = xdr_encode_u32(bp, 0); /* ViceLockType */
+       bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
        yfs_check_req(call, bp);
 
        afs_use_fs_server(call, fc->cbi);
index b906ff70c90f809ba1d7a4e6f38019c0df4da4e8..aaaaf4d12c7394fe1bb9836516b7b7fc1eb69105 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1436,6 +1436,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
        if (unlikely(!req->ki_filp))
                return -EBADF;
        req->ki_complete = aio_complete_rw;
+       req->private = NULL;
        req->ki_pos = iocb->aio_offset;
        req->ki_flags = iocb_flags(req->ki_filp);
        if (iocb->aio_flags & IOCB_FLAG_RESFD)
index d441244b79df98d23d6e0640466a2db68ffdac6b..28d9c2b1b3bb34f4bc1873a27ac08c1200823b85 100644 (file)
@@ -596,7 +596,6 @@ int autofs_expire_run(struct super_block *sb,
        pkt.len = dentry->d_name.len;
        memcpy(pkt.name, dentry->d_name.name, pkt.len);
        pkt.name[pkt.len] = '\0';
-       dput(dentry);
 
        if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
                ret = -EFAULT;
@@ -609,6 +608,8 @@ int autofs_expire_run(struct super_block *sb,
        complete_all(&ino->expire_complete);
        spin_unlock(&sbi->fs_lock);
 
+       dput(dentry);
+
        return ret;
 }
 
index 0e8ea2d9a2bba20b185ffee82aff9652d1012d0f..078992eee299d0861236518643ee164f838e1e2a 100644 (file)
@@ -266,8 +266,10 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        }
        root_inode = autofs_get_inode(s, S_IFDIR | 0755);
        root = d_make_root(root_inode);
-       if (!root)
+       if (!root) {
+               ret = -ENOMEM;
                goto fail_ino;
+       }
        pipe = NULL;
 
        root->d_fsdata = ino;
index d0078cbb718b4855dc520dbfae91223d499da81a..7cde3f46ad263ab084aafaefa14161902f33d4f1 100644 (file)
@@ -42,14 +42,10 @@ static int load_script(struct linux_binprm *bprm)
        fput(bprm->file);
        bprm->file = NULL;
 
-       for (cp = bprm->buf+2;; cp++) {
-               if (cp >= bprm->buf + BINPRM_BUF_SIZE)
-                       return -ENOEXEC;
-               if (!*cp || (*cp == '\n'))
-                       break;
-       }
+       bprm->buf[BINPRM_BUF_SIZE - 1] = '\0';
+       if ((cp = strchr(bprm->buf, '\n')) == NULL)
+               cp = bprm->buf+BINPRM_BUF_SIZE-1;
        *cp = '\0';
-
        while (cp > bprm->buf) {
                cp--;
                if ((*cp == ' ') || (*cp == '\t'))
index c546cdce77e6df48ab48df9b84f3cb6c20c4d173..58a4c1217fa87d60376771a2c315b8b02d0bff1c 100644 (file)
@@ -104,6 +104,20 @@ void invalidate_bdev(struct block_device *bdev)
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
+static void set_init_blocksize(struct block_device *bdev)
+{
+       unsigned bsize = bdev_logical_block_size(bdev);
+       loff_t size = i_size_read(bdev->bd_inode);
+
+       while (bsize < PAGE_SIZE) {
+               if (size & bsize)
+                       break;
+               bsize <<= 1;
+       }
+       bdev->bd_block_size = bsize;
+       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
+}
+
 int set_blocksize(struct block_device *bdev, int size)
 {
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
@@ -1431,18 +1445,9 @@ EXPORT_SYMBOL(check_disk_change);
 
 void bd_set_size(struct block_device *bdev, loff_t size)
 {
-       unsigned bsize = bdev_logical_block_size(bdev);
-
        inode_lock(bdev->bd_inode);
        i_size_write(bdev->bd_inode, size);
        inode_unlock(bdev->bd_inode);
-       while (bsize < PAGE_SIZE) {
-               if (size & bsize)
-                       break;
-               bsize <<= 1;
-       }
-       bdev->bd_block_size = bsize;
-       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
 }
 EXPORT_SYMBOL(bd_set_size);
 
@@ -1519,8 +1524,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                }
                        }
 
-                       if (!ret)
+                       if (!ret) {
                                bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+                               set_init_blocksize(bdev);
+                       }
 
                        /*
                         * If the device is invalidated, rescan partition
@@ -1555,6 +1562,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                goto out_clear;
                        }
                        bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
+                       set_init_blocksize(bdev);
                }
 
                if (bdev->bd_bdi == &noop_backing_dev_info)
index f64aad61372763188bbbe252864685c862b766c3..5a6c39b44c84f4c2f4e39e09797d213ea0f564e7 100644 (file)
@@ -968,6 +968,48 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static struct extent_buffer *alloc_tree_block_no_bg_flush(
+                                         struct btrfs_trans_handle *trans,
+                                         struct btrfs_root *root,
+                                         u64 parent_start,
+                                         const struct btrfs_disk_key *disk_key,
+                                         int level,
+                                         u64 hint,
+                                         u64 empty_size)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct extent_buffer *ret;
+
+       /*
+        * If we are COWing a node/leaf from the extent, chunk, device or free
+        * space trees, make sure that we do not finish block group creation of
+        * pending block groups. We do this to avoid a deadlock.
+        * COWing can result in allocation of a new chunk, and flushing pending
+        * block groups (btrfs_create_pending_block_groups()) can be triggered
+        * when finishing allocation of a new chunk. Creation of a pending block
+        * group modifies the extent, chunk, device and free space trees,
+        * therefore we could deadlock with ourselves since we are holding a
+        * lock on an extent buffer that btrfs_create_pending_block_groups() may
+        * try to COW later.
+        * For similar reasons, we also need to delay flushing pending block
+        * groups when splitting a leaf or node, from one of those trees, since
+        * we are holding a write lock on it and its parent or when inserting a
+        * new root node for one of those trees.
+        */
+       if (root == fs_info->extent_root ||
+           root == fs_info->chunk_root ||
+           root == fs_info->dev_root ||
+           root == fs_info->free_space_root)
+               trans->can_flush_pending_bgs = false;
+
+       ret = btrfs_alloc_tree_block(trans, root, parent_start,
+                                    root->root_key.objectid, disk_key, level,
+                                    hint, empty_size);
+       trans->can_flush_pending_bgs = true;
+
+       return ret;
+}
+
 /*
  * does the dirty work in cow of a single block.  The parent block (if
  * supplied) is updated to point to the new cow copy.  The new buffer is marked
@@ -1015,28 +1057,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
        if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
                parent_start = parent->start;
 
-       /*
-        * If we are COWing a node/leaf from the extent, chunk, device or free
-        * space trees, make sure that we do not finish block group creation of
-        * pending block groups. We do this to avoid a deadlock.
-        * COWing can result in allocation of a new chunk, and flushing pending
-        * block groups (btrfs_create_pending_block_groups()) can be triggered
-        * when finishing allocation of a new chunk. Creation of a pending block
-        * group modifies the extent, chunk, device and free space trees,
-        * therefore we could deadlock with ourselves since we are holding a
-        * lock on an extent buffer that btrfs_create_pending_block_groups() may
-        * try to COW later.
-        */
-       if (root == fs_info->extent_root ||
-           root == fs_info->chunk_root ||
-           root == fs_info->dev_root ||
-           root == fs_info->free_space_root)
-               trans->can_flush_pending_bgs = false;
-
-       cow = btrfs_alloc_tree_block(trans, root, parent_start,
-                       root->root_key.objectid, &disk_key, level,
-                       search_start, empty_size);
-       trans->can_flush_pending_bgs = true;
+       cow = alloc_tree_block_no_bg_flush(trans, root, parent_start, &disk_key,
+                                          level, search_start, empty_size);
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
@@ -3345,8 +3367,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
        else
                btrfs_node_key(lower, &lower_key, 0);
 
-       c = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                                  &lower_key, level, root->node->start, 0);
+       c = alloc_tree_block_no_bg_flush(trans, root, 0, &lower_key, level,
+                                        root->node->start, 0);
        if (IS_ERR(c))
                return PTR_ERR(c);
 
@@ -3475,8 +3497,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
        mid = (c_nritems + 1) / 2;
        btrfs_node_key(c, &disk_key, mid);
 
-       split = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                       &disk_key, level, c->start, 0);
+       split = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, level,
+                                            c->start, 0);
        if (IS_ERR(split))
                return PTR_ERR(split);
 
@@ -4260,8 +4282,8 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
        else
                btrfs_item_key(l, &disk_key, mid);
 
-       right = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                       &disk_key, 0, l->start, 0);
+       right = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, 0,
+                                            l->start, 0);
        if (IS_ERR(right))
                return PTR_ERR(right);
 
index 0a68cf7032f5ed753b85aa017bcff7a4690005b8..7a2a2621f0d9d7402ab2bfc2b10d9421c96dbbb0 100644 (file)
@@ -35,6 +35,7 @@
 struct btrfs_trans_handle;
 struct btrfs_transaction;
 struct btrfs_pending_snapshot;
+struct btrfs_delayed_ref_root;
 extern struct kmem_cache *btrfs_trans_handle_cachep;
 extern struct kmem_cache *btrfs_bit_radix_cachep;
 extern struct kmem_cache *btrfs_path_cachep;
@@ -786,6 +787,9 @@ enum {
         * main phase. The fs_info::balance_ctl is initialized.
         */
        BTRFS_FS_BALANCE_RUNNING,
+
+       /* Indicate that the cleaner thread is awake and doing something. */
+       BTRFS_FS_CLEANER_RUNNING,
 };
 
 struct btrfs_fs_info {
@@ -2661,6 +2665,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                           unsigned long count);
 int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info,
                                 unsigned long count, u64 transid, int wait);
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_delayed_ref_root *delayed_refs,
+                                 struct btrfs_delayed_ref_head *head);
 int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len);
 int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
                             struct btrfs_fs_info *fs_info, u64 bytenr,
index 8da2f380d3c0e45e83bff51c23b5c8adc88cb049..6a2a2a9517058b429b286557fd0a2b1a512c833d 100644 (file)
@@ -1682,6 +1682,8 @@ static int cleaner_kthread(void *arg)
        while (1) {
                again = 0;
 
+               set_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags);
+
                /* Make the cleaner go to sleep early. */
                if (btrfs_need_cleaner_sleep(fs_info))
                        goto sleep;
@@ -1728,6 +1730,7 @@ static int cleaner_kthread(void *arg)
                 */
                btrfs_delete_unused_bgs(fs_info);
 sleep:
+               clear_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags);
                if (kthread_should_park())
                        kthread_parkme();
                if (kthread_should_stop())
@@ -4201,6 +4204,14 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info)
                spin_lock(&fs_info->ordered_root_lock);
        }
        spin_unlock(&fs_info->ordered_root_lock);
+
+       /*
+        * We need this here because if we've been flipped read-only we won't
+        * get sync() from the umount, so we need to make sure any ordered
+        * extents that haven't had their dirty pages IO start writeout yet
+        * actually get run and error out properly.
+        */
+       btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 }
 
 static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
@@ -4265,6 +4276,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                if (pin_bytes)
                        btrfs_pin_extent(fs_info, head->bytenr,
                                         head->num_bytes, 1);
+               btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
                btrfs_put_delayed_ref_head(head);
                cond_resched();
                spin_lock(&delayed_refs->lock);
index b15afeae16df2fec01c92850b8ff752d98d4fc3a..d81035b7ea7d597e229975691fef48f8813a908a 100644 (file)
@@ -2456,12 +2456,10 @@ static int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans,
        return ret ? ret : 1;
 }
 
-static void cleanup_ref_head_accounting(struct btrfs_trans_handle *trans,
-                                       struct btrfs_delayed_ref_head *head)
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_delayed_ref_root *delayed_refs,
+                                 struct btrfs_delayed_ref_head *head)
 {
-       struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct btrfs_delayed_ref_root *delayed_refs =
-               &trans->transaction->delayed_refs;
        int nr_items = 1;       /* Dropping this ref head update. */
 
        if (head->total_ref_mod < 0) {
@@ -2544,7 +2542,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                }
        }
 
-       cleanup_ref_head_accounting(trans, head);
+       btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
 
        trace_run_delayed_ref_head(fs_info, head, 0);
        btrfs_delayed_ref_unlock(head);
@@ -4954,6 +4952,15 @@ static void flush_space(struct btrfs_fs_info *fs_info,
                        ret = 0;
                break;
        case COMMIT_TRANS:
+               /*
+                * If we have pending delayed iputs then we could free up a
+                * bunch of pinned space, so make sure we run the iputs before
+                * we do our pinned bytes check below.
+                */
+               mutex_lock(&fs_info->cleaner_delayed_iput_mutex);
+               btrfs_run_delayed_iputs(fs_info);
+               mutex_unlock(&fs_info->cleaner_delayed_iput_mutex);
+
                ret = may_commit_transaction(fs_info, space_info);
                break;
        default:
@@ -7188,7 +7195,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
        if (head->must_insert_reserved)
                ret = 1;
 
-       cleanup_ref_head_accounting(trans, head);
+       btrfs_cleanup_ref_head_accounting(trans->fs_info, delayed_refs, head);
        mutex_unlock(&head->mutex);
        btrfs_put_delayed_ref_head(head);
        return ret;
index 43eb4535319de994c0ca240ec8f429658df2bf97..5c349667c761b5fed05a15d565c69eff015709e8 100644 (file)
@@ -3129,9 +3129,6 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
        /* once for the tree */
        btrfs_put_ordered_extent(ordered_extent);
 
-       /* Try to release some metadata so we don't get an OOM but don't wait */
-       btrfs_btree_balance_dirty_nodelay(fs_info);
-
        return ret;
 }
 
@@ -3254,6 +3251,8 @@ void btrfs_add_delayed_iput(struct inode *inode)
        ASSERT(list_empty(&binode->delayed_iput));
        list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs);
        spin_unlock(&fs_info->delayed_iput_lock);
+       if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags))
+               wake_up_process(fs_info->cleaner_kthread);
 }
 
 void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
index c5586ffd1426fce1c5076f8b18e536affa99600b..0a3f122dd61fe1858461c0c760b94b78412f3368 100644 (file)
@@ -1621,6 +1621,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                                flags | SB_RDONLY, device_name, data);
                        if (IS_ERR(mnt_root)) {
                                root = ERR_CAST(mnt_root);
+                               kfree(subvol_name);
                                goto out;
                        }
 
@@ -1630,12 +1631,14 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                        if (error < 0) {
                                root = ERR_PTR(error);
                                mntput(mnt_root);
+                               kfree(subvol_name);
                                goto out;
                        }
                }
        }
        if (IS_ERR(mnt_root)) {
                root = ERR_CAST(mnt_root);
+               kfree(subvol_name);
                goto out;
        }
 
index 127fa1535f584e4dbaf201890e7613eb31e9ec6c..4ec2b660d014fcef0b71650ff23bf140722368d1 100644 (file)
@@ -850,14 +850,6 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_chunk_metadata(trans);
 
-       if (lock && should_end_transaction(trans) &&
-           READ_ONCE(cur_trans->state) == TRANS_STATE_RUNNING) {
-               spin_lock(&info->trans_lock);
-               if (cur_trans->state == TRANS_STATE_RUNNING)
-                       cur_trans->state = TRANS_STATE_BLOCKED;
-               spin_unlock(&info->trans_lock);
-       }
-
        if (lock && READ_ONCE(cur_trans->state) == TRANS_STATE_BLOCKED) {
                if (throttle)
                        return btrfs_commit_transaction(trans);
@@ -1879,6 +1871,21 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
 }
 
+/*
+ * Release reserved delayed ref space of all pending block groups of the
+ * transaction and remove them from the list
+ */
+static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
+{
+       struct btrfs_fs_info *fs_info = trans->fs_info;
+       struct btrfs_block_group_cache *block_group, *tmp;
+
+       list_for_each_entry_safe(block_group, tmp, &trans->new_bgs, bg_list) {
+               btrfs_delayed_refs_rsv_release(fs_info, 1);
+               list_del_init(&block_group->bg_list);
+       }
+}
+
 static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
 {
        /*
@@ -2270,6 +2277,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
        btrfs_scrub_continue(fs_info);
 cleanup_transaction:
        btrfs_trans_release_metadata(trans);
+       btrfs_cleanup_pending_block_groups(trans);
        btrfs_trans_release_chunk_metadata(trans);
        trans->block_rsv = NULL;
        btrfs_warn(fs_info, "Skipping commit of aborted transaction.");
index 3e4f8f88353e163454f0ee953a14f92679cfe7bc..15561926ab32cbc8c0ba8a4006fcb8a45e87e6d5 100644 (file)
@@ -957,11 +957,11 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                else
                        fs_devices = alloc_fs_devices(disk_super->fsid, NULL);
 
-               fs_devices->fsid_change = fsid_change_in_progress;
-
                if (IS_ERR(fs_devices))
                        return ERR_CAST(fs_devices);
 
+               fs_devices->fsid_change = fsid_change_in_progress;
+
                mutex_lock(&fs_devices->device_list_mutex);
                list_add(&fs_devices->fs_list, &fs_uuids);
 
index 52d024bfdbc12142a97ff8ec204ce4b658df6fe6..48318fb74938a458184c7b77598994915474ade7 100644 (file)
@@ -200,6 +200,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
        struct buffer_head *head;
        struct page *page;
        int all_mapped = 1;
+       static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
 
        index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
        page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);
@@ -227,15 +228,15 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
         * file io on the block device and getblk.  It gets dealt with
         * elsewhere, don't buffer_error if we had some unmapped buffers
         */
-       if (all_mapped) {
-               printk("__find_get_block_slow() failed. "
-                       "block=%llu, b_blocknr=%llu\n",
-                       (unsigned long long)block,
-                       (unsigned long long)bh->b_blocknr);
-               printk("b_state=0x%08lx, b_size=%zu\n",
-                       bh->b_state, bh->b_size);
-               printk("device %pg blocksize: %d\n", bdev,
-                       1 << bd_inode->i_blkbits);
+       ratelimit_set_flags(&last_warned, RATELIMIT_MSG_ON_RELEASE);
+       if (all_mapped && __ratelimit(&last_warned)) {
+               printk("__find_get_block_slow() failed. block=%llu, "
+                      "b_blocknr=%llu, b_state=0x%08lx, b_size=%zu, "
+                      "device %pg blocksize: %d\n",
+                      (unsigned long long)block,
+                      (unsigned long long)bh->b_blocknr,
+                      bh->b_state, bh->b_size, bdev,
+                      1 << bd_inode->i_blkbits);
        }
 out_unlock:
        spin_unlock(&bd_mapping->private_lock);
index 94c026bba2c226a4b034ca0db2011aa411726179..bba28a5034ba39e53ce68b32ecad1d03b8d60ba7 100644 (file)
@@ -1035,6 +1035,8 @@ static void drop_inode_snap_realm(struct ceph_inode_info *ci)
        list_del_init(&ci->i_snap_realm_item);
        ci->i_snap_realm_counter++;
        ci->i_snap_realm = NULL;
+       if (realm->ino == ci->i_vino.ino)
+               realm->inode = NULL;
        spin_unlock(&realm->inodes_with_caps_lock);
        ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
                            realm);
index 03f4d24db8fe009dc4384b83162979c34f11d1e0..9455d3aef0c3c1b50f5be96e3a804424e55597b4 100644 (file)
@@ -3,19 +3,6 @@
  * quota.c - CephFS quota
  *
  * Copyright (C) 2017-2018 SUSE
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/statfs.h>
index 593fb422d0f3e63f5e51f95e2f9d7eee25c78c33..e92a2fee3c577bd7fc8c63e3e10edf079ca97686 100644 (file)
@@ -252,6 +252,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
        seq_printf(m, ",ACL");
 #endif
        seq_putc(m, '\n');
+       seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
        seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
        seq_printf(m, "Servers:");
 
index d1f9c2f3f5759f6206aff5f51be30b3891fb3860..7652551a1fc4597bdfc4dc90d1569923b680a5ac 100644 (file)
@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.16"
+#define CIFS_VERSION   "2.17"
 #endif                         /* _CIFSFS_H */
index e18915415e1337dc22e5fca260e9011ac5b1a37e..bb54ccf8481c33937d3dfa6b0a782971112a74fc 100644 (file)
@@ -1549,18 +1549,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server)
 }
 
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+                    bool malformed)
 {
        int length;
-       struct cifs_readdata *rdata = mid->callback_data;
 
        length = cifs_discard_remaining_data(server);
-       dequeue_mid(mid, rdata->result);
+       dequeue_mid(mid, malformed);
        mid->resp_buf = server->smallbuf;
        server->smallbuf = NULL;
        return length;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+       struct cifs_readdata *rdata = mid->callback_data;
+
+       return  __cifs_readv_discard(server, mid, rdata->result);
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1602,12 +1610,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                return -1;
        }
 
+       /* set up first two iov for signature check and to get credits */
+       rdata->iov[0].iov_base = buf;
+       rdata->iov[0].iov_len = 4;
+       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[1].iov_len = server->total_read - 4;
+       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+       cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+                rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
        /* Was the SMB read successful? */
        rdata->result = server->ops->map_error(buf, false);
        if (rdata->result != 0) {
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
-               return cifs_readv_discard(server, mid);
+               /* normal error on read response */
+               return __cifs_readv_discard(server, mid, false);
        }
 
        /* Is there enough to get to the rest of the READ_RSP header? */
@@ -1651,14 +1670,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                server->total_read += length;
        }
 
-       /* set up first iov for signature check */
-       rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->total_read - 4;
-       cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
-                rdata->iov[0].iov_base, server->total_read);
-
        /* how much data is in the response? */
 #ifdef CONFIG_CIFS_SMB_DIRECT
        use_rdma_mr = rdata->mr;
index 683310f261718d3d07088342fde4b89a27bac4bc..8463c940e0e59779390b210fa3ebba45df86f80b 100644 (file)
@@ -720,6 +720,21 @@ server_unresponsive(struct TCP_Server_Info *server)
        return false;
 }
 
+static inline bool
+zero_credits(struct TCP_Server_Info *server)
+{
+       int val;
+
+       spin_lock(&server->req_lock);
+       val = server->credits + server->echo_credits + server->oplock_credits;
+       if (server->in_flight == 0 && val == 0) {
+               spin_unlock(&server->req_lock);
+               return true;
+       }
+       spin_unlock(&server->req_lock);
+       return false;
+}
+
 static int
 cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
 {
@@ -732,6 +747,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
        for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
                try_to_freeze();
 
+               /* reconnect if no credits and no requests in flight */
+               if (zero_credits(server)) {
+                       cifs_reconnect(server);
+                       return -ECONNABORTED;
+               }
+
                if (server_unresponsive(server))
                        return -ECONNABORTED;
                if (cifs_rdma_enabled(server) && server->smbd_conn)
index 2c7689f3998d175bae8886da89ea9c389b5b3ab8..659ce1b92c449a9845922ade79154c4421b5b600 100644 (file)
@@ -2696,6 +2696,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
 
                        rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
                        if (rc) {
+                               kvfree(wdata->pages);
                                kfree(wdata);
                                add_credits_and_wake_if(server, credits, 0);
                                break;
@@ -2707,6 +2708,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
                        if (rc) {
                                for (i = 0; i < nr_pages; i++)
                                        put_page(wdata->pages[i]);
+                               kvfree(wdata->pages);
                                kfree(wdata);
                                add_credits_and_wake_if(server, credits, 0);
                                break;
@@ -3386,8 +3388,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                        }
 
                        rc = cifs_read_allocate_pages(rdata, npages);
-                       if (rc)
-                               goto error;
+                       if (rc) {
+                               kvfree(rdata->pages);
+                               kfree(rdata);
+                               add_credits_and_wake_if(server, credits, 0);
+                               break;
+                       }
 
                        rdata->tailsz = PAGE_SIZE;
                }
@@ -3407,7 +3413,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                if (!rdata->cfile->invalidHandle ||
                    !(rc = cifs_reopen_file(rdata->cfile, true)))
                        rc = server->ops->async_readv(rdata);
-error:
                if (rc) {
                        add_credits_and_wake_if(server, rdata->credits, 0);
                        kref_put(&rdata->refcount,
index f14533da3a9328d459073177e970974a6037f550..01a76bccdb8dfd28c1a0fff2036270bea70f08db 100644 (file)
@@ -293,6 +293,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        int rc;
        struct smb2_file_all_info *smb2_data;
        __u32 create_options = 0;
+       struct cifs_fid fid;
+       bool no_cached_open = tcon->nohandlecache;
 
        *adjust_tz = false;
        *symlink = false;
@@ -301,6 +303,21 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                            GFP_KERNEL);
        if (smb2_data == NULL)
                return -ENOMEM;
+
+       /* If it is a root and its handle is cached then use it */
+       if (!strlen(full_path) && !no_cached_open) {
+               rc = open_shroot(xid, tcon, &fid);
+               if (rc)
+                       goto out;
+               rc = SMB2_query_info(xid, tcon, fid.persistent_fid,
+                                    fid.volatile_fid, smb2_data);
+               close_shroot(&tcon->crfid);
+               if (rc)
+                       goto out;
+               move_smb2_info_to_cifs(data, smb2_data);
+               goto out;
+       }
+
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
index 6a9c47541c53d0983a068703106ddacdbc834e04..7b8b58fb4d3fbdcf898d306a585c7332cd2c0ef5 100644 (file)
@@ -648,6 +648,13 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
        if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
                return false;
 
+       if (rsp->sync_hdr.CreditRequest) {
+               spin_lock(&server->req_lock);
+               server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               spin_unlock(&server->req_lock);
+               wake_up(&server->request_q);
+       }
+
        if (rsp->StructureSize !=
                                smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
                if (le16_to_cpu(rsp->StructureSize) == 44)
index cf7eb891804f6f527b7fd4a7512dfc6d66309042..6f96e22928569e08aa0faab6c49f8941573cf21d 100644 (file)
@@ -34,6 +34,7 @@
 #include "cifs_ioctl.h"
 #include "smbdirect.h"
 
+/* Change credits for different ops and return the total number of credits */
 static int
 change_conf(struct TCP_Server_Info *server)
 {
@@ -41,17 +42,15 @@ change_conf(struct TCP_Server_Info *server)
        server->oplock_credits = server->echo_credits = 0;
        switch (server->credits) {
        case 0:
-               return -1;
+               return 0;
        case 1:
                server->echoes = false;
                server->oplocks = false;
-               cifs_dbg(VFS, "disabling echoes and oplocks\n");
                break;
        case 2:
                server->echoes = true;
                server->oplocks = false;
                server->echo_credits = 1;
-               cifs_dbg(FYI, "disabling oplocks\n");
                break;
        default:
                server->echoes = true;
@@ -64,14 +63,15 @@ change_conf(struct TCP_Server_Info *server)
                server->echo_credits = 1;
        }
        server->credits -= server->echo_credits + server->oplock_credits;
-       return 0;
+       return server->credits + server->echo_credits + server->oplock_credits;
 }
 
 static void
 smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
                 const int optype)
 {
-       int *val, rc = 0;
+       int *val, rc = -1;
+
        spin_lock(&server->req_lock);
        val = server->ops->get_credits_field(server, optype);
 
@@ -101,8 +101,26 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
        }
        spin_unlock(&server->req_lock);
        wake_up(&server->request_q);
-       if (rc)
-               cifs_reconnect(server);
+
+       if (server->tcpStatus == CifsNeedReconnect)
+               return;
+
+       switch (rc) {
+       case -1:
+               /* change_conf hasn't been executed */
+               break;
+       case 0:
+               cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
+               break;
+       case 1:
+               cifs_dbg(VFS, "disabling echoes and oplocks\n");
+               break;
+       case 2:
+               cifs_dbg(FYI, "disabling oplocks\n");
+               break;
+       default:
+               cifs_dbg(FYI, "add %u credits total=%d\n", add, rc);
+       }
 }
 
 static void
@@ -136,7 +154,11 @@ smb2_get_credits(struct mid_q_entry *mid)
 {
        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf;
 
-       return le16_to_cpu(shdr->CreditRequest);
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
+               return le16_to_cpu(shdr->CreditRequest);
+
+       return 0;
 }
 
 static int
@@ -165,14 +187,14 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
 
                        scredits = server->credits;
                        /* can deadlock with reopen */
-                       if (scredits == 1) {
+                       if (scredits <= 8) {
                                *num = SMB2_MAX_BUFFER_SIZE;
                                *credits = 0;
                                break;
                        }
 
-                       /* leave one credit for a possible reopen */
-                       scredits--;
+                       /* leave some credits for reopen and other ops */
+                       scredits -= 8;
                        *num = min_t(unsigned int, size,
                                     scredits * SMB2_MAX_BUFFER_SIZE);
 
@@ -844,7 +866,9 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
                                      FILE_READ_EA,
                                      FILE_FULL_EA_INFORMATION,
                                      SMB2_O_INFO_FILE,
-                                     SMB2_MAX_EA_BUF,
+                                     CIFSMaxBufSize -
+                                     MAX_SMB2_CREATE_RESPONSE_SIZE -
+                                     MAX_SMB2_CLOSE_RESPONSE_SIZE,
                                      &rsp_iov, &buftype, cifs_sb);
        if (rc) {
                /*
@@ -3189,11 +3213,23 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                        server->ops->is_status_pending(buf, server, 0))
                return -1;
 
-       rdata->result = server->ops->map_error(buf, false);
+       /* set up first two iov to get credits */
+       rdata->iov[0].iov_base = buf;
+       rdata->iov[0].iov_len = 4;
+       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[1].iov_len =
+               min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4;
+       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+       cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+                rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
+       rdata->result = server->ops->map_error(buf, true);
        if (rdata->result != 0) {
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
-               dequeue_mid(mid, rdata->result);
+               /* normal error on read response */
+               dequeue_mid(mid, false);
                return 0;
        }
 
@@ -3266,14 +3302,6 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                return 0;
        }
 
-       /* set up first iov for signature check */
-       rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->vals->read_rsp_size - 4;
-       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
-                rdata->iov[0].iov_base, server->vals->read_rsp_size);
-
        length = rdata->copy_into_pages(server, rdata, &iter);
 
        kfree(bvec);
index 50811a7dc0e0c6375fa2cdbe5e6c8474da61a8c4..77b3aaa39b35c0c6dc1c96c8bdf0542fa1bf98bc 100644 (file)
@@ -2816,6 +2816,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        int resp_buftype = CIFS_NO_BUFFER;
        struct cifs_ses *ses = tcon->ses;
        int flags = 0;
+       bool allocated = false;
 
        cifs_dbg(FYI, "Query Info\n");
 
@@ -2855,14 +2856,21 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
                                        "Error %d allocating memory for acl\n",
                                        rc);
                                *dlen = 0;
+                               rc = -ENOMEM;
                                goto qinf_exit;
                        }
+                       allocated = true;
                }
        }
 
        rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
                                        le32_to_cpu(rsp->OutputBufferLength),
                                        &rsp_iov, min_len, *data);
+       if (rc && allocated) {
+               kfree(*data);
+               *data = NULL;
+               *dlen = 0;
+       }
 
 qinf_exit:
        SMB2_query_info_free(&rqst);
@@ -2916,9 +2924,10 @@ smb2_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
        struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
-       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
                credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
 
        DeleteMidQEntry(mid);
@@ -3175,7 +3184,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
        struct TCP_Server_Info *server = tcon->ses->server;
        struct smb2_sync_hdr *shdr =
                                (struct smb2_sync_hdr *)rdata->iov[0].iov_base;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2,
                                 .rq_pages = rdata->pages,
@@ -3214,6 +3223,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
                task_io_account_read(rdata->got_bytes);
                cifs_stats_bytes_read(tcon, rdata->got_bytes);
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(shdr->CreditRequest);
+               /* fall through */
        default:
                if (rdata->result != -ENODATA)
                        rdata->result = -EIO;
@@ -3229,8 +3241,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
                rdata->mr = NULL;
        }
 #endif
-       if (rdata->result)
+       if (rdata->result && rdata->result != -ENODATA) {
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
+               trace_smb3_read_err(0 /* xid */,
+                                   rdata->cfile->fid.persistent_fid,
+                                   tcon->tid, tcon->ses->Suid, rdata->offset,
+                                   rdata->bytes, rdata->result);
+       } else
+               trace_smb3_read_done(0 /* xid */,
+                                    rdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid,
+                                    rdata->offset, rdata->got_bytes);
 
        queue_work(cifsiod_wq, &rdata->work);
        DeleteMidQEntry(mid);
@@ -3305,13 +3326,11 @@ smb2_async_readv(struct cifs_readdata *rdata)
        if (rc) {
                kref_put(&rdata->refcount, cifs_readdata_release);
                cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
-               trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
-       } else
-               trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
+               trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
+                                   io_parms.tcon->tid,
+                                   io_parms.tcon->ses->Suid,
+                                   io_parms.offset, io_parms.length, rc);
+       }
 
        cifs_small_buf_release(buf);
        return rc;
@@ -3355,10 +3374,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                if (rc != -ENODATA) {
                        cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
                        cifs_dbg(VFS, "Send error in read = %d\n", rc);
+                       trace_smb3_read_err(xid, req->PersistentFileId,
+                                           io_parms->tcon->tid, ses->Suid,
+                                           io_parms->offset, io_parms->length,
+                                           rc);
                }
-               trace_smb3_read_err(rc, xid, req->PersistentFileId,
-                                   io_parms->tcon->tid, ses->Suid,
-                                   io_parms->offset, io_parms->length);
                free_rsp_buf(resp_buftype, rsp_iov.iov_base);
                return rc == -ENODATA ? 0 : rc;
        } else
@@ -3399,7 +3419,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
        switch (mid->mid_state) {
        case MID_RESPONSE_RECEIVED:
@@ -3427,6 +3447,9 @@ smb2_writev_callback(struct mid_q_entry *mid)
        case MID_RETRY_NEEDED:
                wdata->result = -EAGAIN;
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               /* fall through */
        default:
                wdata->result = -EIO;
                break;
@@ -3444,8 +3467,17 @@ smb2_writev_callback(struct mid_q_entry *mid)
                wdata->mr = NULL;
        }
 #endif
-       if (wdata->result)
+       if (wdata->result) {
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+               trace_smb3_write_err(0 /* no xid */,
+                                    wdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid, wdata->offset,
+                                    wdata->bytes, wdata->result);
+       } else
+               trace_smb3_write_done(0 /* no xid */,
+                                     wdata->cfile->fid.persistent_fid,
+                                     tcon->tid, tcon->ses->Suid,
+                                     wdata->offset, wdata->bytes);
 
        queue_work(cifsiod_wq, &wdata->work);
        DeleteMidQEntry(mid);
@@ -3587,10 +3619,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
                                     wdata->bytes, rc);
                kref_put(&wdata->refcount, release);
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
-       } else
-               trace_smb3_write_done(0 /* no xid */, req->PersistentFileId,
-                                    tcon->tid, tcon->ses->Suid, wdata->offset,
-                                    wdata->bytes);
+       }
 
 async_writev_out:
        cifs_small_buf_release(req);
@@ -3816,8 +3845,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
                    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
                        srch_inf->endOfSearch = true;
                        rc = 0;
-               }
-               cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+               } else
+                       cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
                goto qdir_exit;
        }
 
@@ -4412,8 +4441,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
        rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
        cifs_small_buf_release(req);
 
-       please_key_low = (__u64 *)req->LeaseKey;
-       please_key_high = (__u64 *)(req->LeaseKey+8);
+       please_key_low = (__u64 *)lease_key;
+       please_key_high = (__u64 *)(lease_key+8);
        if (rc) {
                cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
                trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
index 7a2d0a2255e621f97929cbe2c795f615f963dcd2..538e2299805fe52e4bbc569fe8b42035d289d2e3 100644 (file)
@@ -84,8 +84,9 @@
 
 #define NUMBER_OF_SMB2_COMMANDS        0x0013
 
-/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */
-#define MAX_SMB2_HDR_SIZE 0x00b0
+/* 52 transform hdr + 64 hdr + 88 create rsp */
+#define SMB2_TRANSFORM_HEADER_SIZE 52
+#define MAX_SMB2_HDR_SIZE 204
 
 #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
 #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
@@ -648,6 +649,13 @@ struct smb2_create_req {
        __u8   Buffer[0];
 } __packed;
 
+/*
+ * Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
+ * 88 (fixed part of create response) + 520 (path) + 150 (contexts) +
+ * 2 bytes of padding.
+ */
+#define MAX_SMB2_CREATE_RESPONSE_SIZE 824
+
 struct smb2_create_rsp {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize;   /* Must be 89 */
@@ -996,6 +1004,11 @@ struct smb2_close_req {
        __u64  VolatileFileId; /* opaque endianness */
 } __packed;
 
+/*
+ * Maximum size of a SMB2_CLOSE response is 64 (smb2 header) + 60 (data)
+ */
+#define MAX_SMB2_CLOSE_RESPONSE_SIZE 124
+
 struct smb2_close_rsp {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize; /* 60 */
@@ -1398,8 +1411,6 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
        char   FileName[0];     /* Name to be assigned to new link */
 } __packed; /* level 11 Set */
 
-#define SMB2_MAX_EA_BUF 65536
-
 struct smb2_file_full_ea_info { /* encoding of response for level 15 */
        __le32 next_entry_offset;
        __u8   flags;
index bd4a546feec1afb25e13b27f564d78577fe5ec76..4654837871934fe8dd099739660f0a49ef9a10af 100644 (file)
@@ -3,16 +3,6 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
  */
 #define CREATE_TRACE_POINTS
 #include "trace.h"
index fb049809555fea9b3e2cc072b735ac0adfdfe1ae..59be48206932a6fb3051ef6b62bb424cd048513b 100644 (file)
@@ -3,16 +3,6 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM cifs
index 202e0e84efdd7dfa7dff0501c1e9d3861f986afd..53532bd3f50d3d66886cd2465f6cbb0fed498e06 100644 (file)
@@ -786,17 +786,8 @@ static void
 cifs_compound_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->server;
-       unsigned int optype = mid->optype;
-       unsigned int credits_received = 0;
 
-       if (mid->mid_state == MID_RESPONSE_RECEIVED) {
-               if (mid->resp_buf)
-                       credits_received = server->ops->get_credits(mid);
-               else
-                       cifs_dbg(FYI, "Bad state for cancelled MID\n");
-       }
-
-       add_credits(server, credits_received, optype);
+       add_credits(server, server->ops->get_credits(mid), mid->optype);
 }
 
 static void
index 2593153471cf71bb232bc42e73baea2c0bc5615c..aac41adf474336ba11488cc025e1e8d46afd0e32 100644 (file)
@@ -119,6 +119,7 @@ struct dentry_stat_t dentry_stat = {
 
 static DEFINE_PER_CPU(long, nr_dentry);
 static DEFINE_PER_CPU(long, nr_dentry_unused);
+static DEFINE_PER_CPU(long, nr_dentry_negative);
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
 
@@ -152,11 +153,22 @@ static long get_nr_dentry_unused(void)
        return sum < 0 ? 0 : sum;
 }
 
+static long get_nr_dentry_negative(void)
+{
+       int i;
+       long sum = 0;
+
+       for_each_possible_cpu(i)
+               sum += per_cpu(nr_dentry_negative, i);
+       return sum < 0 ? 0 : sum;
+}
+
 int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
                   size_t *lenp, loff_t *ppos)
 {
        dentry_stat.nr_dentry = get_nr_dentry();
        dentry_stat.nr_unused = get_nr_dentry_unused();
+       dentry_stat.nr_negative = get_nr_dentry_negative();
        return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -317,6 +329,8 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry)
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        WRITE_ONCE(dentry->d_flags, flags);
        dentry->d_inode = NULL;
+       if (dentry->d_flags & DCACHE_LRU_LIST)
+               this_cpu_inc(nr_dentry_negative);
 }
 
 static void dentry_free(struct dentry *dentry)
@@ -371,6 +385,11 @@ static void dentry_unlink_inode(struct dentry * dentry)
  * The per-cpu "nr_dentry_unused" counters are updated with
  * the DCACHE_LRU_LIST bit.
  *
+ * The per-cpu "nr_dentry_negative" counters are only updated
+ * when deleted from or added to the per-superblock LRU list, not
+ * from/to the shrink list. That is to avoid an unneeded dec/inc
+ * pair when moving from LRU to shrink list in select_collect().
+ *
  * These helper functions make sure we always follow the
  * rules. d_lock must be held by the caller.
  */
@@ -380,6 +399,8 @@ static void d_lru_add(struct dentry *dentry)
        D_FLAG_VERIFY(dentry, 0);
        dentry->d_flags |= DCACHE_LRU_LIST;
        this_cpu_inc(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_inc(nr_dentry_negative);
        WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -388,6 +409,8 @@ static void d_lru_del(struct dentry *dentry)
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -418,6 +441,8 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry)
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        list_lru_isolate(lru, &dentry->d_lru);
 }
 
@@ -426,6 +451,8 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
 {
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags |= DCACHE_SHRINK_LIST;
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        list_lru_isolate_move(lru, &dentry->d_lru, list);
 }
 
@@ -1188,15 +1215,11 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
  */
 void shrink_dcache_sb(struct super_block *sb)
 {
-       long freed;
-
        do {
                LIST_HEAD(dispose);
 
-               freed = list_lru_walk(&sb->s_dentry_lru,
+               list_lru_walk(&sb->s_dentry_lru,
                        dentry_lru_isolate_shrink, &dispose, 1024);
-
-               this_cpu_sub(nr_dentry_unused, freed);
                shrink_dentry_list(&dispose);
        } while (list_lru_count(&sb->s_dentry_lru) > 0);
 }
@@ -1820,6 +1843,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        WARN_ON(d_in_lookup(dentry));
 
        spin_lock(&dentry->d_lock);
+       /*
+        * Decrement negative dentry count if it was in the LRU list.
+        */
+       if (dentry->d_flags & DCACHE_LRU_LIST)
+               this_cpu_dec(nr_dentry_negative);
        hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
        raw_write_seqcount_begin(&dentry->d_seq);
        __d_set_inode_and_type(dentry, inode, add_flags);
index 13b01351dd1cb3f8381dbddd2ee70717792b9ac7..29c68c5d44d5f179c17676c83be04ed1a3ade190 100644 (file)
@@ -324,7 +324,7 @@ static struct dentry *failed_creating(struct dentry *dentry)
        inode_unlock(d_inode(dentry->d_parent));
        dput(dentry);
        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-       return NULL;
+       return ERR_PTR(-ENOMEM);
 }
 
 static struct dentry *end_creating(struct dentry *dentry)
@@ -347,7 +347,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
        dentry = start_creating(name, parent);
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -386,7 +386,8 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -464,7 +465,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -495,7 +497,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -506,7 +509,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
        struct inode *inode;
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -545,7 +548,7 @@ struct dentry *debugfs_create_automount(const char *name,
        struct inode *inode;
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -581,8 +584,8 @@ EXPORT_SYMBOL(debugfs_create_automount);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the symbolic
  * link is to be removed (no automatic cleanup happens if your module is
- * unloaded, you are responsible here.)  If an error occurs, %NULL will be
- * returned.
+ * unloaded, you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR)
+ * will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -594,12 +597,12 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
        struct inode *inode;
        char *link = kstrdup(target, GFP_KERNEL);
        if (!link)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        dentry = start_creating(name, parent);
        if (IS_ERR(dentry)) {
                kfree(link);
-               return NULL;
+               return dentry;
        }
 
        inode = debugfs_get_inode(dentry->d_sb);
@@ -787,6 +790,13 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
        struct dentry *dentry = NULL, *trap;
        struct name_snapshot old_name;
 
+       if (IS_ERR(old_dir))
+               return old_dir;
+       if (IS_ERR(new_dir))
+               return new_dir;
+       if (IS_ERR_OR_NULL(old_dentry))
+               return old_dentry;
+
        trap = lock_rename(new_dir, old_dir);
        /* Source or destination directories don't exist? */
        if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
@@ -820,7 +830,9 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
        if (dentry && !IS_ERR(dentry))
                dput(dentry);
        unlock_rename(new_dir, old_dir);
-       return NULL;
+       if (IS_ERR(dentry))
+               return dentry;
+       return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(debugfs_rename);
 
index dbc1a1f080ceb231f0553ff270ee7663a5479bfd..ec2fb6fe6d37c628d5335b7a0971b464824b0623 100644 (file)
@@ -679,6 +679,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
        unsigned long fs_count; /* Number of filesystem-sized blocks */
        int create;
        unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
+       loff_t i_size;
 
        /*
         * If there was a memory error and we've overwritten all the
@@ -708,8 +709,8 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
                 */
                create = dio->op == REQ_OP_WRITE;
                if (dio->flags & DIO_SKIP_HOLES) {
-                       if (fs_startblk <= ((i_size_read(dio->inode) - 1) >>
-                                                       i_blkbits))
+                       i_size = i_size_read(dio->inode);
+                       if (i_size && fs_startblk <= (i_size - 1) >> i_blkbits)
                                create = 0;
                }
 
index 82377017130f0137a4208e0082bb61946cc0b817..d31b6c72b47646fd8ae2ebd3746de307f8017fa0 100644 (file)
@@ -21,8 +21,13 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
                spin_lock(&inode->i_lock);
+               /*
+                * We must skip inodes in unusual state. We may also skip
+                * inodes without pages but we deliberately won't in case
+                * we need to reschedule to avoid softlockups.
+                */
                if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
-                   (inode->i_mapping->nrpages == 0)) {
+                   (inode->i_mapping->nrpages == 0 && !need_resched())) {
                        spin_unlock(&inode->i_lock);
                        continue;
                }
@@ -30,6 +35,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
                spin_unlock(&inode->i_lock);
                spin_unlock(&sb->s_inode_list_lock);
 
+               cond_resched();
                invalidate_mapping_pages(inode->i_mapping, 0, -1);
                iput(toput_inode);
                toput_inode = inode;
index 712f00995390ee021249bb6f8478db30f0f8f3bb..5508baa11bb669545724b998af92d9a0375af054 100644 (file)
@@ -116,16 +116,8 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                goto out;
        }
 
-       ret = file_write_and_wait_range(file, start, end);
-       if (ret)
-               return ret;
-
        if (!journal) {
-               struct writeback_control wbc = {
-                       .sync_mode = WB_SYNC_ALL
-               };
-
-               ret = ext4_write_inode(inode, &wbc);
+               ret = __generic_file_fsync(file, start, end, datasync);
                if (!ret)
                        ret = ext4_sync_parent(inode);
                if (test_opt(inode->i_sb, BARRIER))
@@ -133,6 +125,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                goto out;
        }
 
+       ret = file_write_and_wait_range(file, start, end);
+       if (ret)
+               return ret;
        /*
         * data=writeback,ordered:
         *  The caller's filemap_fdatawrite()/wait will sync the data.
index b40168fcc94a6ae6383600b443e67163f820abbb..36855c1f8dafdce42422e0b31ce806d6d9973979 100644 (file)
@@ -331,11 +331,22 @@ struct inode_switch_wbs_context {
        struct work_struct      work;
 };
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+       down_write(&bdi->wb_switch_rwsem);
+}
+
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+       up_write(&bdi->wb_switch_rwsem);
+}
+
 static void inode_switch_wbs_work_fn(struct work_struct *work)
 {
        struct inode_switch_wbs_context *isw =
                container_of(work, struct inode_switch_wbs_context, work);
        struct inode *inode = isw->inode;
+       struct backing_dev_info *bdi = inode_to_bdi(inode);
        struct address_space *mapping = inode->i_mapping;
        struct bdi_writeback *old_wb = inode->i_wb;
        struct bdi_writeback *new_wb = isw->new_wb;
@@ -343,6 +354,12 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
        struct page *page;
        bool switched = false;
 
+       /*
+        * If @inode switches cgwb membership while sync_inodes_sb() is
+        * being issued, sync_inodes_sb() might miss it.  Synchronize.
+        */
+       down_read(&bdi->wb_switch_rwsem);
+
        /*
         * By the time control reaches here, RCU grace period has passed
         * since I_WB_SWITCH assertion and all wb stat update transactions
@@ -428,6 +445,8 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
        spin_unlock(&new_wb->list_lock);
        spin_unlock(&old_wb->list_lock);
 
+       up_read(&bdi->wb_switch_rwsem);
+
        if (switched) {
                wb_wakeup(new_wb);
                wb_put(old_wb);
@@ -468,9 +487,18 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
        if (inode->i_state & I_WB_SWITCH)
                return;
 
+       /*
+        * Avoid starting new switches while sync_inodes_sb() is in
+        * progress.  Otherwise, if the down_write protected issue path
+        * blocks heavily, we might end up starting a large number of
+        * switches which will block on the rwsem.
+        */
+       if (!down_read_trylock(&bdi->wb_switch_rwsem))
+               return;
+
        isw = kzalloc(sizeof(*isw), GFP_ATOMIC);
        if (!isw)
-               return;
+               goto out_unlock;
 
        /* find and pin the new wb */
        rcu_read_lock();
@@ -504,12 +532,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
         * Let's continue after I_WB_SWITCH is guaranteed to be visible.
         */
        call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
-       return;
+       goto out_unlock;
 
 out_free:
        if (isw->new_wb)
                wb_put(isw->new_wb);
        kfree(isw);
+out_unlock:
+       up_read(&bdi->wb_switch_rwsem);
 }
 
 /**
@@ -887,6 +917,9 @@ fs_initcall(cgroup_writeback_init);
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+
 static struct bdi_writeback *
 locked_inode_to_wb_and_lock_list(struct inode *inode)
        __releases(&inode->i_lock)
@@ -2413,8 +2446,11 @@ void sync_inodes_sb(struct super_block *sb)
                return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
+       /* protect against inode wb switch, see inode_switch_wbs_work_fn() */
+       bdi_down_write_wb_switch_rwsem(bdi);
        bdi_split_work_to_wbs(bdi, &work, false);
        wb_wait_for_completion(bdi, &done);
+       bdi_up_write_wb_switch_rwsem(bdi);
 
        wait_sb_inodes(sb);
 }
index a5e516a40e7a359cdae8b2bf289175e971b6e6c9..809c0f2f9942e372d67ddd7e45e6cee2b344414b 100644 (file)
@@ -1742,7 +1742,6 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        req->in.h.nodeid = outarg->nodeid;
        req->in.numargs = 2;
        req->in.argpages = 1;
-       req->page_descs[0].offset = offset;
        req->end = fuse_retrieve_end;
 
        index = outarg->offset >> PAGE_SHIFT;
@@ -1757,6 +1756,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 
                this_num = min_t(unsigned, num, PAGE_SIZE - offset);
                req->pages[req->num_pages] = page;
+               req->page_descs[req->num_pages].offset = offset;
                req->page_descs[req->num_pages].length = this_num;
                req->num_pages++;
 
@@ -2077,8 +2077,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
        ret = fuse_dev_do_write(fud, &cs, len);
 
+       pipe_lock(pipe);
        for (idx = 0; idx < nbuf; idx++)
                pipe_buf_release(pipe, &bufs[idx]);
+       pipe_unlock(pipe);
 
 out:
        kvfree(bufs);
index ffaffe18352a1bb53708f3ac2c0f2638a24337ab..a59c16bd90accaa2f49d924fd232dfd265be1f98 100644 (file)
@@ -1782,7 +1782,7 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
                spin_unlock(&fc->lock);
 
                dec_wb_stat(&bdi->wb, WB_WRITEBACK);
-               dec_node_page_state(page, NR_WRITEBACK_TEMP);
+               dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP);
                wb_writeout_inc(&bdi->wb);
                fuse_writepage_free(fc, new_req);
                fuse_request_free(new_req);
index 76baaa6be3934eef20c1c2a327a4f3b10c9bffed..c2d4099429be0d73c32c87a82dc1a939e89d009b 100644 (file)
@@ -628,6 +628,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns)
        get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
        fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
        fc->user_ns = get_user_ns(user_ns);
+       fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
@@ -1162,7 +1163,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
        fc->max_read = max_t(unsigned, 4096, d.max_read);
-       fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
 
        /* Used by get_root_inode() */
        sb->s_fs_info = fc;
index f15b4c57c4bd72b6ee112d1fa5936042f8229e26..78510ab9183563e14c0c6de60761f87fdd234180 100644 (file)
@@ -28,7 +28,6 @@
 #include "util.h"
 #include "trans.h"
 #include "dir.h"
-#include "lops.h"
 
 struct workqueue_struct *gfs2_freeze_wq;
 
index 5bfaf381921a1d7b8e99d6f3b931359579103a8d..b8830fda51e8f118f30ca02ee1ac9d6e2b19d8c0 100644 (file)
@@ -733,7 +733,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
        lh->lh_crc = cpu_to_be32(crc);
 
        gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
-       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE | op_flags);
+       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, op_flags);
        log_flush_wait(sdp);
 }
 
@@ -810,7 +810,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 
        gfs2_ordered_write(sdp);
        lops_before_commit(sdp, tr);
-       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE);
+       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, 0);
 
        if (sdp->sd_log_head != sdp->sd_log_flush_head) {
                log_flush_wait(sdp);
index 94dcab655bc0211ddffd934886850e3c808903c3..2295042bc6259887c87bfcb786e5d4bfc511662c 100644 (file)
@@ -17,9 +17,7 @@
 #include <linux/bio.h>
 #include <linux/fs.h>
 #include <linux/list_sort.h>
-#include <linux/blkdev.h>
 
-#include "bmap.h"
 #include "dir.h"
 #include "gfs2.h"
 #include "incore.h"
@@ -195,6 +193,7 @@ static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec,
 /**
  * gfs2_end_log_write - end of i/o to the log
  * @bio: The bio
+ * @error: Status of i/o request
  *
  * Each bio_vec contains either data from the pagecache or data
  * relating to the log itself. Here we iterate over the bio_vec
@@ -231,19 +230,20 @@ static void gfs2_end_log_write(struct bio *bio)
 /**
  * gfs2_log_submit_bio - Submit any pending log bio
  * @biop: Address of the bio pointer
- * @opf: REQ_OP | op_flags
+ * @op: REQ_OP
+ * @op_flags: req_flag_bits
  *
  * Submit any pending part-built or full bio to the block device. If
  * there is no pending bio, then this is a no-op.
  */
 
-void gfs2_log_submit_bio(struct bio **biop, int opf)
+void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags)
 {
        struct bio *bio = *biop;
        if (bio) {
                struct gfs2_sbd *sdp = bio->bi_private;
                atomic_inc(&sdp->sd_log_in_flight);
-               bio->bi_opf = opf;
+               bio_set_op_attrs(bio, op, op_flags);
                submit_bio(bio);
                *biop = NULL;
        }
@@ -304,7 +304,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
                nblk >>= sdp->sd_fsb2bb_shift;
                if (blkno == nblk && !flush)
                        return bio;
-               gfs2_log_submit_bio(biop, op);
+               gfs2_log_submit_bio(biop, op, 0);
        }
 
        *biop = gfs2_log_alloc_bio(sdp, blkno, end_io);
@@ -375,184 +375,6 @@ void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
                       gfs2_log_bmap(sdp));
 }
 
-/**
- * gfs2_end_log_read - end I/O callback for reads from the log
- * @bio: The bio
- *
- * Simply unlock the pages in the bio. The main thread will wait on them and
- * process them in order as necessary.
- */
-
-static void gfs2_end_log_read(struct bio *bio)
-{
-       struct page *page;
-       struct bio_vec *bvec;
-       int i;
-
-       bio_for_each_segment_all(bvec, bio, i) {
-               page = bvec->bv_page;
-               if (bio->bi_status) {
-                       int err = blk_status_to_errno(bio->bi_status);
-
-                       SetPageError(page);
-                       mapping_set_error(page->mapping, err);
-               }
-               unlock_page(page);
-       }
-
-       bio_put(bio);
-}
-
-/**
- * gfs2_jhead_pg_srch - Look for the journal head in a given page.
- * @jd: The journal descriptor
- * @page: The page to look in
- *
- * Returns: 1 if found, 0 otherwise.
- */
-
-static bool gfs2_jhead_pg_srch(struct gfs2_jdesc *jd,
-                             struct gfs2_log_header_host *head,
-                             struct page *page)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct gfs2_log_header_host uninitialized_var(lh);
-       void *kaddr = kmap_atomic(page);
-       unsigned int offset;
-       bool ret = false;
-
-       for (offset = 0; offset < PAGE_SIZE; offset += sdp->sd_sb.sb_bsize) {
-               if (!__get_log_header(sdp, kaddr + offset, 0, &lh)) {
-                       if (lh.lh_sequence > head->lh_sequence)
-                               *head = lh;
-                       else {
-                               ret = true;
-                               break;
-                       }
-               }
-       }
-       kunmap_atomic(kaddr);
-       return ret;
-}
-
-/**
- * gfs2_jhead_process_page - Search/cleanup a page
- * @jd: The journal descriptor
- * @index: Index of the page to look into
- * @done: If set, perform only cleanup, else search and set if found.
- *
- * Find the page with 'index' in the journal's mapping. Search the page for
- * the journal head if requested (cleanup == false). Release refs on the
- * page so the page cache can reclaim it (put_page() twice). We grabbed a
- * reference on this page two times, first when we did a find_or_create_page()
- * to obtain the page to add it to the bio and second when we do a
- * find_get_page() here to get the page to wait on while I/O on it is being
- * completed.
- * This function is also used to free up a page we might've grabbed but not
- * used. Maybe we added it to a bio, but not submitted it for I/O. Or we
- * submitted the I/O, but we already found the jhead so we only need to drop
- * our references to the page.
- */
-
-static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
-                                   struct gfs2_log_header_host *head,
-                                   bool *done)
-{
-       struct page *page;
-
-       page = find_get_page(jd->jd_inode->i_mapping, index);
-       wait_on_page_locked(page);
-
-       if (PageError(page))
-               *done = true;
-
-       if (!*done)
-               *done = gfs2_jhead_pg_srch(jd, head, page);
-
-       put_page(page); /* Once for find_get_page */
-       put_page(page); /* Once more for find_or_create_page */
-}
-
-/**
- * gfs2_find_jhead - find the head of a log
- * @jd: The journal descriptor
- * @head: The log descriptor for the head of the log is returned here
- *
- * Do a search of a journal by reading it in large chunks using bios and find
- * the valid log entry with the highest sequence number.  (i.e. the log head)
- *
- * Returns: 0 on success, errno otherwise
- */
-
-int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct address_space *mapping = jd->jd_inode->i_mapping;
-       struct gfs2_journal_extent *je;
-       u32 block, read_idx = 0, submit_idx = 0, index = 0;
-       int shift = PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift;
-       int blocks_per_page = 1 << shift, sz, ret = 0;
-       struct bio *bio = NULL;
-       struct page *page;
-       bool done = false;
-       errseq_t since;
-
-       memset(head, 0, sizeof(*head));
-       if (list_empty(&jd->extent_list))
-               gfs2_map_journal_extents(sdp, jd);
-
-       since = filemap_sample_wb_err(mapping);
-       list_for_each_entry(je, &jd->extent_list, list) {
-               for (block = 0; block < je->blocks; block += blocks_per_page) {
-                       index = (je->lblock + block) >> shift;
-
-                       page = find_or_create_page(mapping, index, GFP_NOFS);
-                       if (!page) {
-                               ret = -ENOMEM;
-                               done = true;
-                               goto out;
-                       }
-
-                       if (bio) {
-                               sz = bio_add_page(bio, page, PAGE_SIZE, 0);
-                               if (sz == PAGE_SIZE)
-                                       goto page_added;
-                               submit_idx = index;
-                               submit_bio(bio);
-                               bio = NULL;
-                       }
-
-                       bio = gfs2_log_alloc_bio(sdp,
-                                                je->dblock + (index << shift),
-                                                gfs2_end_log_read);
-                       bio->bi_opf = REQ_OP_READ;
-                       sz = bio_add_page(bio, page, PAGE_SIZE, 0);
-                       gfs2_assert_warn(sdp, sz == PAGE_SIZE);
-
-page_added:
-                       if (submit_idx <= read_idx + BIO_MAX_PAGES) {
-                               /* Keep at least one bio in flight */
-                               continue;
-                       }
-
-                       gfs2_jhead_process_page(jd, read_idx++, head, &done);
-                       if (done)
-                               goto out;  /* found */
-               }
-       }
-
-out:
-       if (bio)
-               submit_bio(bio);
-       while (read_idx <= index)
-               gfs2_jhead_process_page(jd, read_idx++, head, &done);
-
-       if (!ret)
-               ret = filemap_check_wb_err(mapping, since);
-
-       return ret;
-}
-
 static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type,
                                      u32 ld_length, u32 ld_data1)
 {
index 331160fc568b87ce8fdcc11585542639a8a4b6f6..711c4d89c0639cd0a3b70142070dbcde745ba3f6 100644 (file)
@@ -30,10 +30,8 @@ extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
 extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
                           unsigned size, unsigned offset, u64 blkno);
 extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
-extern void gfs2_log_submit_bio(struct bio **biop, int opf);
+extern void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags);
 extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
-extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
-                          struct gfs2_log_header_host *head);
 
 static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
 {
index 1179763f6370f5064efd6c6001f9b9b9387cc8ef..b041cb8ae383d8fd3642f00e9f2985594573e044 100644 (file)
@@ -41,7 +41,6 @@
 #include "dir.h"
 #include "meta_io.h"
 #include "trace_gfs2.h"
-#include "lops.h"
 
 #define DO 0
 #define UNDO 1
index 7389e445a7a7b82bbb9b0b3f14e65fbf8212c346..2dac430653826b15a1d4f158c167eabdf437b2c3 100644 (file)
@@ -181,6 +181,129 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
        return error;
 }
 
+/**
+ * find_good_lh - find a good log header
+ * @jd: the journal
+ * @blk: the segment to start searching from
+ * @lh: the log header to fill in
+ * @forward: if true search forward in the log, else search backward
+ *
+ * Call get_log_header() to get a log header for a segment, but if the
+ * segment is bad, either scan forward or backward until we find a good one.
+ *
+ * Returns: errno
+ */
+
+static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk,
+                       struct gfs2_log_header_host *head)
+{
+       unsigned int orig_blk = *blk;
+       int error;
+
+       for (;;) {
+               error = get_log_header(jd, *blk, head);
+               if (error <= 0)
+                       return error;
+
+               if (++*blk == jd->jd_blocks)
+                       *blk = 0;
+
+               if (*blk == orig_blk) {
+                       gfs2_consist_inode(GFS2_I(jd->jd_inode));
+                       return -EIO;
+               }
+       }
+}
+
+/**
+ * jhead_scan - make sure we've found the head of the log
+ * @jd: the journal
+ * @head: this is filled in with the log descriptor of the head
+ *
+ * At this point, seg and lh should be either the head of the log or just
+ * before.  Scan forward until we find the head.
+ *
+ * Returns: errno
+ */
+
+static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+{
+       unsigned int blk = head->lh_blkno;
+       struct gfs2_log_header_host lh;
+       int error;
+
+       for (;;) {
+               if (++blk == jd->jd_blocks)
+                       blk = 0;
+
+               error = get_log_header(jd, blk, &lh);
+               if (error < 0)
+                       return error;
+               if (error == 1)
+                       continue;
+
+               if (lh.lh_sequence == head->lh_sequence) {
+                       gfs2_consist_inode(GFS2_I(jd->jd_inode));
+                       return -EIO;
+               }
+               if (lh.lh_sequence < head->lh_sequence)
+                       break;
+
+               *head = lh;
+       }
+
+       return 0;
+}
+
+/**
+ * gfs2_find_jhead - find the head of a log
+ * @jd: the journal
+ * @head: the log descriptor for the head of the log is returned here
+ *
+ * Do a binary search of a journal and find the valid log entry with the
+ * highest sequence number.  (i.e. the log head)
+ *
+ * Returns: errno
+ */
+
+int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+{
+       struct gfs2_log_header_host lh_1, lh_m;
+       u32 blk_1, blk_2, blk_m;
+       int error;
+
+       blk_1 = 0;
+       blk_2 = jd->jd_blocks - 1;
+
+       for (;;) {
+               blk_m = (blk_1 + blk_2) / 2;
+
+               error = find_good_lh(jd, &blk_1, &lh_1);
+               if (error)
+                       return error;
+
+               error = find_good_lh(jd, &blk_m, &lh_m);
+               if (error)
+                       return error;
+
+               if (blk_1 == blk_m || blk_m == blk_2)
+                       break;
+
+               if (lh_1.lh_sequence <= lh_m.lh_sequence)
+                       blk_1 = blk_m;
+               else
+                       blk_2 = blk_m;
+       }
+
+       error = jhead_scan(jd, &lh_1);
+       if (error)
+               return error;
+
+       *head = lh_1;
+
+       return error;
+}
+
 /**
  * foreach_descriptor - go through the active part of the log
  * @jd: the journal
index 99575ab8120294481d7222bbf859adbe92207d12..11d81248be85c001a3f51bc04d5654ce41360e7c 100644 (file)
@@ -27,6 +27,8 @@ extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
 extern int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
 extern void gfs2_revoke_clean(struct gfs2_jdesc *jd);
 
+extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
+                   struct gfs2_log_header_host *head);
 extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait);
 extern void gfs2_recover_func(struct work_struct *work);
 extern int __get_log_header(struct gfs2_sbd *sdp,
index 831d7cb5a49c4bf4fdaa2f208938ecc607d9016b..17a8d3b4399057e18cf8e3ba071187a81390a49c 100644 (file)
@@ -1780,9 +1780,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
                        goto next_iter;
                }
                if (ret == -E2BIG) {
-                       n += rbm->bii - initial_bii;
                        rbm->bii = 0;
                        rbm->offset = 0;
+                       n += (rbm->bii - initial_bii);
                        goto res_covered_end_of_rgrp;
                }
                return ret;
index d4b11c903971cf48ff3c6f1e62cca9e76ad4e884..ca71163ff7cfda20234c434a1932ecbff72ed267 100644 (file)
@@ -45,7 +45,6 @@
 #include "util.h"
 #include "sys.h"
 #include "xattr.h"
-#include "lops.h"
 
 #define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x)
 
index 0cd47fe0dbe51db41233db2cace81b1f64503b32..73432e64f8746179e94bcd580984d78f40da823a 100644 (file)
@@ -730,11 +730,8 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
                return LRU_REMOVED;
        }
 
-       /*
-        * Recently referenced inodes and inodes with many attached pages
-        * get one more pass.
-        */
-       if (inode->i_state & I_REFERENCED || inode->i_data.nrpages > 1) {
+       /* recently referenced inodes get one more pass */
+       if (inode->i_state & I_REFERENCED) {
                inode->i_state &= ~I_REFERENCED;
                spin_unlock(&inode->i_lock);
                return LRU_ROTATE;
index a3088fae567ba3092735667e4f9ac2595a1814b1..897c60215dd1b2906913227158d4ae9d77029a79 100644 (file)
@@ -116,6 +116,12 @@ iomap_page_create(struct inode *inode, struct page *page)
        atomic_set(&iop->read_count, 0);
        atomic_set(&iop->write_count, 0);
        bitmap_zero(iop->uptodate, PAGE_SIZE / SECTOR_SIZE);
+
+       /*
+        * migrate_page_move_mapping() assumes that pages with private data have
+        * their count elevated by 1.
+        */
+       get_page(page);
        set_page_private(page, (unsigned long)iop);
        SetPagePrivate(page);
        return iop;
@@ -132,6 +138,7 @@ iomap_page_release(struct page *page)
        WARN_ON_ONCE(atomic_read(&iop->write_count));
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       put_page(page);
        kfree(iop);
 }
 
@@ -569,8 +576,10 @@ iomap_migrate_page(struct address_space *mapping, struct page *newpage,
 
        if (page_has_private(page)) {
                ClearPagePrivate(page);
+               get_page(newpage);
                set_page_private(newpage, page_private(page));
                set_page_private(page, 0);
+               put_page(page);
                SetPagePrivate(newpage);
        }
 
@@ -1804,6 +1813,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        loff_t pos = iocb->ki_pos, start = pos;
        loff_t end = iocb->ki_pos + count - 1, ret = 0;
        unsigned int flags = IOMAP_DIRECT;
+       bool wait_for_completion = is_sync_kiocb(iocb);
        struct blk_plug plug;
        struct iomap_dio *dio;
 
@@ -1823,7 +1833,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        dio->end_io = end_io;
        dio->error = 0;
        dio->flags = 0;
-       dio->wait_for_completion = is_sync_kiocb(iocb);
 
        dio->submit.iter = iter;
        dio->submit.waiter = current;
@@ -1878,7 +1887,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                dio_warn_stale_pagecache(iocb->ki_filp);
        ret = 0;
 
-       if (iov_iter_rw(iter) == WRITE && !dio->wait_for_completion &&
+       if (iov_iter_rw(iter) == WRITE && !wait_for_completion &&
            !inode->i_sb->s_dio_done_wq) {
                ret = sb_init_dio_done_wq(inode->i_sb);
                if (ret < 0)
@@ -1894,7 +1903,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                if (ret <= 0) {
                        /* magic error code to fall back to buffered I/O */
                        if (ret == -ENOTBLK) {
-                               dio->wait_for_completion = true;
+                               wait_for_completion = true;
                                ret = 0;
                        }
                        break;
@@ -1916,8 +1925,24 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        if (dio->flags & IOMAP_DIO_WRITE_FUA)
                dio->flags &= ~IOMAP_DIO_NEED_SYNC;
 
+       /*
+        * We are about to drop our additional submission reference, which
+        * might be the last reference to the dio.  There are three three
+        * different ways we can progress here:
+        *
+        *  (a) If this is the last reference we will always complete and free
+        *      the dio ourselves.
+        *  (b) If this is not the last reference, and we serve an asynchronous
+        *      iocb, we must never touch the dio after the decrement, the
+        *      I/O completion handler will complete and free it.
+        *  (c) If this is not the last reference, but we serve a synchronous
+        *      iocb, the I/O completion handler will wake us up on the drop
+        *      of the final reference, and we will complete and free it here
+        *      after we got woken by the I/O completion handler.
+        */
+       dio->wait_for_completion = wait_for_completion;
        if (!atomic_dec_and_test(&dio->ref)) {
-               if (!dio->wait_for_completion)
+               if (!wait_for_completion)
                        return -EIOCBQUEUED;
 
                for (;;) {
@@ -1934,9 +1959,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                __set_current_state(TASK_RUNNING);
        }
 
-       ret = iomap_dio_complete(dio);
-
-       return ret;
+       return iomap_dio_complete(dio);
 
 out_free_dio:
        kfree(dio);
index 46d691ba04bc8fdb38b28beca6eb445c50b7443a..45b2322e092d2455b508a8fdc00f5bde0b73c4e9 100644 (file)
@@ -133,15 +133,9 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
                                    struct file *file_out, loff_t pos_out,
                                    size_t count, unsigned int flags)
 {
-       ssize_t ret;
-
        if (file_inode(file_in) == file_inode(file_out))
                return -EINVAL;
-retry:
-       ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
-       if (ret == -EAGAIN)
-               goto retry;
-       return ret;
+       return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
 }
 
 static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
index 22ce3c8a2f463dd64dfba9877baa9071f3e63e22..0570391eaa165cf306d6ec4b31379acfa807b0fb 100644 (file)
@@ -1895,6 +1895,11 @@ static int nfs_parse_devname(const char *dev_name,
        size_t len;
        char *end;
 
+       if (unlikely(!dev_name || !*dev_name)) {
+               dfprintk(MOUNT, "NFS: device name not specified\n");
+               return -EINVAL;
+       }
+
        /* Is the host name protected with square brakcets? */
        if (*dev_name == '[') {
                end = strchr(++dev_name, ']');
index 5a0bbf917a32d45935122f8480d5492b9c65999f..d09c9f878141a5c4213aef1faccb85b979bf4793 100644 (file)
@@ -238,9 +238,9 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
 }
 
 /* A writeback failed: mark the page as bad, and invalidate the page cache */
-static void nfs_set_pageerror(struct page *page)
+static void nfs_set_pageerror(struct address_space *mapping)
 {
-       nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page));
+       nfs_zap_mapping(mapping->host, mapping);
 }
 
 /*
@@ -621,11 +621,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        nfs_set_page_writeback(page);
        WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
-       ret = 0;
+       ret = req->wb_context->error;
        /* If there is a fatal error that covers this write, just exit */
-       if (nfs_error_is_fatal_on_server(req->wb_context->error))
+       if (nfs_error_is_fatal_on_server(ret))
                goto out_launder;
 
+       ret = 0;
        if (!nfs_pageio_add_request(pgio, req)) {
                ret = pgio->pg_error;
                /*
@@ -635,9 +636,9 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                        nfs_context_set_write_error(req->wb_context, ret);
                        if (nfs_error_is_fatal_on_server(ret))
                                goto out_launder;
-               }
+               } else
+                       ret = -EAGAIN;
                nfs_redirty_request(req);
-               ret = -EAGAIN;
        } else
                nfs_add_stats(page_file_mapping(page)->host,
                                NFSIOS_WRITEPAGES, 1);
@@ -993,7 +994,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
                nfs_list_remove_request(req);
                if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) &&
                    (hdr->good_bytes < bytes)) {
-                       nfs_set_pageerror(req->wb_page);
+                       nfs_set_pageerror(page_file_mapping(req->wb_page));
                        nfs_context_set_write_error(req->wb_context, hdr->error);
                        goto remove_req;
                }
@@ -1347,7 +1348,8 @@ int nfs_updatepage(struct file *file, struct page *page,
                unsigned int offset, unsigned int count)
 {
        struct nfs_open_context *ctx = nfs_file_open_context(file);
-       struct inode    *inode = page_file_mapping(page)->host;
+       struct address_space *mapping = page_file_mapping(page);
+       struct inode    *inode = mapping->host;
        int             status = 0;
 
        nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
@@ -1365,7 +1367,7 @@ int nfs_updatepage(struct file *file, struct page *page,
 
        status = nfs_writepage_setup(ctx, page, offset, count);
        if (status < 0)
-               nfs_set_pageerror(page);
+               nfs_set_pageerror(mapping);
        else
                __set_page_dirty_nobuffers(page);
 out:
index b33f9785b756edfa0ab597def3ce3827a5057513..72a7681f404699b89d502102a9c290078900647b 100644 (file)
@@ -1239,8 +1239,8 @@ static __net_init int nfsd_init_net(struct net *net)
        retval = nfsd_idmap_init(net);
        if (retval)
                goto out_idmap_error;
-       nn->nfsd4_lease = 45;   /* default lease time */
-       nn->nfsd4_grace = 45;
+       nn->nfsd4_lease = 90;   /* default lease time */
+       nn->nfsd4_grace = 90;
        nn->somebody_reclaimed = false;
        nn->clverifier_counter = prandom_u32();
        nn->clientid_counter = prandom_u32();
index 9824e32b2f2345312dad32ea207885344313fbb8..7dc98e14655df9af314cfec2f3df1ba3fbb32d10 100644 (file)
@@ -557,9 +557,11 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
        loff_t cloned;
 
        cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0);
+       if (cloned < 0)
+               return nfserrno(cloned);
        if (count && cloned != count)
-               cloned = -EINVAL;
-       return nfserrno(cloned < 0 ? cloned : 0);
+               return nfserrno(-EINVAL);
+       return 0;
 }
 
 ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
index 105576daca4abc35f861e89fc7bafc2b0229223b..798f1253141aee87fe11a1106ada42d33ccaadd2 100644 (file)
@@ -724,8 +724,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
                return -EBADF;
 
        /* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
-       if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
-               return -EINVAL;
+       if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE))) {
+               ret = -EINVAL;
+               goto fput_and_out;
+       }
 
        /* verify that this is indeed an inotify instance */
        if (unlikely(f.file->f_op != &inotify_fops)) {
index 8ae109429a883939ed0241c1e122db7ba857ac1a..e39bac94dead0965733eb779758edfae31aacb81 100644 (file)
@@ -256,7 +256,7 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
                inode = proc_get_inode(dir->i_sb, de);
                if (!inode)
                        return ERR_PTR(-ENOMEM);
-               d_set_d_op(dentry, &proc_misc_dentry_ops);
+               d_set_d_op(dentry, de->proc_dops);
                return d_splice_alias(inode, dentry);
        }
        read_unlock(&proc_subdir_lock);
@@ -429,6 +429,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
        INIT_LIST_HEAD(&ent->pde_openers);
        proc_set_user(ent, (*parent)->uid, (*parent)->gid);
 
+       ent->proc_dops = &proc_misc_dentry_ops;
+
 out:
        return ent;
 }
index 5185d7f6a51ee845fc12c6d49d4497d766af6c23..95b14196f28420934f9fe091854809151e5f39d3 100644 (file)
@@ -44,6 +44,7 @@ struct proc_dir_entry {
        struct completion *pde_unload_completion;
        const struct inode_operations *proc_iops;
        const struct file_operations *proc_fops;
+       const struct dentry_operations *proc_dops;
        union {
                const struct seq_operations *seq_ops;
                int (*single_show)(struct seq_file *, void *);
index d5e0fcb3439e91b8c722b7193c0d8a59e2ecbe98..a7b12435519e048e90abf6bd3250ce8e22da40d0 100644 (file)
@@ -38,6 +38,22 @@ static struct net *get_proc_net(const struct inode *inode)
        return maybe_get_net(PDE_NET(PDE(inode)));
 }
 
+static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       return 0;
+}
+
+static const struct dentry_operations proc_net_dentry_ops = {
+       .d_revalidate   = proc_net_d_revalidate,
+       .d_delete       = always_delete_dentry,
+};
+
+static void pde_force_lookup(struct proc_dir_entry *pde)
+{
+       /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
+       pde->proc_dops = &proc_net_dentry_ops;
+}
+
 static int seq_open_net(struct inode *inode, struct file *file)
 {
        unsigned int state_size = PDE(inode)->state_size;
@@ -90,6 +106,7 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_seq_fops;
        p->seq_ops = ops;
        p->state_size = state_size;
@@ -133,6 +150,7 @@ struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_seq_fops;
        p->seq_ops = ops;
        p->state_size = state_size;
@@ -181,6 +199,7 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_single_fops;
        p->single_show = show;
        return proc_register(parent, p);
@@ -223,6 +242,7 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_single_fops;
        p->single_show = show;
        p->write = write;
index f0ec9edab2f31858c5928b5b425d21192ec60466..85b0ef890b280a8339673b391e058dc68d2fb81c 100644 (file)
@@ -423,7 +423,7 @@ struct mem_size_stats {
 };
 
 static void smaps_account(struct mem_size_stats *mss, struct page *page,
-               bool compound, bool young, bool dirty)
+               bool compound, bool young, bool dirty, bool locked)
 {
        int i, nr = compound ? 1 << compound_order(page) : 1;
        unsigned long size = nr * PAGE_SIZE;
@@ -450,24 +450,31 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
                else
                        mss->private_clean += size;
                mss->pss += (u64)size << PSS_SHIFT;
+               if (locked)
+                       mss->pss_locked += (u64)size << PSS_SHIFT;
                return;
        }
 
        for (i = 0; i < nr; i++, page++) {
                int mapcount = page_mapcount(page);
+               unsigned long pss = (PAGE_SIZE << PSS_SHIFT);
 
                if (mapcount >= 2) {
                        if (dirty || PageDirty(page))
                                mss->shared_dirty += PAGE_SIZE;
                        else
                                mss->shared_clean += PAGE_SIZE;
-                       mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+                       mss->pss += pss / mapcount;
+                       if (locked)
+                               mss->pss_locked += pss / mapcount;
                } else {
                        if (dirty || PageDirty(page))
                                mss->private_dirty += PAGE_SIZE;
                        else
                                mss->private_clean += PAGE_SIZE;
-                       mss->pss += PAGE_SIZE << PSS_SHIFT;
+                       mss->pss += pss;
+                       if (locked)
+                               mss->pss_locked += pss;
                }
        }
 }
@@ -490,6 +497,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
 {
        struct mem_size_stats *mss = walk->private;
        struct vm_area_struct *vma = walk->vma;
+       bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page = NULL;
 
        if (pte_present(*pte)) {
@@ -532,7 +540,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        if (!page)
                return;
 
-       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte));
+       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -541,6 +549,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
 {
        struct mem_size_stats *mss = walk->private;
        struct vm_area_struct *vma = walk->vma;
+       bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page;
 
        /* FOLL_DUMP will return -EFAULT on huge zero page */
@@ -555,7 +564,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
                /* pass */;
        else
                VM_BUG_ON_PAGE(1, page);
-       smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd));
+       smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked);
 }
 #else
 static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
@@ -737,11 +746,8 @@ static void smap_gather_stats(struct vm_area_struct *vma,
                }
        }
 #endif
-
        /* mmap_sem is held in m_start */
        walk_page_vma(vma, &smaps_walk);
-       if (vma->vm_flags & VM_LOCKED)
-               mss->pss_locked += mss->pss;
 }
 
 #define SEQ_PUT_DEC(str, val) \
index 96f7d32cd184a29889892320028e9b09b36b424e..898c8321b343cee6f930b3eb4966c83a574796bb 100644 (file)
@@ -128,7 +128,6 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
                     struct pstore_record *record)
 {
        struct persistent_ram_zone *prz;
-       bool update = (record->type == PSTORE_TYPE_DMESG);
 
        /* Give up if we never existed or have hit the end. */
        if (!przs)
@@ -139,7 +138,7 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
                return NULL;
 
        /* Update old/shadowed buffer. */
-       if (update)
+       if (prz->type == PSTORE_TYPE_DMESG)
                persistent_ram_save_old(prz);
 
        if (!persistent_ram_old_size(prz))
@@ -711,18 +710,15 @@ static int ramoops_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ramoops_platform_data *pdata = dev->platform_data;
+       struct ramoops_platform_data pdata_local;
        struct ramoops_context *cxt = &oops_cxt;
        size_t dump_mem_sz;
        phys_addr_t paddr;
        int err = -EINVAL;
 
        if (dev_of_node(dev) && !pdata) {
-               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-               if (!pdata) {
-                       pr_err("cannot allocate platform data buffer\n");
-                       err = -ENOMEM;
-                       goto fail_out;
-               }
+               pdata = &pdata_local;
+               memset(pdata, 0, sizeof(*pdata));
 
                err = ramoops_parse_dt(pdev, pdata);
                if (err < 0)
index 1c8eecfe52b85688b48fd2507ceeeee18fe64878..6acf1bfa0bfee57e6d5f105e47797c4126d9d88b 100644 (file)
@@ -768,18 +768,23 @@ xrep_findroot_block(
                if (!uuid_equal(&btblock->bb_u.s.bb_uuid,
                                &mp->m_sb.sb_meta_uuid))
                        goto out;
+               /*
+                * Read verifiers can reference b_ops, so we set the pointer
+                * here.  If the verifier fails we'll reset the buffer state
+                * to what it was before we touched the buffer.
+                */
+               bp->b_ops = fab->buf_ops;
                fab->buf_ops->verify_read(bp);
                if (bp->b_error) {
+                       bp->b_ops = NULL;
                        bp->b_error = 0;
                        goto out;
                }
 
                /*
                 * Some read verifiers will (re)set b_ops, so we must be
-                * careful not to blow away any such assignment.
+                * careful not to change b_ops after running the verifier.
                 */
-               if (!bp->b_ops)
-                       bp->b_ops = fab->buf_ops;
        }
 
        /*
index 338b9d9984e04a62d790ae72638017c9ac3329d5..d9048bcea49c5203c6d89186637d63fb33f69c37 100644 (file)
@@ -449,6 +449,7 @@ xfs_map_blocks(
        }
 
        wpc->imap = imap;
+       xfs_trim_extent_eof(&wpc->imap, ip);
        trace_xfs_map_blocks_found(ip, offset, count, wpc->io_type, &imap);
        return 0;
 allocate_blocks:
@@ -459,6 +460,7 @@ xfs_map_blocks(
        ASSERT(whichfork == XFS_COW_FORK || cow_fsb == NULLFILEOFF ||
               imap.br_startoff + imap.br_blockcount <= cow_fsb);
        wpc->imap = imap;
+       xfs_trim_extent_eof(&wpc->imap, ip);
        trace_xfs_map_blocks_alloc(ip, offset, count, wpc->io_type, &imap);
        return 0;
 }
index eedc5e0156ff1cacaf33f18cc3a34a03e6c94311..4f5f2ff3f70f944130f94a674f09f464d2b6c970 100644 (file)
@@ -776,10 +776,26 @@ _xfs_buf_read(
 }
 
 /*
+ * Set buffer ops on an unchecked buffer and validate it, if possible.
+ *
  * If the caller passed in an ops structure and the buffer doesn't have ops
  * assigned, set the ops and use them to verify the contents.  If the contents
  * cannot be verified, we'll clear XBF_DONE.  We assume the buffer has no
  * recorded errors and is already in XBF_DONE state.
+ *
+ * Under normal operations, every in-core buffer must have buffer ops assigned
+ * to them when the buffer is read in from disk so that we can validate the
+ * metadata.
+ *
+ * However, there are two scenarios where one can encounter in-core buffers
+ * that don't have buffer ops.  The first is during log recovery of buffers on
+ * a V4 filesystem, though these buffers are purged at the end of recovery.
+ *
+ * The other is online repair, which tries to match arbitrary metadata blocks
+ * with btree types in order to find the root.  If online repair doesn't match
+ * the buffer with /any/ btree type, the buffer remains in memory in DONE state
+ * with no ops, and a subsequent read_buf call from elsewhere will not set the
+ * ops.  This function helps us fix this situation.
  */
 int
 xfs_buf_ensure_ops(
@@ -1536,8 +1552,7 @@ __xfs_buf_submit(
                xfs_buf_ioerror(bp, -EIO);
                bp->b_flags &= ~XBF_DONE;
                xfs_buf_stale(bp);
-               if (bp->b_flags & XBF_ASYNC)
-                       xfs_buf_ioend(bp);
+               xfs_buf_ioend(bp);
                return -EIO;
        }
 
index b53be41929bec766c4a0c4dc564802a893f89e64..04f7ac345984fa1752529d15b1205505f17a390f 100644 (file)
 #define IMX8MQ_CLK_VPU_G2_ROOT                 241
 
 /* SCCG PLL GATE */
-#define IMX8MQ_SYS1_PLL_OUT                    232
+#define IMX8MQ_SYS1_PLL_OUT                    242
 #define IMX8MQ_SYS2_PLL_OUT                    243
 #define IMX8MQ_SYS3_PLL_OUT                    244
 #define IMX8MQ_DRAM_PLL_OUT                    245
 /* txesc clock */
 #define IMX8MQ_CLK_DSI_IPG_DIV                  256
 
-#define IMX8MQ_CLK_TMU_ROOT                    265
+#define IMX8MQ_CLK_TMU_ROOT                    257
 
 /* Display root clocks */
-#define IMX8MQ_CLK_DISP_AXI_ROOT               266
-#define IMX8MQ_CLK_DISP_APB_ROOT               267
-#define IMX8MQ_CLK_DISP_RTRM_ROOT              268
+#define IMX8MQ_CLK_DISP_AXI_ROOT               258
+#define IMX8MQ_CLK_DISP_APB_ROOT               259
+#define IMX8MQ_CLK_DISP_RTRM_ROOT              260
 
-#define IMX8MQ_CLK_OCOTP_ROOT                  269
+#define IMX8MQ_CLK_OCOTP_ROOT                  261
 
-#define IMX8MQ_CLK_DRAM_ALT_ROOT               270
-#define IMX8MQ_CLK_DRAM_CORE                   271
+#define IMX8MQ_CLK_DRAM_ALT_ROOT               262
+#define IMX8MQ_CLK_DRAM_CORE                   263
 
-#define IMX8MQ_CLK_MU_ROOT                     272
-#define IMX8MQ_VIDEO2_PLL_OUT                  273
+#define IMX8MQ_CLK_MU_ROOT                     264
+#define IMX8MQ_VIDEO2_PLL_OUT                  265
 
-#define IMX8MQ_CLK_CLKO2                       274
+#define IMX8MQ_CLK_CLKO2                       266
 
-#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK  275
+#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK  267
 
-#define IMX8MQ_CLK_END                         276
+#define IMX8MQ_CLK_END                         268
 #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */
index 7b24fc7911465381adf20c59a431f188bcc6fd3f..228a5e234af048ce8388bb02326a16c183fb4444 100644 (file)
@@ -71,7 +71,6 @@
 #define MMP2_CLK_CCIC1_MIX             117
 #define MMP2_CLK_CCIC1_PHY             118
 #define MMP2_CLK_CCIC1_SPHY            119
-#define MMP2_CLK_SP                    120
 
 #define MMP2_NR_CLKS                   200
 #endif
index ad6f55dabd6d72483fa00911a0c6864906188fda..0f2e0fe45ca4bbbd901dc45831c4a73b81658316 100644 (file)
@@ -1,12 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
 /*
- *
  * Copyright (c) 2016 BayLibre, SAS.
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  *
  * Copyright (c) 2017 Amlogic, inc.
  * Author: Yixun Lan <yixun.lan@amlogic.com>
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD)
  */
 
 #ifndef _DT_BINDINGS_AMLOGIC_MESON_AXG_RESET_H
index 4f31f96bbfabd06aad4691366861946fed570bbf..c36c86f1ec9a3ea0d31aba9fed1bf33684ca39bf 100644 (file)
@@ -100,7 +100,7 @@ enum vgic_irq_config {
 };
 
 struct vgic_irq {
-       spinlock_t irq_lock;            /* Protects the content of the struct */
+       raw_spinlock_t irq_lock;        /* Protects the content of the struct */
        struct list_head lpi_list;      /* Used to link all LPIs together */
        struct list_head ap_list;
 
@@ -256,7 +256,7 @@ struct vgic_dist {
        u64                     propbaser;
 
        /* Protects the lpi_list and the count value below. */
-       spinlock_t              lpi_list_lock;
+       raw_spinlock_t          lpi_list_lock;
        struct list_head        lpi_list_head;
        int                     lpi_list_count;
 
@@ -307,7 +307,7 @@ struct vgic_cpu {
        unsigned int used_lrs;
        struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
 
-       spinlock_t ap_list_lock;        /* Protects the ap_list */
+       raw_spinlock_t ap_list_lock;    /* Protects the ap_list */
 
        /*
         * List of IRQs that this VCPU should consider because they are either
index c31157135598150332d3aa193764c39e18f247b2..07e02d6df5ad9f24b262fe2d852e21235de8119f 100644 (file)
@@ -190,6 +190,7 @@ struct backing_dev_info {
        struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
        struct rb_root cgwb_congested_tree; /* their congested states */
        struct mutex cgwb_release_mutex;  /* protect shutdown of wb structs */
+       struct rw_semaphore wb_switch_rwsem; /* no cgwb switch while syncing */
 #else
        struct bdi_writeback_congested *wb_congested;
 #endif
index 7cca5f859a907c16781de6e9a3f4d9067fc7ca38..f3c43519baa74449a8e6df2f0ac6320ddaa8d3f8 100644 (file)
@@ -6,6 +6,7 @@
 
 struct bcma_soc {
        struct bcma_bus bus;
+       struct device *dev;
 };
 
 int __init bcma_host_soc_register(struct bcma_soc *soc);
index 5c7e7f859a2493f58ac65a6f10aee7e611b01458..d66bf5f32610adce133e522b7f3852bd08817ff7 100644 (file)
@@ -287,7 +287,7 @@ enum req_opf {
        REQ_OP_DISCARD          = 3,
        /* securely erase sectors */
        REQ_OP_SECURE_ERASE     = 5,
-       /* seset a zone write pointer */
+       /* reset a zone write pointer */
        REQ_OP_ZONE_RESET       = 6,
        /* write the same sector many times */
        REQ_OP_WRITE_SAME       = 7,
index 8804753805ac554f3b0590b19d43f2509a7aea2c..7bb2d8de9f308e367bcda4a5484f67483f8fc8e5 100644 (file)
@@ -116,7 +116,13 @@ extern void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes);
 
 static inline sector_t blk_rq_trace_sector(struct request *rq)
 {
-       return blk_rq_is_passthrough(rq) ? 0 : blk_rq_pos(rq);
+       /*
+        * Tracing should ignore starting sector for passthrough requests and
+        * requests where starting sector didn't get set.
+        */
+       if (blk_rq_is_passthrough(rq) || blk_rq_pos(rq) == (sector_t)-1)
+               return 0;
+       return blk_rq_pos(rq);
 }
 
 static inline unsigned int blk_rq_trace_nr_sectors(struct request *rq)
index 27b74947cd2bd9de8e9dba3518fc876b2308a528..573cca00a0e6cda76014e8a0610aaaf994a78455 100644 (file)
@@ -172,6 +172,7 @@ struct bpf_verifier_state_list {
 #define BPF_ALU_SANITIZE_SRC           1U
 #define BPF_ALU_SANITIZE_DST           2U
 #define BPF_ALU_NEG_VALUE              (1U << 2)
+#define BPF_ALU_NON_POINTER            (1U << 3)
 #define BPF_ALU_SANITIZE               (BPF_ALU_SANITIZE_SRC | \
                                         BPF_ALU_SANITIZE_DST)
 
index f02cee0225d40afcbb40e8bfc15d49e4a252ecb1..d815622cd31e51da14686c71b8d1907665c1be2f 100644 (file)
@@ -3,13 +3,22 @@
 #define _LINUX_BPFILTER_H
 
 #include <uapi/linux/bpfilter.h>
+#include <linux/umh.h>
 
 struct sock;
 int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
                            unsigned int optlen);
 int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
                            int __user *optlen);
-extern int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
-                                      char __user *optval,
-                                      unsigned int optlen, bool is_set);
+struct bpfilter_umh_ops {
+       struct umh_info info;
+       /* since ip_getsockopt() can run in parallel, serialize access to umh */
+       struct mutex lock;
+       int (*sockopt)(struct sock *sk, int optname,
+                      char __user *optval,
+                      unsigned int optlen, bool is_set);
+       int (*start)(void);
+       bool stop;
+};
+extern struct bpfilter_umh_ops bpfilter_ops;
 #endif
index 39f668d5066b0a8f4228b4d1504ae97760313944..333a6695a918c3dcea8402c054bb7a6069640cb0 100644 (file)
@@ -3,9 +3,8 @@
 #error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead."
 #endif
 
-/* Some compiler specific definitions are overwritten here
- * for Clang compiler
- */
+/* Compiler specific definitions for Clang compiler */
+
 #define uninitialized_var(x) x = *(&(x))
 
 /* same as gcc, this was present in clang-2.6 so we can assume it works
index dd8268f5f5f0a79680a36c5adfaf79ecca81f2b8..e8579412ad214cbfc28124bc5ce1078981d391d9 100644 (file)
        (typeof(ptr)) (__ptr + (off));                                  \
 })
 
-/* Make the optimizer believe the variable can be manipulated arbitrarily. */
-#define OPTIMIZER_HIDE_VAR(var)                                                \
-       __asm__ ("" : "=r" (var) : "0" (var))
-
 /*
  * A trick to suppress uninitialized variable warning without generating any
  * code
index 517bd14e122248f029d27e6dd192b492fe3be93b..b17f3cd18334df3d4958316a52177064ee4248d0 100644 (file)
@@ -5,9 +5,7 @@
 
 #ifdef __ECC
 
-/* Some compiler specific definitions are overwritten here
- * for Intel ECC compiler
- */
+/* Compiler specific definitions for Intel ECC compiler */
 
 #include <asm/intrinsics.h>
 
index fc5004a4b07d7b5b546e07f7d952fd1094892ead..445348facea97d2755f371198ca5730302c3f1ba 100644 (file)
@@ -161,7 +161,9 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #endif
 
 #ifndef OPTIMIZER_HIDE_VAR
-#define OPTIMIZER_HIDE_VAR(var) barrier()
+/* Make the optimizer believe the variable can be manipulated arbitrarily. */
+#define OPTIMIZER_HIDE_VAR(var)                                                \
+       __asm__ ("" : "=r" (var) : "0" (var))
 #endif
 
 /* Not-quite-unique ID. */
index 19f32b0c29af3ded16736b43b33604f910bac3dc..6b318efd8a7428042771b0b83f4e5c5846d46a9d 100644 (file)
@@ -34,6 +34,7 @@
 #ifndef __has_attribute
 # define __has_attribute(x) __GCC4_has_attribute_##x
 # define __GCC4_has_attribute___assume_aligned__      (__GNUC_MINOR__ >= 9)
+# define __GCC4_has_attribute___copy__                0
 # define __GCC4_has_attribute___designated_init__     0
 # define __GCC4_has_attribute___externally_visible__  1
 # define __GCC4_has_attribute___noclone__             1
  */
 #define __attribute_const__             __attribute__((__const__))
 
+/*
+ * Optional: only supported since gcc >= 9
+ * Optional: not supported by clang
+ * Optional: not supported by icc
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute
+ */
+#if __has_attribute(__copy__)
+# define __copy(symbol)                 __attribute__((__copy__(symbol)))
+#else
+# define __copy(symbol)
+#endif
+
 /*
  * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
  * attribute warnings entirely and for good") for more information.
index 218df7f4d3e1df69fda1bab3ee88bbe901eb2194..5041357d0297afdce8b5605970947b34f85e7205 100644 (file)
@@ -180,12 +180,10 @@ enum cpuhp_smt_control {
 #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
 extern enum cpuhp_smt_control cpu_smt_control;
 extern void cpu_smt_disable(bool force);
-extern void cpu_smt_check_topology_early(void);
 extern void cpu_smt_check_topology(void);
 #else
 # define cpu_smt_control               (CPU_SMT_ENABLED)
 static inline void cpu_smt_disable(bool force) { }
-static inline void cpu_smt_check_topology_early(void) { }
 static inline void cpu_smt_check_topology(void) { }
 #endif
 
index ef4b70f64f333ac6c29bd93031a3a80b71c7b439..60996e64c579851accbcf0e70d2aa10f60181179 100644 (file)
@@ -62,9 +62,10 @@ extern const struct qstr slash_name;
 struct dentry_stat_t {
        long nr_dentry;
        long nr_unused;
-       long age_limit;          /* age in seconds */
-       long want_pages;         /* pages requested by system */
-       long dummy[2];
+       long age_limit;         /* age in seconds */
+       long want_pages;        /* pages requested by system */
+       long nr_negative;       /* # of unused negative dentries */
+       long dummy;             /* Reserved for future use */
 };
 extern struct dentry_stat_t dentry_stat;
 
index 45ff763fba76ddad0e0141fca2a5efb2c912b8fa..28604a8d0aa940f862c5cf8a2ce89dd5d6f387a5 100644 (file)
@@ -1198,8 +1198,6 @@ static inline bool efi_enabled(int feature)
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
 
 extern bool efi_is_table_address(unsigned long phys_addr);
-
-extern int efi_apply_persistent_mem_reservations(void);
 #else
 static inline bool efi_enabled(int feature)
 {
@@ -1218,11 +1216,6 @@ static inline bool efi_is_table_address(unsigned long phys_addr)
 {
        return false;
 }
-
-static inline int efi_apply_persistent_mem_reservations(void)
-{
-       return 0;
-}
 #endif
 
 extern int efi_status_to_err(efi_status_t status);
index 7cdd31a6971914c174ed8bcf46c27ceaee54057b..f52ef0ad67816bb82600ad567abc76057e1fe628 100644 (file)
@@ -653,6 +653,7 @@ extern int fb_new_modelist(struct fb_info *info);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
+extern bool fb_center_logo;
 extern struct class *fb_class;
 
 #define for_each_registered_fb(i)              \
index ad106d845b2290a106765b96cab3cdd555dc9211..e532fcc6e4b5a19c0633c7c4d027205b5a3abdc7 100644 (file)
@@ -591,8 +591,8 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
        return qdisc_skb_cb(skb)->data;
 }
 
-static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
-                                      struct sk_buff *skb)
+static inline u32 __bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                        struct sk_buff *skb)
 {
        u8 *cb_data = bpf_skb_cb(skb);
        u8 cb_saved[BPF_SKB_CB_LEN];
@@ -611,15 +611,30 @@ static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
        return res;
 }
 
+static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                      struct sk_buff *skb)
+{
+       u32 res;
+
+       preempt_disable();
+       res = __bpf_prog_run_save_cb(prog, skb);
+       preempt_enable();
+       return res;
+}
+
 static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
                                        struct sk_buff *skb)
 {
        u8 *cb_data = bpf_skb_cb(skb);
+       u32 res;
 
        if (unlikely(prog->cb_access))
                memset(cb_data, 0, BPF_SKB_CB_LEN);
 
-       return BPF_PROG_RUN(prog, skb);
+       preempt_disable();
+       res = BPF_PROG_RUN(prog, skb);
+       preempt_enable();
+       return res;
 }
 
 static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
index 811c77743dad2870282e6c3c85e8f238f8643767..29d8e2cfed0e7b87240a0130fbb00edcb9bc8984 100644 (file)
@@ -1479,11 +1479,12 @@ struct super_block {
        struct user_namespace *s_user_ns;
 
        /*
-        * Keep the lru lists last in the structure so they always sit on their
-        * own individual cachelines.
+        * The list_lru structure is essentially just a pointer to a table
+        * of per-node lru lists, each of which has its own spinlock.
+        * There is no need to put them into separate cachelines.
         */
-       struct list_lru         s_dentry_lru ____cacheline_aligned_in_smp;
-       struct list_lru         s_inode_lru ____cacheline_aligned_in_smp;
+       struct list_lru         s_dentry_lru;
+       struct list_lru         s_inode_lru;
        struct rcu_head         rcu;
        struct work_struct      destroy_work;
 
index 8663f216c563e9023df067c83ec9b6e5fbcbe02b..2d6100edf2049d6195b13f03729ac1165f8c192b 100644 (file)
 
 #ifdef CONFIG_DEBUG_FS
 
+#include <linux/kfifo.h>
+
 #define HID_DEBUG_BUFSIZE 512
+#define HID_DEBUG_FIFOSIZE 512
 
 void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
 void hid_dump_report(struct hid_device *, int , u8 *, int);
@@ -37,11 +40,8 @@ void hid_debug_init(void);
 void hid_debug_exit(void);
 void hid_debug_event(struct hid_device *, char *);
 
-
 struct hid_debug_list {
-       char *hid_debug_buf;
-       int head;
-       int tail;
+       DECLARE_KFIFO_PTR(hid_debug_fifo, char);
        struct fasync_struct *fasync;
        struct hid_device *hdev;
        struct list_head node;
@@ -64,4 +64,3 @@ struct hid_debug_list {
 #endif
 
 #endif
-
index d99287327ef23f630e321d4705da2ef0248a257a..f9707d1dcb584a8bf9cac4d614fef4659bb00b12 100644 (file)
@@ -430,7 +430,7 @@ struct hid_local {
  */
 
 struct hid_collection {
-       struct hid_collection *parent;
+       int parent_idx; /* device->collection */
        unsigned type;
        unsigned usage;
        unsigned level;
@@ -658,7 +658,6 @@ struct hid_parser {
        unsigned int         *collection_stack;
        unsigned int          collection_stack_ptr;
        unsigned int          collection_stack_size;
-       struct hid_collection *active_collection;
        struct hid_device    *device;
        unsigned int          scan_flags;
 };
index f0885cc01db66ba8ff42ac8a02d30eb211865069..dcb6977afce931d2c3407f38c0ed2565b778bdc1 100644 (file)
@@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info {
        u32 bytes_avail_towrite;
 };
 
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-                           struct hv_ring_buffer_debug_info *debug_info);
+
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+                               struct hv_ring_buffer_debug_info *debug_info);
 
 /* Vmbus interface */
 #define vmbus_driver_register(driver)  \
index e7d29ae633cd09d2fb2d0ad6a0094bf9df1cc426..971cf76a78a081d7fc8d96cda096810476169155 100644 (file)
@@ -615,6 +615,7 @@ struct ide_drive_s {
 
        /* current sense rq and buffer */
        bool sense_rq_armed;
+       bool sense_rq_active;
        struct request *sense_rq;
        struct request_sense sense_data;
 
@@ -1219,6 +1220,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
 extern void ide_timer_expiry(struct timer_list *t);
 extern irqreturn_t ide_intr(int irq, void *dev_id);
 extern blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *);
+extern blk_status_t ide_issue_rq(ide_drive_t *, struct request *, bool);
 extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);
index 6756fea18b69f6176bf73c749a977ba15e37d840..e44746de95cdf9193c470d78382797465f39c5ba 100644 (file)
@@ -54,6 +54,7 @@ static inline bool dev_is_mac_header_xmit(const struct net_device *dev)
        case ARPHRD_IPGRE:
        case ARPHRD_VOID:
        case ARPHRD_NONE:
+       case ARPHRD_RAWIP:
                return false;
        default:
                return true;
index c672f34235e74bd47334f5bc97586ca0c42d20f5..4a728dba02e2272d8292bb8e828ab19bbddf16b6 100644 (file)
@@ -260,6 +260,7 @@ struct irq_affinity {
 /**
  * struct irq_affinity_desc - Interrupt affinity descriptor
  * @mask:      cpumask to hold the affinity assignment
+ * @is_managed: 1 if the interrupt is managed internally
  */
 struct irq_affinity_desc {
        struct cpumask  mask;
index 071b4cbdf0104796d962446a759beea76790ff28..c848a7cc502ee54ac1aea1452a23b41c6fb247af 100644 (file)
 #define GITS_TYPER_PLPIS               (1UL << 0)
 #define GITS_TYPER_VLPIS               (1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT        4
-#define GITS_TYPER_ITT_ENTRY_SIZE(r)   ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
+#define GITS_TYPER_ITT_ENTRY_SIZE(r)   ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0xf) + 1)
 #define GITS_TYPER_IDBITS_SHIFT                8
 #define GITS_TYPER_DEVBITS_SHIFT       13
 #define GITS_TYPER_DEVBITS(r)          ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
index 5440f11b0907d33474e4612fcc0dea5374935f15..ad609617aeb87063ecb4fa8090cdced8df8dc74d 100644 (file)
@@ -160,6 +160,7 @@ static inline struct nd_blk_region_desc *to_blk_region_desc(
 }
 
 enum nvdimm_security_state {
+       NVDIMM_SECURITY_ERROR = -1,
        NVDIMM_SECURITY_DISABLED,
        NVDIMM_SECURITY_UNLOCKED,
        NVDIMM_SECURITY_LOCKED,
@@ -234,7 +235,6 @@ static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus,
                        cmd_mask, num_flush, flush_wpq, NULL, NULL);
 }
 
-int nvdimm_security_setup_events(struct nvdimm *nvdimm);
 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
 u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
index 64c41cf455906ab750d042f93410fa0c4c5aded6..859b55b66db2ab5bd6142868e677f2b02bc23ebe 100644 (file)
@@ -29,9 +29,6 @@ extern unsigned long max_pfn;
  */
 extern unsigned long long max_possible_pfn;
 
-#define INIT_MEMBLOCK_REGIONS  128
-#define INIT_PHYSMEM_REGIONS   4
-
 /**
  * enum memblock_flags - definition of memory region attributes
  * @MEMBLOCK_NONE: no special request
index 07da5c6c5ba0fc1de1eac7fb1ccd9ff34e5a0a10..368267c1b71b101f3d1d9927197014e2a24efa85 100644 (file)
@@ -21,14 +21,16 @@ struct vmem_altmap;
  * walkers which rely on the fully initialized page->flags and others
  * should use this rather than pfn_valid && pfn_to_page
  */
-#define pfn_to_online_page(pfn)                                \
-({                                                     \
-       struct page *___page = NULL;                    \
-       unsigned long ___nr = pfn_to_section_nr(pfn);   \
-                                                       \
-       if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr))\
-               ___page = pfn_to_page(pfn);             \
-       ___page;                                        \
+#define pfn_to_online_page(pfn)                                           \
+({                                                                \
+       struct page *___page = NULL;                               \
+       unsigned long ___pfn = pfn;                                \
+       unsigned long ___nr = pfn_to_section_nr(___pfn);           \
+                                                                  \
+       if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr) && \
+           pfn_valid_within(___pfn))                              \
+               ___page = pfn_to_page(___pfn);                     \
+       ___page;                                                   \
 })
 
 /*
index 9a9631f0559e295763105520c1918abd9895b6dd..fc91082d4c357bad552d8eb2578d2da3f16ecef5 100644 (file)
@@ -2790,6 +2790,100 @@ struct ec_response_battery_vendor_param {
        uint32_t value;
 } __packed;
 
+/*****************************************************************************/
+/* Commands for I2S recording on audio codec. */
+
+#define EC_CMD_CODEC_I2S 0x00BC
+
+enum ec_codec_i2s_subcmd {
+       EC_CODEC_SET_SAMPLE_DEPTH = 0x0,
+       EC_CODEC_SET_GAIN = 0x1,
+       EC_CODEC_GET_GAIN = 0x2,
+       EC_CODEC_I2S_ENABLE = 0x3,
+       EC_CODEC_I2S_SET_CONFIG = 0x4,
+       EC_CODEC_I2S_SET_TDM_CONFIG = 0x5,
+       EC_CODEC_I2S_SET_BCLK = 0x6,
+};
+
+enum ec_sample_depth_value {
+       EC_CODEC_SAMPLE_DEPTH_16 = 0,
+       EC_CODEC_SAMPLE_DEPTH_24 = 1,
+};
+
+enum ec_i2s_config {
+       EC_DAI_FMT_I2S = 0,
+       EC_DAI_FMT_RIGHT_J = 1,
+       EC_DAI_FMT_LEFT_J = 2,
+       EC_DAI_FMT_PCM_A = 3,
+       EC_DAI_FMT_PCM_B = 4,
+       EC_DAI_FMT_PCM_TDM = 5,
+};
+
+struct ec_param_codec_i2s {
+       /*
+        * enum ec_codec_i2s_subcmd
+        */
+       uint8_t cmd;
+       union {
+               /*
+                * EC_CODEC_SET_SAMPLE_DEPTH
+                * Value should be one of ec_sample_depth_value.
+                */
+               uint8_t depth;
+
+               /*
+                * EC_CODEC_SET_GAIN
+                * Value should be 0~43 for both channels.
+                */
+               struct ec_param_codec_i2s_set_gain {
+                       uint8_t left;
+                       uint8_t right;
+               } __packed gain;
+
+               /*
+                * EC_CODEC_I2S_ENABLE
+                * 1 to enable, 0 to disable.
+                */
+               uint8_t i2s_enable;
+
+               /*
+                * EC_CODEC_I2S_SET_COFNIG
+                * Value should be one of ec_i2s_config.
+                */
+               uint8_t i2s_config;
+
+               /*
+                * EC_CODEC_I2S_SET_TDM_CONFIG
+                * Value should be one of ec_i2s_config.
+                */
+               struct ec_param_codec_i2s_tdm {
+                       /*
+                        * 0 to 496
+                        */
+                       int16_t ch0_delay;
+                       /*
+                        * -1 to 496
+                        */
+                       int16_t ch1_delay;
+                       uint8_t adjacent_to_ch0;
+                       uint8_t adjacent_to_ch1;
+               } __packed tdm_param;
+
+               /*
+                * EC_CODEC_I2S_SET_BCLK
+                */
+               uint32_t bclk;
+       };
+} __packed;
+
+/*
+ * For subcommand EC_CODEC_GET_GAIN.
+ */
+struct ec_response_codec_gain {
+       uint8_t left;
+       uint8_t right;
+} __packed;
+
 /*****************************************************************************/
 /* System commands */
 
index ab16ad283defa58957200fc4fdb6369e60223c1d..2083fa20821dff3ce2de462add0dacbae3c7b514 100644 (file)
@@ -41,7 +41,7 @@
 #define TCU_TCSR_PRESCALE_LSB          3
 #define TCU_TCSR_PRESCALE_MASK         0x38
 
-#define TCU_TCSR_PWM_SD                BIT(9)  /* 0: Shutdown abruptly 1: gracefully */
+#define TCU_TCSR_PWM_SD                BIT(9)  /* 0: Shutdown gracefully 1: abruptly */
 #define TCU_TCSR_PWM_INITL_HIGH        BIT(8)  /* Sets the initial output level */
 #define TCU_TCSR_PWM_EN                BIT(7)  /* PWM pin output enable */
 
index fe69c0f4398fdf1bc808a541d40dea04afc690a3..4d5d51a9c8a683bf1f49821200f705d8e2f65bd0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/madera/pdata.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
@@ -37,6 +38,8 @@ enum madera_type {
 
 #define MADERA_MAX_MICBIAS             4
 
+#define MADERA_MAX_HP_OUTPUT           3
+
 /* Notifier events */
 #define MADERA_NOTIFY_VOICE_TRIGGER    0x1
 #define MADERA_NOTIFY_HPDET            0x2
@@ -183,6 +186,10 @@ struct madera {
        unsigned int num_childbias[MADERA_MAX_MICBIAS];
 
        struct snd_soc_dapm_context *dapm;
+       struct mutex dapm_ptr_lock;
+       unsigned int hp_ena;
+       bool out_clamp[MADERA_MAX_HP_OUTPUT];
+       bool out_shorted[MADERA_MAX_HP_OUTPUT];
 
        struct blocking_notifier_head notifier;
 };
index b9a53e013bff35e639830130295c065f78ea654e..483168403ae586ea1c662342375afa990ae5b394 100644 (file)
@@ -78,6 +78,8 @@
 #define STEPCONFIG_YNN         BIT(8)
 #define STEPCONFIG_XNP         BIT(9)
 #define STEPCONFIG_YPN         BIT(10)
+#define STEPCONFIG_RFP(val)    ((val) << 12)
+#define STEPCONFIG_RFP_VREFP   (0x3 << 12)
 #define STEPCONFIG_INM_MASK    (0xF << 15)
 #define STEPCONFIG_INM(val)    ((val) << 15)
 #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
@@ -86,6 +88,8 @@
 #define STEPCONFIG_INP_AN4     STEPCONFIG_INP(4)
 #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
 #define STEPCONFIG_FIFO1       BIT(26)
+#define STEPCONFIG_RFM(val)    ((val) << 23)
+#define STEPCONFIG_RFM_VREFN   (0x3 << 23)
 
 /* Delay register */
 #define STEPDELAY_OPEN_MASK    (0x3FFFF << 0)
index e2687a30e5a190edeff1e4e72cdcf9c68576cb84..739b7bf37eaa5aa615d44fee25de958f61cc8f0f 100644 (file)
@@ -79,7 +79,7 @@
 /* Some controllers have a CBSY bit */
 #define TMIO_MMC_HAVE_CBSY             BIT(11)
 
-/* Some controllers that support HS400 use use 4 taps while others use 8. */
+/* Some controllers that support HS400 use 4 taps while others use 8. */
 #define TMIO_MMC_HAVE_4TAP_HS400       BIT(13)
 
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
index de7377815b6b4c9828beccd1c6a37932c8a29d0d..8ef330027b134eb9ea073f5d4e9ac82d1d1bfc29 100644 (file)
@@ -308,6 +308,7 @@ struct mmc_card {
        unsigned int    nr_parts;
 
        unsigned int            bouncesz;       /* Bounce buffer size */
+       struct workqueue_struct *complete_wq;   /* Private workqueue */
 };
 
 static inline bool mmc_large_sector(struct mmc_card *card)
index 8fa38d3e75384c1a9c4d7607fefc24276cf174d2..f5bc4c046461544ad366f0af68c261cb34d2a668 100644 (file)
@@ -129,13 +129,13 @@ extern void cleanup_module(void);
 #define module_init(initfn)                                    \
        static inline initcall_t __maybe_unused __inittest(void)                \
        { return initfn; }                                      \
-       int init_module(void) __attribute__((alias(#initfn)));
+       int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
 
 /* This is only required if you want to be unloadable. */
 #define module_exit(exitfn)                                    \
        static inline exitcall_t __maybe_unused __exittest(void)                \
        { return exitfn; }                                      \
-       void cleanup_module(void) __attribute__((alias(#exitfn)));
+       void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
 
 #endif
 
index 1377d085ef99d64bd2eb07b93f57bb07ef7986ee..86dbb3e29139591d046602003cd7cb115f8b7e1a 100644 (file)
@@ -1483,6 +1483,7 @@ struct net_device_ops {
  * @IFF_NO_RX_HANDLER: device doesn't support the rx_handler hook
  * @IFF_FAILOVER: device is a failover master device
  * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device
+ * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device
  */
 enum netdev_priv_flags {
        IFF_802_1Q_VLAN                 = 1<<0,
@@ -1514,6 +1515,7 @@ enum netdev_priv_flags {
        IFF_NO_RX_HANDLER               = 1<<26,
        IFF_FAILOVER                    = 1<<27,
        IFF_FAILOVER_SLAVE              = 1<<28,
+       IFF_L3MDEV_RX_HANDLER           = 1<<29,
 };
 
 #define IFF_802_1Q_VLAN                        IFF_802_1Q_VLAN
@@ -1544,6 +1546,7 @@ enum netdev_priv_flags {
 #define IFF_NO_RX_HANDLER              IFF_NO_RX_HANDLER
 #define IFF_FAILOVER                   IFF_FAILOVER
 #define IFF_FAILOVER_SLAVE             IFF_FAILOVER_SLAVE
+#define IFF_L3MDEV_RX_HANDLER          IFF_L3MDEV_RX_HANDLER
 
 /**
  *     struct net_device - The DEVICE structure.
@@ -4549,6 +4552,11 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
        return dev->priv_flags & IFF_SUPP_NOFCS;
 }
 
+static inline bool netif_has_l3_rx_handler(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_L3MDEV_RX_HANDLER;
+}
+
 static inline bool netif_is_l3_master(const struct net_device *dev)
 {
        return dev->priv_flags & IFF_L3MDEV_MASTER;
index fe472e5195a9d21d1a52e3817d3f91e27ff9080c..e240992e5cb62d0dccf0ec73879185e93cb419b4 100644 (file)
@@ -50,7 +50,6 @@ struct of_irq_controller;
 
 struct device_node {
        const char *name;
-       const char *type;
        phandle phandle;
        const char *full_name;
        struct fwnode_handle fwnode;
index 1d5c551a5add50794e6d0ae38456b98380f800e6..e1a051724f7ef9c89864bfaffe31af328c5ecd68 100644 (file)
@@ -447,6 +447,11 @@ struct pmu {
         * Filter events for PMU-specific reasons.
         */
        int (*filter_match)             (struct perf_event *event); /* optional */
+
+       /*
+        * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+        */
+       int (*check_period)             (struct perf_event *event, u64 value); /* optional */
 };
 
 enum perf_addr_filter_action_t {
index 3b051f7614505ada10ac2a5bebbabf4f6cf9c8b4..127fcc9c37781564d72978ad0626e5d4c19cf740 100644 (file)
@@ -48,6 +48,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
+extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 
 #define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
@@ -56,6 +57,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_ini
 #define PHY_GBIT_FIBRE_FEATURES ((unsigned long *)&phy_gbit_fibre_features)
 #define PHY_GBIT_ALL_PORTS_FEATURES ((unsigned long *)&phy_gbit_all_ports_features)
 #define PHY_10GBIT_FEATURES ((unsigned long *)&phy_10gbit_features)
+#define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features)
 #define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
 
 extern const int phy_10_100_features_array[4];
@@ -467,8 +469,8 @@ struct phy_device {
  *   only works for PHYs with IDs which match this field
  * name: The friendly name of this PHY type
  * phy_id_mask: Defines the important bits of the phy_id
- * features: A list of features (speed, duplex, etc) supported
- *   by this PHY
+ * features: A mandatory list of features (speed, duplex, etc)
+ *   supported by this PHY
  * flags: A bitfield defining certain other features this PHY
  *   supports (like interrupts)
  *
@@ -672,26 +674,13 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 size_t phy_speeds(unsigned int *speeds, size_t size,
                  unsigned long *mask);
 
-static inline bool __phy_is_started(struct phy_device *phydev)
-{
-       WARN_ON(!mutex_is_locked(&phydev->lock));
-
-       return phydev->state >= PHY_UP;
-}
-
 /**
  * phy_is_started - Convenience function to check whether PHY is started
  * @phydev: The phy_device struct
  */
 static inline bool phy_is_started(struct phy_device *phydev)
 {
-       bool started;
-
-       mutex_lock(&phydev->lock);
-       started = __phy_is_started(phydev);
-       mutex_unlock(&phydev->lock);
-
-       return started;
+       return phydev->state >= PHY_UP;
 }
 
 void phy_resolve_aneg_linkmode(struct phy_device *phydev);
index 54af4eef169f3e6b8e775a2352a83f99cfa36b37..fed5be706bc9410dfd4b5593e2ea71b73067c00b 100644 (file)
@@ -105,7 +105,7 @@ static inline bool pm_runtime_callbacks_present(struct device *dev)
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
 {
-       WRITE_ONCE(dev->power.last_busy, ktime_to_ns(ktime_get()));
+       WRITE_ONCE(dev->power.last_busy, ktime_get_mono_fast_ns());
 }
 
 static inline bool pm_runtime_is_irq_safe(struct device *dev)
index 59ddf9af909e456fcc6c3ed3b3574b6d4da06477..2dd0a9ed5b361472fbb1794b3b77f96fc69780ce 100644 (file)
@@ -663,6 +663,37 @@ static inline void *qed_chain_get_last_elem(struct qed_chain *p_chain)
 static inline void qed_chain_set_prod(struct qed_chain *p_chain,
                                      u32 prod_idx, void *p_prod_elem)
 {
+       if (p_chain->mode == QED_CHAIN_MODE_PBL) {
+               u32 cur_prod, page_mask, page_cnt, page_diff;
+
+               cur_prod = is_chain_u16(p_chain) ? p_chain->u.chain16.prod_idx :
+                          p_chain->u.chain32.prod_idx;
+
+               /* Assume that number of elements in a page is power of 2 */
+               page_mask = ~p_chain->elem_per_page_mask;
+
+               /* Use "cur_prod - 1" and "prod_idx - 1" since producer index
+                * reaches the first element of next page before the page index
+                * is incremented. See qed_chain_produce().
+                * Index wrap around is not a problem because the difference
+                * between current and given producer indices is always
+                * positive and lower than the chain's capacity.
+                */
+               page_diff = (((cur_prod - 1) & page_mask) -
+                            ((prod_idx - 1) & page_mask)) /
+                           p_chain->elem_per_page;
+
+               page_cnt = qed_chain_get_page_cnt(p_chain);
+               if (is_chain_u16(p_chain))
+                       p_chain->pbl.c.u16.prod_page_idx =
+                               (p_chain->pbl.c.u16.prod_page_idx -
+                                page_diff + page_cnt) % page_cnt;
+               else
+                       p_chain->pbl.c.u32.prod_page_idx =
+                               (p_chain->pbl.c.u32.prod_page_idx -
+                                page_diff + page_cnt) % page_cnt;
+       }
+
        if (is_chain_u16(p_chain))
                p_chain->u.chain16.prod_idx = (u16) prod_idx;
        else
index 224666226e87b0032a72fef1c1d59c585ad57bc7..bba3afb4e9bf8a782200246ebe8d019be5c7b700 100644 (file)
@@ -995,7 +995,7 @@ struct task_struct {
        /* cg_list protected by css_set_lock and tsk->alloc_lock: */
        struct list_head                cg_list;
 #endif
-#ifdef CONFIG_X86_RESCTRL
+#ifdef CONFIG_X86_CPU_RESCTRL
        u32                             closid;
        u32                             rmid;
 #endif
@@ -1406,6 +1406,7 @@ extern struct pid *cad_pid;
 #define PF_RANDOMIZE           0x00400000      /* Randomize virtual address space */
 #define PF_SWAPWRITE           0x00800000      /* Allowed to write to swap */
 #define PF_MEMSTALL            0x01000000      /* Stalled due to lack of memory */
+#define PF_UMH                 0x02000000      /* I'm an Usermodehelper process */
 #define PF_NO_SETAFFINITY      0x04000000      /* Userland is not allowed to meddle with cpus_allowed */
 #define PF_MCE_EARLY           0x08000000      /* Early kill for mce process policy */
 #define PF_MUTEX_TESTER                0x20000000      /* Thread belongs to the rt mutex tester */
@@ -1904,6 +1905,14 @@ static inline void rseq_execve(struct task_struct *t)
 
 #endif
 
+void __exit_umh(struct task_struct *tsk);
+
+static inline void exit_umh(struct task_struct *tsk)
+{
+       if (unlikely(tsk->flags & PF_UMH))
+               __exit_umh(tsk);
+}
+
 #ifdef CONFIG_DEBUG_RSEQ
 
 void rseq_syscall(struct pt_regs *regs);
index ec912d01126f4b01f5ac61ebae7f73f8e0527d23..ecdc6542070f11a01fc99665dc6489af59eebef0 100644 (file)
@@ -71,6 +71,7 @@ static inline int get_dumpable(struct mm_struct *mm)
 #define MMF_HUGE_ZERO_PAGE     23      /* mm has ever used the global huge zero page */
 #define MMF_DISABLE_THP                24      /* disable THP for all VMAs */
 #define MMF_OOM_VICTIM         25      /* mm is the oom victim */
+#define MMF_OOM_REAP_QUEUED    26      /* mm was queued for oom_reaper */
 #define MMF_DISABLE_THP_MASK   (1 << MMF_DISABLE_THP)
 
 #define MMF_INIT_MASK          (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
index 10b19a192b2d000121eff7dc91e8f224918d5fec..545f371380574e785abbb0ab3a09eeff9657ce94 100644 (file)
  * called near the end of a function. Otherwise, the list can be
  * re-initialized for later re-use by wake_q_init().
  *
- * Note that this can cause spurious wakeups. schedule() callers
+ * NOTE that this can cause spurious wakeups. schedule() callers
  * must ensure the call is done inside a loop, confirming that the
  * wakeup condition has in fact occurred.
+ *
+ * NOTE that there is no guarantee the wakeup will happen any later than the
+ * wake_q_add() location. Therefore task must be ready to be woken at the
+ * location of the wake_q_add().
  */
 
 #include <linux/sched.h>
index cc7e2c1cd44465926c3626a014dbd051319c2a64..9702016734b1ad7e53b204511b1167e05bc6b858 100644 (file)
@@ -392,7 +392,7 @@ extern bool unhandled_signal(struct task_struct *tsk, int sig);
 #endif
 
 #define siginmask(sig, mask) \
-       ((sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))
+       ((sig) > 0 && (sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))
 
 #define SIG_KERNEL_ONLY_MASK (\
        rt_sigmask(SIGKILL)   |  rt_sigmask(SIGSTOP))
index 93f56fddd92affec18bba942ba93b844675c5303..95d25b010a257f2fbb385f8fe8df719ac6d357f4 100644 (file)
@@ -3218,6 +3218,7 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len);
  *
  *     This is exactly the same as pskb_trim except that it ensures the
  *     checksum of received packets are still valid after the operation.
+ *     It can change skb pointers.
  */
 
 static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
index 7ddfc65586b046e80e3ae7357368b696b406507f..4335bd771ce57b40776bcaf875f52df09c8e6233 100644 (file)
@@ -184,6 +184,7 @@ struct plat_stmmacenet_data {
        struct clk *pclk;
        struct clk *clk_ptp_ref;
        unsigned int clk_ptp_rate;
+       unsigned int clk_ref_rate;
        struct reset_control *stmmac_rst;
        struct stmmac_axi *axi;
        int has_gmac4;
index 235f51b62c71ed030179eeae7ef5d14701e7e430..0c08de356d0d4974e3816421e933d2c7128a33d4 100644 (file)
@@ -47,6 +47,8 @@ struct umh_info {
        const char *cmdline;
        struct file *pipe_to_umh;
        struct file *pipe_from_umh;
+       struct list_head list;
+       void (*cleanup)(struct umh_info *info);
        pid_t pid;
 };
 int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
index 32baf8e26735d5fd9c693105b681c557cab049e2..987b6491b9461bfe33c9d1306999da1c21c9f63d 100644 (file)
@@ -12,6 +12,11 @@ struct irq_affinity;
 
 /**
  * virtio_config_ops - operations for configuring a virtio device
+ * Note: Do not assume that a transport implements all of the operations
+ *       getting/setting a value as a simple read/write! Generally speaking,
+ *       any of @get/@set, @get_status/@set_status, or @get_features/
+ *       @finalize_features are NOT safe to be called from an atomic
+ *       context.
  * @get: read the value of a configuration field
  *     vdev: the virtio_device
  *     offset: the offset of the configuration field
@@ -22,7 +27,7 @@ struct irq_affinity;
  *     offset: the offset of the configuration field
  *     buf: the buffer to read the field value from.
  *     len: the length of the buffer
- * @generation: config generation counter
+ * @generation: config generation counter (optional)
  *     vdev: the virtio_device
  *     Returns the config generation counter
  * @get_status: read the status byte
@@ -48,17 +53,17 @@ struct irq_affinity;
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
  *     vdev: the virtio_device
- *     Returns the first 32 feature bits (all we currently need).
+ *     Returns the first 64 feature bits (all we currently need).
  * @finalize_features: confirm what device features we'll be using.
  *     vdev: the virtio_device
  *     This gives the final feature bits for the device: it can change
  *     the dev->feature bits if it wants.
  *     Returns 0 on success or error status
- * @bus_name: return the bus name associated with the device
+ * @bus_name: return the bus name associated with the device (optional)
  *     vdev: the virtio_device
  *      This returns a pointer to the bus name a la pci_name from which
  *      the caller can then copy.
- * @set_vq_affinity: set the affinity for a virtqueue.
+ * @set_vq_affinity: set the affinity for a virtqueue (optional).
  * @get_vq_affinity: get the affinity for a virtqueue (optional).
  */
 typedef void vq_callback_t(struct virtqueue *);
index f492e21c4aa2c81f5301116408f84d0703a61a18..5d9d318bcf7a1af4379195ed048f3ddeea1fa0ed 100644 (file)
@@ -176,7 +176,8 @@ static inline bool xa_is_internal(const void *entry)
  */
 static inline bool xa_is_err(const void *entry)
 {
-       return unlikely(xa_is_internal(entry));
+       return unlikely(xa_is_internal(entry) &&
+                       entry >= xa_mk_internal(-MAX_ERRNO));
 }
 
 /**
@@ -286,7 +287,6 @@ struct xarray {
  */
 #define DEFINE_XARRAY_ALLOC(name) DEFINE_XARRAY_FLAGS(name, XA_FLAGS_ALLOC)
 
-void xa_init_flags(struct xarray *, gfp_t flags);
 void *xa_load(struct xarray *, unsigned long index);
 void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
 void *xa_erase(struct xarray *, unsigned long index);
@@ -303,6 +303,24 @@ unsigned int xa_extract(struct xarray *, void **dst, unsigned long start,
                unsigned long max, unsigned int n, xa_mark_t);
 void xa_destroy(struct xarray *);
 
+/**
+ * xa_init_flags() - Initialise an empty XArray with flags.
+ * @xa: XArray.
+ * @flags: XA_FLAG values.
+ *
+ * If you need to initialise an XArray with special flags (eg you need
+ * to take the lock from interrupt context), use this function instead
+ * of xa_init().
+ *
+ * Context: Any context.
+ */
+static inline void xa_init_flags(struct xarray *xa, gfp_t flags)
+{
+       spin_lock_init(&xa->xa_lock);
+       xa->xa_flags = flags;
+       xa->xa_head = NULL;
+}
+
 /**
  * xa_init() - Initialise an empty XArray.
  * @xa: XArray.
@@ -342,20 +360,45 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
 }
 
 /**
- * xa_for_each() - Iterate over a portion of an XArray.
+ * xa_for_each_start() - Iterate over a portion of an XArray.
  * @xa: XArray.
+ * @index: Index of @entry.
  * @entry: Entry retrieved from array.
+ * @start: First index to retrieve from array.
+ *
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  You may modify @index during the iteration if you
+ * want to skip or reprocess indices.  It is safe to modify the array
+ * during the iteration.  At the end of the iteration, @entry will be set
+ * to NULL and @index will have a value less than or equal to max.
+ *
+ * xa_for_each_start() is O(n.log(n)) while xas_for_each() is O(n).  You have
+ * to handle your own locking with xas_for_each(), and if you have to unlock
+ * after each iteration, it will also end up being O(n.log(n)).
+ * xa_for_each_start() will spin if it hits a retry entry; if you intend to
+ * see retry entries, you should use the xas_for_each() iterator instead.
+ * The xas_for_each() iterator will expand into more inline code than
+ * xa_for_each_start().
+ *
+ * Context: Any context.  Takes and releases the RCU lock.
+ */
+#define xa_for_each_start(xa, index, entry, start)                     \
+       for (index = start,                                             \
+            entry = xa_find(xa, &index, ULONG_MAX, XA_PRESENT);        \
+            entry;                                                     \
+            entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT))
+
+/**
+ * xa_for_each() - Iterate over present entries in an XArray.
+ * @xa: XArray.
  * @index: Index of @entry.
- * @max: Maximum index to retrieve from array.
- * @filter: Selection criterion.
+ * @entry: Entry retrieved from array.
  *
- * Initialise @index to the lowest index you want to retrieve from the
- * array.  During the iteration, @entry will have the value of the entry
- * stored in @xa at @index.  The iteration will skip all entries in the
- * array which do not match @filter.  You may modify @index during the
- * iteration if you want to skip or reprocess indices.  It is safe to modify
- * the array during the iteration.  At the end of the iteration, @entry will
- * be set to NULL and @index will have a value less than or equal to max.
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  You may modify @index during the iteration if you want
+ * to skip or reprocess indices.  It is safe to modify the array during the
+ * iteration.  At the end of the iteration, @entry will be set to NULL and
+ * @index will have a value less than or equal to max.
  *
  * xa_for_each() is O(n.log(n)) while xas_for_each() is O(n).  You have
  * to handle your own locking with xas_for_each(), and if you have to unlock
@@ -366,9 +409,36 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
  *
  * Context: Any context.  Takes and releases the RCU lock.
  */
-#define xa_for_each(xa, entry, index, max, filter) \
-       for (entry = xa_find(xa, &index, max, filter); entry; \
-            entry = xa_find_after(xa, &index, max, filter))
+#define xa_for_each(xa, index, entry) \
+       xa_for_each_start(xa, index, entry, 0)
+
+/**
+ * xa_for_each_marked() - Iterate over marked entries in an XArray.
+ * @xa: XArray.
+ * @index: Index of @entry.
+ * @entry: Entry retrieved from array.
+ * @filter: Selection criterion.
+ *
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  The iteration will skip all entries in the array
+ * which do not match @filter.  You may modify @index during the iteration
+ * if you want to skip or reprocess indices.  It is safe to modify the array
+ * during the iteration.  At the end of the iteration, @entry will be set to
+ * NULL and @index will have a value less than or equal to max.
+ *
+ * xa_for_each_marked() is O(n.log(n)) while xas_for_each_marked() is O(n).
+ * You have to handle your own locking with xas_for_each(), and if you have
+ * to unlock after each iteration, it will also end up being O(n.log(n)).
+ * xa_for_each_marked() will spin if it hits a retry entry; if you intend to
+ * see retry entries, you should use the xas_for_each_marked() iterator
+ * instead.  The xas_for_each_marked() iterator will expand into more inline
+ * code than xa_for_each_marked().
+ *
+ * Context: Any context.  Takes and releases the RCU lock.
+ */
+#define xa_for_each_marked(xa, index, entry, filter) \
+       for (index = 0, entry = xa_find(xa, &index, ULONG_MAX, filter); \
+            entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
 
 #define xa_trylock(xa)         spin_trylock(&(xa)->xa_lock)
 #define xa_lock(xa)            spin_lock(&(xa)->xa_lock)
@@ -393,39 +463,12 @@ void *__xa_erase(struct xarray *, unsigned long index);
 void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
 void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,
                void *entry, gfp_t);
+int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t);
 int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t);
 int __xa_reserve(struct xarray *, unsigned long index, gfp_t);
 void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
 void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
 
-/**
- * __xa_insert() - Store this entry in the XArray unless another entry is
- *                     already present.
- * @xa: XArray.
- * @index: Index into array.
- * @entry: New entry.
- * @gfp: Memory allocation flags.
- *
- * If you would rather see the existing entry in the array, use __xa_cmpxchg().
- * This function is for users who don't care what the entry is, only that
- * one is present.
- *
- * Context: Any context.  Expects xa_lock to be held on entry.  May
- *         release and reacquire xa_lock if the @gfp flags permit.
- * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
- * -ENOMEM if memory could not be allocated.
- */
-static inline int __xa_insert(struct xarray *xa, unsigned long index,
-               void *entry, gfp_t gfp)
-{
-       void *curr = __xa_cmpxchg(xa, index, NULL, entry, gfp);
-       if (!curr)
-               return 0;
-       if (xa_is_err(curr))
-               return xa_err(curr);
-       return -EEXIST;
-}
-
 /**
  * xa_store_bh() - Store this entry in the XArray.
  * @xa: XArray.
@@ -453,7 +496,7 @@ static inline void *xa_store_bh(struct xarray *xa, unsigned long index,
 }
 
 /**
- * xa_store_irq() - Erase this entry from the XArray.
+ * xa_store_irq() - Store this entry in the XArray.
  * @xa: XArray.
  * @index: Index into array.
  * @entry: New entry.
@@ -615,24 +658,83 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * If you would rather see the existing entry in the array, use xa_cmpxchg().
- * This function is for users who don't care what the entry is, only that
- * one is present.
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
  *
- * Context: Process context.  Takes and releases the xa_lock.
- *         May sleep if the @gfp flags permit.
+ * Context: Any context.  Takes and releases the xa_lock.  May sleep if
+ * the @gfp flags permit.
  * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
  * -ENOMEM if memory could not be allocated.
  */
 static inline int xa_insert(struct xarray *xa, unsigned long index,
                void *entry, gfp_t gfp)
 {
-       void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
-       if (!curr)
-               return 0;
-       if (xa_is_err(curr))
-               return xa_err(curr);
-       return -EEXIST;
+       int err;
+
+       xa_lock(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock(xa);
+
+       return err;
+}
+
+/**
+ * xa_insert_bh() - Store this entry in the XArray unless another entry is
+ *                     already present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Any context.  Takes and releases the xa_lock while
+ * disabling softirqs.  May sleep if the @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+static inline int xa_insert_bh(struct xarray *xa, unsigned long index,
+               void *entry, gfp_t gfp)
+{
+       int err;
+
+       xa_lock_bh(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock_bh(xa);
+
+       return err;
+}
+
+/**
+ * xa_insert_irq() - Store this entry in the XArray unless another entry is
+ *                     already present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Process context.  Takes and releases the xa_lock while
+ * disabling interrupts.  May sleep if the @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+static inline int xa_insert_irq(struct xarray *xa, unsigned long index,
+               void *entry, gfp_t gfp)
+{
+       int err;
+
+       xa_lock_irq(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock_irq(xa);
+
+       return err;
 }
 
 /**
@@ -970,8 +1072,8 @@ static inline bool xa_is_sibling(const void *entry)
                (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1));
 }
 
-#define XA_ZERO_ENTRY          xa_mk_internal(256)
-#define XA_RETRY_ENTRY         xa_mk_internal(257)
+#define XA_RETRY_ENTRY         xa_mk_internal(256)
+#define XA_ZERO_ENTRY          xa_mk_internal(257)
 
 /**
  * xa_is_zero() - Is the entry a zero entry?
@@ -995,6 +1097,17 @@ static inline bool xa_is_retry(const void *entry)
        return unlikely(entry == XA_RETRY_ENTRY);
 }
 
+/**
+ * xa_is_advanced() - Is the entry only permitted for the advanced API?
+ * @entry: Entry to be stored in the XArray.
+ *
+ * Return: %true if the entry cannot be stored by the normal API.
+ */
+static inline bool xa_is_advanced(const void *entry)
+{
+       return xa_is_internal(entry) && (entry <= XA_RETRY_ENTRY);
+}
+
 /**
  * typedef xa_update_node_t - A callback function from the XArray.
  * @node: The node which is being processed
index 1adefe42c0a689b839492d500327ef891c4c395c..2bfb87eb98ce15cd693819d42205a036ae6dd42f 100644 (file)
@@ -20,18 +20,6 @@ struct sock;
 struct socket;
 struct rxrpc_call;
 
-/*
- * Call completion condition (state == RXRPC_CALL_COMPLETE).
- */
-enum rxrpc_call_completion {
-       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
-       RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
-       RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
-       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
-       RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
-       NR__RXRPC_CALL_COMPLETIONS
-};
-
 /*
  * Debug ID counter for tracing.
  */
@@ -73,10 +61,6 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
                               rxrpc_user_attach_call_t, unsigned long, gfp_t,
                               unsigned int);
 void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
-int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
-                           struct sockaddr_rxrpc *, struct key *);
-int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
-                           enum rxrpc_call_completion *, u32 *);
 u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
 void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *);
 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
index 3f9aea8087e3c823cdd5a22530ed4b25dd7621e1..8b7eb46ad72d8804c1ffaa3943bb2816113239d8 100644 (file)
@@ -201,6 +201,18 @@ static inline void ax25_hold_route(ax25_route *ax25_rt)
 
 void __ax25_put_route(ax25_route *ax25_rt);
 
+extern rwlock_t ax25_route_lock;
+
+static inline void ax25_route_lock_use(void)
+{
+       read_lock(&ax25_route_lock);
+}
+
+static inline void ax25_route_lock_unuse(void)
+{
+       read_unlock(&ax25_route_lock);
+}
+
 static inline void ax25_put_route(ax25_route *ax25_rt)
 {
        if (refcount_dec_and_test(&ax25_rt->refcount))
index 00b5e7825508aab5c72156f7fba889dd166899c2..74ff688568a0c6559946a9ae763d5c9822f1d112 100644 (file)
@@ -39,6 +39,7 @@ struct inet_peer {
 
        u32                     metrics[RTAX_MAX];
        u32                     rate_tokens;    /* rate limiting for ICMP */
+       u32                     n_redirects;
        unsigned long           rate_last;
        /*
         * Once inet_peer is queued for deletion (refcnt == 0), following field
index c5969762a8f44b18b27d1776752331768743bf2f..9c8214d2116d3caacf54853d00fd97ee7557db00 100644 (file)
@@ -241,7 +241,7 @@ int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
                     struct netlink_ext_ack *extack);
 int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
                   struct netlink_callback *cb, struct fib_dump_filter *filter);
-int fib_table_flush(struct net *net, struct fib_table *table);
+int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all);
 struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
 void fib_table_flush_external(struct fib_table *table);
 void fib_free_table(struct fib_table *tb);
index 78fa0ac4613c3946590677f53d946d37d97f7bde..5175fd63cd8278fcb9e54cf184b10d6d86bdb528 100644 (file)
@@ -153,7 +153,8 @@ struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
 
        if (netif_is_l3_slave(skb->dev))
                master = netdev_master_upper_dev_get_rcu(skb->dev);
-       else if (netif_is_l3_master(skb->dev))
+       else if (netif_is_l3_master(skb->dev) ||
+                netif_has_l3_rx_handler(skb->dev))
                master = skb->dev;
 
        if (master && master->l3mdev_ops->l3mdev_l3_rcv)
index 7d5cda7ce32abefc218ea5d0b5b71d94eb7472fc..3e370cb36263a26335dd65cc7230b50de9eb7564 100644 (file)
@@ -84,7 +84,6 @@ struct flow_offload {
 struct nf_flow_route {
        struct {
                struct dst_entry        *dst;
-               int                     ifindex;
        } tuple[FLOW_OFFLOAD_DIR_MAX];
 };
 
index 841835a387e17849155ae85f63b3197e747f3469..b4984bbbe15713da8c0fb7f6c58c6c7ea1520f00 100644 (file)
@@ -469,9 +469,7 @@ struct nft_set_binding {
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                       struct nft_set_binding *binding);
 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding);
-void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding);
+                         struct nft_set_binding *binding, bool commit);
 void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set);
 
 /**
@@ -721,6 +719,13 @@ struct nft_expr_type {
 #define NFT_EXPR_STATEFUL              0x1
 #define NFT_EXPR_GC                    0x2
 
+enum nft_trans_phase {
+       NFT_TRANS_PREPARE,
+       NFT_TRANS_ABORT,
+       NFT_TRANS_COMMIT,
+       NFT_TRANS_RELEASE
+};
+
 /**
  *     struct nft_expr_ops - nf_tables expression operations
  *
@@ -750,7 +755,8 @@ struct nft_expr_ops {
        void                            (*activate)(const struct nft_ctx *ctx,
                                                    const struct nft_expr *expr);
        void                            (*deactivate)(const struct nft_ctx *ctx,
-                                                     const struct nft_expr *expr);
+                                                     const struct nft_expr *expr,
+                                                     enum nft_trans_phase phase);
        void                            (*destroy)(const struct nft_ctx *ctx,
                                                   const struct nft_expr *expr);
        void                            (*destroy_clone)(const struct nft_ctx *ctx,
@@ -1323,12 +1329,15 @@ struct nft_trans_rule {
 struct nft_trans_set {
        struct nft_set                  *set;
        u32                             set_id;
+       bool                            bound;
 };
 
 #define nft_trans_set(trans)   \
        (((struct nft_trans_set *)trans->data)->set)
 #define nft_trans_set_id(trans)        \
        (((struct nft_trans_set *)trans->data)->set_id)
+#define nft_trans_set_bound(trans)     \
+       (((struct nft_trans_set *)trans->data)->bound)
 
 struct nft_trans_chain {
        bool                            update;
index 2b229f7be8ebbc160706012f7ed03db85c5689d0..f43f935cb113b73c6fc0df35b5f43103ba131ab2 100644 (file)
@@ -1277,7 +1277,7 @@ static inline void sk_sockets_allocated_inc(struct sock *sk)
        percpu_counter_inc(sk->sk_prot->sockets_allocated);
 }
 
-static inline int
+static inline u64
 sk_sockets_allocated_read_positive(struct sock *sk)
 {
        return percpu_counter_read_positive(sk->sk_prot->sockets_allocated);
index 2a6ac8d642afa0d358d6d3633eb099f47647626f..1486b60c4de8d130a6b6d41aad7192960c200b30 100644 (file)
@@ -120,6 +120,8 @@ struct tls_rec {
        struct scatterlist sg_aead_out[2];
 
        char aad_space[TLS_AAD_SPACE_SIZE];
+       u8 iv_data[TLS_CIPHER_AES_GCM_128_IV_SIZE +
+                  TLS_CIPHER_AES_GCM_128_SALT_SIZE];
        struct aead_request aead_req;
        u8 aead_req_ctx[];
 };
index a3ceed3a040a7215ad7d99cc2ad98b50ba86aa9c..80debf5982acbb788e654761d86247bd33a45554 100644 (file)
@@ -2579,9 +2579,10 @@ struct ib_device {
 
        const struct uapi_definition   *driver_def;
        enum rdma_driver_id             driver_id;
+
        /*
-        * Provides synchronization between device unregistration and netlink
-        * commands on a device. To be used only by core.
+        * Positive refcount indicates that the device is currently
+        * registered and cannot be unregistered.
         */
        refcount_t refcount;
        struct completion unreg_completion;
@@ -3926,6 +3927,25 @@ static inline bool ib_access_writable(int access_flags)
 int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
                       struct ib_mr_status *mr_status);
 
+/**
+ * ib_device_try_get: Hold a registration lock
+ * device: The device to lock
+ *
+ * A device under an active registration lock cannot become unregistered. It
+ * is only possible to obtain a registration lock on a device that is fully
+ * registered, otherwise this function returns false.
+ *
+ * The registration lock is only necessary for actions which require the
+ * device to still be registered. Uses that only require the device pointer to
+ * be valid should use get_device(&ibdev->dev) to hold the memory.
+ *
+ */
+static inline bool ib_device_try_get(struct ib_device *dev)
+{
+       return refcount_inc_not_zero(&dev->refcount);
+}
+
+void ib_device_put(struct ib_device *device);
 struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port,
                                            u16 pkey, const union ib_gid *gid,
                                            const struct sockaddr *addr);
index 0cdc3999ecfa84ebb289eca932b33d1806c2fa13..c5188ff724d1220b991e7e2c1591f8f396138796 100644 (file)
@@ -173,7 +173,11 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
        if (snd_BUG_ON(!stream))
                return;
 
-       stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       if (stream->direction == SND_COMPRESS_PLAYBACK)
+               stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       else
+               stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+
        wake_up(&stream->runtime->sleep);
 }
 
index 7fa48b100936183464d17c9eb3c42711d28336be..cc7c8d42d4fd9a8a494f6b0cf59d48a8fbf2f902 100644 (file)
@@ -68,6 +68,7 @@ struct hda_bus {
        unsigned int response_reset:1;  /* controller was reset */
        unsigned int in_reset:1;        /* during reset operation */
        unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
+       unsigned int bus_probing :1;    /* during probing process */
 
        int primary_dig_out_type;       /* primary digital out PCM type */
        unsigned int mixer_assigned;    /* codec addr for mixer name */
index 8ec1de856ee7e17f0d080623544a17e09d8746bd..e665f111b0d27548015b2b35e8f4c7bfab098df1 100644 (file)
@@ -985,6 +985,12 @@ struct snd_soc_dai_link {
        /* Do not create a PCM for this DAI link (Backend link) */
        unsigned int ignore:1;
 
+       /*
+        * This driver uses legacy platform naming. Set by the core, machine
+        * drivers should not modify this value.
+        */
+       unsigned int legacy_platform:1;
+
        struct list_head list; /* DAI link list of the soc card */
        struct snd_soc_dobj dobj; /* For topology */
 };
index 33d291888ba9c1ceb6edc3cbcd9db4467633939e..e3f005eae1f7679f9b30dcb8b5d0e5d7032c7ebf 100644 (file)
@@ -25,6 +25,7 @@
 enum afs_call_trace {
        afs_call_trace_alloc,
        afs_call_trace_free,
+       afs_call_trace_get,
        afs_call_trace_put,
        afs_call_trace_wake,
        afs_call_trace_work,
@@ -159,6 +160,7 @@ enum afs_file_error {
 #define afs_call_traces \
        EM(afs_call_trace_alloc,                "ALLOC") \
        EM(afs_call_trace_free,                 "FREE ") \
+       EM(afs_call_trace_get,                  "GET  ") \
        EM(afs_call_trace_put,                  "PUT  ") \
        EM(afs_call_trace_wake,                 "WAKE ") \
        E_(afs_call_trace_work,                 "WORK ")
similarity index 83%
rename from include/uapi/linux/android/binder_ctl.h
rename to include/uapi/linux/android/binderfs.h
index 65b2efd1a0a542bfa17deeb2f1ee7aff5f91e6de..87410477aea91cdccf57af137c74b2c8adc08187 100644 (file)
@@ -4,8 +4,8 @@
  *
  */
 
-#ifndef _UAPI_LINUX_BINDER_CTL_H
-#define _UAPI_LINUX_BINDER_CTL_H
+#ifndef _UAPI_LINUX_BINDERFS_H
+#define _UAPI_LINUX_BINDERFS_H
 
 #include <linux/android/binder.h>
 #include <linux/types.h>
@@ -22,8 +22,8 @@
  */
 struct binderfs_device {
        char name[BINDERFS_MAX_NAME + 1];
-       __u8 major;
-       __u8 minor;
+       __u32 major;
+       __u32 minor;
 };
 
 /**
@@ -31,5 +31,5 @@ struct binderfs_device {
  */
 #define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device)
 
-#endif /* _UAPI_LINUX_BINDER_CTL_H */
+#endif /* _UAPI_LINUX_BINDERFS_H */
 
index 6fa38d001d84ff5af90fe6014e7874d18f8e2bc1..498eec813494c6ccbef5d939211088b90bb534d9 100644 (file)
@@ -138,6 +138,7 @@ struct blk_zone_range {
  * @BLKRESETZONE: Reset the write pointer of the zones in the specified
  *                sector range. The sector range must be zone aligned.
  * @BLKGETZONESZ: Get the device zone size in number of 512 B sectors.
+ * @BLKGETNRZONES: Get the total number of zones of the device.
  */
 #define BLKREPORTZONE  _IOWR(0x12, 130, struct blk_zone_report)
 #define BLKRESETZONE   _IOW(0x12, 131, struct blk_zone_range)
index f6052e70bf403950eb658cd350337162a100df5f..a55cb8b10165abcf8a07d8228b590bbc1d8a0c08 100644 (file)
@@ -268,7 +268,7 @@ struct sockaddr_in {
 #define        IN_MULTICAST(a)         IN_CLASSD(a)
 #define        IN_MULTICAST_NET        0xe0000000
 
-#define        IN_BADCLASS(a)          ((((long int) (a) ) == 0xffffffff)
+#define        IN_BADCLASS(a)          (((long int) (a) ) == (long int)0xffffffff)
 #define        IN_EXPERIMENTAL(a)      IN_BADCLASS((a))
 
 #define        IN_CLASSE(a)            ((((long int) (a)) & 0xf0000000) == 0xf0000000)
index 14565d703291b949193bde44638007e2d175edd5..e8baca85bac6a0eed1c7d5e51c88392461a65ad2 100644 (file)
@@ -137,15 +137,21 @@ enum {
        INET_DIAG_TCLASS,
        INET_DIAG_SKMEMINFO,
        INET_DIAG_SHUTDOWN,
-       INET_DIAG_DCTCPINFO,
-       INET_DIAG_PROTOCOL,  /* response attribute only */
+
+       /*
+        * Next extenstions cannot be requested in struct inet_diag_req_v2:
+        * its field idiag_ext has only 8 bits.
+        */
+
+       INET_DIAG_DCTCPINFO,    /* request as INET_DIAG_VEGASINFO */
+       INET_DIAG_PROTOCOL,     /* response attribute only */
        INET_DIAG_SKV6ONLY,
        INET_DIAG_LOCALS,
        INET_DIAG_PEERS,
        INET_DIAG_PAD,
-       INET_DIAG_MARK,
-       INET_DIAG_BBRINFO,
-       INET_DIAG_CLASS_ID,
+       INET_DIAG_MARK,         /* only with CAP_NET_ADMIN */
+       INET_DIAG_BBRINFO,      /* request as INET_DIAG_VEGASINFO */
+       INET_DIAG_CLASS_ID,     /* request as INET_DIAG_TCLASS */
        INET_DIAG_MD5SIG,
        __INET_DIAG_MAX,
 };
index fb78f6f500f37d19bf5dc531ba90c1e5f23746a5..f056b2a00d5c7695a69826786b5e2336c79c3c31 100644 (file)
  */
 
 struct input_event {
-#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL)
+#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__)
        struct timeval time;
 #define input_event_sec time.tv_sec
 #define input_event_usec time.tv_usec
 #else
        __kernel_ulong_t __sec;
+#if defined(__sparc__) && defined(__arch64__)
+       unsigned int __usec;
+#else
        __kernel_ulong_t __usec;
+#endif
 #define input_event_sec  __sec
 #define input_event_usec __usec
 #endif
index d73d83950265dfb315880e0a252e7ac9c6f8431f..1bc794ad957a72729c352ea6eebf40e96b63dffc 100644 (file)
@@ -147,7 +147,7 @@ struct ptp_pin_desc {
 #define PTP_SYS_OFFSET_PRECISE \
        _IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
 #define PTP_SYS_OFFSET_EXTENDED \
-       _IOW(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
+       _IOWR(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
 
 struct ptp_extts_event {
        struct ptp_clock_time t; /* Time event occured. */
index 1196e1c1d4f6c494ee95b8d679e90a7def6d66b4..ff8e7dc9d4dd22f4ce6f98b77fe34142bf2ec63b 100644 (file)
 /* This feature indicates support for the packed virtqueue layout. */
 #define VIRTIO_F_RING_PACKED           34
 
+/*
+ * This feature indicates that memory accesses by the driver and the
+ * device are ordered in a way described by the platform.
+ */
+#define VIRTIO_F_ORDER_PLATFORM                36
+
 /*
  * Does the device support Single Root I/O Virtualization?
  */
index 2414f8af26b3ee882be9acc96fa273b33befa317..4c4e24c291a5b0f7c44453b3d7bb9630246ed81f 100644 (file)
@@ -213,14 +213,4 @@ struct vring_packed_desc {
        __le16 flags;
 };
 
-struct vring_packed {
-       unsigned int num;
-
-       struct vring_packed_desc *desc;
-
-       struct vring_packed_desc_event *driver;
-
-       struct vring_packed_desc_event *device;
-};
-
 #endif /* _UAPI_LINUX_VIRTIO_RING_H */
index ef3c7ec793a756fe30860108868fc995c5bd6dfd..eb76b38a00d4461dc99efc494ddc669d761fbb9a 100644 (file)
@@ -52,6 +52,11 @@ struct hns_roce_ib_create_srq {
        __aligned_u64 que_addr;
 };
 
+struct hns_roce_ib_create_srq_resp {
+       __u32   srqn;
+       __u32   reserved;
+};
+
 struct hns_roce_ib_create_qp {
        __aligned_u64 buf_addr;
        __aligned_u64 db_addr;
index d13fd490b66da2a78436dcf5bd84fd2d12c34ecb..6e73f0274e412abb6fcbd611f7e3063386adbfb7 100644 (file)
@@ -78,6 +78,7 @@ enum pvrdma_wr_opcode {
        PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD,
        PVRDMA_WR_BIND_MW,
        PVRDMA_WR_REG_SIG_MR,
+       PVRDMA_WR_ERROR,
 };
 
 enum pvrdma_wc_status {
index 59a260712a5666d19cc617578bde3d4a273bf04d..2ca9164a79bfdcc1c48844692c874b823e6f87a0 100644 (file)
@@ -1,17 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
-#define _ASM_ARM_XEN_PAGE_COHERENT_H
-
-#include <asm/page.h>
-#include <asm/dma-mapping.h>
-#include <linux/dma-mapping.h>
-
-static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev)
-{
-       if (dev && dev->archdata.dev_dma_ops)
-               return dev->archdata.dev_dma_ops;
-       return get_arch_dma_ops(NULL);
-}
+#ifndef _XEN_ARM_PAGE_COHERENT_H
+#define _XEN_ARM_PAGE_COHERENT_H
 
 void __xen_dma_map_page(struct device *hwdev, struct page *page,
             dma_addr_t dev_addr, unsigned long offset, size_t size,
@@ -21,87 +10,7 @@ void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                unsigned long attrs);
 void __xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir);
-
 void __xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir);
 
-static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
-               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
-{
-       return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
-}
-
-static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
-               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
-{
-       xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
-}
-
-static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
-            dma_addr_t dev_addr, unsigned long offset, size_t size,
-            enum dma_data_direction dir, unsigned long attrs)
-{
-       unsigned long page_pfn = page_to_xen_pfn(page);
-       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
-       unsigned long compound_pages =
-               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
-       bool local = (page_pfn <= dev_pfn) &&
-               (dev_pfn - page_pfn < compound_pages);
-
-       /*
-        * Dom0 is mapped 1:1, while the Linux page can span across
-        * multiple Xen pages, it's not possible for it to contain a
-        * mix of local and foreign Xen pages. So if the first xen_pfn
-        * == mfn the page is local otherwise it's a foreign page
-        * grant-mapped in dom0. If the page is local we can safely
-        * call the native dma_ops function, otherwise we call the xen
-        * specific function.
-        */
-       if (local)
-               xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
-       else
-               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
-}
-
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       /*
-        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
-        * multiple Xen page, it's not possible to have a mix of local and
-        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
-        * foreign mfn will always return false. If the page is local we can
-        * safely call the native dma_ops function, otherwise we call the xen
-        * specific function.
-        */
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->unmap_page)
-                       xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
-       } else
-               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
-}
-
-static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->sync_single_for_cpu)
-                       xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
-       } else
-               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
-}
-
-static inline void xen_dma_sync_single_for_device(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->sync_single_for_device)
-                       xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
-       } else
-               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
-}
-
-#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
+#endif /* _XEN_ARM_PAGE_COHERENT_H */
index d47cb77a220e83672b2746fc6ed871027f3d6490..c9386a365eea2ce71642cbf973105ee30f4cc6f6 100644 (file)
@@ -512,6 +512,17 @@ config PSI_DEFAULT_DISABLED
          per default but can be enabled through passing psi=1 on the
          kernel commandline during boot.
 
+         This feature adds some code to the task wakeup and sleep
+         paths of the scheduler. The overhead is too low to affect
+         common scheduling-intense workloads in practice (such as
+         webservers, memcache), but it does show up in artificial
+         scheduler stress tests, such as hackbench.
+
+         If you are paranoid and not sure what the kernel will be
+         used for, say Y.
+
+         Say N if unsure.
+
 endmenu # "CPU/Task time and stats accounting"
 
 config CPU_ISOLATION
@@ -825,7 +836,7 @@ config CGROUP_PIDS
          PIDs controller is designed to stop this from happening.
 
          It should be noted that organisational operations (such as attaching
-         to a cgroup hierarchy will *not* be blocked by the PIDs controller),
+         to a cgroup hierarchy) will *not* be blocked by the PIDs controller,
          since the PIDs limit only affects a process's ability to fork, not to
          attach to a cgroup.
 
@@ -1124,6 +1135,7 @@ config LD_DEAD_CODE_DATA_ELIMINATION
        bool "Dead code and data elimination (EXPERIMENTAL)"
        depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        depends on EXPERT
+       depends on !(FUNCTION_TRACER && CC_IS_GCC && GCC_VERSION < 40800)
        depends on $(cc-option,-ffunction-sections -fdata-sections)
        depends on $(ld-option,--gc-sections)
        help
index e2e80ca3165a8726c8f13cbd6d62dcadbefb5abc..c86a1c8f19f40be9508b7b979959bc57a47e70ce 100644 (file)
@@ -695,7 +695,6 @@ asmlinkage __visible void __init start_kernel(void)
                initrd_start = 0;
        }
 #endif
-       page_ext_init();
        kmemleak_init();
        setup_per_cpu_pageset();
        numa_policy_init();
@@ -1131,6 +1130,8 @@ static noinline void __init kernel_init_freeable(void)
        sched_init_smp();
 
        page_alloc_init_late();
+       /* Initialize page ext after all struct pages are initialized. */
+       page_ext_init();
 
        do_basic_setup();
 
index 715f9fcf4712b5842a37019c114fd1f625ab848a..c57bd10340ed8dd9484ce716835b87a68099b481 100644 (file)
@@ -467,7 +467,7 @@ static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
        return kind_ops[BTF_INFO_KIND(t->info)];
 }
 
-bool btf_name_offset_valid(const struct btf *btf, u32 offset)
+static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
 {
        return BTF_STR_OFFSET_VALID(offset) &&
                offset < btf->hdr.str_len;
@@ -1219,8 +1219,6 @@ static void btf_bitfield_seq_show(void *data, u8 bits_offset,
        u8 nr_copy_bits;
        u64 print_num;
 
-       data += BITS_ROUNDDOWN_BYTES(bits_offset);
-       bits_offset = BITS_PER_BYTE_MASKED(bits_offset);
        nr_copy_bits = nr_bits + bits_offset;
        nr_copy_bytes = BITS_ROUNDUP_BYTES(nr_copy_bits);
 
@@ -1255,7 +1253,9 @@ static void btf_int_bits_seq_show(const struct btf *btf,
         * BTF_INT_OFFSET() cannot exceed 64 bits.
         */
        total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data);
-       btf_bitfield_seq_show(data, total_bits_offset, nr_bits, m);
+       data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+       bits_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+       btf_bitfield_seq_show(data, bits_offset, nr_bits, m);
 }
 
 static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t,
@@ -1459,7 +1459,8 @@ static int btf_modifier_resolve(struct btf_verifier_env *env,
 
                /* "typedef void new_void", "const void"...etc */
                if (!btf_type_is_void(next_type) &&
-                   !btf_type_is_fwd(next_type)) {
+                   !btf_type_is_fwd(next_type) &&
+                   !btf_type_is_func_proto(next_type)) {
                        btf_verifier_log_type(env, v->t, "Invalid type_id");
                        return -EINVAL;
                }
@@ -2001,12 +2002,12 @@ static void btf_struct_seq_show(const struct btf *btf, const struct btf_type *t,
 
                member_offset = btf_member_bit_offset(t, member);
                bitfield_size = btf_member_bitfield_size(t, member);
+               bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
+               bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
                if (bitfield_size) {
-                       btf_bitfield_seq_show(data, member_offset,
+                       btf_bitfield_seq_show(data + bytes_offset, bits8_offset,
                                              bitfield_size, m);
                } else {
-                       bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
-                       bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
                        ops = btf_type_ops(member_type);
                        ops->seq_show(btf, member_type, member->type,
                                      data + bytes_offset, bits8_offset, m);
index 9425c2fb872f78f1a0c6cb1bcd00019e78c741ba..d17d05570a3fd4eead90b4806362b66b6cb8bea4 100644 (file)
@@ -572,7 +572,7 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
        bpf_compute_and_save_data_end(skb, &saved_data_end);
 
        ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], skb,
-                                bpf_prog_run_save_cb);
+                                __bpf_prog_run_save_cb);
        bpf_restore_data_end(skb, saved_data_end);
        __skb_pull(skb, offset);
        skb->sk = save_sk;
@@ -718,6 +718,7 @@ cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_trace_printk:
                if (capable(CAP_SYS_ADMIN))
                        return bpf_get_trace_printk_proto();
+               /* fall through */
        default:
                return NULL;
        }
index 4b7c76765d9d6998cdbb273ced0d30770d3f6b1e..f9274114c88d37d889d0337dd1f3247d6f40a7e2 100644 (file)
@@ -686,7 +686,7 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
        }
 
        if (htab_is_prealloc(htab)) {
-               pcpu_freelist_push(&htab->freelist, &l->fnode);
+               __pcpu_freelist_push(&htab->freelist, &l->fnode);
        } else {
                atomic_dec(&htab->count);
                l->htab = htab;
@@ -748,7 +748,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
                } else {
                        struct pcpu_freelist_node *l;
 
-                       l = pcpu_freelist_pop(&htab->freelist);
+                       l = __pcpu_freelist_pop(&htab->freelist);
                        if (!l)
                                return ERR_PTR(-E2BIG);
                        l_new = container_of(l, struct htab_elem, fnode);
index 99d243e1ad6e8e5de8f081ec8c458af34c7037c0..52378d3e34b3296d5ff07b1418b9b9307da53bf5 100644 (file)
@@ -12,6 +12,7 @@
 struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
 {
        struct bpf_map *inner_map, *inner_map_meta;
+       u32 inner_map_meta_size;
        struct fd f;
 
        f = fdget(inner_map_ufd);
@@ -36,7 +37,12 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
                return ERR_PTR(-EINVAL);
        }
 
-       inner_map_meta = kzalloc(sizeof(*inner_map_meta), GFP_USER);
+       inner_map_meta_size = sizeof(*inner_map_meta);
+       /* In some cases verifier needs to access beyond just base map. */
+       if (inner_map->ops == &array_map_ops)
+               inner_map_meta_size = sizeof(struct bpf_array);
+
+       inner_map_meta = kzalloc(inner_map_meta_size, GFP_USER);
        if (!inner_map_meta) {
                fdput(f);
                return ERR_PTR(-ENOMEM);
@@ -46,9 +52,16 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
        inner_map_meta->key_size = inner_map->key_size;
        inner_map_meta->value_size = inner_map->value_size;
        inner_map_meta->map_flags = inner_map->map_flags;
-       inner_map_meta->ops = inner_map->ops;
        inner_map_meta->max_entries = inner_map->max_entries;
 
+       /* Misc members not needed in bpf_map_meta_equal() check. */
+       inner_map_meta->ops = inner_map->ops;
+       if (inner_map->ops == &array_map_ops) {
+               inner_map_meta->unpriv_array = inner_map->unpriv_array;
+               container_of(inner_map_meta, struct bpf_array, map)->index_mask =
+                    container_of(inner_map, struct bpf_array, map)->index_mask;
+       }
+
        fdput(f);
        return inner_map_meta;
 }
index 673fa6fe2d73cf815daf8a0c2eb0ce6eab15b41e..0c1b4ba9e90e755f7cef80e1267ed2c9557d5354 100644 (file)
@@ -28,8 +28,8 @@ void pcpu_freelist_destroy(struct pcpu_freelist *s)
        free_percpu(s->freelist);
 }
 
-static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
-                                       struct pcpu_freelist_node *node)
+static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
+                                        struct pcpu_freelist_node *node)
 {
        raw_spin_lock(&head->lock);
        node->next = head->first;
@@ -37,12 +37,22 @@ static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
        raw_spin_unlock(&head->lock);
 }
 
-void pcpu_freelist_push(struct pcpu_freelist *s,
+void __pcpu_freelist_push(struct pcpu_freelist *s,
                        struct pcpu_freelist_node *node)
 {
        struct pcpu_freelist_head *head = this_cpu_ptr(s->freelist);
 
-       __pcpu_freelist_push(head, node);
+       ___pcpu_freelist_push(head, node);
+}
+
+void pcpu_freelist_push(struct pcpu_freelist *s,
+                       struct pcpu_freelist_node *node)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __pcpu_freelist_push(s, node);
+       local_irq_restore(flags);
 }
 
 void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
@@ -63,7 +73,7 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
        for_each_possible_cpu(cpu) {
 again:
                head = per_cpu_ptr(s->freelist, cpu);
-               __pcpu_freelist_push(head, buf);
+               ___pcpu_freelist_push(head, buf);
                i++;
                buf += elem_size;
                if (i == nr_elems)
@@ -74,14 +84,12 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
        local_irq_restore(flags);
 }
 
-struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
+struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
 {
        struct pcpu_freelist_head *head;
        struct pcpu_freelist_node *node;
-       unsigned long flags;
        int orig_cpu, cpu;
 
-       local_irq_save(flags);
        orig_cpu = cpu = raw_smp_processor_id();
        while (1) {
                head = per_cpu_ptr(s->freelist, cpu);
@@ -89,16 +97,25 @@ struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
                node = head->first;
                if (node) {
                        head->first = node->next;
-                       raw_spin_unlock_irqrestore(&head->lock, flags);
+                       raw_spin_unlock(&head->lock);
                        return node;
                }
                raw_spin_unlock(&head->lock);
                cpu = cpumask_next(cpu, cpu_possible_mask);
                if (cpu >= nr_cpu_ids)
                        cpu = 0;
-               if (cpu == orig_cpu) {
-                       local_irq_restore(flags);
+               if (cpu == orig_cpu)
                        return NULL;
-               }
        }
 }
+
+struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
+{
+       struct pcpu_freelist_node *ret;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       ret = __pcpu_freelist_pop(s);
+       local_irq_restore(flags);
+       return ret;
+}
index 3049aae8ea1e2214b888ee40b550d7646da63752..c3960118e617881644f1c726796cc1071face893 100644 (file)
@@ -22,8 +22,12 @@ struct pcpu_freelist_node {
        struct pcpu_freelist_node *next;
 };
 
+/* pcpu_freelist_* do spin_lock_irqsave. */
 void pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
 struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *);
+/* __pcpu_freelist_* do spin_lock only. caller must disable irqs. */
+void __pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
+struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *);
 void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
                            u32 nr_elems);
 int pcpu_freelist_init(struct pcpu_freelist *);
index 90daf285de032a78d565df9be243f7d2f695f35d..d43b145358275d314d02939f674a2ecc719852b2 100644 (file)
@@ -180,11 +180,14 @@ static inline int stack_map_parse_build_id(void *page_addr,
 
                if (nhdr->n_type == BPF_BUILD_ID &&
                    nhdr->n_namesz == sizeof("GNU") &&
-                   nhdr->n_descsz == BPF_BUILD_ID_SIZE) {
+                   nhdr->n_descsz > 0 &&
+                   nhdr->n_descsz <= BPF_BUILD_ID_SIZE) {
                        memcpy(build_id,
                               note_start + note_offs +
                               ALIGN(sizeof("GNU"), 4) + sizeof(Elf32_Nhdr),
-                              BPF_BUILD_ID_SIZE);
+                              nhdr->n_descsz);
+                       memset(build_id + nhdr->n_descsz, 0,
+                              BPF_BUILD_ID_SIZE - nhdr->n_descsz);
                        return 0;
                }
                new_offs = note_offs + sizeof(Elf32_Nhdr) +
@@ -260,7 +263,7 @@ static int stack_map_get_build_id(struct vm_area_struct *vma,
                return -EFAULT; /* page not mapped */
 
        ret = -EINVAL;
-       page_addr = page_address(page);
+       page_addr = kmap_atomic(page);
        ehdr = (Elf32_Ehdr *)page_addr;
 
        /* compare magic x7f "ELF" */
@@ -276,6 +279,7 @@ static int stack_map_get_build_id(struct vm_area_struct *vma,
        else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
                ret = stack_map_get_build_id_64(page_addr, build_id);
 out:
+       kunmap_atomic(page_addr);
        put_page(page);
        return ret;
 }
@@ -310,6 +314,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
                for (i = 0; i < trace_nr; i++) {
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
+                       memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
                }
                return;
        }
@@ -320,6 +325,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
                        /* per entry fall back to ips */
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
+                       memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
                        continue;
                }
                id_offs[i].offset = (vma->vm_pgoff << PAGE_SHIFT) + ips[i]
index b155cd17c1bd77d6c40e215a09ef2af37bd2a077..8577bb7f8be6739f143667af19f916b04de01126 100644 (file)
@@ -713,8 +713,13 @@ static int map_lookup_elem(union bpf_attr *attr)
 
        if (bpf_map_is_dev_bound(map)) {
                err = bpf_map_offload_lookup_elem(map, key, value);
-       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
-                  map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
+               goto done;
+       }
+
+       preempt_disable();
+       this_cpu_inc(bpf_prog_active);
+       if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+           map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
                err = bpf_percpu_hash_copy(map, key, value);
        } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
                err = bpf_percpu_array_copy(map, key, value);
@@ -744,7 +749,10 @@ static int map_lookup_elem(union bpf_attr *attr)
                }
                rcu_read_unlock();
        }
+       this_cpu_dec(bpf_prog_active);
+       preempt_enable();
 
+done:
        if (err)
                goto free_value;
 
index f6bc62a9ee8e9ddea251e353dfe4b6758560ba4f..56674a7c377884b17d8296b6cf6f6e31a8158916 100644 (file)
@@ -3103,6 +3103,40 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
        }
 }
 
+static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env,
+                                   const struct bpf_insn *insn)
+{
+       return env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K;
+}
+
+static int update_alu_sanitation_state(struct bpf_insn_aux_data *aux,
+                                      u32 alu_state, u32 alu_limit)
+{
+       /* If we arrived here from different branches with different
+        * state or limits to sanitize, then this won't work.
+        */
+       if (aux->alu_state &&
+           (aux->alu_state != alu_state ||
+            aux->alu_limit != alu_limit))
+               return -EACCES;
+
+       /* Corresponding fixup done in fixup_bpf_calls(). */
+       aux->alu_state = alu_state;
+       aux->alu_limit = alu_limit;
+       return 0;
+}
+
+static int sanitize_val_alu(struct bpf_verifier_env *env,
+                           struct bpf_insn *insn)
+{
+       struct bpf_insn_aux_data *aux = cur_aux(env);
+
+       if (can_skip_alu_sanitation(env, insn))
+               return 0;
+
+       return update_alu_sanitation_state(aux, BPF_ALU_NON_POINTER, 0);
+}
+
 static int sanitize_ptr_alu(struct bpf_verifier_env *env,
                            struct bpf_insn *insn,
                            const struct bpf_reg_state *ptr_reg,
@@ -3117,7 +3151,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
        struct bpf_reg_state tmp;
        bool ret;
 
-       if (env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K)
+       if (can_skip_alu_sanitation(env, insn))
                return 0;
 
        /* We already marked aux for masking from non-speculative
@@ -3133,19 +3167,8 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 
        if (retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg))
                return 0;
-
-       /* If we arrived here from different branches with different
-        * limits to sanitize, then this won't work.
-        */
-       if (aux->alu_state &&
-           (aux->alu_state != alu_state ||
-            aux->alu_limit != alu_limit))
+       if (update_alu_sanitation_state(aux, alu_state, alu_limit))
                return -EACCES;
-
-       /* Corresponding fixup done in fixup_bpf_calls(). */
-       aux->alu_state = alu_state;
-       aux->alu_limit = alu_limit;
-
 do_sim:
        /* Simulate and find potential out-of-bounds access under
         * speculative execution from truncation as a result of
@@ -3418,6 +3441,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
        s64 smin_val, smax_val;
        u64 umin_val, umax_val;
        u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
+       u32 dst = insn->dst_reg;
+       int ret;
 
        if (insn_bitness == 32) {
                /* Relevant for 32-bit RSH: Information can propagate towards
@@ -3452,6 +3477,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
 
        switch (opcode) {
        case BPF_ADD:
+               ret = sanitize_val_alu(env, insn);
+               if (ret < 0) {
+                       verbose(env, "R%d tried to add from different pointers or scalars\n", dst);
+                       return ret;
+               }
                if (signed_add_overflows(dst_reg->smin_value, smin_val) ||
                    signed_add_overflows(dst_reg->smax_value, smax_val)) {
                        dst_reg->smin_value = S64_MIN;
@@ -3471,6 +3501,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
                dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off);
                break;
        case BPF_SUB:
+               ret = sanitize_val_alu(env, insn);
+               if (ret < 0) {
+                       verbose(env, "R%d tried to sub from different pointers or scalars\n", dst);
+                       return ret;
+               }
                if (signed_sub_overflows(dst_reg->smin_value, smax_val) ||
                    signed_sub_overflows(dst_reg->smax_value, smin_val)) {
                        /* Overflow possible, we know nothing */
index 91d5c38eb7e5b91a5d2cf821414f7cbbaa854c7a..d1c6d152da890dab7b8dab9530dbd1550d85fef6 100644 (file)
@@ -376,9 +376,6 @@ void __weak arch_smt_update(void) { }
 
 #ifdef CONFIG_HOTPLUG_SMT
 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
-EXPORT_SYMBOL_GPL(cpu_smt_control);
-
-static bool cpu_smt_available __read_mostly;
 
 void __init cpu_smt_disable(bool force)
 {
@@ -397,25 +394,11 @@ void __init cpu_smt_disable(bool force)
 
 /*
  * The decision whether SMT is supported can only be done after the full
- * CPU identification. Called from architecture code before non boot CPUs
- * are brought up.
- */
-void __init cpu_smt_check_topology_early(void)
-{
-       if (!topology_smt_supported())
-               cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
-}
-
-/*
- * If SMT was disabled by BIOS, detect it here, after the CPUs have been
- * brought online. This ensures the smt/l1tf sysfs entries are consistent
- * with reality. cpu_smt_available is set to true during the bringup of non
- * boot CPUs when a SMT sibling is detected. Note, this may overwrite
- * cpu_smt_control's previous setting.
+ * CPU identification. Called from architecture code.
  */
 void __init cpu_smt_check_topology(void)
 {
-       if (!cpu_smt_available)
+       if (!topology_smt_supported())
                cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
 }
 
@@ -428,18 +411,10 @@ early_param("nosmt", smt_cmdline_disable);
 
 static inline bool cpu_smt_allowed(unsigned int cpu)
 {
-       if (topology_is_primary_thread(cpu))
+       if (cpu_smt_control == CPU_SMT_ENABLED)
                return true;
 
-       /*
-        * If the CPU is not a 'primary' thread and the booted_once bit is
-        * set then the processor has SMT support. Store this information
-        * for the late check of SMT support in cpu_smt_check_topology().
-        */
-       if (per_cpu(cpuhp_state, cpu).booted_once)
-               cpu_smt_available = true;
-
-       if (cpu_smt_control == CPU_SMT_ENABLED)
+       if (topology_is_primary_thread(cpu))
                return true;
 
        /*
@@ -2090,10 +2065,8 @@ static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
                 */
                cpuhp_offline_cpu_device(cpu);
        }
-       if (!ret) {
+       if (!ret)
                cpu_smt_control = ctrlval;
-               arch_smt_update();
-       }
        cpu_maps_update_done();
        return ret;
 }
@@ -2104,7 +2077,6 @@ static int cpuhp_smt_enable(void)
 
        cpu_maps_update_begin();
        cpu_smt_control = CPU_SMT_ENABLED;
-       arch_smt_update();
        for_each_present_cpu(cpu) {
                /* Skip online CPUs and CPUs on offline nodes */
                if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
index d6361776dc5cea40ac830fb6e3940d986dd13841..1fb6fd68b9c7e80c969072642a4064f4e9608008 100644 (file)
@@ -378,6 +378,8 @@ void __init swiotlb_exit(void)
                memblock_free_late(io_tlb_start,
                                   PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
        }
+       io_tlb_start = 0;
+       io_tlb_end = 0;
        io_tlb_nslabs = 0;
        max_segment = 0;
 }
index 3cd13a30f732921bec9ac0235613b02da5f91de9..26d6edab051a1e41c81d23b8c29ab097d6c4c71b 100644 (file)
@@ -436,18 +436,18 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos)
 {
-       int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
-
-       if (ret || !write)
-               return ret;
-
+       int ret;
+       int perf_cpu = sysctl_perf_cpu_time_max_percent;
        /*
         * If throttling is disabled don't allow the write:
         */
-       if (sysctl_perf_cpu_time_max_percent == 100 ||
-           sysctl_perf_cpu_time_max_percent == 0)
+       if (write && (perf_cpu == 100 || perf_cpu == 0))
                return -EINVAL;
 
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       if (ret || !write)
+               return ret;
+
        max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
        perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
        update_perf_cpu_limits();
@@ -4963,6 +4963,11 @@ static void __perf_event_period(struct perf_event *event,
        }
 }
 
+static int perf_event_check_period(struct perf_event *event, u64 value)
+{
+       return event->pmu->check_period(event, value);
+}
+
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
        u64 value;
@@ -4979,6 +4984,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
        if (event->attr.freq && value > sysctl_perf_event_sample_rate)
                return -EINVAL;
 
+       if (perf_event_check_period(event, value))
+               return -EINVAL;
+
        event_function_call(event, __perf_event_period, &value);
 
        return 0;
@@ -9391,6 +9399,11 @@ static int perf_pmu_nop_int(struct pmu *pmu)
        return 0;
 }
 
+static int perf_event_nop_int(struct perf_event *event, u64 value)
+{
+       return 0;
+}
+
 static DEFINE_PER_CPU(unsigned int, nop_txn_flags);
 
 static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags)
@@ -9691,6 +9704,9 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type)
                pmu->pmu_disable = perf_pmu_nop_void;
        }
 
+       if (!pmu->check_period)
+               pmu->check_period = perf_event_nop_int;
+
        if (!pmu->event_idx)
                pmu->event_idx = perf_event_idx_default;
 
index 4a99370763319dd14d39c7547e4af930779dc38f..5ab4fe3b1dcc0b6a90bc2b4a5eb0e02a44ee909b 100644 (file)
@@ -734,6 +734,9 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
        size = sizeof(struct ring_buffer);
        size += nr_pages * sizeof(void *);
 
+       if (order_base_2(size) >= PAGE_SHIFT+MAX_ORDER)
+               goto fail;
+
        rb = kzalloc(size, GFP_KERNEL);
        if (!rb)
                goto fail;
index 2d14979577ee1ef536bf3e554057e14dab90ce0f..2639a30a8aa5dd9054bc0af5951397efb1083713 100644 (file)
@@ -307,7 +307,7 @@ void rcuwait_wake_up(struct rcuwait *w)
         *        MB (A)              MB (B)
         *    [L] cond            [L] tsk
         */
-       smp_rmb(); /* (B) */
+       smp_mb(); /* (B) */
 
        /*
         * Avoid using task_rcu_dereference() magic as long as we are careful,
@@ -558,12 +558,14 @@ static struct task_struct *find_alive_thread(struct task_struct *p)
        return NULL;
 }
 
-static struct task_struct *find_child_reaper(struct task_struct *father)
+static struct task_struct *find_child_reaper(struct task_struct *father,
+                                               struct list_head *dead)
        __releases(&tasklist_lock)
        __acquires(&tasklist_lock)
 {
        struct pid_namespace *pid_ns = task_active_pid_ns(father);
        struct task_struct *reaper = pid_ns->child_reaper;
+       struct task_struct *p, *n;
 
        if (likely(reaper != father))
                return reaper;
@@ -579,6 +581,12 @@ static struct task_struct *find_child_reaper(struct task_struct *father)
                panic("Attempted to kill init! exitcode=0x%08x\n",
                        father->signal->group_exit_code ?: father->exit_code);
        }
+
+       list_for_each_entry_safe(p, n, dead, ptrace_entry) {
+               list_del_init(&p->ptrace_entry);
+               release_task(p);
+       }
+
        zap_pid_ns_processes(pid_ns);
        write_lock_irq(&tasklist_lock);
 
@@ -668,7 +676,7 @@ static void forget_original_parent(struct task_struct *father,
                exit_ptrace(father, dead);
 
        /* Can drop and reacquire tasklist_lock */
-       reaper = find_child_reaper(father);
+       reaper = find_child_reaper(father, dead);
        if (list_empty(&father->children))
                return;
 
@@ -866,6 +874,7 @@ void __noreturn do_exit(long code)
        exit_task_namespaces(tsk);
        exit_task_work(tsk);
        exit_thread(tsk);
+       exit_umh(tsk);
 
        /*
         * Flush inherited counters to the parent - before the parent
index be3bff2315ff75c46565a42c126f05641c753b98..a0514e01c3eb0c87ecb854c4c19fa0f9a64d6408 100644 (file)
@@ -1452,11 +1452,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
        if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
                return;
 
-       /*
-        * Queue the task for later wakeup for after we've released
-        * the hb->lock. wake_q_add() grabs reference to p.
-        */
-       wake_q_add(wake_q, p);
+       get_task_struct(p);
        __unqueue_futex(q);
        /*
         * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
@@ -1466,6 +1462,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
         * plist_del in __unqueue_futex().
         */
        smp_store_release(&q->lock_ptr, NULL);
+
+       /*
+        * Queue the task for later wakeup for after we've released
+        * the hb->lock. wake_q_add() grabs reference to p.
+        */
+       wake_q_add(wake_q, p);
+       put_task_struct(p);
 }
 
 /*
@@ -2218,11 +2221,11 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
         * decrement the counter at queue_unlock() when some error has
         * occurred and we don't end up adding the task to the list.
         */
-       hb_waiters_inc(hb);
+       hb_waiters_inc(hb); /* implies smp_mb(); (A) */
 
        q->lock_ptr = &hb->lock;
 
-       spin_lock(&hb->lock); /* implies smp_mb(); (A) */
+       spin_lock(&hb->lock);
        return hb;
 }
 
@@ -2858,35 +2861,39 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags,
         * and BUG when futex_unlock_pi() interleaves with this.
         *
         * Therefore acquire wait_lock while holding hb->lock, but drop the
-        * latter before calling rt_mutex_start_proxy_lock(). This still fully
-        * serializes against futex_unlock_pi() as that does the exact same
-        * lock handoff sequence.
+        * latter before calling __rt_mutex_start_proxy_lock(). This
+        * interleaves with futex_unlock_pi() -- which does a similar lock
+        * handoff -- such that the latter can observe the futex_q::pi_state
+        * before __rt_mutex_start_proxy_lock() is done.
         */
        raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
        spin_unlock(q.lock_ptr);
+       /*
+        * __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
+        * such that futex_unlock_pi() is guaranteed to observe the waiter when
+        * it sees the futex_q::pi_state.
+        */
        ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
        raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
 
        if (ret) {
                if (ret == 1)
                        ret = 0;
-
-               spin_lock(q.lock_ptr);
-               goto no_block;
+               goto cleanup;
        }
 
-
        if (unlikely(to))
                hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS);
 
        ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
 
+cleanup:
        spin_lock(q.lock_ptr);
        /*
-        * If we failed to acquire the lock (signal/timeout), we must
+        * If we failed to acquire the lock (deadlock/signal/timeout), we must
         * first acquire the hb->lock before removing the lock from the
-        * rt_mutex waitqueue, such that we can keep the hb and rt_mutex
-        * wait lists consistent.
+        * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
+        * lists consistent.
         *
         * In particular; it is important that futex_unlock_pi() can not
         * observe this inconsistency.
@@ -3010,6 +3017,10 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
                 * there is no point where we hold neither; and therefore
                 * wake_futex_pi() must observe a state consistent with what we
                 * observed.
+                *
+                * In particular; this forces __rt_mutex_start_proxy() to
+                * complete such that we're guaranteed to observe the
+                * rt_waiter. Also see the WARN in wake_futex_pi().
                 */
                raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
                spin_unlock(&hb->lock);
index ee062b7939d3fce9f2813e2bb8f37c5159448631..ef8ad36cadcf0e0b048416b219632a9edcc80636 100644 (file)
@@ -457,7 +457,7 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node,
 
        /* Validate affinity mask(s) */
        if (affinity) {
-               for (i = 0; i < cnt; i++, i++) {
+               for (i = 0; i < cnt; i++) {
                        if (cpumask_empty(&affinity[i].mask))
                                return -EINVAL;
                }
index a4888ce4667a489ccd67afc1e6de40762936b3b3..84b54a17b95d3f3a1b4f2148c58e958f0d534dec 100644 (file)
@@ -393,6 +393,9 @@ int irq_setup_affinity(struct irq_desc *desc)
        }
 
        cpumask_and(&mask, cpu_online_mask, set);
+       if (cpumask_empty(&mask))
+               cpumask_copy(&mask, cpu_online_mask);
+
        if (node != NUMA_NO_NODE) {
                const struct cpumask *nodemask = cpumask_of_node(node);
 
index 581edcc63c2689f52eae98094f984b9fb3846bc8..978d63a8261c265e76eddcc1f933cd714e1b6e66 100644 (file)
@@ -1726,12 +1726,33 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock,
        rt_mutex_set_owner(lock, NULL);
 }
 
+/**
+ * __rt_mutex_start_proxy_lock() - Start lock acquisition for another task
+ * @lock:              the rt_mutex to take
+ * @waiter:            the pre-initialized rt_mutex_waiter
+ * @task:              the task to prepare
+ *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: does _NOT_ remove the @waiter on failure; must either call
+ * rt_mutex_wait_proxy_lock() or rt_mutex_cleanup_proxy_lock() after this.
+ *
+ * Returns:
+ *  0 - task blocked on lock
+ *  1 - acquired the lock for task, caller should wake it up
+ * <0 - error
+ *
+ * Special API call for PI-futex support.
+ */
 int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                              struct rt_mutex_waiter *waiter,
                              struct task_struct *task)
 {
        int ret;
 
+       lockdep_assert_held(&lock->wait_lock);
+
        if (try_to_take_rt_mutex(lock, task, NULL))
                return 1;
 
@@ -1749,9 +1770,6 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                ret = 0;
        }
 
-       if (unlikely(ret))
-               remove_waiter(lock, waiter);
-
        debug_rt_mutex_print_deadlock(waiter);
 
        return ret;
@@ -1763,12 +1781,18 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
  * @waiter:            the pre-initialized rt_mutex_waiter
  * @task:              the task to prepare
  *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: unlike __rt_mutex_start_proxy_lock this _DOES_ remove the @waiter
+ * on failure.
+ *
  * Returns:
  *  0 - task blocked on lock
  *  1 - acquired the lock for task, caller should wake it up
  * <0 - error
  *
- * Special API call for FUTEX_REQUEUE_PI support.
+ * Special API call for PI-futex support.
  */
 int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                              struct rt_mutex_waiter *waiter,
@@ -1778,6 +1802,8 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 
        raw_spin_lock_irq(&lock->wait_lock);
        ret = __rt_mutex_start_proxy_lock(lock, waiter, task);
+       if (unlikely(ret))
+               remove_waiter(lock, waiter);
        raw_spin_unlock_irq(&lock->wait_lock);
 
        return ret;
@@ -1845,7 +1871,8 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
  * @lock:              the rt_mutex we were woken on
  * @waiter:            the pre-initialized rt_mutex_waiter
  *
- * Attempt to clean up after a failed rt_mutex_wait_proxy_lock().
+ * Attempt to clean up after a failed __rt_mutex_start_proxy_lock() or
+ * rt_mutex_wait_proxy_lock().
  *
  * Unless we acquired the lock; we're still enqueued on the wait-list and can
  * in fact still be granted ownership until we're removed. Therefore we can
index 09b180063ee11681f30a0f7e9b71a01acb3e7cc0..50d9af615dc49850acb3e0dd263cebf14130a8b6 100644 (file)
@@ -198,15 +198,22 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
                woken++;
                tsk = waiter->task;
 
-               wake_q_add(wake_q, tsk);
+               get_task_struct(tsk);
                list_del(&waiter->list);
                /*
-                * Ensure that the last operation is setting the reader
+                * Ensure calling get_task_struct() before setting the reader
                 * waiter to nil such that rwsem_down_read_failed() cannot
                 * race with do_exit() by always holding a reference count
                 * to the task to wakeup.
                 */
                smp_store_release(&waiter->task, NULL);
+               /*
+                * Ensure issuing the wakeup (either by us or someone else)
+                * after setting the reader waiter to nil.
+                */
+               wake_q_add(wake_q, tsk);
+               /* wake_q_add() already take the task ref */
+               put_task_struct(tsk);
        }
 
        adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
index 04f248644e065f601d78744be2bbe580a6aa1810..9e0f52375487d7be47ee4c265ee0cbd5227186d0 100644 (file)
@@ -428,6 +428,8 @@ static struct dentry *relay_create_buf_file(struct rchan *chan,
        dentry = chan->cb->create_buf_file(tmpname, chan->parent,
                                           S_IRUSR, buf,
                                           &chan->is_global);
+       if (IS_ERR(dentry))
+               dentry = NULL;
 
        kfree(tmpname);
 
@@ -461,7 +463,7 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan, unsigned int cpu)
                dentry = chan->cb->create_buf_file(NULL, NULL,
                                                   S_IRUSR, buf,
                                                   &chan->is_global);
-               if (WARN_ON(dentry))
+               if (IS_ERR_OR_NULL(dentry))
                        goto free_buf;
        }
 
index a674c7db2f29db1e35af199e09db84aeb65cde66..d8d76a65cfdd55538378b4725b6c1219d25f97a9 100644 (file)
@@ -396,6 +396,18 @@ static bool set_nr_if_polling(struct task_struct *p)
 #endif
 #endif
 
+/**
+ * wake_q_add() - queue a wakeup for 'later' waking.
+ * @head: the wake_q_head to add @task to
+ * @task: the task to queue for 'later' wakeup
+ *
+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
+ * instantly.
+ *
+ * This function must be used as-if it were wake_up_process(); IOW the task
+ * must be ready to be woken at this location.
+ */
 void wake_q_add(struct wake_q_head *head, struct task_struct *task)
 {
        struct wake_q_node *node = &task->wake_q;
@@ -405,10 +417,11 @@ void wake_q_add(struct wake_q_head *head, struct task_struct *task)
         * its already queued (either by us or someone else) and will get the
         * wakeup due to that.
         *
-        * This cmpxchg() executes a full barrier, which pairs with the full
-        * barrier executed by the wakeup in wake_up_q().
+        * In order to ensure that a pending wakeup will observe our pending
+        * state, even in the failed case, an explicit smp_mb() must be used.
         */
-       if (cmpxchg(&node->next, NULL, WAKE_Q_TAIL))
+       smp_mb__before_atomic();
+       if (cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))
                return;
 
        get_task_struct(task);
index 50aa2aba69bd4daba02dd6e697a011f364b3f2da..310d0637fe4b23e6bff5e090be1ea18c09a7decf 100644 (file)
@@ -5980,6 +5980,7 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
 
 #ifdef CONFIG_SCHED_SMT
 DEFINE_STATIC_KEY_FALSE(sched_smt_present);
+EXPORT_SYMBOL_GPL(sched_smt_present);
 
 static inline void set_idle_cores(int cpu, int val)
 {
index fe24de3fbc93805f0c1e913a85657a15d141ad2f..c3484785b17958df85b11ca2823a1f4a4d41f59b 100644 (file)
  * sampling of the aggregate task states would be.
  */
 
+#include "../workqueue_internal.h"
 #include <linux/sched/loadavg.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
@@ -480,9 +481,6 @@ static void psi_group_change(struct psi_group *group, int cpu,
                        groupc->tasks[t]++;
 
        write_seqcount_end(&groupc->seq);
-
-       if (!delayed_work_pending(&group->clock_work))
-               schedule_delayed_work(&group->clock_work, PSI_FREQ);
 }
 
 static struct psi_group *iterate_groups(struct task_struct *task, void **iter)
@@ -513,6 +511,7 @@ void psi_task_change(struct task_struct *task, int clear, int set)
 {
        int cpu = task_cpu(task);
        struct psi_group *group;
+       bool wake_clock = true;
        void *iter = NULL;
 
        if (!task->pid)
@@ -530,8 +529,22 @@ void psi_task_change(struct task_struct *task, int clear, int set)
        task->psi_flags &= ~clear;
        task->psi_flags |= set;
 
-       while ((group = iterate_groups(task, &iter)))
+       /*
+        * Periodic aggregation shuts off if there is a period of no
+        * task changes, so we wake it back up if necessary. However,
+        * don't do this if the task change is the aggregation worker
+        * itself going to sleep, or we'll ping-pong forever.
+        */
+       if (unlikely((clear & TSK_RUNNING) &&
+                    (task->flags & PF_WQ_WORKER) &&
+                    wq_worker_last_func(task) == psi_update_work))
+               wake_clock = false;
+
+       while ((group = iterate_groups(task, &iter))) {
                psi_group_change(group, cpu, clear, set);
+               if (wake_clock && !delayed_work_pending(&group->clock_work))
+                       schedule_delayed_work(&group->clock_work, PSI_FREQ);
+       }
 }
 
 void psi_memstall_tick(struct task_struct *task, int cpu)
index d7f538847b8413eca4c91112f26a563623a59904..e815781ed751b912d67348aa9cb7d23b561e503b 100644 (file)
@@ -976,6 +976,9 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
        struct seccomp_filter *filter = file->private_data;
        struct seccomp_knotif *knotif;
 
+       if (!filter)
+               return 0;
+
        mutex_lock(&filter->notify_lock);
 
        /*
@@ -1300,6 +1303,7 @@ static long seccomp_set_mode_filter(unsigned int flags,
 out_put_fd:
        if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
                if (ret < 0) {
+                       listener_f->private_data = NULL;
                        fput(listener_f);
                        put_unused_fd(listener);
                } else {
index e1d7ad8e6ab179835d719d87aa9cb5c87c29339d..57b7771e20d7e7e1e87c1eac93fab30cc2b1e662 100644 (file)
@@ -688,6 +688,48 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, kernel_siginfo_t *in
 }
 EXPORT_SYMBOL_GPL(dequeue_signal);
 
+static int dequeue_synchronous_signal(kernel_siginfo_t *info)
+{
+       struct task_struct *tsk = current;
+       struct sigpending *pending = &tsk->pending;
+       struct sigqueue *q, *sync = NULL;
+
+       /*
+        * Might a synchronous signal be in the queue?
+        */
+       if (!((pending->signal.sig[0] & ~tsk->blocked.sig[0]) & SYNCHRONOUS_MASK))
+               return 0;
+
+       /*
+        * Return the first synchronous signal in the queue.
+        */
+       list_for_each_entry(q, &pending->list, list) {
+               /* Synchronous signals have a postive si_code */
+               if ((q->info.si_code > SI_USER) &&
+                   (sigmask(q->info.si_signo) & SYNCHRONOUS_MASK)) {
+                       sync = q;
+                       goto next;
+               }
+       }
+       return 0;
+next:
+       /*
+        * Check if there is another siginfo for the same signal.
+        */
+       list_for_each_entry_continue(q, &pending->list, list) {
+               if (q->info.si_signo == sync->info.si_signo)
+                       goto still_pending;
+       }
+
+       sigdelset(&pending->signal, sync->info.si_signo);
+       recalc_sigpending();
+still_pending:
+       list_del_init(&sync->list);
+       copy_siginfo(info, &sync->info);
+       __sigqueue_free(sync);
+       return info->si_signo;
+}
+
 /*
  * Tell a process that it has a new active signal..
  *
@@ -1057,10 +1099,9 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
 
        result = TRACE_SIGNAL_DELIVERED;
        /*
-        * Skip useless siginfo allocation for SIGKILL SIGSTOP,
-        * and kernel threads.
+        * Skip useless siginfo allocation for SIGKILL and kernel threads.
         */
-       if (sig_kernel_only(sig) || (t->flags & PF_KTHREAD))
+       if ((sig == SIGKILL) || (t->flags & PF_KTHREAD))
                goto out_set;
 
        /*
@@ -2394,6 +2435,14 @@ bool get_signal(struct ksignal *ksig)
                goto relock;
        }
 
+       /* Has this task already been marked for death? */
+       if (signal_group_exit(signal)) {
+               ksig->info.si_signo = signr = SIGKILL;
+               sigdelset(&current->pending.signal, SIGKILL);
+               recalc_sigpending();
+               goto fatal;
+       }
+
        for (;;) {
                struct k_sigaction *ka;
 
@@ -2407,7 +2456,15 @@ bool get_signal(struct ksignal *ksig)
                        goto relock;
                }
 
-               signr = dequeue_signal(current, &current->blocked, &ksig->info);
+               /*
+                * Signals generated by the execution of an instruction
+                * need to be delivered before any other pending signals
+                * so that the instruction pointer in the signal stack
+                * frame points to the faulting instruction.
+                */
+               signr = dequeue_synchronous_signal(&ksig->info);
+               if (!signr)
+                       signr = dequeue_signal(current, &current->blocked, &ksig->info);
 
                if (!signr)
                        break; /* will return 0 */
@@ -2489,6 +2546,7 @@ bool get_signal(struct ksignal *ksig)
                        continue;
                }
 
+       fatal:
                spin_unlock_irq(&sighand->siglock);
 
                /*
index 163c451af42e44c36a71ec8fe2c0a5c25ead9b27..f4cf1b0bb3b86efed73b1bb2aeabf932f87c515e 100644 (file)
@@ -584,8 +584,6 @@ void __init smp_init(void)
                num_nodes, (num_nodes > 1 ? "s" : ""),
                num_cpus,  (num_cpus  > 1 ? "s" : ""));
 
-       /* Final decision about SMT support */
-       cpu_smt_check_topology();
        /* Any cleanup work */
        smp_cpus_done(setup_max_cpus);
 }
index 8f0644af40be7e5869f8f664775183bdb07a0f56..80f955210861a591fd383028ba6b045903be26fd 100644 (file)
@@ -685,6 +685,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
         * set up the signal and overrun bookkeeping.
         */
        timer->it.cpu.incr = timespec64_to_ns(&new->it_interval);
+       timer->it_interval = ns_to_ktime(timer->it.cpu.incr);
 
        /*
         * This acts as a modification timestamp for the timer,
index 8b068adb9da1ce23538eeb3bdf3fc7fbd94f2f59..f1a86a0d881ddb877b4a800bd4f31c30c76fab8e 100644 (file)
@@ -1204,22 +1204,12 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *
 
 int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
 {
-       int err;
-
-       mutex_lock(&bpf_event_mutex);
-       err = __bpf_probe_register(btp, prog);
-       mutex_unlock(&bpf_event_mutex);
-       return err;
+       return __bpf_probe_register(btp, prog);
 }
 
 int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
 {
-       int err;
-
-       mutex_lock(&bpf_event_mutex);
-       err = tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
-       mutex_unlock(&bpf_event_mutex);
-       return err;
+       return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
 }
 
 int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
index 5c19b8c41c7e706efb8da85d6b4d45a3931d2a3c..d5fb09ebba8b79da9e82bc6d23fc48e8d1a02274 100644 (file)
@@ -607,11 +607,17 @@ static int trace_kprobe_create(int argc, const char *argv[])
        char buf[MAX_EVENT_NAME_LEN];
        unsigned int flags = TPARG_FL_KERNEL;
 
-       /* argc must be >= 1 */
-       if (argv[0][0] == 'r') {
+       switch (argv[0][0]) {
+       case 'r':
                is_return = true;
                flags |= TPARG_FL_RETURN;
-       } else if (argv[0][0] != 'p' || argc < 2)
+               break;
+       case 'p':
+               break;
+       default:
+               return -ECANCELED;
+       }
+       if (argc < 2)
                return -ECANCELED;
 
        event = strchr(&argv[0][1], ':');
index 5c56afc17cf869166158d5188eb55cf89ce57352..4737bb8c07a3851c30fa565d48e3b4dae5da2e8b 100644 (file)
@@ -180,10 +180,12 @@ store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs,
                if (unlikely(arg->dynamic))
                        *dl = make_data_loc(maxlen, dyndata - base);
                ret = process_fetch_insn(arg->code, regs, dl, base);
-               if (unlikely(ret < 0 && arg->dynamic))
+               if (unlikely(ret < 0 && arg->dynamic)) {
                        *dl = make_data_loc(0, dyndata - base);
-               else
+               } else {
                        dyndata += ret;
+                       maxlen -= ret;
+               }
        }
 }
 
index e335576b941181614abd9eb8c15b0b710c3c0972..9bde07c06362fb9a00196358f333e2408583c78a 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) IBM Corporation, 2010-2012
  * Author:     Srikar Dronamraju <srikar@linux.vnet.ibm.com>
  */
-#define pr_fmt(fmt)    "trace_kprobe: " fmt
+#define pr_fmt(fmt)    "trace_uprobe: " fmt
 
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -160,6 +160,13 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
        if (ret >= 0) {
                if (ret == maxlen)
                        dst[ret - 1] = '\0';
+               else
+                       /*
+                        * Include the terminating null byte. In this case it
+                        * was copied by strncpy_from_user but not accounted
+                        * for in ret.
+                        */
+                       ret++;
                *(u32 *)dest = make_data_loc(ret, (void *)dst - base);
        }
 
index 0baa672e023cb86e84ad11a34e6cf22cb82e2e6e..d937cbad903aad4935bcc67331a27c1c73c57839 100644 (file)
@@ -37,6 +37,8 @@ static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
 static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
 static DEFINE_SPINLOCK(umh_sysctl_lock);
 static DECLARE_RWSEM(umhelper_sem);
+static LIST_HEAD(umh_list);
+static DEFINE_MUTEX(umh_list_lock);
 
 static void call_usermodehelper_freeinfo(struct subprocess_info *info)
 {
@@ -100,10 +102,12 @@ static int call_usermodehelper_exec_async(void *data)
        commit_creds(new);
 
        sub_info->pid = task_pid_nr(current);
-       if (sub_info->file)
+       if (sub_info->file) {
                retval = do_execve_file(sub_info->file,
                                        sub_info->argv, sub_info->envp);
-       else
+               if (!retval)
+                       current->flags |= PF_UMH;
+       } else
                retval = do_execve(getname_kernel(sub_info->path),
                                   (const char __user *const __user *)sub_info->argv,
                                   (const char __user *const __user *)sub_info->envp);
@@ -517,6 +521,11 @@ int fork_usermode_blob(void *data, size_t len, struct umh_info *info)
                goto out;
 
        err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
+       if (!err) {
+               mutex_lock(&umh_list_lock);
+               list_add(&info->list, &umh_list);
+               mutex_unlock(&umh_list_lock);
+       }
 out:
        fput(file);
        return err;
@@ -679,6 +688,26 @@ static int proc_cap_handler(struct ctl_table *table, int write,
        return 0;
 }
 
+void __exit_umh(struct task_struct *tsk)
+{
+       struct umh_info *info;
+       pid_t pid = tsk->pid;
+
+       mutex_lock(&umh_list_lock);
+       list_for_each_entry(info, &umh_list, list) {
+               if (info->pid == pid) {
+                       list_del(&info->list);
+                       mutex_unlock(&umh_list_lock);
+                       goto out;
+               }
+       }
+       mutex_unlock(&umh_list_lock);
+       return;
+out:
+       if (info->cleanup)
+               info->cleanup(info);
+}
+
 struct ctl_table usermodehelper_table[] = {
        {
                .procname       = "bset",
index 392be4b252f69d02f5cd1770c17344b8067aec2f..fc5d23d752a574d3c03487c8c817352a5972f83c 100644 (file)
@@ -909,6 +909,26 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task)
        return to_wakeup ? to_wakeup->task : NULL;
 }
 
+/**
+ * wq_worker_last_func - retrieve worker's last work function
+ *
+ * Determine the last function a worker executed. This is called from
+ * the scheduler to get a worker's last known identity.
+ *
+ * CONTEXT:
+ * spin_lock_irq(rq->lock)
+ *
+ * Return:
+ * The last work function %current executed as a worker, NULL if it
+ * hasn't executed any work yet.
+ */
+work_func_t wq_worker_last_func(struct task_struct *task)
+{
+       struct worker *worker = kthread_data(task);
+
+       return worker->last_func;
+}
+
 /**
  * worker_set_flags - set worker flags and adjust nr_running accordingly
  * @worker: self
@@ -2184,6 +2204,9 @@ __acquires(&pool->lock)
        if (unlikely(cpu_intensive))
                worker_clr_flags(worker, WORKER_CPU_INTENSIVE);
 
+       /* tag the worker for identification in schedule() */
+       worker->last_func = worker->current_func;
+
        /* we're done with it, release */
        hash_del(&worker->hentry);
        worker->current_work = NULL;
index 66fbb5a9e633b4fbe2b9d6090774ad89a8bfebf9..cb68b03ca89aaf074821a1dfe5a2152c31d3a9d3 100644 (file)
@@ -53,6 +53,9 @@ struct worker {
 
        /* used only by rescuers to point to the target workqueue */
        struct workqueue_struct *rescue_wq;     /* I: the workqueue to rescue */
+
+       /* used by the scheduler to determine a worker's last known identity */
+       work_func_t             last_func;
 };
 
 /**
@@ -67,9 +70,10 @@ static inline struct worker *current_wq_worker(void)
 
 /*
  * Scheduler hooks for concurrency managed workqueue.  Only to be used from
- * sched/core.c and workqueue.c.
+ * sched/ and workqueue.c.
  */
 void wq_worker_waking_up(struct task_struct *task, int cpu);
 struct task_struct *wq_worker_sleeping(struct task_struct *task);
+work_func_t wq_worker_last_func(struct task_struct *task);
 
 #endif /* _KERNEL_WORKQUEUE_INTERNAL_H */
index 45b1d67a176710c8b4e4081331c5e9dfa1c9a30e..4a20455d1f61e36afabf8befadb15dfc0f42a3a2 100644 (file)
@@ -206,8 +206,8 @@ u32 __pure __weak __crc32c_le(u32 crc, unsigned char const *p, size_t len)
 EXPORT_SYMBOL(crc32_le);
 EXPORT_SYMBOL(__crc32c_le);
 
-u32 crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
-u32 __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le);
+u32 __pure crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
+u32 __pure __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le);
 
 /*
  * This multiplies the polynomials x and y modulo the given modulus.
index 14436f4ca6bd7f340971a4f85ded981a9c0b25dc..30e0f9770f88cef66f8655c0b377366b7d986db8 100644 (file)
@@ -52,7 +52,7 @@ u32 int_sqrt64(u64 x)
        if (x <= ULONG_MAX)
                return int_sqrt((unsigned long) x);
 
-       m = 1ULL << (fls64(x) & ~1ULL);
+       m = 1ULL << ((fls64(x) - 1) & ~1ULL);
        while (m != 0) {
                b = y + m;
                y >>= 1;
index 65c2d06250a63acd453614011fa42ccd55836beb..5b382c1244ede33c14016142ac2d7fec4d0608da 100644 (file)
 static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
 {
        unsigned long mask, val;
-       unsigned long __maybe_unused flags;
        bool ret = false;
+       unsigned long flags;
 
-       /* Silence bogus lockdep warning */
-#if defined(CONFIG_LOCKDEP)
-       local_irq_save(flags);
-#endif
-       spin_lock(&sb->map[index].swap_lock);
+       spin_lock_irqsave(&sb->map[index].swap_lock, flags);
 
        if (!sb->map[index].cleared)
                goto out_unlock;
@@ -54,10 +50,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
 
        ret = true;
 out_unlock:
-       spin_unlock(&sb->map[index].swap_lock);
-#if defined(CONFIG_LOCKDEP)
-       local_irq_restore(flags);
-#endif
+       spin_unlock_irqrestore(&sb->map[index].swap_lock, flags);
        return ret;
 }
 
index d82d022111e0e5321ef17cff105e1e87bc90ba0e..9cf77628fc913e0e63ae29e843c34f6a685e9f3d 100644 (file)
@@ -632,7 +632,7 @@ static void __kmod_config_free(struct test_config *config)
        config->test_driver = NULL;
 
        kfree_const(config->test_fs);
-       config->test_driver = NULL;
+       config->test_fs = NULL;
 }
 
 static void kmod_config_free(struct kmod_test_device *test_dev)
index 6a8ac7626797854899e77afb4cff0505272dca97..e52f8cafe227d8b9a687b9d3cebd17dfacea50f4 100644 (file)
@@ -541,38 +541,45 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
 static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects,
                                  int cnt, bool slow)
 {
-       struct rhltable rhlt;
+       struct rhltable *rhlt;
        unsigned int i, ret;
        const char *key;
        int err = 0;
 
-       err = rhltable_init(&rhlt, &test_rht_params_dup);
-       if (WARN_ON(err))
+       rhlt = kmalloc(sizeof(*rhlt), GFP_KERNEL);
+       if (WARN_ON(!rhlt))
+               return -EINVAL;
+
+       err = rhltable_init(rhlt, &test_rht_params_dup);
+       if (WARN_ON(err)) {
+               kfree(rhlt);
                return err;
+       }
 
        for (i = 0; i < cnt; i++) {
                rhl_test_objects[i].value.tid = i;
-               key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead);
+               key = rht_obj(&rhlt->ht, &rhl_test_objects[i].list_node.rhead);
                key += test_rht_params_dup.key_offset;
 
                if (slow) {
-                       err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key,
+                       err = PTR_ERR(rhashtable_insert_slow(&rhlt->ht, key,
                                                             &rhl_test_objects[i].list_node.rhead));
                        if (err == -EAGAIN)
                                err = 0;
                } else
-                       err = rhltable_insert(&rhlt,
+                       err = rhltable_insert(rhlt,
                                              &rhl_test_objects[i].list_node,
                                              test_rht_params_dup);
                if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast"))
                        goto skip_print;
        }
 
-       ret = print_ht(&rhlt);
+       ret = print_ht(rhlt);
        WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast");
 
 skip_print:
-       rhltable_destroy(&rhlt);
+       rhltable_destroy(rhlt);
+       kfree(rhlt);
 
        return 0;
 }
index 4676c0a1eeca0f7f7c559176b2c580cedcccce6d..c596a957f7643e56b45956a61ed999980568ad53 100644 (file)
@@ -199,7 +199,7 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL));
                xa_set_mark(xa, index + 1, XA_MARK_0);
                XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
-               xa_set_mark(xa, index + 2, XA_MARK_1);
+               xa_set_mark(xa, index + 2, XA_MARK_2);
                XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
                xa_store_order(xa, index, order, xa_mk_index(index),
                                GFP_KERNEL);
@@ -209,8 +209,8 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                        void *entry;
 
                        XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
-                       XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1));
-                       XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2));
+                       XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_1));
+                       XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_2));
 
                        /* We should see two elements in the array */
                        rcu_read_lock();
@@ -357,7 +357,7 @@ static noinline void check_cmpxchg(struct xarray *xa)
 static noinline void check_reserve(struct xarray *xa)
 {
        void *entry;
-       unsigned long index = 0;
+       unsigned long index;
 
        /* An array with a reserved entry is not empty */
        XA_BUG_ON(xa, !xa_empty(xa));
@@ -382,10 +382,12 @@ static noinline void check_reserve(struct xarray *xa)
        xa_erase_index(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
-       /* And so does xa_insert */
+       /* But xa_insert does not */
        xa_reserve(xa, 12345678, GFP_KERNEL);
-       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != 0);
-       xa_erase_index(xa, 12345678);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) !=
+                       -EEXIST);
+       XA_BUG_ON(xa, xa_empty(xa));
+       XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* Can iterate through a reserved entry */
@@ -393,7 +395,7 @@ static noinline void check_reserve(struct xarray *xa)
        xa_reserve(xa, 6, GFP_KERNEL);
        xa_store_index(xa, 7, GFP_KERNEL);
 
-       xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+       xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, index != 5 && index != 7);
        }
        xa_destroy(xa);
@@ -812,17 +814,16 @@ static noinline void check_find_1(struct xarray *xa)
 static noinline void check_find_2(struct xarray *xa)
 {
        void *entry;
-       unsigned long i, j, index = 0;
+       unsigned long i, j, index;
 
-       xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+       xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, true);
        }
 
        for (i = 0; i < 1024; i++) {
                xa_store_index(xa, index, GFP_KERNEL);
                j = 0;
-               index = 0;
-               xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+               xa_for_each(xa, index, entry) {
                        XA_BUG_ON(xa, xa_mk_index(index) != entry);
                        XA_BUG_ON(xa, index != j++);
                }
@@ -839,6 +840,7 @@ static noinline void check_find_3(struct xarray *xa)
 
        for (i = 0; i < 100; i++) {
                for (j = 0; j < 100; j++) {
+                       rcu_read_lock();
                        for (k = 0; k < 100; k++) {
                                xas_set(&xas, j);
                                xas_for_each_marked(&xas, entry, k, XA_MARK_0)
@@ -847,6 +849,7 @@ static noinline void check_find_3(struct xarray *xa)
                                        XA_BUG_ON(xa,
                                                xas.xa_node != XAS_RESTART);
                        }
+                       rcu_read_unlock();
                }
                xa_store_index(xa, i, GFP_KERNEL);
                xa_set_mark(xa, i, XA_MARK_0);
@@ -1183,6 +1186,35 @@ static noinline void check_store_range(struct xarray *xa)
        }
 }
 
+static void check_align_1(struct xarray *xa, char *name)
+{
+       int i;
+       unsigned int id;
+       unsigned long index;
+       void *entry;
+
+       for (i = 0; i < 8; i++) {
+               id = 0;
+               XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, name + i, GFP_KERNEL)
+                               != 0);
+               XA_BUG_ON(xa, id != i);
+       }
+       xa_for_each(xa, index, entry)
+               XA_BUG_ON(xa, xa_is_err(entry));
+       xa_destroy(xa);
+}
+
+static noinline void check_align(struct xarray *xa)
+{
+       char name[] = "Motorola 68000";
+
+       check_align_1(xa, name);
+       check_align_1(xa, name + 1);
+       check_align_1(xa, name + 2);
+       check_align_1(xa, name + 3);
+//     check_align_2(xa, name);
+}
+
 static LIST_HEAD(shadow_nodes);
 
 static void test_update_node(struct xa_node *node)
@@ -1332,6 +1364,7 @@ static int xarray_checks(void)
        check_create_range(&array);
        check_store_range(&array);
        check_store_iter(&array);
+       check_align(&xa0);
 
        check_workingset(&array, 0);
        check_workingset(&array, 64);
index 5f3f9311de893a2975990060f5dfae6a6fb3d462..81c3171ddde9cce9d6e4898352b5addf5393de4a 100644 (file)
@@ -232,6 +232,8 @@ void *xas_load(struct xa_state *xas)
                if (xas->xa_shift > node->shift)
                        break;
                entry = xas_descend(xas, node);
+               if (node->shift == 0)
+                       break;
        }
        return entry;
 }
@@ -506,7 +508,7 @@ static void xas_free_nodes(struct xa_state *xas, struct xa_node *top)
        for (;;) {
                void *entry = xa_entry_locked(xas->xa, node, offset);
 
-               if (xa_is_node(entry)) {
+               if (node->shift && xa_is_node(entry)) {
                        node = xa_to_node(entry);
                        offset = 0;
                        continue;
@@ -604,6 +606,7 @@ static int xas_expand(struct xa_state *xas, void *head)
 /*
  * xas_create() - Create a slot to store an entry in.
  * @xas: XArray operation state.
+ * @allow_root: %true if we can store the entry in the root directly
  *
  * Most users will not need to call this function directly, as it is called
  * by xas_store().  It is useful for doing conditional store operations
@@ -613,7 +616,7 @@ static int xas_expand(struct xa_state *xas, void *head)
  * If the slot was newly created, returns %NULL.  If it failed to create the
  * slot, returns %NULL and indicates the error in @xas.
  */
-static void *xas_create(struct xa_state *xas)
+static void *xas_create(struct xa_state *xas, bool allow_root)
 {
        struct xarray *xa = xas->xa;
        void *entry;
@@ -628,6 +631,8 @@ static void *xas_create(struct xa_state *xas)
                shift = xas_expand(xas, entry);
                if (shift < 0)
                        return NULL;
+               if (!shift && !allow_root)
+                       shift = XA_CHUNK_SHIFT;
                entry = xa_head_locked(xa);
                slot = &xa->xa_head;
        } else if (xas_error(xas)) {
@@ -687,7 +692,7 @@ void xas_create_range(struct xa_state *xas)
        xas->xa_sibs = 0;
 
        for (;;) {
-               xas_create(xas);
+               xas_create(xas, true);
                if (xas_error(xas))
                        goto restore;
                if (xas->xa_index <= (index | XA_CHUNK_MASK))
@@ -754,7 +759,7 @@ void *xas_store(struct xa_state *xas, void *entry)
        bool value = xa_is_value(entry);
 
        if (entry)
-               first = xas_create(xas);
+               first = xas_create(xas, !xa_is_node(entry));
        else
                first = xas_load(xas);
 
@@ -1250,35 +1255,6 @@ void *xas_find_conflict(struct xa_state *xas)
 }
 EXPORT_SYMBOL_GPL(xas_find_conflict);
 
-/**
- * xa_init_flags() - Initialise an empty XArray with flags.
- * @xa: XArray.
- * @flags: XA_FLAG values.
- *
- * If you need to initialise an XArray with special flags (eg you need
- * to take the lock from interrupt context), use this function instead
- * of xa_init().
- *
- * Context: Any context.
- */
-void xa_init_flags(struct xarray *xa, gfp_t flags)
-{
-       unsigned int lock_type;
-       static struct lock_class_key xa_lock_irq;
-       static struct lock_class_key xa_lock_bh;
-
-       spin_lock_init(&xa->xa_lock);
-       xa->xa_flags = flags;
-       xa->xa_head = NULL;
-
-       lock_type = xa_lock_type(xa);
-       if (lock_type == XA_LOCK_IRQ)
-               lockdep_set_class(&xa->xa_lock, &xa_lock_irq);
-       else if (lock_type == XA_LOCK_BH)
-               lockdep_set_class(&xa->xa_lock, &xa_lock_bh);
-}
-EXPORT_SYMBOL(xa_init_flags);
-
 /**
  * xa_load() - Load an entry from an XArray.
  * @xa: XArray.
@@ -1308,7 +1284,6 @@ static void *xas_result(struct xa_state *xas, void *curr)
 {
        if (xa_is_zero(curr))
                return NULL;
-       XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr));
        if (xas_error(xas))
                curr = xas->xa_node;
        return curr;
@@ -1378,7 +1353,7 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
        XA_STATE(xas, xa, index);
        void *curr;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return XA_ERROR(-EINVAL);
        if (xa_track_free(xa) && !entry)
                entry = XA_ZERO_ENTRY;
@@ -1444,7 +1419,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
        XA_STATE(xas, xa, index);
        void *curr;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return XA_ERROR(-EINVAL);
        if (xa_track_free(xa) && !entry)
                entry = XA_ZERO_ENTRY;
@@ -1464,6 +1439,47 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
 }
 EXPORT_SYMBOL(__xa_cmpxchg);
 
+/**
+ * __xa_insert() - Store this entry in the XArray if no entry is present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Any context.  Expects xa_lock to be held on entry.  May
+ * release and reacquire xa_lock if @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
+{
+       XA_STATE(xas, xa, index);
+       void *curr;
+
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
+               return -EINVAL;
+       if (!entry)
+               entry = XA_ZERO_ENTRY;
+
+       do {
+               curr = xas_load(&xas);
+               if (!curr) {
+                       xas_store(&xas, entry);
+                       if (xa_track_free(xa))
+                               xas_clear_mark(&xas, XA_FREE_MARK);
+               } else {
+                       xas_set_err(&xas, -EEXIST);
+               }
+       } while (__xas_nomem(&xas, gfp));
+
+       return xas_error(&xas);
+}
+EXPORT_SYMBOL(__xa_insert);
+
 /**
  * __xa_reserve() - Reserve this index in the XArray.
  * @xa: XArray.
@@ -1567,7 +1583,7 @@ void *xa_store_range(struct xarray *xa, unsigned long first,
                        if (last + 1)
                                order = __ffs(last + 1);
                        xas_set_order(&xas, last, order);
-                       xas_create(&xas);
+                       xas_create(&xas, true);
                        if (xas_error(&xas))
                                goto unlock;
                }
@@ -1609,7 +1625,7 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
        XA_STATE(xas, xa, 0);
        int err;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return -EINVAL;
        if (WARN_ON_ONCE(!xa_track_free(xa)))
                return -EINVAL;
index 8a8bb8796c6c43cb711c0f618c488df188853623..72e6d0c55cfad9b51b173cca10c34011b035879e 100644 (file)
@@ -689,6 +689,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
        INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC);
        bdi->cgwb_congested_tree = RB_ROOT;
        mutex_init(&bdi->cgwb_release_mutex);
+       init_rwsem(&bdi->wb_switch_rwsem);
 
        ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
        if (!ret) {
index 05acd7e2eb22e0849c5125d0cabc671fdc58f71f..75029649baca4ac834732b931cb9f743cdc58afb 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1674,7 +1674,8 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (!pmd_present(pmd))
                        return 0;
 
-               if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd))) {
+               if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd) ||
+                            pmd_devmap(pmd))) {
                        /*
                         * NUMA hinting faults need to be handled in the GUP
                         * slowpath for accounting purposes and so that they
index df2e7dd5ff17fedb3dd2fdeb1ef9c76c72052eeb..afef61656c1e1ac7bdaf6eb5babf9d040ed51805 100644 (file)
@@ -4268,7 +4268,8 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                                break;
                        }
                        if (ret & VM_FAULT_RETRY) {
-                               if (nonblocking)
+                               if (nonblocking &&
+                                   !(fault_flags & FAULT_FLAG_RETRY_NOWAIT))
                                        *nonblocking = 0;
                                *nr_pages = 0;
                                /*
index 0a14fcff70ed70b385bddd0d842176966d88547b..e2bb06c1b45e9e1583b0407c29dd75370f5251e1 100644 (file)
@@ -5,6 +5,7 @@ UBSAN_SANITIZE_generic.o := n
 UBSAN_SANITIZE_tags.o := n
 KCOV_INSTRUMENT := n
 
+CFLAGS_REMOVE_common.o = -pg
 CFLAGS_REMOVE_generic.o = -pg
 # Function splitter causes unnecessary splits in __asan_load1/__asan_store1
 # see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63533
index 022d4cbb3618bb3886cec62e69912b4e9a5e8067..ea31045ba70423d128575ab7e9e182a40bea425f 100644 (file)
 
 #include "internal.h"
 
+#define INIT_MEMBLOCK_REGIONS                  128
+#define INIT_PHYSMEM_REGIONS                   4
+
+#ifndef INIT_MEMBLOCK_RESERVED_REGIONS
+# define INIT_MEMBLOCK_RESERVED_REGIONS                INIT_MEMBLOCK_REGIONS
+#endif
+
 /**
  * DOC: memblock overview
  *
@@ -92,7 +99,7 @@ unsigned long max_pfn;
 unsigned long long max_possible_pfn;
 
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
-static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
+static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
 static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
 #endif
@@ -105,7 +112,7 @@ struct memblock memblock __initdata_memblock = {
 
        .reserved.regions       = memblock_reserved_init_regions,
        .reserved.cnt           = 1,    /* empty dummy entry */
-       .reserved.max           = INIT_MEMBLOCK_REGIONS,
+       .reserved.max           = INIT_MEMBLOCK_RESERVED_REGIONS,
        .reserved.name          = "reserved",
 
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
index 7c72f2a95785e0d3d5df615ea33477b0bdcc5278..831be5ff5f4df4bee8b9996b99705beeeeb45571 100644 (file)
@@ -372,7 +372,8 @@ static void kill_procs(struct list_head *to_kill, int forcekill, bool fail,
                        if (fail || tk->addr_valid == 0) {
                                pr_err("Memory failure: %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n",
                                       pfn, tk->tsk->comm, tk->tsk->pid);
-                               force_sig(SIGKILL, tk->tsk);
+                               do_send_sig_info(SIGKILL, SEND_SIG_PRIV,
+                                                tk->tsk, PIDTYPE_PID);
                        }
 
                        /*
index b9a667d36c554afc46c2d337a2712e6ca8664fb5..124e794867c564c693e80a2b5827aebe3d3643d3 100644 (file)
@@ -1233,7 +1233,8 @@ static bool is_pageblock_removable_nolock(struct page *page)
 bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 {
        struct page *page = pfn_to_page(start_pfn);
-       struct page *end_page = page + nr_pages;
+       unsigned long end_pfn = min(start_pfn + nr_pages, zone_end_pfn(page_zone(page)));
+       struct page *end_page = pfn_to_page(end_pfn);
 
        /* Check the starting page of each pageblock within the range */
        for (; page < end_page; page = next_active_pageblock(page)) {
@@ -1273,6 +1274,9 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
                                i++;
                        if (i == MAX_ORDER_NR_PAGES || pfn + i >= end_pfn)
                                continue;
+                       /* Check if we got outside of the zone */
+                       if (zone && !zone_spans_pfn(zone, pfn + i))
+                               return 0;
                        page = pfn_to_page(pfn + i);
                        if (zone && page_zone(page) != zone)
                                return 0;
@@ -1301,23 +1305,27 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
 static unsigned long scan_movable_pages(unsigned long start, unsigned long end)
 {
        unsigned long pfn;
-       struct page *page;
+
        for (pfn = start; pfn < end; pfn++) {
-               if (pfn_valid(pfn)) {
-                       page = pfn_to_page(pfn);
-                       if (PageLRU(page))
-                               return pfn;
-                       if (__PageMovable(page))
-                               return pfn;
-                       if (PageHuge(page)) {
-                               if (hugepage_migration_supported(page_hstate(page)) &&
-                                   page_huge_active(page))
-                                       return pfn;
-                               else
-                                       pfn = round_up(pfn + 1,
-                                               1 << compound_order(page)) - 1;
-                       }
-               }
+               struct page *page, *head;
+               unsigned long skip;
+
+               if (!pfn_valid(pfn))
+                       continue;
+               page = pfn_to_page(pfn);
+               if (PageLRU(page))
+                       return pfn;
+               if (__PageMovable(page))
+                       return pfn;
+
+               if (!PageHuge(page))
+                       continue;
+               head = compound_head(page);
+               if (hugepage_migration_supported(page_hstate(head)) &&
+                   page_huge_active(head))
+                       return pfn;
+               skip = (1 << compound_order(head)) - (page - head);
+               pfn += skip - 1;
        }
        return 0;
 }
@@ -1344,7 +1352,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 {
        unsigned long pfn;
        struct page *page;
-       int not_managed = 0;
        int ret = 0;
        LIST_HEAD(source);
 
@@ -1392,7 +1399,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                else
                        ret = isolate_movable_page(page, ISOLATE_UNEVICTABLE);
                if (!ret) { /* Success */
-                       put_page(page);
                        list_add_tail(&page->lru, &source);
                        if (!__PageMovable(page))
                                inc_node_page_state(page, NR_ISOLATED_ANON +
@@ -1401,22 +1407,10 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                } else {
                        pr_warn("failed to isolate pfn %lx\n", pfn);
                        dump_page(page, "isolation failed");
-                       put_page(page);
-                       /* Because we don't have big zone->lock. we should
-                          check this again here. */
-                       if (page_count(page)) {
-                               not_managed++;
-                               ret = -EBUSY;
-                               break;
-                       }
                }
+               put_page(page);
        }
        if (!list_empty(&source)) {
-               if (not_managed) {
-                       putback_movable_pages(&source);
-                       goto out;
-               }
-
                /* Allocate a new page from the nearest neighbor node */
                ret = migrate_pages(&source, new_node_page, NULL, 0,
                                        MIGRATE_SYNC, MR_MEMORY_HOTPLUG);
@@ -1429,7 +1423,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                        putback_movable_pages(&source);
                }
        }
-out:
+
        return ret;
 }
 
@@ -1576,7 +1570,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
           we assume this for now. .*/
        if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
                                  &valid_end)) {
-               mem_hotplug_done();
                ret = -EINVAL;
                reason = "multizone range";
                goto failed_removal;
@@ -1591,7 +1584,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
                                       MIGRATE_MOVABLE,
                                       SKIP_HWPOISON | REPORT_FAILURE);
        if (ret) {
-               mem_hotplug_done();
                reason = "failure to isolate range";
                goto failed_removal;
        }
index a16b15090df3b5f62e8421b16d642db113075eeb..d4fd680be3b0facd6ca1730612b74372a77a196a 100644 (file)
@@ -709,7 +709,6 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
        /* Simple case, sync compaction */
        if (mode != MIGRATE_ASYNC) {
                do {
-                       get_bh(bh);
                        lock_buffer(bh);
                        bh = bh->b_this_page;
 
@@ -720,18 +719,15 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
 
        /* async case, we cannot block on lock_buffer so use trylock_buffer */
        do {
-               get_bh(bh);
                if (!trylock_buffer(bh)) {
                        /*
                         * We failed to lock the buffer and cannot stall in
                         * async migration. Release the taken locks
                         */
                        struct buffer_head *failed_bh = bh;
-                       put_bh(failed_bh);
                        bh = head;
                        while (bh != failed_bh) {
                                unlock_buffer(bh);
-                               put_bh(bh);
                                bh = bh->b_this_page;
                        }
                        return false;
@@ -818,7 +814,6 @@ static int __buffer_migrate_page(struct address_space *mapping,
        bh = head;
        do {
                unlock_buffer(bh);
-               put_bh(bh);
                bh = bh->b_this_page;
 
        } while (bh != head);
@@ -1135,10 +1130,13 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
         * If migration is successful, decrease refcount of the newpage
         * which will not free the page because new page owner increased
         * refcounter. As well, if it is LRU page, add the page to LRU
-        * list in here.
+        * list in here. Use the old state of the isolated source page to
+        * determine if we migrated a LRU page. newpage was already unlocked
+        * and possibly modified by its owner - don't rely on the page
+        * state.
         */
        if (rc == MIGRATEPAGE_SUCCESS) {
-               if (unlikely(__PageMovable(newpage)))
+               if (unlikely(!is_lru))
                        put_page(newpage);
                else
                        putback_lru_page(newpage);
index f0f91461a9f45c350fd8fccc0ccaf6c9578e4b3a..218099b5ed31d1e971d8d64b0951a31b8e310c01 100644 (file)
@@ -42,14 +42,72 @@ static int mincore_hugetlb(pte_t *pte, unsigned long hmask, unsigned long addr,
        return 0;
 }
 
-static int mincore_unmapped_range(unsigned long addr, unsigned long end,
-                                  struct mm_walk *walk)
+/*
+ * Later we can get more picky about what "in core" means precisely.
+ * For now, simply check to see if the page is in the page cache,
+ * and is up to date; i.e. that no page-in operation would be required
+ * at this time if an application were to map and access this page.
+ */
+static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
+{
+       unsigned char present = 0;
+       struct page *page;
+
+       /*
+        * When tmpfs swaps out a page from a file, any process mapping that
+        * file will not get a swp_entry_t in its pte, but rather it is like
+        * any other file mapping (ie. marked !present and faulted in with
+        * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
+        */
+#ifdef CONFIG_SWAP
+       if (shmem_mapping(mapping)) {
+               page = find_get_entry(mapping, pgoff);
+               /*
+                * shmem/tmpfs may return swap: account for swapcache
+                * page too.
+                */
+               if (xa_is_value(page)) {
+                       swp_entry_t swp = radix_to_swp_entry(page);
+                       page = find_get_page(swap_address_space(swp),
+                                            swp_offset(swp));
+               }
+       } else
+               page = find_get_page(mapping, pgoff);
+#else
+       page = find_get_page(mapping, pgoff);
+#endif
+       if (page) {
+               present = PageUptodate(page);
+               put_page(page);
+       }
+
+       return present;
+}
+
+static int __mincore_unmapped_range(unsigned long addr, unsigned long end,
+                               struct vm_area_struct *vma, unsigned char *vec)
 {
-       unsigned char *vec = walk->private;
        unsigned long nr = (end - addr) >> PAGE_SHIFT;
+       int i;
 
-       memset(vec, 0, nr);
-       walk->private += nr;
+       if (vma->vm_file) {
+               pgoff_t pgoff;
+
+               pgoff = linear_page_index(vma, addr);
+               for (i = 0; i < nr; i++, pgoff++)
+                       vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
+       } else {
+               for (i = 0; i < nr; i++)
+                       vec[i] = 0;
+       }
+       return nr;
+}
+
+static int mincore_unmapped_range(unsigned long addr, unsigned long end,
+                                  struct mm_walk *walk)
+{
+       walk->private += __mincore_unmapped_range(addr, end,
+                                                 walk->vma, walk->private);
        return 0;
 }
 
@@ -69,9 +127,8 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                goto out;
        }
 
-       /* We'll consider a THP page under construction to be there */
        if (pmd_trans_unstable(pmd)) {
-               memset(vec, 1, nr);
+               __mincore_unmapped_range(addr, end, vma, vec);
                goto out;
        }
 
@@ -80,17 +137,28 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                pte_t pte = *ptep;
 
                if (pte_none(pte))
-                       *vec = 0;
+                       __mincore_unmapped_range(addr, addr + PAGE_SIZE,
+                                                vma, vec);
                else if (pte_present(pte))
                        *vec = 1;
                else { /* pte is a swap entry */
                        swp_entry_t entry = pte_to_swp_entry(pte);
 
-                       /*
-                        * migration or hwpoison entries are always
-                        * uptodate
-                        */
-                       *vec = !!non_swap_entry(entry);
+                       if (non_swap_entry(entry)) {
+                               /*
+                                * migration or hwpoison entries are always
+                                * uptodate
+                                */
+                               *vec = 1;
+                       } else {
+#ifdef CONFIG_SWAP
+                               *vec = mincore_page(swap_address_space(entry),
+                                                   swp_offset(entry));
+#else
+                               WARN_ON(1);
+                               *vec = 1;
+#endif
+                       }
                }
                vec++;
        }
index f0e8cd9edb1a875819aca9f72c0c5225e90c590b..26ea8636758f8d760564ab2fefeccdc5d7d3b602 100644 (file)
@@ -647,8 +647,8 @@ static int oom_reaper(void *unused)
 
 static void wake_oom_reaper(struct task_struct *tsk)
 {
-       /* tsk is already queued? */
-       if (tsk == oom_reaper_list || tsk->oom_reaper_list)
+       /* mm is already queued? */
+       if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
                return;
 
        get_task_struct(tsk);
@@ -975,6 +975,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
         * still freeing memory.
         */
        read_lock(&tasklist_lock);
+
+       /*
+        * The task 'p' might have already exited before reaching here. The
+        * put_task_struct() will free task_struct 'p' while the loop still try
+        * to access the field of 'p', so, get an extra reference.
+        */
+       get_task_struct(p);
        for_each_thread(p, t) {
                list_for_each_entry(child, &t->children, sibling) {
                        unsigned int child_points;
@@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
                        }
                }
        }
+       put_task_struct(p);
        read_unlock(&tasklist_lock);
 
        /*
index d295c9bc01a898e94a16c077f8834a1492fca9cb..46285d28e43b529b333dbd8c3b3cf0123df66417 100644 (file)
@@ -4675,11 +4675,11 @@ void *page_frag_alloc(struct page_frag_cache *nc,
                /* Even if we own the page, we do not use atomic_set().
                 * This would break get_page_unless_zero() users.
                 */
-               page_ref_add(page, size - 1);
+               page_ref_add(page, size);
 
                /* reset page count bias and offset to start of new frag */
                nc->pfmemalloc = page_is_pfmemalloc(page);
-               nc->pagecnt_bias = size;
+               nc->pagecnt_bias = size + 1;
                nc->offset = size;
        }
 
@@ -4695,10 +4695,10 @@ void *page_frag_alloc(struct page_frag_cache *nc,
                size = nc->size;
 #endif
                /* OK, page count is 0, we can safely set it */
-               set_page_count(page, size);
+               set_page_count(page, size + 1);
 
                /* reset page count bias and offset to start of new frag */
-               nc->pagecnt_bias = size;
+               nc->pagecnt_bias = size + 1;
                offset = size - fragsz;
        }
 
@@ -5701,18 +5701,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                        cond_resched();
                }
        }
-#ifdef CONFIG_SPARSEMEM
-       /*
-        * If the zone does not span the rest of the section then
-        * we should at least initialize those pages. Otherwise we
-        * could blow up on a poisoned page in some paths which depend
-        * on full sections being initialized (e.g. memory hotplug).
-        */
-       while (end_pfn % PAGES_PER_SECTION) {
-               __init_single_page(pfn_to_page(end_pfn), end_pfn, zone, nid);
-               end_pfn++;
-       }
-#endif
 }
 
 #ifdef CONFIG_ZONE_DEVICE
index ae44f7adbe07df3e32b5092ecc74f3c28c7416c2..8c78b8d451179710f7652bc5db7160d28b4161b8 100644 (file)
@@ -398,10 +398,8 @@ void __init page_ext_init(void)
                         * We know some arch can have a nodes layout such as
                         * -------------pfn-------------->
                         * N0 | N1 | N2 | N0 | N1 | N2|....
-                        *
-                        * Take into account DEFERRED_STRUCT_PAGE_INIT.
                         */
-                       if (early_pfn_to_nid(pfn) != nid)
+                       if (pfn_to_nid(pfn) != nid)
                                continue;
                        if (init_section_page_ext(pfn, nid))
                                goto oom;
index a714c4f800e9b8d6a449333363469667ee622767..e979705bbf325531b0cf2d90d26660fe308ea310 100644 (file)
@@ -491,16 +491,6 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
                delta = freeable / 2;
        }
 
-       /*
-        * Make sure we apply some minimal pressure on default priority
-        * even on small cgroups. Stale objects are not only consuming memory
-        * by themselves, but can also hold a reference to a dying cgroup,
-        * preventing it from being reclaimed. A dying cgroup with all
-        * corresponding structures like per-cpu stats and kmem caches
-        * can be really big, so it may lead to a significant waste of memory.
-        */
-       delta = max_t(unsigned long long, delta, min(freeable, batch_size));
-
        total_scan += delta;
        if (total_scan < 0) {
                pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
index 70417e9b932ddcc2d7e5eb8ff1652a0d6ae6d457..314bbc8010fbedaa779d8b3eb772cc5a0fb26eda 100644 (file)
@@ -114,6 +114,7 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
        dst = (ax25_address *)(bp + 1);
        src = (ax25_address *)(bp + 8);
 
+       ax25_route_lock_use();
        route = ax25_get_route(dst, NULL);
        if (route) {
                digipeat = route->digipeat;
@@ -206,9 +207,8 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
        ax25_queue_xmit(skb, dev);
 
 put:
-       if (route)
-               ax25_put_route(route);
 
+       ax25_route_lock_unuse();
        return NETDEV_TX_OK;
 }
 
index a0eff323af12c027ea13a70bfbfffa68b5e48324..66f74c85cf6bd1487a13fbfeeca9eabcdf58fe11 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/export.h>
 
 static ax25_route *ax25_route_list;
-static DEFINE_RWLOCK(ax25_route_lock);
+DEFINE_RWLOCK(ax25_route_lock);
 
 void ax25_rt_device_down(struct net_device *dev)
 {
@@ -335,6 +335,7 @@ const struct seq_operations ax25_rt_seqops = {
  *     Find AX.25 route
  *
  *     Only routes with a reference count of zero can be destroyed.
+ *     Must be called with ax25_route_lock read locked.
  */
 ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 {
@@ -342,7 +343,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
        ax25_route *ax25_def_rt = NULL;
        ax25_route *ax25_rt;
 
-       read_lock(&ax25_route_lock);
        /*
         *      Bind to the physical interface we heard them on, or the default
         *      route if none is found;
@@ -365,11 +365,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
        if (ax25_spe_rt != NULL)
                ax25_rt = ax25_spe_rt;
 
-       if (ax25_rt != NULL)
-               ax25_hold_route(ax25_rt);
-
-       read_unlock(&ax25_route_lock);
-
        return ax25_rt;
 }
 
@@ -400,9 +395,12 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        ax25_route *ax25_rt;
        int err = 0;
 
-       if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
+       ax25_route_lock_use();
+       ax25_rt = ax25_get_route(addr, NULL);
+       if (!ax25_rt) {
+               ax25_route_lock_unuse();
                return -EHOSTUNREACH;
-
+       }
        if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
                err = -EHOSTUNREACH;
                goto put;
@@ -437,8 +435,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        }
 
 put:
-       ax25_put_route(ax25_rt);
-
+       ax25_route_lock_unuse();
        return err;
 }
 
index e8090f099eb805626ffaa1445d3d0f8254f6c9a7..ef0dec20c7d87b283737ad659b244ec2769c1d45 100644 (file)
@@ -104,6 +104,9 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 
                ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
 
+               /* free the TID stats immediately */
+               cfg80211_sinfo_release_content(&sinfo);
+
                dev_put(real_netdev);
                if (ret == -ENOENT) {
                        /* Node is not associated anymore! It would be
index 508f4416dfc9154494888adb5b76efa62673eeaa..415d494cbe223375650b80696f1288fccdd54973 100644 (file)
@@ -20,7 +20,6 @@
 #include "main.h"
 
 #include <linux/atomic.h>
-#include <linux/bug.h>
 #include <linux/byteorder/generic.h>
 #include <linux/errno.h>
 #include <linux/gfp.h>
@@ -179,8 +178,10 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
        parent_dev = __dev_get_by_index((struct net *)parent_net,
                                        dev_get_iflink(net_dev));
        /* if we got a NULL parent_dev there is something broken.. */
-       if (WARN(!parent_dev, "Cannot find parent device"))
+       if (!parent_dev) {
+               pr_err("Cannot find parent device\n");
                return false;
+       }
 
        if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net))
                return false;
index 5db5a0a4c959b796c86315832f64073b5642e46a..ffc83bebfe4038df24c5b8cce093c32a302dac18 100644 (file)
@@ -221,10 +221,14 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
 
        netif_trans_update(soft_iface);
        vid = batadv_get_vid(skb, 0);
+
+       skb_reset_mac_header(skb);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
        case ETH_P_8021Q:
+               if (!pskb_may_pull(skb, sizeof(*vhdr)))
+                       goto dropped;
                vhdr = vlan_eth_hdr(skb);
 
                /* drop batman-in-batman packets to prevent loops */
index 7acfc83087d5c4e2bd923ef6065f534b49da9bfd..7ee4fea93637534a0aa97f95eee3d00270b7044e 100644 (file)
 extern char bpfilter_umh_start;
 extern char bpfilter_umh_end;
 
-static struct umh_info info;
-/* since ip_getsockopt() can run in parallel, serialize access to umh */
-static DEFINE_MUTEX(bpfilter_lock);
-
-static void shutdown_umh(struct umh_info *info)
+static void shutdown_umh(void)
 {
        struct task_struct *tsk;
 
-       if (!info->pid)
+       if (bpfilter_ops.stop)
                return;
-       tsk = get_pid_task(find_vpid(info->pid), PIDTYPE_PID);
+
+       tsk = get_pid_task(find_vpid(bpfilter_ops.info.pid), PIDTYPE_PID);
        if (tsk) {
                force_sig(SIGKILL, tsk);
                put_task_struct(tsk);
        }
-       fput(info->pipe_to_umh);
-       fput(info->pipe_from_umh);
-       info->pid = 0;
 }
 
 static void __stop_umh(void)
 {
-       if (IS_ENABLED(CONFIG_INET)) {
-               bpfilter_process_sockopt = NULL;
-               shutdown_umh(&info);
-       }
-}
-
-static void stop_umh(void)
-{
-       mutex_lock(&bpfilter_lock);
-       __stop_umh();
-       mutex_unlock(&bpfilter_lock);
+       if (IS_ENABLED(CONFIG_INET))
+               shutdown_umh();
 }
 
 static int __bpfilter_process_sockopt(struct sock *sk, int optname,
@@ -63,10 +48,10 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        req.cmd = optname;
        req.addr = (long __force __user)optval;
        req.len = optlen;
-       mutex_lock(&bpfilter_lock);
-       if (!info.pid)
+       if (!bpfilter_ops.info.pid)
                goto out;
-       n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
+       n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
+                          &pos);
        if (n != sizeof(req)) {
                pr_err("write fail %zd\n", n);
                __stop_umh();
@@ -74,7 +59,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
                goto out;
        }
        pos = 0;
-       n = kernel_read(info.pipe_from_umh, &reply, sizeof(reply), &pos);
+       n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
+                       &pos);
        if (n != sizeof(reply)) {
                pr_err("read fail %zd\n", n);
                __stop_umh();
@@ -83,37 +69,59 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        }
        ret = reply.status;
 out:
-       mutex_unlock(&bpfilter_lock);
        return ret;
 }
 
-static int __init load_umh(void)
+static int start_umh(void)
 {
        int err;
 
        /* fork usermode process */
-       info.cmdline = "bpfilter_umh";
        err = fork_usermode_blob(&bpfilter_umh_start,
                                 &bpfilter_umh_end - &bpfilter_umh_start,
-                                &info);
+                                &bpfilter_ops.info);
        if (err)
                return err;
-       pr_info("Loaded bpfilter_umh pid %d\n", info.pid);
+       bpfilter_ops.stop = false;
+       pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid);
 
        /* health check that usermode process started correctly */
        if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) {
-               stop_umh();
+               shutdown_umh();
                return -EFAULT;
        }
-       if (IS_ENABLED(CONFIG_INET))
-               bpfilter_process_sockopt = &__bpfilter_process_sockopt;
 
        return 0;
 }
 
+static int __init load_umh(void)
+{
+       int err;
+
+       mutex_lock(&bpfilter_ops.lock);
+       if (!bpfilter_ops.stop) {
+               err = -EFAULT;
+               goto out;
+       }
+       err = start_umh();
+       if (!err && IS_ENABLED(CONFIG_INET)) {
+               bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
+               bpfilter_ops.start = &start_umh;
+       }
+out:
+       mutex_unlock(&bpfilter_ops.lock);
+       return err;
+}
+
 static void __exit fini_umh(void)
 {
-       stop_umh();
+       mutex_lock(&bpfilter_ops.lock);
+       if (IS_ENABLED(CONFIG_INET)) {
+               shutdown_umh();
+               bpfilter_ops.start = NULL;
+               bpfilter_ops.sockopt = NULL;
+       }
+       mutex_unlock(&bpfilter_ops.lock);
 }
 module_init(load_umh);
 module_exit(fini_umh);
index 40311d10d2f270adbb7a51cfc3bad0c2834ca438..9ea6100dca875fe463b689211a20bb66eb263659 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-       .section .init.rodata, "a"
+       .section .rodata, "a"
        .global bpfilter_umh_start
 bpfilter_umh_start:
        .incbin "net/bpfilter/bpfilter_umh"
index fe3c758791ca99671d57b151b656e72cba38a718..9e14767500ea8982a5b2cf33b4800a18c4562a12 100644 (file)
@@ -1128,6 +1128,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                        err = -ENOMEM;
                        goto err_unlock;
                }
+               if (swdev_notify)
+                       fdb->added_by_user = 1;
                fdb->added_by_external_learn = 1;
                fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
        } else {
@@ -1147,6 +1149,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                        modified = true;
                }
 
+               if (swdev_notify)
+                       fdb->added_by_user = 1;
+
                if (modified)
                        fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
        }
index 5372e2042adfe20d3cd039c29057535b2413be61..48ddc60b4fbdece571592bc86689860707ddf6ba 100644 (file)
@@ -36,10 +36,10 @@ static inline int should_deliver(const struct net_bridge_port *p,
 
 int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       skb_push(skb, ETH_HLEN);
        if (!is_skb_forwardable(skb->dev, skb))
                goto drop;
 
-       skb_push(skb, ETH_HLEN);
        br_drop_fake_rtable(skb);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
@@ -65,6 +65,7 @@ EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
 
 int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       skb->tstamp = 0;
        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING,
                       net, sk, skb, NULL, skb->dev,
                       br_dev_queue_push_xmit);
@@ -97,12 +98,11 @@ static void __br_forward(const struct net_bridge_port *to,
                net = dev_net(indev);
        } else {
                if (unlikely(netpoll_tx_running(to->br->dev))) {
-                       if (!is_skb_forwardable(skb->dev, skb)) {
+                       skb_push(skb, ETH_HLEN);
+                       if (!is_skb_forwardable(skb->dev, skb))
                                kfree_skb(skb);
-                       } else {
-                               skb_push(skb, ETH_HLEN);
+                       else
                                br_netpoll_send_skb(to, skb);
-                       }
                        return;
                }
                br_hook = NF_BR_LOCAL_OUT;
index d21a23698410152d977576c0bd7973731077081f..c93c35bb73ddeda8b6d0056016c30846674299fc 100644 (file)
@@ -265,7 +265,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
                struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
                int ret;
 
-               if (neigh->hh.hh_len) {
+               if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) {
                        neigh_hh_bridge(&neigh->hh, skb);
                        skb->dev = nf_bridge->physindev;
                        ret = br_handle_frame_finish(net, sk, skb);
index 94039f588f1dd1c390f5b65dd62c23f86ee2687e..564710f88f938cb314f2f59177289ecb127454f4 100644 (file)
@@ -131,6 +131,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
                                        IPSTATS_MIB_INDISCARDS);
                        goto drop;
                }
+               hdr = ipv6_hdr(skb);
        }
        if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb))
                goto drop;
index d240b3e7919fe02d2334192e23996d6af89235ce..eabf8bf28a3f1fd5909b17ebe9fb00caace24881 100644 (file)
@@ -107,6 +107,7 @@ struct br_tunnel_info {
 /* private vlan flags */
 enum {
        BR_VLFLAG_PER_PORT_STATS = BIT(0),
+       BR_VLFLAG_ADDED_BY_SWITCHDEV = BIT(1),
 };
 
 /**
index 4a2f31157ef5efaa4f380be7d6bd50d805d1d27b..96abf8feb9dc6c2e01a39fa1f9827fc4da1bb1b7 100644 (file)
@@ -80,16 +80,18 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags)
 }
 
 static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
-                         u16 vid, u16 flags, struct netlink_ext_ack *extack)
+                         struct net_bridge_vlan *v, u16 flags,
+                         struct netlink_ext_ack *extack)
 {
        int err;
 
        /* Try switchdev op first. In case it is not supported, fallback to
         * 8021q add.
         */
-       err = br_switchdev_port_vlan_add(dev, vid, flags, extack);
+       err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack);
        if (err == -EOPNOTSUPP)
-               return vlan_vid_add(dev, br->vlan_proto, vid);
+               return vlan_vid_add(dev, br->vlan_proto, v->vid);
+       v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV;
        return err;
 }
 
@@ -121,19 +123,17 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 }
 
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
-                         u16 vid)
+                         const struct net_bridge_vlan *v)
 {
        int err;
 
        /* Try switchdev op first. In case it is not supported, fallback to
         * 8021q del.
         */
-       err = br_switchdev_port_vlan_del(dev, vid);
-       if (err == -EOPNOTSUPP) {
-               vlan_vid_del(dev, br->vlan_proto, vid);
-               return 0;
-       }
-       return err;
+       err = br_switchdev_port_vlan_del(dev, v->vid);
+       if (!(v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV))
+               vlan_vid_del(dev, br->vlan_proto, v->vid);
+       return err == -EOPNOTSUPP ? 0 : err;
 }
 
 /* Returns a master vlan, if it didn't exist it gets created. In all cases a
@@ -242,7 +242,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
                 * This ensures tagged traffic enters the bridge when
                 * promiscuous mode is disabled by br_manage_promisc().
                 */
-               err = __vlan_vid_add(dev, br, v->vid, flags, extack);
+               err = __vlan_vid_add(dev, br, v, flags, extack);
                if (err)
                        goto out;
 
@@ -305,7 +305,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
 
 out_filt:
        if (p) {
-               __vlan_vid_del(dev, br, v->vid);
+               __vlan_vid_del(dev, br, v);
                if (masterv) {
                        if (v->stats && masterv->stats != v->stats)
                                free_percpu(v->stats);
@@ -338,7 +338,7 @@ static int __vlan_del(struct net_bridge_vlan *v)
 
        __vlan_delete_pvid(vg, v->vid);
        if (p) {
-               err = __vlan_vid_del(p->dev, p->br, v->vid);
+               err = __vlan_vid_del(p->dev, p->br, v);
                if (err)
                        goto out;
        } else {
index 491828713e0bd738763beae0c48aff44dcc5c76f..6693e209efe809c86047abbfa019212e0e36c314 100644 (file)
@@ -1137,14 +1137,16 @@ static int do_replace(struct net *net, const void __user *user,
        tmp.name[sizeof(tmp.name) - 1] = 0;
 
        countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
-       newinfo = vmalloc(sizeof(*newinfo) + countersize);
+       newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT,
+                           PAGE_KERNEL);
        if (!newinfo)
                return -ENOMEM;
 
        if (countersize)
                memset(newinfo->counters, 0, countersize);
 
-       newinfo->entries = vmalloc(tmp.entries_size);
+       newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT,
+                                    PAGE_KERNEL);
        if (!newinfo->entries) {
                ret = -ENOMEM;
                goto free_newinfo;
@@ -2291,9 +2293,12 @@ static int compat_do_replace(struct net *net, void __user *user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
-       ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
-       if (ret < 0)
-               goto out_unlock;
+       if (tmp.nentries) {
+               ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
+               if (ret < 0)
+                       goto out_unlock;
+       }
+
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
                goto out_unlock;
index 08cbed7d940e37ee34e58c364326f3b75bab50f7..419e8edf23ba8bb5f7626529bc873f81b0f4c63c 100644 (file)
@@ -229,6 +229,7 @@ static bool reject6_br_csum_ok(struct sk_buff *skb, int hook)
            pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h)))
                return false;
 
+       ip6h = ipv6_hdr(skb);
        thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo);
        if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0)
                return false;
index 0af8f0db892a3311fb5a1a898ab0bff5696adf00..79bb8afa9c0c0990729a781acc7220a78ee317af 100644 (file)
@@ -67,6 +67,9 @@
  */
 #define MAX_NFRAMES 256
 
+/* limit timers to 400 days for sending/timeouts */
+#define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
+
 /* use of last_frames[index].flags */
 #define RX_RECV    0x40 /* received data for this element */
 #define RX_THR     0x80 /* element not been sent due to throttle feature */
@@ -140,6 +143,22 @@ static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
        return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
 }
 
+/* check limitations for timeval provided by user */
+static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
+{
+       if ((msg_head->ival1.tv_sec < 0) ||
+           (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
+           (msg_head->ival1.tv_usec < 0) ||
+           (msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
+           (msg_head->ival2.tv_sec < 0) ||
+           (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
+           (msg_head->ival2.tv_usec < 0) ||
+           (msg_head->ival2.tv_usec >= USEC_PER_SEC))
+               return true;
+
+       return false;
+}
+
 #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU)
 #define OPSIZ sizeof(struct bcm_op)
 #define MHSIZ sizeof(struct bcm_msg_head)
@@ -873,6 +892,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
        if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
                return -EINVAL;
 
+       /* check timeval limitations */
+       if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+               return -EINVAL;
+
        /* check the given can_id */
        op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
        if (op) {
@@ -1053,6 +1076,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
             (!(msg_head->can_id & CAN_RTR_FLAG))))
                return -EINVAL;
 
+       /* check timeval limitations */
+       if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+               return -EINVAL;
+
        /* check the given can_id */
        op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
        if (op) {
index faa3da88a127785836bcf5ee31064a663a03568c..53859346dc9a92f76daf35e4daf68a15ef1c2c9b 100644 (file)
@@ -416,13 +416,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
        while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
                (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
 
-       /* check for checksum updates when the CAN frame has been modified */
+       /* Has the CAN frame been modified? */
        if (modidx) {
-               if (gwj->mod.csumfunc.crc8)
+               /* get available space for the processed CAN frame type */
+               int max_len = nskb->len - offsetof(struct can_frame, data);
+
+               /* dlc may have changed, make sure it fits to the CAN frame */
+               if (cf->can_dlc > max_len)
+                       goto out_delete;
+
+               /* check for checksum updates in classic CAN length only */
+               if (gwj->mod.csumfunc.crc8) {
+                       if (cf->can_dlc > 8)
+                               goto out_delete;
+
                        (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
+               }
+
+               if (gwj->mod.csumfunc.xor) {
+                       if (cf->can_dlc > 8)
+                               goto out_delete;
 
-               if (gwj->mod.csumfunc.xor)
                        (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
+               }
        }
 
        /* clear the skb timestamp if not configured the other way */
@@ -434,6 +450,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
                gwj->dropped_frames++;
        else
                gwj->handled_frames++;
+
+       return;
+
+ out_delete:
+       /* delete frame due to misconfiguration */
+       gwj->deleted_frames++;
+       kfree_skb(nskb);
+       return;
 }
 
 static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
index d5718284db5721dfe96554b48cca5d38bdc40942..3661cdd927f15fc78a8b1436822924be5d4c8a17 100644 (file)
@@ -3206,9 +3206,10 @@ void ceph_con_keepalive(struct ceph_connection *con)
        dout("con_keepalive %p\n", con);
        mutex_lock(&con->mutex);
        clear_standby(con);
+       con_flag_set(con, CON_FLAG_KEEPALIVE_PENDING);
        mutex_unlock(&con->mutex);
-       if (con_flag_test_and_set(con, CON_FLAG_KEEPALIVE_PENDING) == 0 &&
-           con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
+
+       if (con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
                queue_con(con);
 }
 EXPORT_SYMBOL(ceph_con_keepalive);
index 82f20022259da123e085e0e296e9cd1b97580999..8e276e0192a11add47992a6cca955e8eb13e66d8 100644 (file)
@@ -8712,6 +8712,9 @@ int init_dummy_netdev(struct net_device *dev)
        set_bit(__LINK_STATE_PRESENT, &dev->state);
        set_bit(__LINK_STATE_START, &dev->state);
 
+       /* napi_busy_loop stats accounting wants this */
+       dev_net_set(dev, &init_net);
+
        /* Note : We dont allocate pcpu_refcnt for dummy devices,
         * because users of this 'device' dont need to change
         * its refcount.
index 447dd1bad31fa953e222304e60af5519b2621798..7a54dc11ac2d3c7f4f81d8e9c34a3ae5a8cff4b4 100644 (file)
@@ -2020,18 +2020,19 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
 static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
                                 u32 flags)
 {
-       /* skb->mac_len is not set on normal egress */
-       unsigned int mlen = skb->network_header - skb->mac_header;
+       unsigned int mlen = skb_network_offset(skb);
 
-       __skb_pull(skb, mlen);
+       if (mlen) {
+               __skb_pull(skb, mlen);
 
-       /* At ingress, the mac header has already been pulled once.
-        * At egress, skb_pospull_rcsum has to be done in case that
-        * the skb is originated from ingress (i.e. a forwarded skb)
-        * to ensure that rcsum starts at net header.
-        */
-       if (!skb_at_tc_ingress(skb))
-               skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+               /* At ingress, the mac header has already been pulled once.
+                * At egress, skb_pospull_rcsum has to be done in case that
+                * the skb is originated from ingress (i.e. a forwarded skb)
+                * to ensure that rcsum starts at net header.
+                */
+               if (!skb_at_tc_ingress(skb))
+                       skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+       }
        skb_pop_mac_header(skb);
        skb_reset_mac_len(skb);
        return flags & BPF_F_INGRESS ?
@@ -4111,14 +4112,20 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                /* Only some socketops are supported */
                switch (optname) {
                case SO_RCVBUF:
+                       val = min_t(u32, val, sysctl_rmem_max);
                        sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
                        sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
                        break;
                case SO_SNDBUF:
+                       val = min_t(u32, val, sysctl_wmem_max);
                        sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
                        sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
                        break;
                case SO_MAX_PACING_RATE: /* 32bit version */
+                       if (val != ~0U)
+                               cmpxchg(&sk->sk_pacing_status,
+                                       SK_PACING_NONE,
+                                       SK_PACING_NEEDED);
                        sk->sk_max_pacing_rate = (val == ~0U) ? ~0UL : val;
                        sk->sk_pacing_rate = min(sk->sk_pacing_rate,
                                                 sk->sk_max_pacing_rate);
@@ -4132,7 +4139,10 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        sk->sk_rcvlowat = val ? : 1;
                        break;
                case SO_MARK:
-                       sk->sk_mark = val;
+                       if (sk->sk_mark != val) {
+                               sk->sk_mark = val;
+                               sk_dst_reset(sk);
+                       }
                        break;
                default:
                        ret = -EINVAL;
@@ -4203,7 +4213,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        /* Only some options are supported */
                        switch (optname) {
                        case TCP_BPF_IW:
-                               if (val <= 0 || tp->data_segs_out > 0)
+                               if (val <= 0 || tp->data_segs_out > tp->syn_data)
                                        ret = -EINVAL;
                                else
                                        tp->snd_cwnd = val;
@@ -5309,7 +5319,7 @@ bpf_base_func_proto(enum bpf_func_id func_id)
        case BPF_FUNC_trace_printk:
                if (capable(CAP_SYS_ADMIN))
                        return bpf_get_trace_printk_proto();
-               /* else: fall through */
+               /* else, fall through */
        default:
                return NULL;
        }
index 3e85437f710608ca78db3d5645cf42ac45fee801..a648568c5e8fed087769f70c71e9c6300aa8002c 100644 (file)
@@ -63,6 +63,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
                                     lwt->name ? : "<unknown>");
                        ret = BPF_OK;
                } else {
+                       skb_reset_mac_header(skb);
                        ret = skb_do_redirect(skb);
                        if (ret == 0)
                                ret = BPF_REDIRECT;
index 763a7b08df67cbc63a3fa2e78067d5e23ff6257d..4230400b9a309fb7c317d7ec7230a0db17f4ac3d 100644 (file)
@@ -18,6 +18,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/slab.h>
+#include <linux/kmemleak.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -443,12 +444,14 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
        ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
        if (!ret)
                return NULL;
-       if (size <= PAGE_SIZE)
+       if (size <= PAGE_SIZE) {
                buckets = kzalloc(size, GFP_ATOMIC);
-       else
+       } else {
                buckets = (struct neighbour __rcu **)
                          __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
                                           get_order(size));
+               kmemleak_alloc(buckets, size, 1, GFP_ATOMIC);
+       }
        if (!buckets) {
                kfree(ret);
                return NULL;
@@ -468,10 +471,12 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
        size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
        struct neighbour __rcu **buckets = nht->hash_buckets;
 
-       if (size <= PAGE_SIZE)
+       if (size <= PAGE_SIZE) {
                kfree(buckets);
-       else
+       } else {
+               kmemleak_free(buckets);
                free_pages((unsigned long)buckets, get_order(size));
+       }
        kfree(nht);
 }
 
@@ -1002,7 +1007,7 @@ static void neigh_probe(struct neighbour *neigh)
        if (neigh->ops->solicit)
                neigh->ops->solicit(neigh, skb);
        atomic_inc(&neigh->probes);
-       kfree_skb(skb);
+       consume_skb(skb);
 }
 
 /* Called when a timer expires for a neighbour entry. */
index 37317ffec146f18ec04c82384c39d0ee3d018c6d..26d8484849126ea0a418b6290dcdcba30bf44c2f 100644 (file)
@@ -5270,7 +5270,6 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
        unsigned long chunk;
        struct sk_buff *skb;
        struct page *page;
-       gfp_t gfp_head;
        int i;
 
        *errcode = -EMSGSIZE;
@@ -5280,12 +5279,8 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
        if (npages > MAX_SKB_FRAGS)
                return NULL;
 
-       gfp_head = gfp_mask;
-       if (gfp_head & __GFP_DIRECT_RECLAIM)
-               gfp_head |= __GFP_RETRY_MAYFAIL;
-
        *errcode = -ENOBUFS;
-       skb = alloc_skb(header_len, gfp_head);
+       skb = alloc_skb(header_len, gfp_mask);
        if (!skb)
                return NULL;
 
index d6d5c20d7044c88c82ef9b61d83abfcce1ad9d92..8c826603bf36313e2ee945e802003bc77355597b 100644 (file)
@@ -545,8 +545,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc)
        struct sk_psock *psock = container_of(gc, struct sk_psock, gc);
 
        /* No sk_callback_lock since already detached. */
-       if (psock->parser.enabled)
-               strp_done(&psock->parser.strp);
+       strp_done(&psock->parser.strp);
 
        cancel_work_sync(&psock->work);
 
index 6aa2e7e0b4fbdbc29d43d6b61a53b8de2a7ba269..bc3512f230a304c97c519a82c69d1e86f115b651 100644 (file)
@@ -2380,7 +2380,7 @@ int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
        }
 
        if (sk_has_memory_pressure(sk)) {
-               int alloc;
+               u64 alloc;
 
                if (!sk_under_memory_pressure(sk))
                        return 1;
index 6eb837a47b5c42f8c73c498525fe4d269fc5b97d..baaaeb2b2c4230edee893579d0ae5a755da3b2ee 100644 (file)
@@ -202,7 +202,7 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
                                           u8 pkt, u8 opt, u8 *val, u8 len)
 {
-       if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
+       if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
                return 0;
        return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
 }
@@ -214,7 +214,7 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
                                           u8 pkt, u8 opt, u8 *val, u8 len)
 {
-       if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
+       if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
                return 0;
        return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
 }
index d0b3e69c6b39ba2f051f128dc1e0daa44291fc77..0962f9201baa14854be26a44fc5c9d807d700295 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/dn_neigh.h>
 #include <net/dn_fib.h>
 
-#define DN_IFREQ_SIZE (sizeof(struct ifreq) - sizeof(struct sockaddr) + sizeof(struct sockaddr_dn))
+#define DN_IFREQ_SIZE (offsetof(struct ifreq, ifr_ifru) + sizeof(struct sockaddr_dn))
 
 static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
 static char dn_rt_all_rt_mcast[ETH_ALEN]  = {0xAB,0x00,0x00,0x03,0x00,0x00};
index 71bb15f491c81af1c911d4182d746e89095ae68e..54f5551fb79920ddefb37ee16b945e7e839f4696 100644 (file)
@@ -205,6 +205,8 @@ static void dsa_master_reset_mtu(struct net_device *dev)
        rtnl_unlock();
 }
 
+static struct lock_class_key dsa_master_addr_list_lock_key;
+
 int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 {
        int ret;
@@ -218,6 +220,8 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
        wmb();
 
        dev->dsa_ptr = cpu_dp;
+       lockdep_set_class(&dev->addr_list_lock,
+                         &dsa_master_addr_list_lock_key);
 
        ret = dsa_master_ethtool_setup(dev);
        if (ret)
index a3fcc1d016153c03bd2ec34a738e29b3ecdae9b0..a1c9fe155057299206683311c88c55e6f2cc0095 100644 (file)
@@ -140,11 +140,14 @@ static int dsa_slave_close(struct net_device *dev)
 static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 {
        struct net_device *master = dsa_slave_to_master(dev);
-
-       if (change & IFF_ALLMULTI)
-               dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
-       if (change & IFF_PROMISC)
-               dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1);
+       if (dev->flags & IFF_UP) {
+               if (change & IFF_ALLMULTI)
+                       dev_set_allmulti(master,
+                                        dev->flags & IFF_ALLMULTI ? 1 : -1);
+               if (change & IFF_PROMISC)
+                       dev_set_promiscuity(master,
+                                           dev->flags & IFF_PROMISC ? 1 : -1);
+       }
 }
 
 static void dsa_slave_set_rx_mode(struct net_device *dev)
@@ -639,7 +642,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
        int ret;
 
        /* Port's PHY and MAC both need to be EEE capable */
-       if (!dev->phydev && !dp->pl)
+       if (!dev->phydev || !dp->pl)
                return -ENODEV;
 
        if (!ds->ops->set_mac_eee)
@@ -659,7 +662,7 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
        int ret;
 
        /* Port's PHY and MAC both need to be EEE capable */
-       if (!dev->phydev && !dp->pl)
+       if (!dev->phydev || !dp->pl)
                return -ENODEV;
 
        if (!ds->ops->get_mac_eee)
index 5e04ed25bc0e92a5f4e62c78b45b50d9e6b7d1fc..1e976bb93d99821ba63e444017bd839f231b7092 100644 (file)
@@ -1,28 +1,54 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/bpfilter.h>
 #include <uapi/linux/bpf.h>
 #include <linux/wait.h>
 #include <linux/kmod.h>
+#include <linux/fs.h>
+#include <linux/file.h>
 
-int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
-                               char __user *optval,
-                               unsigned int optlen, bool is_set);
-EXPORT_SYMBOL_GPL(bpfilter_process_sockopt);
+struct bpfilter_umh_ops bpfilter_ops;
+EXPORT_SYMBOL_GPL(bpfilter_ops);
+
+static void bpfilter_umh_cleanup(struct umh_info *info)
+{
+       mutex_lock(&bpfilter_ops.lock);
+       bpfilter_ops.stop = true;
+       fput(info->pipe_to_umh);
+       fput(info->pipe_from_umh);
+       info->pid = 0;
+       mutex_unlock(&bpfilter_ops.lock);
+}
 
 static int bpfilter_mbox_request(struct sock *sk, int optname,
                                 char __user *optval,
                                 unsigned int optlen, bool is_set)
 {
-       if (!bpfilter_process_sockopt) {
-               int err = request_module("bpfilter");
+       int err;
+       mutex_lock(&bpfilter_ops.lock);
+       if (!bpfilter_ops.sockopt) {
+               mutex_unlock(&bpfilter_ops.lock);
+               err = request_module("bpfilter");
+               mutex_lock(&bpfilter_ops.lock);
 
                if (err)
-                       return err;
-               if (!bpfilter_process_sockopt)
-                       return -ECHILD;
+                       goto out;
+               if (!bpfilter_ops.sockopt) {
+                       err = -ECHILD;
+                       goto out;
+               }
+       }
+       if (bpfilter_ops.stop) {
+               err = bpfilter_ops.start();
+               if (err)
+                       goto out;
        }
-       return bpfilter_process_sockopt(sk, optname, optval, optlen, is_set);
+       err = bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set);
+out:
+       mutex_unlock(&bpfilter_ops.lock);
+       return err;
 }
 
 int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
@@ -41,3 +67,15 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
 
        return bpfilter_mbox_request(sk, optname, optval, len, false);
 }
+
+static int __init bpfilter_sockopt_init(void)
+{
+       mutex_init(&bpfilter_ops.lock);
+       bpfilter_ops.stop = true;
+       bpfilter_ops.info.cmdline = "bpfilter_umh";
+       bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;
+
+       return 0;
+}
+
+module_init(bpfilter_sockopt_init);
index 04ba321ae5cee0cf9bb2a6d3e47c8df4f1c11976..e258a00b4a3d6c11df57bf951213795b14f792d6 100644 (file)
@@ -1826,7 +1826,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
-       return err < 0 ? err : skb->len;
+       return skb->len ? : err;
 }
 
 static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
index 6df95be963116ced81f70e5fb51bfe6114e8965a..fe4f6a62423834a79705e0c01cd1329d9da4f836 100644 (file)
@@ -203,7 +203,7 @@ static void fib_flush(struct net *net)
                struct fib_table *tb;
 
                hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
-                       flushed += fib_table_flush(net, tb);
+                       flushed += fib_table_flush(net, tb, false);
        }
 
        if (flushed)
@@ -1463,7 +1463,7 @@ static void ip_fib_net_exit(struct net *net)
 
                hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
                        hlist_del(&tb->tb_hlist);
-                       fib_table_flush(net, tb);
+                       fib_table_flush(net, tb, true);
                        fib_free_table(tb);
                }
        }
index 237c9f72b2658ce6c622af1bbdbb4792da12ade1..a573e37e0615b1b1b5093ae3ada97f07c44f27cb 100644 (file)
@@ -1856,7 +1856,7 @@ void fib_table_flush_external(struct fib_table *tb)
 }
 
 /* Caller must hold RTNL. */
-int fib_table_flush(struct net *net, struct fib_table *tb)
+int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 {
        struct trie *t = (struct trie *)tb->tb_data;
        struct key_vector *pn = t->kv;
@@ -1904,8 +1904,17 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
                hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) {
                        struct fib_info *fi = fa->fa_info;
 
-                       if (!fi || !(fi->fib_flags & RTNH_F_DEAD) ||
-                           tb->tb_id != fa->tb_id) {
+                       if (!fi || tb->tb_id != fa->tb_id ||
+                           (!(fi->fib_flags & RTNH_F_DEAD) &&
+                            !fib_props[fa->fa_type].error)) {
+                               slen = fa->fa_slen;
+                               continue;
+                       }
+
+                       /* Do not flush error routes if network namespace is
+                        * not being dismantled
+                        */
+                       if (!flush_all && fib_props[fa->fa_type].error) {
                                slen = fa->fa_slen;
                                continue;
                        }
index 0c9f171fb085e15c50416b5969e68c98569faecd..437070d1ffb180ef3601eae03c7666ae5e1bd78b 100644 (file)
@@ -1020,10 +1020,11 @@ static int gue_err(struct sk_buff *skb, u32 info)
 {
        int transport_offset = skb_transport_offset(skb);
        struct guehdr *guehdr;
-       size_t optlen;
+       size_t len, optlen;
        int ret;
 
-       if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr))
+       len = sizeof(struct udphdr) + sizeof(struct guehdr);
+       if (!pskb_may_pull(skb, len))
                return -EINVAL;
 
        guehdr = (struct guehdr *)&udp_hdr(skb)[1];
@@ -1058,6 +1059,10 @@ static int gue_err(struct sk_buff *skb, u32 info)
 
        optlen = guehdr->hlen << 2;
 
+       if (!pskb_may_pull(skb, len + optlen))
+               return -EINVAL;
+
+       guehdr = (struct guehdr *)&udp_hdr(skb)[1];
        if (validate_gue_flags(guehdr, optlen))
                return -EINVAL;
 
@@ -1065,7 +1070,8 @@ static int gue_err(struct sk_buff *skb, u32 info)
         * recursion. Besides, this kind of encapsulation can't even be
         * configured currently. Discard this.
         */
-       if (guehdr->proto_ctype == IPPROTO_UDP)
+       if (guehdr->proto_ctype == IPPROTO_UDP ||
+           guehdr->proto_ctype == IPPROTO_UDPLITE)
                return -EOPNOTSUPP;
 
        skb_set_transport_header(skb, -(int)sizeof(struct icmphdr));
index a4bf22ee3aedb746c999a20a4e6f0bd9e0ccbfe0..7c4a41dc04bbe13fa7d955d40b15fe963623186a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 #include <net/gre.h>
+#include <net/erspan.h>
 
 #include <net/icmp.h>
 #include <net/route.h>
@@ -119,6 +120,22 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                        hdr_len += 4;
        }
        tpi->hdr_len = hdr_len;
+
+       /* ERSPAN ver 1 and 2 protocol sets GRE key field
+        * to 0 and sets the configured key in the
+        * inner erspan header field
+        */
+       if (greh->protocol == htons(ETH_P_ERSPAN) ||
+           greh->protocol == htons(ETH_P_ERSPAN2)) {
+               struct erspan_base_hdr *ershdr;
+
+               if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr)))
+                       return -EINVAL;
+
+               ershdr = (struct erspan_base_hdr *)options;
+               tpi->key = cpu_to_be32(get_session_id(ershdr));
+       }
+
        return hdr_len;
 }
 EXPORT_SYMBOL(gre_parse_header);
index 1a4e9ff02762ed757545da13de1ee352f38c867b..5731670c560b04a85bcc3bd92e8422108c91b58b 100644 (file)
@@ -108,6 +108,7 @@ static size_t inet_sk_attr_size(struct sock *sk,
                + nla_total_size(1) /* INET_DIAG_TOS */
                + nla_total_size(1) /* INET_DIAG_TCLASS */
                + nla_total_size(4) /* INET_DIAG_MARK */
+               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(sizeof(struct inet_diag_meminfo))
                + nla_total_size(sizeof(struct inet_diag_msg))
                + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
@@ -287,12 +288,19 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                        goto errout;
        }
 
-       if (ext & (1 << (INET_DIAG_CLASS_ID - 1))) {
+       if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
+           ext & (1 << (INET_DIAG_TCLASS - 1))) {
                u32 classid = 0;
 
 #ifdef CONFIG_SOCK_CGROUP_DATA
                classid = sock_cgroup_classid(&sk->sk_cgrp_data);
 #endif
+               /* Fallback to socket priority if class id isn't set.
+                * Classful qdiscs use it as direct reference to class.
+                * For cgroup2 classid is always zero.
+                */
+               if (!classid)
+                       classid = sk->sk_priority;
 
                if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid))
                        goto errout;
index d757b9642d0d1c418bffad5bcd50e8e7bf336c66..be778599bfedf73be139f67e814d46092a88dc40 100644 (file)
@@ -216,6 +216,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
                        atomic_set(&p->rid, 0);
                        p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
                        p->rate_tokens = 0;
+                       p->n_redirects = 0;
                        /* 60*HZ is arbitrary, but chosen enough high so that the first
                         * calculation of tokens is at its maximum.
                         */
index d1d09f3e5f9ec9493d7749447307784a771f501e..3978f807fa8b7c8514f7727174facdb9812c9c59 100644 (file)
@@ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
        int len;
 
        itn = net_generic(net, erspan_net_id);
-       len = gre_hdr_len + sizeof(*ershdr);
-
-       /* Check based hdr len */
-       if (unlikely(!pskb_may_pull(skb, len)))
-               return PACKET_REJECT;
 
        iph = ip_hdr(skb);
        ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
        ver = ershdr->ver;
 
-       /* The original GRE header does not have key field,
-        * Use ERSPAN 10-bit session ID as key.
-        */
-       tpi->key = cpu_to_be32(get_session_id(ershdr));
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
                                  tpi->flags | TUNNEL_KEY,
                                  iph->saddr, iph->daddr, tpi->key);
@@ -569,8 +560,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        dev->stats.tx_dropped++;
 }
 
-static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
-                          __be16 proto)
+static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        struct ip_tunnel_info *tun_info;
@@ -578,10 +568,10 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        struct erspan_metadata *md;
        struct rtable *rt = NULL;
        bool truncate = false;
+       __be16 df, proto;
        struct flowi4 fl;
        int tunnel_hlen;
        int version;
-       __be16 df;
        int nhoff;
        int thoff;
 
@@ -626,18 +616,20 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        if (version == 1) {
                erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
                                    ntohl(md->u.index), truncate, true);
+               proto = htons(ETH_P_ERSPAN);
        } else if (version == 2) {
                erspan_build_header_v2(skb,
                                       ntohl(tunnel_id_to_key32(key->tun_id)),
                                       md->u.md2.dir,
                                       get_hwid(&md->u.md2),
                                       truncate, true);
+               proto = htons(ETH_P_ERSPAN2);
        } else {
                goto err_free_rt;
        }
 
        gre_build_header(skb, 8, TUNNEL_SEQ,
-                        htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
+                        proto, 0, htonl(tunnel->o_seqno++));
 
        df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
 
@@ -721,12 +713,13 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        bool truncate = false;
+       __be16 proto;
 
        if (!pskb_inet_may_pull(skb))
                goto free_skb;
 
        if (tunnel->collect_md) {
-               erspan_fb_xmit(skb, dev, skb->protocol);
+               erspan_fb_xmit(skb, dev);
                return NETDEV_TX_OK;
        }
 
@@ -742,19 +735,22 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
        }
 
        /* Push ERSPAN header */
-       if (tunnel->erspan_ver == 1)
+       if (tunnel->erspan_ver == 1) {
                erspan_build_header(skb, ntohl(tunnel->parms.o_key),
                                    tunnel->index,
                                    truncate, true);
-       else if (tunnel->erspan_ver == 2)
+               proto = htons(ETH_P_ERSPAN);
+       } else if (tunnel->erspan_ver == 2) {
                erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
                                       tunnel->dir, tunnel->hwid,
                                       truncate, true);
-       else
+               proto = htons(ETH_P_ERSPAN2);
+       } else {
                goto free_skb;
+       }
 
        tunnel->parms.o_flags &= ~TUNNEL_KEY;
-       __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
+       __gre_xmit(skb, dev, &tunnel->parms.iph, proto);
        return NETDEV_TX_OK;
 
 free_skb:
@@ -1459,12 +1455,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *t = netdev_priv(dev);
        struct ip_tunnel_parm *p = &t->parms;
+       __be16 o_flags = p->o_flags;
+
+       if ((t->erspan_ver == 1 || t->erspan_ver == 2) &&
+           !t->collect_md)
+               o_flags |= TUNNEL_KEY;
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
            nla_put_be16(skb, IFLA_GRE_IFLAGS,
                         gre_tnl_flags_to_gre_flags(p->i_flags)) ||
            nla_put_be16(skb, IFLA_GRE_OFLAGS,
-                        gre_tnl_flags_to_gre_flags(p->o_flags)) ||
+                        gre_tnl_flags_to_gre_flags(o_flags)) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
            nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
index 26921f6b3b9225906bea534514266cacc593a20d..51d8efba6de21c13712d35c6ee37c6a13f6fd5e9 100644 (file)
@@ -488,6 +488,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
                goto drop;
        }
 
+       iph = ip_hdr(skb);
        skb->transport_header = skb->network_header + iph->ihl*4;
 
        /* Remove any debris in the socket control block */
index fffcc130900e518874027562272b1052cf0bdd16..82f341e84faecf3d273ea87785ca98d42f648f67 100644 (file)
@@ -148,19 +148,17 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 
 static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
 {
+       __be16 _ports[2], *ports;
        struct sockaddr_in sin;
-       __be16 *ports;
-       int end;
-
-       end = skb_transport_offset(skb) + 4;
-       if (end > 0 && !pskb_may_pull(skb, end))
-               return;
 
        /* All current transport protocols have the port numbers in the
         * first four bytes of the transport header and this function is
         * written with this assumption in mind.
         */
-       ports = (__be16 *)skb_transport_header(skb);
+       ports = skb_header_pointer(skb, skb_transport_offset(skb),
+                                  sizeof(_ports), &_ports);
+       if (!ports)
+               return;
 
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
index c4f5602308edca064297fe8764764f65ebe84569..054d01c16dc6add2e8754f1d0c3c8f9e9772f863 100644 (file)
@@ -644,13 +644,19 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        dst = tnl_params->daddr;
        if (dst == 0) {
                /* NBMA tunnel */
+               struct ip_tunnel_info *tun_info;
 
                if (!skb_dst(skb)) {
                        dev->stats.tx_fifo_errors++;
                        goto tx_error;
                }
 
-               if (skb->protocol == htons(ETH_P_IP)) {
+               tun_info = skb_tunnel_info(skb);
+               if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
+                   ip_tunnel_info_af(tun_info) == AF_INET &&
+                   tun_info->key.u.ipv4.dst)
+                       dst = tun_info->key.u.ipv4.dst;
+               else if (skb->protocol == htons(ETH_P_IP)) {
                        rt = skb_rtable(skb);
                        dst = rt_nexthop(rt, inner_iph->daddr);
                }
index d7b43e700023a0fa8791600393f0c2931b22bb25..68a21bf75dd0bb860ee61b63b66c8712ffbf9985 100644 (file)
@@ -74,6 +74,33 @@ static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
        return 0;
 }
 
+static int vti_input_ipip(struct sk_buff *skb, int nexthdr, __be32 spi,
+                    int encap_type)
+{
+       struct ip_tunnel *tunnel;
+       const struct iphdr *iph = ip_hdr(skb);
+       struct net *net = dev_net(skb->dev);
+       struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
+
+       tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+                                 iph->saddr, iph->daddr, 0);
+       if (tunnel) {
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       goto drop;
+
+               XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
+
+               skb->dev = tunnel->dev;
+
+               return xfrm_input(skb, nexthdr, spi, encap_type);
+       }
+
+       return -EINVAL;
+drop:
+       kfree_skb(skb);
+       return 0;
+}
+
 static int vti_rcv(struct sk_buff *skb)
 {
        XFRM_SPI_SKB_CB(skb)->family = AF_INET;
@@ -82,6 +109,14 @@ static int vti_rcv(struct sk_buff *skb)
        return vti_input(skb, ip_hdr(skb)->protocol, 0, 0);
 }
 
+static int vti_rcv_ipip(struct sk_buff *skb)
+{
+       XFRM_SPI_SKB_CB(skb)->family = AF_INET;
+       XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+
+       return vti_input_ipip(skb, ip_hdr(skb)->protocol, ip_hdr(skb)->saddr, 0);
+}
+
 static int vti_rcv_cb(struct sk_buff *skb, int err)
 {
        unsigned short family;
@@ -435,6 +470,12 @@ static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
        .priority       =       100,
 };
 
+static struct xfrm_tunnel ipip_handler __read_mostly = {
+       .handler        =       vti_rcv_ipip,
+       .err_handler    =       vti4_err,
+       .priority       =       0,
+};
+
 static int __net_init vti_init_net(struct net *net)
 {
        int err;
@@ -603,6 +644,13 @@ static int __init vti_init(void)
        if (err < 0)
                goto xfrm_proto_comp_failed;
 
+       msg = "ipip tunnel";
+       err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
+       if (err < 0) {
+               pr_info("%s: cant't register tunnel\n",__func__);
+               goto xfrm_tunnel_failed;
+       }
+
        msg = "netlink interface";
        err = rtnl_link_register(&vti_link_ops);
        if (err < 0)
@@ -612,6 +660,8 @@ static int __init vti_init(void)
 
 rtnl_link_failed:
        xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
+xfrm_tunnel_failed:
+       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
 xfrm_proto_comp_failed:
        xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
 xfrm_proto_ah_failed:
index b61977db9b7ffd781f5ec4b8eac4dc9a59613751..2a909e5f9ba007b80f75398b99db8db0cebeed20 100644 (file)
@@ -846,9 +846,9 @@ static int clusterip_net_init(struct net *net)
 
 static void clusterip_net_exit(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
        struct clusterip_net *cn = clusterip_pernet(net);
 
-#ifdef CONFIG_PROC_FS
        mutex_lock(&cn->mutex);
        proc_remove(cn->procdir);
        cn->procdir = NULL;
index 2687db015b6f1b3a51caecb26a38ca11c2384938..fa2ba7c500e41139ca03641cf33ec4e2a16764a9 100644 (file)
@@ -215,6 +215,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
 
        /* Change outer to look like the reply to an incoming packet */
        nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+       target.dst.protonum = IPPROTO_ICMP;
        if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip))
                return 0;
 
index a0aa13bcabda09155a8db81e40ad660c7af2e265..0a8a60c1bf9af107ff88ea57569a687df666d5af 100644 (file)
@@ -105,6 +105,8 @@ static void fast_csum(struct snmp_ctx *ctx, unsigned char offset)
 int snmp_version(void *context, size_t hdrlen, unsigned char tag,
                 const void *data, size_t datalen)
 {
+       if (datalen != 1)
+               return -EINVAL;
        if (*(unsigned char *)data > 1)
                return -ENOTSUPP;
        return 1;
@@ -114,8 +116,11 @@ int snmp_helper(void *context, size_t hdrlen, unsigned char tag,
                const void *data, size_t datalen)
 {
        struct snmp_ctx *ctx = (struct snmp_ctx *)context;
-       __be32 *pdata = (__be32 *)data;
+       __be32 *pdata;
 
+       if (datalen != 4)
+               return -EINVAL;
+       pdata = (__be32 *)data;
        if (*pdata == ctx->from) {
                pr_debug("%s: %pI4 to %pI4\n", __func__,
                         (void *)&ctx->from, (void *)&ctx->to);
index ce92f73cf1042613cf29c95b59e10b31b1cd649b..5163b64f8fb3e31a8ebb3a0f3d49aad0191d2197 100644 (file)
@@ -887,13 +887,15 @@ void ip_rt_send_redirect(struct sk_buff *skb)
        /* No redirected packets during ip_rt_redirect_silence;
         * reset the algorithm.
         */
-       if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence))
+       if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence)) {
                peer->rate_tokens = 0;
+               peer->n_redirects = 0;
+       }
 
        /* Too many ignored redirects; do not send anything
         * set dst.rate_last to the last seen redirected packet.
         */
-       if (peer->rate_tokens >= ip_rt_redirect_number) {
+       if (peer->n_redirects >= ip_rt_redirect_number) {
                peer->rate_last = jiffies;
                goto out_put_peer;
        }
@@ -910,6 +912,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
                icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
                peer->rate_last = jiffies;
                ++peer->rate_tokens;
+               ++peer->n_redirects;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
                if (log_martians &&
                    peer->rate_tokens == ip_rt_redirect_number)
index 27e2f6837062374baaea267a8788b9fd91db25ff..2079145a3b7c5f498af429c9a8289342e4421fca 100644 (file)
@@ -1186,7 +1186,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
        flags = msg->msg_flags;
 
        if (flags & MSG_ZEROCOPY && size && sock_flag(sk, SOCK_ZEROCOPY)) {
-               if (sk->sk_state != TCP_ESTABLISHED) {
+               if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
                        err = -EINVAL;
                        goto out_err;
                }
index f87dbc78b6bcb85e12b72bdf57679a36440bb5bf..71a29e9c06206f3826296515d81ab5c010d222e7 100644 (file)
@@ -226,7 +226,7 @@ static int tcp_write_timeout(struct sock *sk)
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
                if (icsk->icsk_retransmits) {
                        dst_negative_advice(sk);
-               } else if (!tp->syn_data && !tp->syn_fastopen) {
+               } else {
                        sk_rethink_txhash(sk);
                }
                retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries;
index 3fb0ed5e4789e066d07992e764fd76de5fe1e459..5c3cd5d84a6f6f09cd5744373fee168a10a6baf4 100644 (file)
@@ -847,15 +847,23 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
                const int hlen = skb_network_header_len(skb) +
                                 sizeof(struct udphdr);
 
-               if (hlen + cork->gso_size > cork->fragsize)
+               if (hlen + cork->gso_size > cork->fragsize) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
+               }
+               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (sk->sk_no_check_tx)
+               }
+               if (sk->sk_no_check_tx) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
                if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
-                   dst_xfrm(skb_dst(skb)))
+                   dst_xfrm(skb_dst(skb))) {
+                       kfree_skb(skb);
                        return -EIO;
+               }
 
                skb_shinfo(skb)->gso_size = cork->gso_size;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1918,7 +1926,7 @@ void udp_lib_rehash(struct sock *sk, u16 newhash)
 }
 EXPORT_SYMBOL(udp_lib_rehash);
 
-static void udp_v4_rehash(struct sock *sk)
+void udp_v4_rehash(struct sock *sk)
 {
        u16 new_hash = ipv4_portaddr_hash(sock_net(sk),
                                          inet_sk(sk)->inet_rcv_saddr,
index 3226726554196ec42e84819bae2b8ee66f2bdf5b..6b2fa77eeb1c3e3cf79f64a596b9799f460007c3 100644 (file)
@@ -10,6 +10,7 @@ int __udp4_lib_rcv(struct sk_buff *, struct udp_table *, int);
 int __udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
 
 int udp_v4_get_port(struct sock *sk, unsigned short snum);
+void udp_v4_rehash(struct sock *sk);
 
 int udp_setsockopt(struct sock *sk, int level, int optname,
                   char __user *optval, unsigned int optlen);
index 39c7f17d916feadca83fa9c6b1b54b63c64c55b7..3c94b8f0ff27850e684de5e27f2f3e336909291d 100644 (file)
@@ -53,6 +53,7 @@ struct proto  udplite_prot = {
        .sendpage          = udp_sendpage,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v4_rehash,
        .get_port          = udp_v4_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index 8eeec6eb2bd3730a7445eabffb06ffb03e82e78f..72ffd3d760ffe7caf99b6f8d0e92373907ffda76 100644 (file)
@@ -1165,7 +1165,8 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
                if (ifa == ifp)
                        continue;
-               if (!ipv6_prefix_equal(&ifa->addr, &ifp->addr,
+               if (ifa->prefix_len != ifp->prefix_len ||
+                   !ipv6_prefix_equal(&ifa->addr, &ifp->addr,
                                       ifp->prefix_len))
                        continue;
                if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
@@ -3495,8 +3496,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
                        if (!addrconf_link_ready(dev)) {
                                /* device is not ready yet. */
-                               pr_info("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
-                                       dev->name);
+                               pr_debug("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
+                                        dev->name);
                                break;
                        }
 
@@ -5120,6 +5121,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                        if (idev) {
                                err = in6_dump_addrs(idev, skb, cb, s_ip_idx,
                                                     &fillargs);
+                               if (err > 0)
+                                       err = 0;
                        }
                        goto put_tgt_net;
                }
@@ -5154,7 +5157,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
-       return err < 0 ? err : skb->len;
+       return skb->len ? : err;
 }
 
 static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
index 0bfb6cc0a30a6387baffef47c83eb2e2fb1bddf8..d99753b5e39b243ba4567b93b2f990f8728103c6 100644 (file)
@@ -310,6 +310,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 
        /* Check if the address belongs to the host. */
        if (addr_type == IPV6_ADDR_MAPPED) {
+               struct net_device *dev = NULL;
                int chk_addr_ret;
 
                /* Binding to v4-mapped address on a v6-only socket
@@ -320,9 +321,20 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
                        goto out;
                }
 
+               rcu_read_lock();
+               if (sk->sk_bound_dev_if) {
+                       dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
+                       if (!dev) {
+                               err = -ENODEV;
+                               goto out_unlock;
+                       }
+               }
+
                /* Reproduce AF_INET checks to make the bindings consistent */
                v4addr = addr->sin6_addr.s6_addr32[3];
-               chk_addr_ret = inet_addr_type(net, v4addr);
+               chk_addr_ret = inet_addr_type_dev_table(net, dev, v4addr);
+               rcu_read_unlock();
+
                if (!inet_can_nonlocal_bind(net, inet) &&
                    v4addr != htonl(INADDR_ANY) &&
                    chk_addr_ret != RTN_LOCAL &&
index bde08aa549f38cf844227cad37bb2b5e67ddaf88..ee4a4e54d0168446c45a2b70e59d162e9e91df07 100644 (file)
@@ -341,6 +341,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
        skb_reset_network_header(skb);
        iph = ipv6_hdr(skb);
        iph->daddr = fl6->daddr;
+       ip6_flow_hdr(iph, 0, 0);
 
        serr = SKB_EXT_ERR(skb);
        serr->ee.ee_errno = err;
@@ -700,17 +701,15 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
        }
        if (np->rxopt.bits.rxorigdstaddr) {
                struct sockaddr_in6 sin6;
-               __be16 *ports;
-               int end;
+               __be16 _ports[2], *ports;
 
-               end = skb_transport_offset(skb) + 4;
-               if (end <= 0 || pskb_may_pull(skb, end)) {
+               ports = skb_header_pointer(skb, skb_transport_offset(skb),
+                                          sizeof(_ports), &_ports);
+               if (ports) {
                        /* All current transport protocols have the port numbers in the
                         * first four bytes of the transport header and this function is
                         * written with this assumption in mind.
                         */
-                       ports = (__be16 *)skb_transport_header(skb);
-
                        sin6.sin6_family = AF_INET6;
                        sin6.sin6_addr = ipv6_hdr(skb)->daddr;
                        sin6.sin6_port = ports[1];
index bd675c61deb1fcc6bfe9f332637590451327fd05..b858bd5280bf54155f31032313f95aa30373f814 100644 (file)
@@ -90,10 +90,11 @@ static int gue6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 {
        int transport_offset = skb_transport_offset(skb);
        struct guehdr *guehdr;
-       size_t optlen;
+       size_t len, optlen;
        int ret;
 
-       if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr))
+       len = sizeof(struct udphdr) + sizeof(struct guehdr);
+       if (!pskb_may_pull(skb, len))
                return -EINVAL;
 
        guehdr = (struct guehdr *)&udp_hdr(skb)[1];
@@ -128,9 +129,21 @@ static int gue6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        optlen = guehdr->hlen << 2;
 
+       if (!pskb_may_pull(skb, len + optlen))
+               return -EINVAL;
+
+       guehdr = (struct guehdr *)&udp_hdr(skb)[1];
        if (validate_gue_flags(guehdr, optlen))
                return -EINVAL;
 
+       /* Handling exceptions for direct UDP encapsulation in GUE would lead to
+        * recursion. Besides, this kind of encapsulation can't even be
+        * configured currently. Discard this.
+        */
+       if (guehdr->proto_ctype == IPPROTO_UDP ||
+           guehdr->proto_ctype == IPPROTO_UDPLITE)
+               return -EOPNOTSUPP;
+
        skb_set_transport_header(skb, -(int)sizeof(struct icmp6hdr));
        ret = gue6_err_proto_handler(guehdr->proto_ctype, skb,
                                     opt, type, code, offset, info);
index 5d7aa2c2770ca2b4981d2dd211c3cf0a79a6f9e2..bbcdfd2996926a78c3ea0b274adfa9b5f297efbc 100644 (file)
@@ -423,10 +423,10 @@ static int icmp6_iif(const struct sk_buff *skb)
 static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
                       const struct in6_addr *force_saddr)
 {
-       struct net *net = dev_net(skb->dev);
        struct inet6_dev *idev = NULL;
        struct ipv6hdr *hdr = ipv6_hdr(skb);
        struct sock *sk;
+       struct net *net;
        struct ipv6_pinfo *np;
        const struct in6_addr *saddr = NULL;
        struct dst_entry *dst;
@@ -437,12 +437,16 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
        int iif = 0;
        int addr_type = 0;
        int len;
-       u32 mark = IP6_REPLY_MARK(net, skb->mark);
+       u32 mark;
 
        if ((u8 *)hdr < skb->head ||
            (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
                return;
 
+       if (!skb->dev)
+               return;
+       net = dev_net(skb->dev);
+       mark = IP6_REPLY_MARK(net, skb->mark);
        /*
         *      Make sure we respect the rules
         *      i.e. RFC 1885 2.4(e)
index 09d0826742f89f32fec444993f50812bbaec8366..801a9a0c217e8746b7dd2850b979702031fa81a3 100644 (file)
@@ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
        struct ip6_tnl *tunnel;
        u8 ver;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
-               return PACKET_REJECT;
-
        ipv6h = ipv6_hdr(skb);
        ershdr = (struct erspan_base_hdr *)skb->data;
        ver = ershdr->ver;
-       tpi->key = cpu_to_be32(get_session_id(ershdr));
 
        tunnel = ip6gre_tunnel_lookup(skb->dev,
                                      &ipv6h->saddr, &ipv6h->daddr, tpi->key,
@@ -922,6 +918,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        __u8 dsfield = false;
        struct flowi6 fl6;
        int err = -EINVAL;
+       __be16 proto;
        __u32 mtu;
        int nhoff;
        int thoff;
@@ -1035,8 +1032,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        }
 
        /* Push GRE header. */
-       gre_build_header(skb, 8, TUNNEL_SEQ,
-                        htons(ETH_P_ERSPAN), 0, htonl(t->o_seqno++));
+       proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN)
+                                          : htons(ETH_P_ERSPAN2);
+       gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++));
 
        /* TooBig packet may have updated dst->dev's mtu */
        if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
@@ -1169,6 +1167,10 @@ static void ip6gre_tnl_copy_tnl_parm(struct ip6_tnl *t,
        t->parms.i_flags = p->i_flags;
        t->parms.o_flags = p->o_flags;
        t->parms.fwmark = p->fwmark;
+       t->parms.erspan_ver = p->erspan_ver;
+       t->parms.index = p->index;
+       t->parms.dir = p->dir;
+       t->parms.hwid = p->hwid;
        dst_cache_reset(&t->dst_cache);
 }
 
@@ -2025,9 +2027,9 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
                             struct nlattr *data[],
                             struct netlink_ext_ack *extack)
 {
-       struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id);
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
        struct __ip6_tnl_parm p;
-       struct ip6_tnl *t;
 
        t = ip6gre_changelink_common(dev, tb, data, &p, extack);
        if (IS_ERR(t))
@@ -2096,12 +2098,17 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
        struct __ip6_tnl_parm *p = &t->parms;
+       __be16 o_flags = p->o_flags;
+
+       if ((p->erspan_ver == 1 || p->erspan_ver == 2) &&
+           !p->collect_md)
+               o_flags |= TUNNEL_KEY;
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
            nla_put_be16(skb, IFLA_GRE_IFLAGS,
                         gre_tnl_flags_to_gre_flags(p->i_flags)) ||
            nla_put_be16(skb, IFLA_GRE_OFLAGS,
-                        gre_tnl_flags_to_gre_flags(p->o_flags)) ||
+                        gre_tnl_flags_to_gre_flags(o_flags)) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
            nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) ||
index 30337b38274b29f0f4816f9f0a3c7f6a1ffbf1cb..cc01aa3f2b5e3aed278dbe08c889f727ff565dac 100644 (file)
@@ -1516,6 +1516,9 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
                        continue;
                rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
                list_del_rcu(&c->list);
+               call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
+                                              FIB_EVENT_ENTRY_DEL,
+                                              (struct mfc6_cache *)c, mrt->id);
                mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
                mr_cache_put(c);
        }
@@ -1524,10 +1527,6 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
                spin_lock_bh(&mfc_unres_lock);
                list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
                        list_del(&c->list);
-                       call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
-                                                      FIB_EVENT_ENTRY_DEL,
-                                                      (struct mfc6_cache *)c,
-                                                      mrt->id);
                        mr6_netlink_event(mrt, (struct mfc6_cache *)c,
                                          RTM_DELROUTE);
                        ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
index 8b075f0bc35169b4098bda738950d631b62ec415..6d0b1f3e927bd75f07cc36fe7b087723e05b85b2 100644 (file)
@@ -23,9 +23,11 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
        struct sock *sk = sk_to_full_sk(skb->sk);
        unsigned int hh_len;
        struct dst_entry *dst;
+       int strict = (ipv6_addr_type(&iph->daddr) &
+                     (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
        struct flowi6 fl6 = {
                .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
-                       rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
+                       strict ? skb_dst(skb)->dev->ifindex : 0,
                .flowi6_mark = skb->mark,
                .flowi6_uid = sock_net_uid(net, sk),
                .daddr = iph->daddr,
index 23022447eb497ec279c6585da86dbff09f8d5973..7a41ee3c11b4d076c91c57095472b6a48b4112ba 100644 (file)
@@ -226,6 +226,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
        }
 
        nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+       target.dst.protonum = IPPROTO_ICMPV6;
        if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip))
                return 0;
 
index 40b225f87d5e1d9095bb7209bfb9581fb7cfe026..964491cf36720fc3fa5601076002e9c90a4e3302 100644 (file)
@@ -4251,17 +4251,6 @@ struct rt6_nh {
        struct list_head next;
 };
 
-static void ip6_print_replace_route_err(struct list_head *rt6_nh_list)
-{
-       struct rt6_nh *nh;
-
-       list_for_each_entry(nh, rt6_nh_list, next) {
-               pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6c nexthop %pI6c ifi %d\n",
-                       &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway,
-                       nh->r_cfg.fc_ifindex);
-       }
-}
-
 static int ip6_route_info_append(struct net *net,
                                 struct list_head *rt6_nh_list,
                                 struct fib6_info *rt,
@@ -4407,7 +4396,8 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
                nh->fib6_info = NULL;
                if (err) {
                        if (replace && nhn)
-                               ip6_print_replace_route_err(&rt6_nh_list);
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "multipath route replace failed (check consistency of installed routes)");
                        err_nh = nh;
                        goto add_errout;
                }
index 8d0ba757a46ce52bf85d5e88d43567b5bd96678d..9b2f272ca164919aa4c9a6559852f55a10ce24aa 100644 (file)
@@ -221,9 +221,7 @@ static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
        rcu_read_unlock();
 
        genlmsg_end(msg, hdr);
-       genlmsg_reply(msg, info);
-
-       return 0;
+       return genlmsg_reply(msg, info);
 
 nla_put_failure:
        rcu_read_unlock();
index 8181ee7e1e27051040bd3bbce9d6a228632a5297..ee5403cbe655ee2d51eef2cf4913ef39a36b67b1 100644 (file)
@@ -146,6 +146,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
        } else {
                ip6_flow_hdr(hdr, 0, flowlabel);
                hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));
+
+               memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
        }
 
        hdr->nexthdr = NEXTHDR_ROUTING;
index 1e03305c0549220550d1e940c66fce967062aa89..e8a1dabef803e5583b0fb3bd70d75a48dad46e9c 100644 (file)
@@ -546,7 +546,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        }
 
        err = 0;
-       if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
+       if (__in6_dev_get(skb->dev) &&
+           !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
                goto out;
 
        if (t->parms.iph.daddr == 0)
index 9cbf363172bdc2010d2c01b91e49f3ecc1b895fc..2596ffdeebeaaa60f096d774f3da32bd5486a2f4 100644 (file)
@@ -102,7 +102,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
        return udp_lib_get_port(sk, snum, hash2_nulladdr);
 }
 
-static void udp_v6_rehash(struct sock *sk)
+void udp_v6_rehash(struct sock *sk)
 {
        u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
                                          &sk->sk_v6_rcv_saddr,
@@ -1132,15 +1132,23 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
                const int hlen = skb_network_header_len(skb) +
                                 sizeof(struct udphdr);
 
-               if (hlen + cork->gso_size > cork->fragsize)
+               if (hlen + cork->gso_size > cork->fragsize) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
+               }
+               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (udp_sk(sk)->no_check6_tx)
+               }
+               if (udp_sk(sk)->no_check6_tx) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
                if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
-                   dst_xfrm(skb_dst(skb)))
+                   dst_xfrm(skb_dst(skb))) {
+                       kfree_skb(skb);
                        return -EIO;
+               }
 
                skb_shinfo(skb)->gso_size = cork->gso_size;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1390,10 +1398,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        ipc6.opt = opt;
 
        fl6.flowi6_proto = sk->sk_protocol;
-       if (!ipv6_addr_any(daddr))
-               fl6.daddr = *daddr;
-       else
-               fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+       fl6.daddr = *daddr;
        if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
                fl6.saddr = np->saddr;
        fl6.fl6_sport = inet->inet_sport;
@@ -1421,6 +1426,9 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                }
        }
 
+       if (ipv6_addr_any(&fl6.daddr))
+               fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+
        final_p = fl6_update_dst(&fl6, opt, &final);
        if (final_p)
                connected = false;
index 5730e6503cb496c6adfcada286ac24b4bab65ab8..20e324b6f3584e8f52473eb703943025c81288f8 100644 (file)
@@ -13,6 +13,7 @@ int __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int,
                   __be32, struct udp_table *);
 
 int udp_v6_get_port(struct sock *sk, unsigned short snum);
+void udp_v6_rehash(struct sock *sk);
 
 int udpv6_getsockopt(struct sock *sk, int level, int optname,
                     char __user *optval, int __user *optlen);
index a125aebc29e5e9d2874b3c7bd5f1f1e9970fda67..f359078364448fc9e1d9a45d98bb8f9ca9b1e63a 100644 (file)
@@ -49,6 +49,7 @@ struct proto udplitev6_prot = {
        .recvmsg           = udpv6_recvmsg,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v6_rehash,
        .get_port          = udp_v6_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index 26f1d435696a628aca844edb2a88f8b793839d91..fed6becc5daf86afa2ad9188bb28e151244bb5a6 100644 (file)
@@ -83,8 +83,7 @@
 #define L2TP_SLFLAG_S     0x40000000
 #define L2TP_SL_SEQ_MASK   0x00ffffff
 
-#define L2TP_HDR_SIZE_SEQ              10
-#define L2TP_HDR_SIZE_NOSEQ            6
+#define L2TP_HDR_SIZE_MAX              14
 
 /* Default trace flags */
 #define L2TP_DEFAULT_DEBUG_FLAGS       0
@@ -808,7 +807,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
        __skb_pull(skb, sizeof(struct udphdr));
 
        /* Short packet? */
-       if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) {
+       if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
                l2tp_info(tunnel, L2TP_MSG_DATA,
                          "%s: recv short packet (len=%d)\n",
                          tunnel->name, skb->len);
@@ -884,6 +883,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
                goto error;
        }
 
+       if (tunnel->version == L2TP_HDR_VER_3 &&
+           l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto error;
+
        l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
        l2tp_session_dec_refcount(session);
 
index 9c9afe94d389bb6fd0440e053043cb01fcd85528..b2ce90260c35f6d0cdd70241a28f54cedf580ea3 100644 (file)
@@ -301,6 +301,26 @@ static inline bool l2tp_tunnel_uses_xfrm(const struct l2tp_tunnel *tunnel)
 }
 #endif
 
+static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, struct sk_buff *skb,
+                                              unsigned char **ptr, unsigned char **optr)
+{
+       int opt_len = session->peer_cookie_len + l2tp_get_l2specific_len(session);
+
+       if (opt_len > 0) {
+               int off = *ptr - *optr;
+
+               if (!pskb_may_pull(skb, off + opt_len))
+                       return -1;
+
+               if (skb->data != *optr) {
+                       *optr = skb->data;
+                       *ptr = skb->data + off;
+               }
+       }
+
+       return 0;
+}
+
 #define l2tp_printk(ptr, type, func, fmt, ...)                         \
 do {                                                                   \
        if (((ptr)->debug) & (type))                                    \
index 35f6f86d4dcce898f0deacbeba695cfe438cdd91..d4c60523c549d33c6ea29641a37a63040b70530d 100644 (file)
@@ -165,6 +165,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
 
+       if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto discard_sess;
+
        l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
        l2tp_session_dec_refcount(session);
 
index 237f1a4a0b0c8b7fdc76cd67e7c682dee7bdaf79..0ae6899edac0705851df7306c3779033c4a42a37 100644 (file)
@@ -178,6 +178,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
 
+       if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto discard_sess;
+
        l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
        l2tp_session_dec_refcount(session);
 
index 69e831bc317beb666e2a836facb572e59e727a9c..54821fb1a960da626be57a94fd726d8803332c58 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
  * Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -366,6 +366,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 
        set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
 
+       ieee80211_agg_stop_txq(sta, tid);
+
        spin_unlock_bh(&sta->lock);
 
        ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n",
index de65fe3ed9cc66e9d6373c4df22d356e8b36579d..2493c74c2d3789a2e504f91b53fc93a02a7234c0 100644 (file)
@@ -1490,6 +1490,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
                sta->sta.tdls = true;
 
+       if (sta->sta.tdls && sdata->vif.type == NL80211_IFTYPE_STATION &&
+           !sdata->u.mgd.associated)
+               return -EINVAL;
+
        err = sta_apply_parameters(local, sta, params);
        if (err) {
                sta_info_free(local, sta);
index 45aad3d3108cccce9626c2682ae390a8b0991568..bb4d71efb6fb87f462887312ed631a4f11a16148 100644 (file)
@@ -231,7 +231,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_hdr_3addr hdr;
                u8 category;
                u8 action_code;
-       } __packed action;
+       } __packed __aligned(2) action;
 
        if (!sdata)
                return;
@@ -2723,7 +2723,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        skb_set_queue_mapping(skb, q);
 
        if (!--mesh_hdr->ttl) {
-               IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
+               if (!is_multicast_ether_addr(hdr->addr1))
+                       IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
+                                                    dropped_frames_ttl);
                goto out;
        }
 
index f170d6c6629a0097f7bf3f874799049fdb39d046..928f13a208b058c199a5e679b7afd53a5e8e84db 100644 (file)
@@ -1938,9 +1938,16 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
                                int head_need, bool may_encrypt)
 {
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_hdr *hdr;
+       bool enc_tailroom;
        int tail_need = 0;
 
-       if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
+       hdr = (struct ieee80211_hdr *) skb->data;
+       enc_tailroom = may_encrypt &&
+                      (sdata->crypto_tx_tailroom_needed_cnt ||
+                       ieee80211_is_mgmt(hdr->frame_control));
+
+       if (enc_tailroom) {
                tail_need = IEEE80211_ENCRYPT_TAILROOM;
                tail_need -= skb_tailroom(skb);
                tail_need = max_t(int, tail_need, 0);
@@ -1948,8 +1955,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 
        if (skb_cloned(skb) &&
            (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
-            !skb_clone_writable(skb, ETH_HLEN) ||
-            (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt)))
+            !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
                I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
        else if (head_need || tail_need)
                I802_DEBUG_INC(local->tx_expand_skb_head);
index d0eb38b890aa65934d752e547190624132cc31a9..ba950ae974fc636b4640fe54d8fa9f544515cef3 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017     Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -2146,6 +2146,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                case NL80211_IFTYPE_AP_VLAN:
                case NL80211_IFTYPE_MONITOR:
                        break;
+               case NL80211_IFTYPE_ADHOC:
+                       if (sdata->vif.bss_conf.ibss_joined)
+                               WARN_ON(drv_join_ibss(local, sdata));
+                       /* fall through */
                default:
                        ieee80211_reconfig_stations(sdata);
                        /* fall through */
index cad48d07c818a81930ac15916b5b1430bcac9df9..8401cefd9f654cec5d75d3a3e3b2f2d66b9539df 100644 (file)
@@ -29,6 +29,7 @@ config        IP_VS_IPV6
        bool "IPv6 support for IPVS"
        depends on IPV6 = y || IP_VS = IPV6
        select IP6_NF_IPTABLES
+       select NF_DEFRAG_IPV6
        ---help---
          Add IPv6 support to IPVS.
 
index fe9abf3cc10a0d6d81ebf0ad69c37de81d315759..235205c93e14b8214c3dc54b1e0f322c172c7035 100644 (file)
@@ -1536,14 +1536,12 @@ ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
                /* sorry, all this trouble for a no-hit :) */
                IP_VS_DBG_PKT(12, af, pp, skb, iph->off,
                              "ip_vs_in: packet continues traversal as normal");
-               if (iph->fragoffs) {
-                       /* Fragment that couldn't be mapped to a conn entry
-                        * is missing module nf_defrag_ipv6
-                        */
-                       IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
+
+               /* Fragment couldn't be mapped to a conn entry */
+               if (iph->fragoffs)
                        IP_VS_DBG_PKT(7, af, pp, skb, iph->off,
                                      "unhandled fragment");
-               }
+
                *verdict = NF_ACCEPT;
                return 0;
        }
index 432141f04af3d98b356332ac9723b7a286f93538..86afacb07e5fd6f3849b5339d3315dfa642fbe3b 100644 (file)
@@ -43,6 +43,7 @@
 #ifdef CONFIG_IP_VS_IPV6
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #endif
 #include <net/route.h>
 #include <net/sock.h>
@@ -895,6 +896,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 {
        struct ip_vs_dest *dest;
        unsigned int atype, i;
+       int ret = 0;
 
        EnterFunction(2);
 
@@ -905,6 +907,10 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
                        atype & IPV6_ADDR_LINKLOCAL) &&
                        !__ip_vs_addr_is_local_v6(svc->ipvs->net, &udest->addr.in6))
                        return -EINVAL;
+
+               ret = nf_defrag_ipv6_enable(svc->ipvs->net);
+               if (ret)
+                       return ret;
        } else
 #endif
        {
@@ -1228,6 +1234,10 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
                        ret = -EINVAL;
                        goto out_err;
                }
+
+               ret = nf_defrag_ipv6_enable(ipvs->net);
+               if (ret)
+                       goto out_err;
        }
 #endif
 
@@ -2220,6 +2230,18 @@ static int ip_vs_set_timeout(struct netns_ipvs *ipvs, struct ip_vs_timeout_user
                  u->tcp_fin_timeout,
                  u->udp_timeout);
 
+#ifdef CONFIG_IP_VS_PROTO_TCP
+       if (u->tcp_timeout < 0 || u->tcp_timeout > (INT_MAX / HZ) ||
+           u->tcp_fin_timeout < 0 || u->tcp_fin_timeout > (INT_MAX / HZ)) {
+               return -EINVAL;
+       }
+#endif
+
+#ifdef CONFIG_IP_VS_PROTO_UDP
+       if (u->udp_timeout < 0 || u->udp_timeout > (INT_MAX / HZ))
+               return -EINVAL;
+#endif
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
        if (u->tcp_timeout) {
                pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP);
index 741b533148baedd70cd4184ba47bb507b055c142..db4d46332e8681ab7ccbe1e920a14ecd3776f0d1 100644 (file)
@@ -1007,6 +1007,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
                }
 
                if (nf_ct_key_equal(h, tuple, zone, net)) {
+                       /* Tuple is taken already, so caller will need to find
+                        * a new source port to use.
+                        *
+                        * Only exception:
+                        * If the *original tuples* are identical, then both
+                        * conntracks refer to the same flow.
+                        * This is a rare situation, it can occur e.g. when
+                        * more than one UDP packet is sent from same socket
+                        * in different threads.
+                        *
+                        * Let nf_ct_resolve_clash() deal with this later.
+                        */
+                       if (nf_ct_tuple_equal(&ignored_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                             &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple))
+                               continue;
+
                        NF_CT_STAT_INC_ATOMIC(net, found);
                        rcu_read_unlock();
                        return 1;
index fa0844e2a68d694183c12e508efb602048321dc2..c0c72ae9df42fb8eff80621753dfe0afa84d7456 100644 (file)
@@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
 {
        struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
        struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
+       struct dst_entry *other_dst = route->tuple[!dir].dst;
        struct dst_entry *dst = route->tuple[dir].dst;
 
        ft->dir = dir;
@@ -50,8 +51,8 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
        ft->src_port = ctt->src.u.tcp.port;
        ft->dst_port = ctt->dst.u.tcp.port;
 
-       ft->iifidx = route->tuple[dir].ifindex;
-       ft->oifidx = route->tuple[!dir].ifindex;
+       ft->iifidx = other_dst->dev->ifindex;
+       ft->oifidx = dst->dev->ifindex;
        ft->dst_cache = dst;
 }
 
index 2b0a93300dd712f24f80567da1548f34b1eff44c..5a92f23f179fe0242016c7ec1deb6e6a5b4fbf4f 100644 (file)
@@ -116,6 +116,23 @@ static void nft_trans_destroy(struct nft_trans *trans)
        kfree(trans);
 }
 
+static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+       struct net *net = ctx->net;
+       struct nft_trans *trans;
+
+       if (!nft_set_is_anonymous(set))
+               return;
+
+       list_for_each_entry_reverse(trans, &net->nft.commit_list, list) {
+               if (trans->msg_type == NFT_MSG_NEWSET &&
+                   nft_trans_set(trans) == set) {
+                       nft_trans_set_bound(trans) = true;
+                       break;
+               }
+       }
+}
+
 static int nf_tables_register_hook(struct net *net,
                                   const struct nft_table *table,
                                   struct nft_chain *chain)
@@ -211,18 +228,6 @@ static int nft_delchain(struct nft_ctx *ctx)
        return err;
 }
 
-/* either expr ops provide both activate/deactivate, or neither */
-static bool nft_expr_check_ops(const struct nft_expr_ops *ops)
-{
-       if (!ops)
-               return true;
-
-       if (WARN_ON_ONCE((!ops->activate ^ !ops->deactivate)))
-               return false;
-
-       return true;
-}
-
 static void nft_rule_expr_activate(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
@@ -238,14 +243,15 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
 }
 
 static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
-                                    struct nft_rule *rule)
+                                    struct nft_rule *rule,
+                                    enum nft_trans_phase phase)
 {
        struct nft_expr *expr;
 
        expr = nft_expr_first(rule);
        while (expr != nft_expr_last(rule) && expr->ops) {
                if (expr->ops->deactivate)
-                       expr->ops->deactivate(ctx, expr);
+                       expr->ops->deactivate(ctx, expr, phase);
 
                expr = nft_expr_next(expr);
        }
@@ -296,7 +302,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
                nft_trans_destroy(trans);
                return err;
        }
-       nft_rule_expr_deactivate(ctx, rule);
+       nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_PREPARE);
 
        return 0;
 }
@@ -1929,9 +1935,6 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
  */
 int nft_register_expr(struct nft_expr_type *type)
 {
-       if (!nft_expr_check_ops(type->ops))
-               return -EINVAL;
-
        nfnl_lock(NFNL_SUBSYS_NFTABLES);
        if (type->family == NFPROTO_UNSPEC)
                list_add_tail_rcu(&type->list, &nf_tables_expressions);
@@ -2079,10 +2082,6 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
                        err = PTR_ERR(ops);
                        goto err1;
                }
-               if (!nft_expr_check_ops(ops)) {
-                       err = -EINVAL;
-                       goto err1;
-               }
        } else
                ops = type->ops;
 
@@ -2304,7 +2303,6 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        unsigned int s_idx = cb->args[0];
        const struct nft_rule *rule;
-       int rc = 1;
 
        list_for_each_entry_rcu(rule, &chain->rules, list) {
                if (!nft_is_active(net, rule))
@@ -2321,16 +2319,13 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
                                        NLM_F_MULTI | NLM_F_APPEND,
                                        table->family,
                                        table, chain, rule) < 0)
-                       goto out_unfinished;
+                       return 1;
 
                nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
                (*idx)++;
        }
-       rc = 0;
-out_unfinished:
-       cb->args[0] = *idx;
-       return rc;
+       return 0;
 }
 
 static int nf_tables_dump_rules(struct sk_buff *skb,
@@ -2354,7 +2349,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
                if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
                        continue;
 
-               if (ctx && ctx->chain) {
+               if (ctx && ctx->table && ctx->chain) {
                        struct rhlist_head *list, *tmp;
 
                        list = rhltable_lookup(&table->chains_ht, ctx->chain,
@@ -2382,6 +2377,8 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
        }
 done:
        rcu_read_unlock();
+
+       cb->args[0] = idx;
        return skb->len;
 }
 
@@ -2513,7 +2510,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
 static void nf_tables_rule_release(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
-       nft_rule_expr_deactivate(ctx, rule);
+       nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
        nf_tables_rule_destroy(ctx, rule);
 }
 
@@ -3710,39 +3707,30 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
 bind:
        binding->chain = ctx->chain;
        list_add_tail_rcu(&binding->list, &set->bindings);
+       nft_set_trans_bind(ctx, set);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(nf_tables_bind_set);
 
-void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding)
-{
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set))
-               list_add_tail_rcu(&set->list, &ctx->table->sets);
-
-       list_add_tail_rcu(&binding->list, &set->bindings);
-}
-EXPORT_SYMBOL_GPL(nf_tables_rebind_set);
-
 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding)
+                         struct nft_set_binding *binding, bool event)
 {
        list_del_rcu(&binding->list);
 
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set))
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) {
                list_del_rcu(&set->list);
+               if (event)
+                       nf_tables_set_notify(ctx, set, NFT_MSG_DELSET,
+                                            GFP_KERNEL);
+       }
 }
 EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
 
 void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set)
 {
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set)) {
-               nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set))
                nft_set_destroy(set);
-       }
 }
 EXPORT_SYMBOL_GPL(nf_tables_destroy_set);
 
@@ -4508,6 +4496,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
 err5:
        kfree(trans);
 err4:
+       if (obj)
+               obj->use--;
        kfree(elem.priv);
 err3:
        if (nla[NFTA_SET_ELEM_DATA] != NULL)
@@ -6535,6 +6525,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                        nf_tables_rule_notify(&trans->ctx,
                                              nft_trans_rule(trans),
                                              NFT_MSG_DELRULE);
+                       nft_rule_expr_deactivate(&trans->ctx,
+                                                nft_trans_rule(trans),
+                                                NFT_TRANS_COMMIT);
                        break;
                case NFT_MSG_NEWSET:
                        nft_clear(net, nft_trans_set(trans));
@@ -6621,7 +6614,8 @@ static void nf_tables_abort_release(struct nft_trans *trans)
                nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
                break;
        case NFT_MSG_NEWSET:
-               nft_set_destroy(nft_trans_set(trans));
+               if (!nft_trans_set_bound(trans))
+                       nft_set_destroy(nft_trans_set(trans));
                break;
        case NFT_MSG_NEWSETELEM:
                nft_set_elem_destroy(nft_trans_elem_set(trans),
@@ -6682,7 +6676,9 @@ static int __nf_tables_abort(struct net *net)
                case NFT_MSG_NEWRULE:
                        trans->ctx.chain->use--;
                        list_del_rcu(&nft_trans_rule(trans)->list);
-                       nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
+                       nft_rule_expr_deactivate(&trans->ctx,
+                                                nft_trans_rule(trans),
+                                                NFT_TRANS_ABORT);
                        break;
                case NFT_MSG_DELRULE:
                        trans->ctx.chain->use++;
@@ -6692,7 +6688,8 @@ static int __nf_tables_abort(struct net *net)
                        break;
                case NFT_MSG_NEWSET:
                        trans->ctx.table->use--;
-                       list_del_rcu(&nft_trans_set(trans)->list);
+                       if (!nft_trans_set_bound(trans))
+                               list_del_rcu(&nft_trans_set(trans)->list);
                        break;
                case NFT_MSG_DELSET:
                        trans->ctx.table->use++;
index 6f41dd74729d9ff1b6a8984004174ae1935258e2..1f1d90c1716b5bd697b18870e0bb0a7f9d7e63ec 100644 (file)
@@ -66,6 +66,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
                             int ttl_check,
                             struct nf_osf_hdr_ctx *ctx)
 {
+       const __u8 *optpinit = ctx->optp;
        unsigned int check_WSS = 0;
        int fmatch = FMATCH_WRONG;
        int foptsize, optnum;
@@ -155,6 +156,9 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
                }
        }
 
+       if (fmatch != FMATCH_OK)
+               ctx->optp = optpinit;
+
        return fmatch == FMATCH_OK;
 }
 
index 7334e0b80a5effe521bb807dda2ab259a62df8d8..0a4bad55a8aaae1a205e63b967e767e45c249f8b 100644 (file)
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_arp/arp_tables.h>
 #include <net/netfilter/nf_tables.h>
+#include <net/netns/generic.h>
 
 struct nft_xt {
        struct list_head        head;
        struct nft_expr_ops     ops;
-       unsigned int            refcnt;
+       refcount_t              refcnt;
+
+       /* used only when transaction mutex is locked */
+       unsigned int            listcnt;
 
        /* Unlike other expressions, ops doesn't have static storage duration.
         * nft core assumes they do.  We use kfree_rcu so that nft core can
@@ -43,10 +47,39 @@ struct nft_xt_match_priv {
        void *info;
 };
 
+struct nft_compat_net {
+       struct list_head nft_target_list;
+       struct list_head nft_match_list;
+};
+
+static unsigned int nft_compat_net_id __read_mostly;
+static struct nft_expr_type nft_match_type;
+static struct nft_expr_type nft_target_type;
+
+static struct nft_compat_net *nft_compat_pernet(struct net *net)
+{
+       return net_generic(net, nft_compat_net_id);
+}
+
+static void nft_xt_get(struct nft_xt *xt)
+{
+       /* refcount_inc() warns on 0 -> 1 transition, but we can't
+        * init the reference count to 1 in .select_ops -- we can't
+        * undo such an increase when another expression inside the same
+        * rule fails afterwards.
+        */
+       if (xt->listcnt == 0)
+               refcount_set(&xt->refcnt, 1);
+       else
+               refcount_inc(&xt->refcnt);
+
+       xt->listcnt++;
+}
+
 static bool nft_xt_put(struct nft_xt *xt)
 {
-       if (--xt->refcnt == 0) {
-               list_del(&xt->head);
+       if (refcount_dec_and_test(&xt->refcnt)) {
+               WARN_ON_ONCE(!list_empty(&xt->head));
                kfree_rcu(xt, rcu_head);
                return true;
        }
@@ -273,7 +306,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                return -EINVAL;
 
        nft_xt = container_of(expr->ops, struct nft_xt, ops);
-       nft_xt->refcnt++;
+       nft_xt_get(nft_xt);
        return 0;
 }
 
@@ -282,6 +315,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
        struct xt_target *target = expr->ops->data;
        void *info = nft_expr_priv(expr);
+       struct module *me = target->me;
        struct xt_tgdtor_param par;
 
        par.net = ctx->net;
@@ -292,7 +326,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
                par.target->destroy(&par);
 
        if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
-               module_put(target->me);
+               module_put(me);
 }
 
 static int nft_extension_dump_info(struct sk_buff *skb, int attr,
@@ -486,7 +520,7 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                return ret;
 
        nft_xt = container_of(expr->ops, struct nft_xt, ops);
-       nft_xt->refcnt++;
+       nft_xt_get(nft_xt);
        return 0;
 }
 
@@ -540,6 +574,18 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
        __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
 }
 
+static void nft_compat_deactivate(const struct nft_ctx *ctx,
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
+{
+       struct nft_xt *xt = container_of(expr->ops, struct nft_xt, ops);
+
+       if (phase == NFT_TRANS_ABORT || phase == NFT_TRANS_COMMIT) {
+               if (--xt->listcnt == 0)
+                       list_del_init(&xt->head);
+       }
+}
+
 static void
 nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -734,10 +780,6 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = {
        .cb             = nfnl_nft_compat_cb,
 };
 
-static LIST_HEAD(nft_match_list);
-
-static struct nft_expr_type nft_match_type;
-
 static bool nft_match_cmp(const struct xt_match *match,
                          const char *name, u32 rev, u32 family)
 {
@@ -749,6 +791,7 @@ static const struct nft_expr_ops *
 nft_match_select_ops(const struct nft_ctx *ctx,
                     const struct nlattr * const tb[])
 {
+       struct nft_compat_net *cn;
        struct nft_xt *nft_match;
        struct xt_match *match;
        unsigned int matchsize;
@@ -765,8 +808,10 @@ nft_match_select_ops(const struct nft_ctx *ctx,
        rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
        family = ctx->family;
 
+       cn = nft_compat_pernet(ctx->net);
+
        /* Re-use the existing match if it's already loaded. */
-       list_for_each_entry(nft_match, &nft_match_list, head) {
+       list_for_each_entry(nft_match, &cn->nft_match_list, head) {
                struct xt_match *match = nft_match->ops.data;
 
                if (nft_match_cmp(match, mt_name, rev, family))
@@ -789,11 +834,12 @@ nft_match_select_ops(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nft_match->refcnt = 0;
+       refcount_set(&nft_match->refcnt, 0);
        nft_match->ops.type = &nft_match_type;
        nft_match->ops.eval = nft_match_eval;
        nft_match->ops.init = nft_match_init;
        nft_match->ops.destroy = nft_match_destroy;
+       nft_match->ops.deactivate = nft_compat_deactivate;
        nft_match->ops.dump = nft_match_dump;
        nft_match->ops.validate = nft_match_validate;
        nft_match->ops.data = match;
@@ -810,7 +856,8 @@ nft_match_select_ops(const struct nft_ctx *ctx,
 
        nft_match->ops.size = matchsize;
 
-       list_add(&nft_match->head, &nft_match_list);
+       nft_match->listcnt = 0;
+       list_add(&nft_match->head, &cn->nft_match_list);
 
        return &nft_match->ops;
 err:
@@ -826,10 +873,6 @@ static struct nft_expr_type nft_match_type __read_mostly = {
        .owner          = THIS_MODULE,
 };
 
-static LIST_HEAD(nft_target_list);
-
-static struct nft_expr_type nft_target_type;
-
 static bool nft_target_cmp(const struct xt_target *tg,
                           const char *name, u32 rev, u32 family)
 {
@@ -841,6 +884,7 @@ static const struct nft_expr_ops *
 nft_target_select_ops(const struct nft_ctx *ctx,
                      const struct nlattr * const tb[])
 {
+       struct nft_compat_net *cn;
        struct nft_xt *nft_target;
        struct xt_target *target;
        char *tg_name;
@@ -861,8 +905,9 @@ nft_target_select_ops(const struct nft_ctx *ctx,
            strcmp(tg_name, "standard") == 0)
                return ERR_PTR(-EINVAL);
 
+       cn = nft_compat_pernet(ctx->net);
        /* Re-use the existing target if it's already loaded. */
-       list_for_each_entry(nft_target, &nft_target_list, head) {
+       list_for_each_entry(nft_target, &cn->nft_target_list, head) {
                struct xt_target *target = nft_target->ops.data;
 
                if (!target->target)
@@ -893,11 +938,12 @@ nft_target_select_ops(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nft_target->refcnt = 0;
+       refcount_set(&nft_target->refcnt, 0);
        nft_target->ops.type = &nft_target_type;
        nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
        nft_target->ops.init = nft_target_init;
        nft_target->ops.destroy = nft_target_destroy;
+       nft_target->ops.deactivate = nft_compat_deactivate;
        nft_target->ops.dump = nft_target_dump;
        nft_target->ops.validate = nft_target_validate;
        nft_target->ops.data = target;
@@ -907,7 +953,8 @@ nft_target_select_ops(const struct nft_ctx *ctx,
        else
                nft_target->ops.eval = nft_target_eval_xt;
 
-       list_add(&nft_target->head, &nft_target_list);
+       nft_target->listcnt = 0;
+       list_add(&nft_target->head, &cn->nft_target_list);
 
        return &nft_target->ops;
 err:
@@ -923,13 +970,74 @@ static struct nft_expr_type nft_target_type __read_mostly = {
        .owner          = THIS_MODULE,
 };
 
+static int __net_init nft_compat_init_net(struct net *net)
+{
+       struct nft_compat_net *cn = nft_compat_pernet(net);
+
+       INIT_LIST_HEAD(&cn->nft_target_list);
+       INIT_LIST_HEAD(&cn->nft_match_list);
+
+       return 0;
+}
+
+static void __net_exit nft_compat_exit_net(struct net *net)
+{
+       struct nft_compat_net *cn = nft_compat_pernet(net);
+       struct nft_xt *xt, *next;
+
+       if (list_empty(&cn->nft_match_list) &&
+           list_empty(&cn->nft_target_list))
+               return;
+
+       /* If there was an error that caused nft_xt expr to not be initialized
+        * fully and noone else requested the same expression later, the lists
+        * contain 0-refcount entries that still hold module reference.
+        *
+        * Clean them here.
+        */
+       mutex_lock(&net->nft.commit_mutex);
+       list_for_each_entry_safe(xt, next, &cn->nft_target_list, head) {
+               struct xt_target *target = xt->ops.data;
+
+               list_del_init(&xt->head);
+
+               if (refcount_read(&xt->refcnt))
+                       continue;
+               module_put(target->me);
+               kfree(xt);
+       }
+
+       list_for_each_entry_safe(xt, next, &cn->nft_match_list, head) {
+               struct xt_match *match = xt->ops.data;
+
+               list_del_init(&xt->head);
+
+               if (refcount_read(&xt->refcnt))
+                       continue;
+               module_put(match->me);
+               kfree(xt);
+       }
+       mutex_unlock(&net->nft.commit_mutex);
+}
+
+static struct pernet_operations nft_compat_net_ops = {
+       .init   = nft_compat_init_net,
+       .exit   = nft_compat_exit_net,
+       .id     = &nft_compat_net_id,
+       .size   = sizeof(struct nft_compat_net),
+};
+
 static int __init nft_compat_module_init(void)
 {
        int ret;
 
+       ret = register_pernet_subsys(&nft_compat_net_ops);
+       if (ret < 0)
+               goto err_target;
+
        ret = nft_register_expr(&nft_match_type);
        if (ret < 0)
-               return ret;
+               goto err_pernet;
 
        ret = nft_register_expr(&nft_target_type);
        if (ret < 0)
@@ -942,45 +1050,21 @@ static int __init nft_compat_module_init(void)
        }
 
        return ret;
-
 err_target:
        nft_unregister_expr(&nft_target_type);
 err_match:
        nft_unregister_expr(&nft_match_type);
+err_pernet:
+       unregister_pernet_subsys(&nft_compat_net_ops);
        return ret;
 }
 
 static void __exit nft_compat_module_exit(void)
 {
-       struct nft_xt *xt, *next;
-
-       /* list should be empty here, it can be non-empty only in case there
-        * was an error that caused nft_xt expr to not be initialized fully
-        * and noone else requested the same expression later.
-        *
-        * In this case, the lists contain 0-refcount entries that still
-        * hold module reference.
-        */
-       list_for_each_entry_safe(xt, next, &nft_target_list, head) {
-               struct xt_target *target = xt->ops.data;
-
-               if (WARN_ON_ONCE(xt->refcnt))
-                       continue;
-               module_put(target->me);
-               kfree(xt);
-       }
-
-       list_for_each_entry_safe(xt, next, &nft_match_list, head) {
-               struct xt_match *match = xt->ops.data;
-
-               if (WARN_ON_ONCE(xt->refcnt))
-                       continue;
-               module_put(match->me);
-               kfree(xt);
-       }
        nfnetlink_subsys_unregister(&nfnl_compat_subsys);
        nft_unregister_expr(&nft_target_type);
        nft_unregister_expr(&nft_match_type);
+       unregister_pernet_subsys(&nft_compat_net_ops);
 }
 
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
index 07d4efd3d85182997edb4ae0a1fd74d88221a07f..f1172f99752bd1a5d127c1086885b6fc83efc0dc 100644 (file)
@@ -235,20 +235,17 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
        return err;
 }
 
-static void nft_dynset_activate(const struct nft_ctx *ctx,
-                               const struct nft_expr *expr)
-{
-       struct nft_dynset *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_dynset_deactivate(const struct nft_ctx *ctx,
-                                 const struct nft_expr *expr)
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
 {
        struct nft_dynset *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_dynset_destroy(const struct nft_ctx *ctx,
@@ -296,7 +293,6 @@ static const struct nft_expr_ops nft_dynset_ops = {
        .eval           = nft_dynset_eval,
        .init           = nft_dynset_init,
        .destroy        = nft_dynset_destroy,
-       .activate       = nft_dynset_activate,
        .deactivate     = nft_dynset_deactivate,
        .dump           = nft_dynset_dump,
 };
index 974525eb92df7246c2e3acbc4cec495dcfd31862..6e6b9adf7d387717ff6f99a87093e41478c9889f 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <linux/netfilter/nf_conntrack_common.h>
 #include <net/netfilter/nf_flow_table.h>
+#include <net/netfilter/nf_conntrack_helper.h>
 
 struct nft_flow_offload {
        struct nft_flowtable    *flowtable;
@@ -29,10 +30,12 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
        memset(&fl, 0, sizeof(fl));
        switch (nft_pf(pkt)) {
        case NFPROTO_IPV4:
-               fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
+               fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+               fl.u.ip4.flowi4_oif = nft_in(pkt)->ifindex;
                break;
        case NFPROTO_IPV6:
-               fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
+               fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+               fl.u.ip6.flowi6_oif = nft_in(pkt)->ifindex;
                break;
        }
 
@@ -41,9 +44,7 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
                return -ENOENT;
 
        route->tuple[dir].dst           = this_dst;
-       route->tuple[dir].ifindex       = nft_in(pkt)->ifindex;
        route->tuple[!dir].dst          = other_dst;
-       route->tuple[!dir].ifindex      = nft_out(pkt)->ifindex;
 
        return 0;
 }
@@ -66,6 +67,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 {
        struct nft_flow_offload *priv = nft_expr_priv(expr);
        struct nf_flowtable *flowtable = &priv->flowtable->data;
+       const struct nf_conn_help *help;
        enum ip_conntrack_info ctinfo;
        struct nf_flow_route route;
        struct flow_offload *flow;
@@ -88,7 +90,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
                goto out;
        }
 
-       if (test_bit(IPS_HELPER_BIT, &ct->status))
+       help = nfct_help(ct);
+       if (help)
                goto out;
 
        if (ctinfo == IP_CT_NEW ||
index 0777a93211e2b576e57eec2f4aaec71d57f3700d..3f6d1d2a628186c964e79727bbb62fb59370b919 100644 (file)
@@ -72,10 +72,14 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
 }
 
 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
-                                    const struct nft_expr *expr)
+                                    const struct nft_expr *expr,
+                                    enum nft_trans_phase phase)
 {
        const struct nft_immediate_expr *priv = nft_expr_priv(expr);
 
+       if (phase == NFT_TRANS_COMMIT)
+               return;
+
        return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
 }
 
index 227b2b15a19cbd979df780b3660e2395b689c5db..14496da5141d3f1fa72ec4deb16fba3d8930c62c 100644 (file)
@@ -121,20 +121,17 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
        return 0;
 }
 
-static void nft_lookup_activate(const struct nft_ctx *ctx,
-                               const struct nft_expr *expr)
-{
-       struct nft_lookup *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_lookup_deactivate(const struct nft_ctx *ctx,
-                                 const struct nft_expr *expr)
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
 {
        struct nft_lookup *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_lookup_destroy(const struct nft_ctx *ctx,
@@ -225,7 +222,6 @@ static const struct nft_expr_ops nft_lookup_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_lookup)),
        .eval           = nft_lookup_eval,
        .init           = nft_lookup_init,
-       .activate       = nft_lookup_activate,
        .deactivate     = nft_lookup_deactivate,
        .destroy        = nft_lookup_destroy,
        .dump           = nft_lookup_dump,
index a3185ca2a3a985712f5b2262df3f9e28af6fab4e..ae178e914486174cd0c259497159a3eef8bcbb0c 100644 (file)
@@ -155,20 +155,17 @@ static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr)
        return -1;
 }
 
-static void nft_objref_map_activate(const struct nft_ctx *ctx,
-                                   const struct nft_expr *expr)
-{
-       struct nft_objref_map *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_objref_map_deactivate(const struct nft_ctx *ctx,
-                                     const struct nft_expr *expr)
+                                     const struct nft_expr *expr,
+                                     enum nft_trans_phase phase)
 {
        struct nft_objref_map *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_objref_map_destroy(const struct nft_ctx *ctx,
@@ -185,7 +182,6 @@ static const struct nft_expr_ops nft_objref_map_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
        .eval           = nft_objref_map_eval,
        .init           = nft_objref_map_init,
-       .activate       = nft_objref_map_activate,
        .deactivate     = nft_objref_map_deactivate,
        .destroy        = nft_objref_map_destroy,
        .dump           = nft_objref_map_dump,
index aecadd471e1d00350f062c556291300c50e0f4ae..13e1ac333fa461dbcf063f41ea40f4f4b5e5215e 100644 (file)
@@ -1899,7 +1899,7 @@ static int __init xt_init(void)
                seqcount_init(&per_cpu(xt_recseq, i));
        }
 
-       xt = kmalloc_array(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
+       xt = kcalloc(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
        if (!xt)
                return -ENOMEM;
 
index cbd51ed5a2d7bef7540ea8a8a2e0fea9ff8fc02f..908e53ab47a47dd79b7d08927003b617cd6b4143 100644 (file)
@@ -52,21 +52,21 @@ void nr_start_t1timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t1timer, jiffies + nr->t1);
+       sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);
 }
 
 void nr_start_t2timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t2timer, jiffies + nr->t2);
+       sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);
 }
 
 void nr_start_t4timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t4timer, jiffies + nr->t4);
+       sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);
 }
 
 void nr_start_idletimer(struct sock *sk)
@@ -74,37 +74,37 @@ void nr_start_idletimer(struct sock *sk)
        struct nr_sock *nr = nr_sk(sk);
 
        if (nr->idle > 0)
-               mod_timer(&nr->idletimer, jiffies + nr->idle);
+               sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);
 }
 
 void nr_start_heartbeat(struct sock *sk)
 {
-       mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
+       sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);
 }
 
 void nr_stop_t1timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t1timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t1timer);
 }
 
 void nr_stop_t2timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t2timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t2timer);
 }
 
 void nr_stop_t4timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t4timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t4timer);
 }
 
 void nr_stop_idletimer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->idletimer);
+       sk_stop_timer(sk, &nr_sk(sk)->idletimer);
 }
 
 void nr_stop_heartbeat(struct sock *sk)
 {
-       del_timer(&sk->sk_timer);
+       sk_stop_timer(sk, &sk->sk_timer);
 }
 
 int nr_t1timer_running(struct sock *sk)
index 57e07768c9d12b65e9f1dc8d7271040e25cfd82f..f54cf17ef7a8bc3fa1449644fff07dd1cba523d2 100644 (file)
@@ -276,10 +276,12 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 
        nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
        if (flags & IP6_FH_F_FRAG) {
-               if (frag_off)
+               if (frag_off) {
                        key->ip.frag = OVS_FRAG_TYPE_LATER;
-               else
-                       key->ip.frag = OVS_FRAG_TYPE_FIRST;
+                       key->ip.proto = nexthdr;
+                       return 0;
+               }
+               key->ip.frag = OVS_FRAG_TYPE_FIRST;
        } else {
                key->ip.frag = OVS_FRAG_TYPE_NONE;
        }
index 435a4bdf8f89dbac1cb7eab5351f203b76114c78..691da853bef5cb801d963cae4e9bf7b23a3dddd6 100644 (file)
@@ -500,7 +500,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
                        return -EINVAL;
                }
 
-               if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
+               if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
                        attrs |= 1 << type;
                        a[type] = nla;
                }
index eedacdebcd4c61c7fbd3f781b993fee7ce00500f..1cd1d83a4be081e2d67f3fda5fbc1267e1464654 100644 (file)
@@ -2628,7 +2628,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
                dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
                if (addr && dev && saddr->sll_halen < dev->addr_len)
-                       goto out;
+                       goto out_put;
        }
 
        err = -ENXIO;
@@ -2828,7 +2828,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
                dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
                if (addr && dev && saddr->sll_halen < dev->addr_len)
-                       goto out;
+                       goto out_unlock;
        }
 
        err = -ENXIO;
@@ -2887,7 +2887,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                        goto out_free;
        } else if (reserve) {
                skb_reserve(skb, -reserve);
-               if (len < reserve)
+               if (len < reserve + sizeof(struct ipv6hdr) &&
+                   dev->min_header_len != dev->hard_header_len)
                        skb_reset_network_header(skb);
        }
 
@@ -4291,7 +4292,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
                if (unlikely(rb->frames_per_block == 0))
                        goto out;
-               if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+               if (unlikely(rb->frames_per_block > UINT_MAX / req->tp_block_nr))
                        goto out;
                if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
                                        req->tp_frame_nr))
index 762d2c6788a385631a312a39625d67a1154ef596..17c9d9f0c8483b4b0a887e69e7caac246c369423 100644 (file)
@@ -78,10 +78,10 @@ struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
        __rds_create_bind_key(key, addr, port, scope_id);
        rcu_read_lock();
        rs = rhashtable_lookup(&bind_hash_table, key, ht_parms);
-       if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
-               rds_sock_addref(rs);
-       else
+       if (rs && (sock_flag(rds_rs_to_sk(rs), SOCK_DEAD) ||
+                  !refcount_inc_not_zero(&rds_rs_to_sk(rs)->sk_refcnt)))
                rs = NULL;
+
        rcu_read_unlock();
 
        rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr,
index 2dcb555e6350d12197584ba898e6d4dd464d9c61..4e0c36acf86604dd793218e3053076d16a36f6c7 100644 (file)
@@ -522,7 +522,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
        if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0)
                i = 1;
        else
-               i = ceil(be32_to_cpu(rm->m_inc.i_hdr.h_len), RDS_FRAG_SIZE);
+               i = DIV_ROUND_UP(be32_to_cpu(rm->m_inc.i_hdr.h_len), RDS_FRAG_SIZE);
 
        work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
        if (work_alloc == 0) {
@@ -879,7 +879,7 @@ int rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op)
         * Instead of knowing how to return a partial rdma read/write we insist that there
         * be enough work requests to send the entire message.
         */
-       i = ceil(op->op_count, max_sge);
+       i = DIV_ROUND_UP(op->op_count, max_sge);
 
        work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
        if (work_alloc != i) {
index f139420ba1f6837998567f9a7d1ac786147080cf..50f13f1d4ae091accfbeae36192cc219e9e63aca 100644 (file)
@@ -341,7 +341,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 {
        struct rds_message *rm;
        unsigned int i;
-       int num_sgs = ceil(total_len, PAGE_SIZE);
+       int num_sgs = DIV_ROUND_UP(total_len, PAGE_SIZE);
        int extra_bytes = num_sgs * sizeof(struct scatterlist);
        int ret;
 
@@ -351,7 +351,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 
        set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);
        rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
-       rm->data.op_nents = ceil(total_len, PAGE_SIZE);
+       rm->data.op_nents = DIV_ROUND_UP(total_len, PAGE_SIZE);
        rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs, &ret);
        if (!rm->data.op_sg) {
                rds_message_put(rm);
index 02ec4a3b2799018f7c99a09a24821fc8a72abb13..4ffe100ff5e697847c2631933a17155443b82f4b 100644 (file)
@@ -48,10 +48,6 @@ void rdsdebug(char *fmt, ...)
 }
 #endif
 
-/* XXX is there one of these somewhere? */
-#define ceil(x, y) \
-       ({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; })
-
 #define RDS_FRAG_SHIFT 12
 #define RDS_FRAG_SIZE  ((unsigned int)(1 << RDS_FRAG_SHIFT))
 
index 3d822bad7de9093c4673349b0c465406b89d4722..fd8b687d5c05ed665b6b8e770ba398af85b8a2c8 100644 (file)
@@ -1107,7 +1107,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
        size_t total_payload_len = payload_len, rdma_payload_len = 0;
        bool zcopy = ((msg->msg_flags & MSG_ZEROCOPY) &&
                      sock_flag(rds_rs_to_sk(rs), SOCK_ZEROCOPY));
-       int num_sgs = ceil(payload_len, PAGE_SIZE);
+       int num_sgs = DIV_ROUND_UP(payload_len, PAGE_SIZE);
        int namelen;
        struct rds_iov_vector_arr vct;
        int ind;
index 77e9f85a2c92c81726289c1a31d12d3320cdda6a..f2ff21d7df0815c0a8401a4ef8b0c1ad45a26a60 100644 (file)
@@ -850,6 +850,7 @@ void rose_link_device_down(struct net_device *dev)
 
 /*
  *     Route a frame to an appropriate AX.25 connection.
+ *     A NULL ax25_cb indicates an internally generated frame.
  */
 int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 {
@@ -867,6 +868,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 
        if (skb->len < ROSE_MIN_LEN)
                return res;
+
+       if (!ax25)
+               return rose_loopback_queue(skb, NULL);
+
        frametype = skb->data[2];
        lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
        if (frametype == ROSE_CALL_REQUEST &&
index a2522f9d71e266d338f1c0d223ce5bcb670fd00f..96f2952bbdfd6e62ffcec87f0a565378abbfe4f5 100644 (file)
@@ -418,76 +418,6 @@ u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
 }
 EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
 
-/**
- * rxrpc_kernel_check_call - Check a call's state
- * @sock: The socket the call is on
- * @call: The call to check
- * @_compl: Where to store the completion state
- * @_abort_code: Where to store any abort code
- *
- * Allow a kernel service to query the state of a call and find out the manner
- * of its termination if it has completed.  Returns -EINPROGRESS if the call is
- * still going, 0 if the call finished successfully, -ECONNABORTED if the call
- * was aborted and an appropriate error if the call failed in some other way.
- */
-int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
-                           enum rxrpc_call_completion *_compl, u32 *_abort_code)
-{
-       if (call->state != RXRPC_CALL_COMPLETE)
-               return -EINPROGRESS;
-       smp_rmb();
-       *_compl = call->completion;
-       *_abort_code = call->abort_code;
-       return call->error;
-}
-EXPORT_SYMBOL(rxrpc_kernel_check_call);
-
-/**
- * rxrpc_kernel_retry_call - Allow a kernel service to retry a call
- * @sock: The socket the call is on
- * @call: The call to retry
- * @srx: The address of the peer to contact
- * @key: The security context to use (defaults to socket setting)
- *
- * Allow a kernel service to try resending a client call that failed due to a
- * network error to a new address.  The Tx queue is maintained intact, thereby
- * relieving the need to re-encrypt any request data that has already been
- * buffered.
- */
-int rxrpc_kernel_retry_call(struct socket *sock, struct rxrpc_call *call,
-                           struct sockaddr_rxrpc *srx, struct key *key)
-{
-       struct rxrpc_conn_parameters cp;
-       struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
-       int ret;
-
-       _enter("%d{%d}", call->debug_id, atomic_read(&call->usage));
-
-       if (!key)
-               key = rx->key;
-       if (key && !key->payload.data[0])
-               key = NULL; /* a no-security key */
-
-       memset(&cp, 0, sizeof(cp));
-       cp.local                = rx->local;
-       cp.key                  = key;
-       cp.security_level       = 0;
-       cp.exclusive            = false;
-       cp.service_id           = srx->srx_service;
-
-       mutex_lock(&call->user_mutex);
-
-       ret = rxrpc_prepare_call_for_retry(rx, call);
-       if (ret == 0)
-               ret = rxrpc_retry_client_call(rx, call, &cp, srx, GFP_KERNEL);
-
-       mutex_unlock(&call->user_mutex);
-       rxrpc_put_peer(cp.peer);
-       _leave(" = %d", ret);
-       return ret;
-}
-EXPORT_SYMBOL(rxrpc_kernel_retry_call);
-
 /**
  * rxrpc_kernel_new_call_notification - Get notifications of new calls
  * @sock: The socket to intercept received messages on
index bc628acf4f4ffe7172e1be6591811e056ccb4f1b..4b1a534d290a79e3f035ee60766b4f2ebb2e35c2 100644 (file)
@@ -476,7 +476,6 @@ enum rxrpc_call_flag {
        RXRPC_CALL_EXPOSED,             /* The call was exposed to the world */
        RXRPC_CALL_RX_LAST,             /* Received the last packet (at rxtx_top) */
        RXRPC_CALL_TX_LAST,             /* Last packet in Tx buffer (at rxtx_top) */
-       RXRPC_CALL_TX_LASTQ,            /* Last packet has been queued */
        RXRPC_CALL_SEND_PING,           /* A ping will need to be sent */
        RXRPC_CALL_PINGING,             /* Ping in process */
        RXRPC_CALL_RETRANS_TIMEOUT,     /* Retransmission due to timeout occurred */
@@ -517,6 +516,18 @@ enum rxrpc_call_state {
        NR__RXRPC_CALL_STATES
 };
 
+/*
+ * Call completion condition (state == RXRPC_CALL_COMPLETE).
+ */
+enum rxrpc_call_completion {
+       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
+       RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
+       RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
+       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
+       RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
+       NR__RXRPC_CALL_COMPLETIONS
+};
+
 /*
  * Call Tx congestion management modes.
  */
@@ -761,15 +772,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
                                         struct sockaddr_rxrpc *,
                                         struct rxrpc_call_params *, gfp_t,
                                         unsigned int);
-int rxrpc_retry_client_call(struct rxrpc_sock *,
-                           struct rxrpc_call *,
-                           struct rxrpc_conn_parameters *,
-                           struct sockaddr_rxrpc *,
-                           gfp_t);
 void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
                         struct sk_buff *);
 void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
-int rxrpc_prepare_call_for_retry(struct rxrpc_sock *, struct rxrpc_call *);
 void rxrpc_release_calls_on_socket(struct rxrpc_sock *);
 bool __rxrpc_queue_call(struct rxrpc_call *);
 bool rxrpc_queue_call(struct rxrpc_call *);
index 8f1a8f85b1f99ef7ded560bf1da2ec80a08f0fcb..8aa2937b069f78a7b296704e773398c722b66749 100644 (file)
@@ -324,48 +324,6 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
        return ERR_PTR(ret);
 }
 
-/*
- * Retry a call to a new address.  It is expected that the Tx queue of the call
- * will contain data previously packaged for an old call.
- */
-int rxrpc_retry_client_call(struct rxrpc_sock *rx,
-                           struct rxrpc_call *call,
-                           struct rxrpc_conn_parameters *cp,
-                           struct sockaddr_rxrpc *srx,
-                           gfp_t gfp)
-{
-       const void *here = __builtin_return_address(0);
-       int ret;
-
-       /* Set up or get a connection record and set the protocol parameters,
-        * including channel number and call ID.
-        */
-       ret = rxrpc_connect_call(rx, call, cp, srx, gfp);
-       if (ret < 0)
-               goto error;
-
-       trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage),
-                        here, NULL);
-
-       rxrpc_start_call_timer(call);
-
-       _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id);
-
-       if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events))
-               rxrpc_queue_call(call);
-
-       _leave(" = 0");
-       return 0;
-
-error:
-       rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
-                                 RX_CALL_DEAD, ret);
-       trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage),
-                        here, ERR_PTR(ret));
-       _leave(" = %d", ret);
-       return ret;
-}
-
 /*
  * Set up an incoming call.  call->conn points to the connection.
  * This is called in BH context and isn't allowed to fail.
@@ -533,61 +491,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
        _leave("");
 }
 
-/*
- * Prepare a kernel service call for retry.
- */
-int rxrpc_prepare_call_for_retry(struct rxrpc_sock *rx, struct rxrpc_call *call)
-{
-       const void *here = __builtin_return_address(0);
-       int i;
-       u8 last = 0;
-
-       _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
-
-       trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage),
-                        here, (const void *)call->flags);
-
-       ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
-       ASSERTCMP(call->completion, !=, RXRPC_CALL_REMOTELY_ABORTED);
-       ASSERTCMP(call->completion, !=, RXRPC_CALL_LOCALLY_ABORTED);
-       ASSERT(list_empty(&call->recvmsg_link));
-
-       del_timer_sync(&call->timer);
-
-       _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, call->conn);
-
-       if (call->conn)
-               rxrpc_disconnect_call(call);
-
-       if (rxrpc_is_service_call(call) ||
-           !call->tx_phase ||
-           call->tx_hard_ack != 0 ||
-           call->rx_hard_ack != 0 ||
-           call->rx_top != 0)
-               return -EINVAL;
-
-       call->state = RXRPC_CALL_UNINITIALISED;
-       call->completion = RXRPC_CALL_SUCCEEDED;
-       call->call_id = 0;
-       call->cid = 0;
-       call->cong_cwnd = 0;
-       call->cong_extra = 0;
-       call->cong_ssthresh = 0;
-       call->cong_mode = 0;
-       call->cong_dup_acks = 0;
-       call->cong_cumul_acks = 0;
-       call->acks_lowest_nak = 0;
-
-       for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-               last |= call->rxtx_annotations[i];
-               call->rxtx_annotations[i] &= RXRPC_TX_ANNO_LAST;
-               call->rxtx_annotations[i] |= RXRPC_TX_ANNO_RETRANS;
-       }
-
-       _leave(" = 0");
-       return 0;
-}
-
 /*
  * release all the calls associated with a socket
  */
index 521189f4b6667fee627bf27fb0742882227a51b3..b2adfa825363bb76fcae70634ab0a1b2d8a0af5a 100644 (file)
@@ -562,10 +562,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
        clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
 
        write_lock_bh(&call->state_lock);
-       if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags))
-               call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
-       else
-               call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
+       call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
        write_unlock_bh(&call->state_lock);
 
        rxrpc_see_call(call);
index eaf19ebaa964e6442cfa4117f862fb4aca9b2345..3f7bb11f3290e57fe27007cb2ce57936f6ae47f4 100644 (file)
@@ -596,6 +596,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
        }
 error_no_call:
        release_sock(&rx->sk);
+error_trace:
        trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
        return ret;
 
@@ -604,7 +605,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 wait_error:
        finish_wait(sk_sleep(&rx->sk), &wait);
        call = NULL;
-       goto error_no_call;
+       goto error_trace;
 }
 
 /**
index be01f9c5d963ddfc766fac811ace9a381b89a7f7..46c9312085b1ba81b4941607f751a07adb8f3c20 100644 (file)
@@ -169,10 +169,8 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 
        ASSERTCMP(seq, ==, call->tx_top + 1);
 
-       if (last) {
+       if (last)
                annotation |= RXRPC_TX_ANNO_LAST;
-               set_bit(RXRPC_CALL_TX_LASTQ, &call->flags);
-       }
 
        /* We have to set the timestamp before queueing as the retransmit
         * algorithm can see the packet as soon as we queue it.
@@ -386,6 +384,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                                call->tx_total_len -= copy;
                }
 
+               /* check for the far side aborting the call or a network error
+                * occurring */
+               if (call->state == RXRPC_CALL_COMPLETE)
+                       goto call_terminated;
+
                /* add the packet to the send queue if it's now full */
                if (sp->remain <= 0 ||
                    (msg_data_left(msg) == 0 && !more)) {
@@ -425,16 +428,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                                           notify_end_tx);
                        skb = NULL;
                }
-
-               /* Check for the far side aborting the call or a network error
-                * occurring.  If this happens, save any packet that was under
-                * construction so that in the case of a network error, the
-                * call can be retried or redirected.
-                */
-               if (call->state == RXRPC_CALL_COMPLETE) {
-                       ret = call->error;
-                       goto out;
-               }
        } while (msg_data_left(msg) > 0);
 
 success:
@@ -444,6 +437,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
        _leave(" = %d", ret);
        return ret;
 
+call_terminated:
+       rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+       _leave(" = %d", call->error);
+       return call->error;
+
 maybe_error:
        if (copied)
                goto success;
index c3b90fadaff67357d111f7aded3066e24a522097..8b43fe0130f73039e3f1802701df910e079fc4ba 100644 (file)
@@ -197,6 +197,15 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
        [TCA_TUNNEL_KEY_ENC_TTL]      = { .type = NLA_U8 },
 };
 
+static void tunnel_key_release_params(struct tcf_tunnel_key_params *p)
+{
+       if (!p)
+               return;
+       if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
+               dst_release(&p->tcft_enc_metadata->dst);
+       kfree_rcu(p, rcu);
+}
+
 static int tunnel_key_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a,
                           int ovr, int bind, bool rtnl_held,
@@ -360,8 +369,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        rcu_swap_protected(t->params, params_new,
                           lockdep_is_held(&t->tcf_lock));
        spin_unlock_bh(&t->tcf_lock);
-       if (params_new)
-               kfree_rcu(params_new, rcu);
+       tunnel_key_release_params(params_new);
 
        if (ret == ACT_P_CREATED)
                tcf_idr_insert(tn, *a);
@@ -385,12 +393,7 @@ static void tunnel_key_release(struct tc_action *a)
        struct tcf_tunnel_key_params *params;
 
        params = rcu_dereference_protected(t->params, 1);
-       if (params) {
-               if (params->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
-                       dst_release(&params->tcft_enc_metadata->dst);
-
-               kfree_rcu(params, rcu);
-       }
+       tunnel_key_release_params(params);
 }
 
 static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
index 8ce2a050797049a1b20715a88e44a8542f637966..e2b5cb2eb34e6d965707e0bc8eaa12f20b011c85 100644 (file)
@@ -1277,7 +1277,6 @@ EXPORT_SYMBOL(tcf_block_cb_unregister);
 int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                 struct tcf_result *res, bool compat_mode)
 {
-       __be16 protocol = tc_skb_protocol(skb);
 #ifdef CONFIG_NET_CLS_ACT
        const int max_reclassify_loop = 4;
        const struct tcf_proto *orig_tp = tp;
@@ -1287,6 +1286,7 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 reclassify:
 #endif
        for (; tp; tp = rcu_dereference_bh(tp->next)) {
+               __be16 protocol = tc_skb_protocol(skb);
                int err;
 
                if (tp->protocol != protocol &&
@@ -1319,7 +1319,6 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
        }
 
        tp = first_tp;
-       protocol = tc_skb_protocol(skb);
        goto reclassify;
 #endif
 }
index dad04e710493b02df68c1286e1804b6dcb0c2485..12ca9d13db83320b6fe3381b1874206dec433a74 100644 (file)
@@ -1290,17 +1290,23 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        struct cls_fl_head *head = rtnl_dereference(tp->root);
        struct cls_fl_filter *fold = *arg;
        struct cls_fl_filter *fnew;
+       struct fl_flow_mask *mask;
        struct nlattr **tb;
-       struct fl_flow_mask mask = {};
        int err;
 
        if (!tca[TCA_OPTIONS])
                return -EINVAL;
 
-       tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
-       if (!tb)
+       mask = kzalloc(sizeof(struct fl_flow_mask), GFP_KERNEL);
+       if (!mask)
                return -ENOBUFS;
 
+       tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
+       if (!tb) {
+               err = -ENOBUFS;
+               goto errout_mask_alloc;
+       }
+
        err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS],
                               fl_policy, NULL);
        if (err < 0)
@@ -1343,12 +1349,12 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
                }
        }
 
-       err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr,
+       err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
                           tp->chain->tmplt_priv, extack);
        if (err)
                goto errout_idr;
 
-       err = fl_check_assign_mask(head, fnew, fold, &mask);
+       err = fl_check_assign_mask(head, fnew, fold, mask);
        if (err)
                goto errout_idr;
 
@@ -1365,7 +1371,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        if (!tc_skip_hw(fnew->flags)) {
                err = fl_hw_replace_filter(tp, fnew, extack);
                if (err)
-                       goto errout_mask;
+                       goto errout_mask_ht;
        }
 
        if (!tc_in_hw(fnew->flags))
@@ -1392,8 +1398,13 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        }
 
        kfree(tb);
+       kfree(mask);
        return 0;
 
+errout_mask_ht:
+       rhashtable_remove_fast(&fnew->mask->ht, &fnew->ht_node,
+                              fnew->mask->filter_ht_params);
+
 errout_mask:
        fl_mask_put(head, fnew->mask, false);
 
@@ -1405,6 +1416,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        kfree(fnew);
 errout_tb:
        kfree(tb);
+errout_mask_alloc:
+       kfree(mask);
        return err;
 }
 
index 9ccc93f257db0966f5ea5206819cfdb7605c1e2a..38bb882bb9587e57195f37ac81b3da8bdec81cdd 100644 (file)
@@ -48,7 +48,7 @@ struct tcindex_data {
        u32 hash;               /* hash table size; 0 if undefined */
        u32 alloc_hash;         /* allocated size */
        u32 fall_through;       /* 0: only classify if explicit match */
-       struct rcu_head rcu;
+       struct rcu_work rwork;
 };
 
 static inline int tcindex_filter_is_set(struct tcindex_filter_result *r)
@@ -221,17 +221,11 @@ static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last,
        return 0;
 }
 
-static int tcindex_destroy_element(struct tcf_proto *tp,
-                                  void *arg, struct tcf_walker *walker)
-{
-       bool last;
-
-       return tcindex_delete(tp, arg, &last, NULL);
-}
-
-static void __tcindex_destroy(struct rcu_head *head)
+static void tcindex_destroy_work(struct work_struct *work)
 {
-       struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
+       struct tcindex_data *p = container_of(to_rcu_work(work),
+                                             struct tcindex_data,
+                                             rwork);
 
        kfree(p->perfect);
        kfree(p->h);
@@ -258,9 +252,11 @@ static int tcindex_filter_result_init(struct tcindex_filter_result *r)
        return tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
 }
 
-static void __tcindex_partial_destroy(struct rcu_head *head)
+static void tcindex_partial_destroy_work(struct work_struct *work)
 {
-       struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
+       struct tcindex_data *p = container_of(to_rcu_work(work),
+                                             struct tcindex_data,
+                                             rwork);
 
        kfree(p->perfect);
        kfree(p);
@@ -275,7 +271,7 @@ static void tcindex_free_perfect_hash(struct tcindex_data *cp)
        kfree(cp->perfect);
 }
 
-static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
+static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp)
 {
        int i, err = 0;
 
@@ -289,6 +285,9 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
                                    TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
                if (err < 0)
                        goto errout;
+#ifdef CONFIG_NET_CLS_ACT
+               cp->perfect[i].exts.net = net;
+#endif
        }
 
        return 0;
@@ -305,9 +304,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                  struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
 {
        struct tcindex_filter_result new_filter_result, *old_r = r;
-       struct tcindex_filter_result cr;
        struct tcindex_data *cp = NULL, *oldp;
        struct tcindex_filter *f = NULL; /* make gcc behave */
+       struct tcf_result cr = {};
        int err, balloc = 0;
        struct tcf_exts e;
 
@@ -337,7 +336,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        if (p->perfect) {
                int i;
 
-               if (tcindex_alloc_perfect_hash(cp) < 0)
+               if (tcindex_alloc_perfect_hash(net, cp) < 0)
                        goto errout;
                for (i = 0; i < cp->hash; i++)
                        cp->perfect[i].res = p->perfect[i].res;
@@ -346,13 +345,10 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        cp->h = p->h;
 
        err = tcindex_filter_result_init(&new_filter_result);
-       if (err < 0)
-               goto errout1;
-       err = tcindex_filter_result_init(&cr);
        if (err < 0)
                goto errout1;
        if (old_r)
-               cr.res = r->res;
+               cr = r->res;
 
        if (tb[TCA_TCINDEX_HASH])
                cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
@@ -406,7 +402,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        err = -ENOMEM;
        if (!cp->perfect && !cp->h) {
                if (valid_perfect_hash(cp)) {
-                       if (tcindex_alloc_perfect_hash(cp) < 0)
+                       if (tcindex_alloc_perfect_hash(net, cp) < 0)
                                goto errout_alloc;
                        balloc = 1;
                } else {
@@ -443,8 +439,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        if (tb[TCA_TCINDEX_CLASSID]) {
-               cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
-               tcf_bind_filter(tp, &cr.res, base);
+               cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
+               tcf_bind_filter(tp, &cr, base);
        }
 
        if (old_r && old_r != r) {
@@ -456,7 +452,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        oldp = p;
-       r->res = cr.res;
+       r->res = cr;
        tcf_exts_change(&r->exts, &e);
 
        rcu_assign_pointer(tp->root, cp);
@@ -475,10 +471,12 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                                ; /* nothing */
 
                rcu_assign_pointer(*fp, f);
+       } else {
+               tcf_exts_destroy(&new_filter_result.exts);
        }
 
        if (oldp)
-               call_rcu(&oldp->rcu, __tcindex_partial_destroy);
+               tcf_queue_work(&oldp->rwork, tcindex_partial_destroy_work);
        return 0;
 
 errout_alloc:
@@ -487,7 +485,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        else if (balloc == 2)
                kfree(cp->h);
 errout1:
-       tcf_exts_destroy(&cr.exts);
        tcf_exts_destroy(&new_filter_result.exts);
 errout:
        kfree(cp);
@@ -562,15 +559,34 @@ static void tcindex_destroy(struct tcf_proto *tp,
                            struct netlink_ext_ack *extack)
 {
        struct tcindex_data *p = rtnl_dereference(tp->root);
-       struct tcf_walker walker;
+       int i;
 
        pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
-       walker.count = 0;
-       walker.skip = 0;
-       walker.fn = tcindex_destroy_element;
-       tcindex_walk(tp, &walker);
 
-       call_rcu(&p->rcu, __tcindex_destroy);
+       if (p->perfect) {
+               for (i = 0; i < p->hash; i++) {
+                       struct tcindex_filter_result *r = p->perfect + i;
+
+                       tcf_unbind_filter(tp, &r->res);
+                       if (tcf_exts_get_net(&r->exts))
+                               tcf_queue_work(&r->rwork,
+                                              tcindex_destroy_rexts_work);
+                       else
+                               __tcindex_destroy_rexts(r);
+               }
+       }
+
+       for (i = 0; p->h && i < p->hash; i++) {
+               struct tcindex_filter *f, *next;
+               bool last;
+
+               for (f = rtnl_dereference(p->h[i]); f; f = next) {
+                       next = rtnl_dereference(f->next);
+                       tcindex_delete(tp, &f->result, &last, NULL);
+               }
+       }
+
+       tcf_queue_work(&p->rwork, tcindex_destroy_work);
 }
 
 
index b910cd5c56f7434cd34decec7d521479e77f441f..73940293700d7a56507d1b35fd8a2a05c2ba945e 100644 (file)
@@ -1667,7 +1667,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        if (skb_is_gso(skb) && q->rate_flags & CAKE_FLAG_SPLIT_GSO) {
                struct sk_buff *segs, *nskb;
                netdev_features_t features = netif_skb_features(skb);
-               unsigned int slen = 0;
+               unsigned int slen = 0, numsegs = 0;
 
                segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
                if (IS_ERR_OR_NULL(segs))
@@ -1683,6 +1683,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                        flow_queue_add(flow, segs);
 
                        sch->q.qlen++;
+                       numsegs++;
                        slen += segs->len;
                        q->buffer_used += segs->truesize;
                        b->packets++;
@@ -1696,7 +1697,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                sch->qstats.backlog += slen;
                q->avg_window_bytes += slen;
 
-               qdisc_tree_reduce_backlog(sch, 1len);
+               qdisc_tree_reduce_backlog(sch, 1-numsegs, len-slen);
                consume_skb(skb);
        } else {
                /* not splitting */
index e689e11b6d0f5cc1acebdcb53a65ab47221afe65..c6a502933fe78b250b971416caeffd796d3f31d3 100644 (file)
@@ -88,13 +88,14 @@ static int cbs_child_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                             struct Qdisc *child,
                             struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        int err;
 
        err = child->ops->enqueue(skb, child, to_free);
        if (err != NET_XMIT_SUCCESS)
                return err;
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index cdebaed0f8cfdc79a4f4902b2d211d03f4b1ff27..09b8009910657ace91e838eccfa520c81d800750 100644 (file)
@@ -350,9 +350,11 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch,
 static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl;
        int err = 0;
+       bool first;
 
        cl = drr_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -362,6 +364,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -371,12 +374,12 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       if (cl->qdisc->q.qlen == 1) {
+       if (first) {
                list_add_tail(&cl->alist, &q->active);
                cl->deficit = cl->quantum;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return err;
 }
index f6f480784bc652429596b84431c4de697ec65c76..42471464ded3fdf28b712e2d16b7cb4f34939cc0 100644 (file)
@@ -199,6 +199,7 @@ static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl,
 static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                          struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        int err;
 
@@ -271,7 +272,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 66ba2ce2320f9625fe5b223864ffbaf1e16f1acc..968a85fe4d4a9a0f5887989789cdd97ae7033f5a 100644 (file)
@@ -500,7 +500,7 @@ static void dev_watchdog_down(struct net_device *dev)
  *     netif_carrier_on - set carrier
  *     @dev: network device
  *
- * Device has detected that carrier.
+ * Device has detected acquisition of carrier.
  */
 void netif_carrier_on(struct net_device *dev)
 {
index b18ec1f6de60cf584f8a2f421c5cbabfca188ff1..24cc220a3218aee4f6c44ed271050c0b8d137ec9 100644 (file)
@@ -1539,8 +1539,10 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
 static int
 hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct hfsc_class *cl;
        int uninitialized_var(err);
+       bool first;
 
        cl = hfsc_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1550,6 +1552,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
                return err;
        }
 
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -1559,9 +1562,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
                return err;
        }
 
-       if (cl->qdisc->q.qlen == 1) {
-               unsigned int len = qdisc_pkt_len(skb);
-
+       if (first) {
                if (cl->cl_flags & HFSC_RSC)
                        init_ed(cl, len);
                if (cl->cl_flags & HFSC_FSC)
@@ -1576,7 +1577,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 58b44949075721a60261e1a975041ebf58d98f04..30f9da7e1076368f2b0718d2bb0e1e3c5432998c 100644 (file)
@@ -581,6 +581,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
        int uninitialized_var(ret);
+       unsigned int len = qdisc_pkt_len(skb);
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = htb_classify(skb, sch, &ret);
 
@@ -610,7 +611,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                htb_activate(q, cl);
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
index cdf68706e40fe0d89ca4fbd56347bb907f02d6cd..847141cd900f1933f0b48684085c747f06c092c1 100644 (file)
@@ -72,6 +72,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 static int
 prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct Qdisc *qdisc;
        int ret;
 
@@ -88,7 +89,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
        ret = qdisc_enqueue(skb, qdisc, to_free);
        if (ret == NET_XMIT_SUCCESS) {
-               qdisc_qstats_backlog_inc(sch, skb);
+               sch->qstats.backlog += len;
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
index dc37c4ead439bec3cc7414e1c29681eacf236a0c..29f5c4a2468829457ddf734aa1e7711ebfe4bcc8 100644 (file)
@@ -1210,10 +1210,12 @@ static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q)
 static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb), gso_segs;
        struct qfq_sched *q = qdisc_priv(sch);
        struct qfq_class *cl;
        struct qfq_aggregate *agg;
        int err = 0;
+       bool first;
 
        cl = qfq_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1224,17 +1226,18 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
 
-       if (unlikely(cl->agg->lmax < qdisc_pkt_len(skb))) {
+       if (unlikely(cl->agg->lmax < len)) {
                pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
-                        cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
-               err = qfq_change_agg(sch, cl, cl->agg->class_weight,
-                                    qdisc_pkt_len(skb));
+                        cl->agg->lmax, len, cl->common.classid);
+               err = qfq_change_agg(sch, cl, cl->agg->class_weight, len);
                if (err) {
                        cl->qstats.drops++;
                        return qdisc_drop(skb, sch, to_free);
                }
        }
 
+       gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
@@ -1245,16 +1248,17 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       bstats_update(&cl->bstats, skb);
-       qdisc_qstats_backlog_inc(sch, skb);
+       cl->bstats.bytes += len;
+       cl->bstats.packets += gso_segs;
+       sch->qstats.backlog += len;
        ++sch->q.qlen;
 
        agg = cl->agg;
        /* if the queue was not empty, then done here */
-       if (cl->qdisc->q.qlen != 1) {
+       if (!first) {
                if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
                    list_first_entry(&agg->active, struct qfq_class, alist)
-                   == cl && cl->deficit < qdisc_pkt_len(skb))
+                   == cl && cl->deficit < len)
                        list_move_tail(&cl->alist, &agg->active);
 
                return err;
index 942dcca09cf2e85c8b9a73331067d529bd973459..7f272a9070c5753e61dd140eca77afe4d17d6692 100644 (file)
@@ -185,6 +185,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
+       unsigned int len = qdisc_pkt_len(skb);
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
@@ -200,7 +201,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return ret;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
index 078f01a8d582a94d4302b5088f64c6a4f77f6a81..435847d98b51cbbfe04a48b83e516560d3450eba 100644 (file)
@@ -256,6 +256,7 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
                + nla_total_size(1) /* INET_DIAG_TOS */
                + nla_total_size(1) /* INET_DIAG_TCLASS */
                + nla_total_size(4) /* INET_DIAG_MARK */
+               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(addrlen * asoc->peer.transport_count)
                + nla_total_size(addrlen * addrcnt)
                + nla_total_size(sizeof(struct inet_diag_meminfo))
index b9ed271b7ef7fc13c60d2ef07100daad46794982..6200cd2b4b996b156aad38e3d94f0e87335f9cad 100644 (file)
@@ -97,11 +97,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 
        switch (ev) {
        case NETDEV_UP:
-               addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+               addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
-                       addr->a.v6.sin6_port = 0;
-                       addr->a.v6.sin6_flowinfo = 0;
                        addr->a.v6.sin6_addr = ifa->addr;
                        addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
                        addr->valid = 1;
@@ -282,7 +280,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 
        if (saddr) {
                fl6->saddr = saddr->v6.sin6_addr;
-               fl6->fl6_sport = saddr->v6.sin6_port;
+               if (!fl6->fl6_sport)
+                       fl6->fl6_sport = saddr->v6.sin6_port;
 
                pr_debug("src=%pI6 - ", &fl6->saddr);
        }
@@ -434,7 +433,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
                addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
-                       addr->a.v6.sin6_port = 0;
                        addr->a.v6.sin6_addr = ifp->addr;
                        addr->a.v6.sin6_scope_id = dev->ifindex;
                        addr->valid = 1;
index 123e9f2dc22652ba0e7bf26cd329682b9afefa0c..edfcf16e704c4e02a93a13e2bdd507e91658ba0f 100644 (file)
@@ -36,6 +36,7 @@ static __le32 sctp_gso_make_checksum(struct sk_buff *skb)
 {
        skb->ip_summed = CHECKSUM_NONE;
        skb->csum_not_inet = 0;
+       gso_reset_checksum(skb, ~0);
        return sctp_compute_cksum(skb, skb_transport_offset(skb));
 }
 
index d5878ae5584090dbfd2841953a87088538593908..6abc8b274270730e482730bbc3ef735a7ffd2e52 100644 (file)
@@ -101,7 +101,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
                addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v4.sin_family = AF_INET;
-                       addr->a.v4.sin_port = 0;
                        addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
                        addr->valid = 1;
                        INIT_LIST_HEAD(&addr->list);
@@ -441,7 +440,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        }
        if (saddr) {
                fl4->saddr = saddr->v4.sin_addr.s_addr;
-               fl4->fl4_sport = saddr->v4.sin_port;
+               if (!fl4->fl4_sport)
+                       fl4->fl4_sport = saddr->v4.sin_port;
        }
 
        pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
@@ -776,10 +776,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 
        switch (ev) {
        case NETDEV_UP:
-               addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+               addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v4.sin_family = AF_INET;
-                       addr->a.v4.sin_port = 0;
                        addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
                        addr->valid = 1;
                        spin_lock_bh(&net->sctp.local_addr_lock);
index f4ac6c592e1396e136311defe312be22ece411d8..d05c57664e36e073304e0dc083a9c1d4a342002d 100644 (file)
@@ -495,7 +495,10 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
         *
         * [INIT ACK back to where the INIT came from.]
         */
-       retval->transport = chunk->transport;
+       if (chunk->transport)
+               retval->transport =
+                       sctp_assoc_lookup_paddr(asoc,
+                                               &chunk->transport->ipaddr);
 
        retval->subh.init_hdr =
                sctp_addto_chunk(retval, sizeof(initack), &initack);
@@ -642,8 +645,10 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,
         *
         * [COOKIE ACK back to where the COOKIE ECHO came from.]
         */
-       if (retval && chunk)
-               retval->transport = chunk->transport;
+       if (retval && chunk && chunk->transport)
+               retval->transport =
+                       sctp_assoc_lookup_paddr(asoc,
+                                               &chunk->transport->ipaddr);
 
        return retval;
 }
index f93c3cf9e5674b5d446e90ccd43611eca5fab508..65d6d04546aee0febd6a533264c27701674f6815 100644 (file)
@@ -2027,7 +2027,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
        struct sctp_endpoint *ep = sctp_sk(sk)->ep;
        struct sctp_transport *transport = NULL;
        struct sctp_sndrcvinfo _sinfo, *sinfo;
-       struct sctp_association *asoc;
+       struct sctp_association *asoc, *tmp;
        struct sctp_cmsgs cmsgs;
        union sctp_addr *daddr;
        bool new = false;
@@ -2053,7 +2053,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
 
        /* SCTP_SENDALL process */
        if ((sflags & SCTP_SENDALL) && sctp_style(sk, UDP)) {
-               list_for_each_entry(asoc, &ep->asocs, asocs) {
+               list_for_each_entry_safe(asoc, tmp, &ep->asocs, asocs) {
                        err = sctp_sendmsg_check_sflags(asoc, sflags, msg,
                                                        msg_len);
                        if (err == 0)
index 3892e7630f3adf6d42b57244b761c9e1aa558e95..2936ed17bf9ef8ce30046d148a249b80a341d59f 100644 (file)
@@ -84,6 +84,19 @@ static void fa_zero(struct flex_array *fa, size_t index, size_t count)
        }
 }
 
+static size_t fa_index(struct flex_array *fa, void *elem, size_t count)
+{
+       size_t index = 0;
+
+       while (count--) {
+               if (elem == flex_array_get(fa, index))
+                       break;
+               index++;
+       }
+
+       return index;
+}
+
 /* Migrates chunks from stream queues to new stream queues if needed,
  * but not across associations. Also, removes those chunks to streams
  * higher than the new max.
@@ -131,8 +144,10 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
                }
        }
 
-       for (i = outcnt; i < stream->outcnt; i++)
+       for (i = outcnt; i < stream->outcnt; i++) {
                kfree(SCTP_SO(stream, i)->ext);
+               SCTP_SO(stream, i)->ext = NULL;
+       }
 }
 
 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
@@ -147,6 +162,13 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
 
        if (stream->out) {
                fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
+               if (stream->out_curr) {
+                       size_t index = fa_index(stream->out, stream->out_curr,
+                                               stream->outcnt);
+
+                       BUG_ON(index == stream->outcnt);
+                       stream->out_curr = flex_array_get(out, index);
+               }
                fa_free(stream->out);
        }
 
@@ -585,9 +607,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
        struct sctp_strreset_outreq *outreq = param.v;
        struct sctp_stream *stream = &asoc->stream;
        __u32 result = SCTP_STRRESET_DENIED;
-       __u16 i, nums, flags = 0;
        __be16 *str_p = NULL;
        __u32 request_seq;
+       __u16 i, nums;
 
        request_seq = ntohl(outreq->request_seq);
 
@@ -615,6 +637,15 @@ struct sctp_chunk *sctp_process_strreset_outreq(
        if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
                goto out;
 
+       nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
+       str_p = outreq->list_of_streams;
+       for (i = 0; i < nums; i++) {
+               if (ntohs(str_p[i]) >= stream->incnt) {
+                       result = SCTP_STRRESET_ERR_WRONG_SSN;
+                       goto out;
+               }
+       }
+
        if (asoc->strreset_chunk) {
                if (!sctp_chunk_lookup_strreset_param(
                                asoc, outreq->response_seq,
@@ -637,32 +668,19 @@ struct sctp_chunk *sctp_process_strreset_outreq(
                        sctp_chunk_put(asoc->strreset_chunk);
                        asoc->strreset_chunk = NULL;
                }
-
-               flags = SCTP_STREAM_RESET_INCOMING_SSN;
        }
 
-       nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
-       if (nums) {
-               str_p = outreq->list_of_streams;
-               for (i = 0; i < nums; i++) {
-                       if (ntohs(str_p[i]) >= stream->incnt) {
-                               result = SCTP_STRRESET_ERR_WRONG_SSN;
-                               goto out;
-                       }
-               }
-
+       if (nums)
                for (i = 0; i < nums; i++)
                        SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
-       } else {
+       else
                for (i = 0; i < stream->incnt; i++)
                        SCTP_SI(stream, i)->mid = 0;
-       }
 
        result = SCTP_STRRESET_PERFORMED;
 
        *evp = sctp_ulpevent_make_stream_reset_event(asoc,
-               flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
-               GFP_ATOMIC);
+               SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
 
 out:
        sctp_update_strreset_result(asoc, result);
@@ -738,9 +756,6 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 
        result = SCTP_STRRESET_PERFORMED;
 
-       *evp = sctp_ulpevent_make_stream_reset_event(asoc,
-               SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
-
 out:
        sctp_update_strreset_result(asoc, result);
 err:
@@ -873,6 +888,14 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
        if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
                goto out;
 
+       in = ntohs(addstrm->number_of_streams);
+       incnt = stream->incnt + in;
+       if (!in || incnt > SCTP_MAX_STREAM)
+               goto out;
+
+       if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
+               goto out;
+
        if (asoc->strreset_chunk) {
                if (!sctp_chunk_lookup_strreset_param(
                        asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
@@ -896,14 +919,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
                }
        }
 
-       in = ntohs(addstrm->number_of_streams);
-       incnt = stream->incnt + in;
-       if (!in || incnt > SCTP_MAX_STREAM)
-               goto out;
-
-       if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
-               goto out;
-
        stream->incnt = incnt;
 
        result = SCTP_STRRESET_PERFORMED;
@@ -973,9 +988,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 
        result = SCTP_STRRESET_PERFORMED;
 
-       *evp = sctp_ulpevent_make_stream_change_event(asoc,
-               0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
-
 out:
        sctp_update_strreset_result(asoc, result);
 err:
@@ -1036,10 +1048,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
                                        sout->mid_uo = 0;
                                }
                        }
-
-                       flags = SCTP_STREAM_RESET_OUTGOING_SSN;
                }
 
+               flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
+
                for (i = 0; i < stream->outcnt; i++)
                        SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
 
@@ -1058,6 +1070,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
                nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) /
                       sizeof(__u16);
 
+               flags |= SCTP_STREAM_RESET_INCOMING_SSN;
+
                *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
                        nums, str_p, GFP_ATOMIC);
        } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
index c4da4a78d369e359f237772090ff0890a1782c5b..b04a813fc865a4299a6d9e19844710bfef1d3836 100644 (file)
@@ -146,6 +146,9 @@ static int smc_release(struct socket *sock)
                sock_set_flag(sk, SOCK_DEAD);
                sk->sk_shutdown |= SHUTDOWN_MASK;
        }
+
+       sk->sk_prot->unhash(sk);
+
        if (smc->clcsock) {
                if (smc->use_fallback && sk->sk_state == SMC_LISTEN) {
                        /* wake up clcsock accept */
@@ -170,7 +173,6 @@ static int smc_release(struct socket *sock)
                smc_conn_free(&smc->conn);
        release_sock(sk);
 
-       sk->sk_prot->unhash(sk);
        sock_put(sk); /* final sock_put */
 out:
        return rc;
@@ -1503,6 +1505,11 @@ static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
        smc = smc_sk(sk);
        lock_sock(sk);
+       if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
+               /* socket was connected before, no more data to read */
+               rc = 0;
+               goto out;
+       }
        if ((sk->sk_state == SMC_INIT) ||
            (sk->sk_state == SMC_LISTEN) ||
            (sk->sk_state == SMC_CLOSED))
@@ -1838,7 +1845,11 @@ static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos,
 
        smc = smc_sk(sk);
        lock_sock(sk);
-
+       if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
+               /* socket was connected before, no more data to read */
+               rc = 0;
+               goto out;
+       }
        if (sk->sk_state == SMC_INIT ||
            sk->sk_state == SMC_LISTEN ||
            sk->sk_state == SMC_CLOSED)
index db83332ac1c8ce285f29e2bcc69e22f203b8afc3..fb07ad8d69a62a7789c6651b50fb939c8ccf8d83 100644 (file)
 
 /********************************** send *************************************/
 
-struct smc_cdc_tx_pend {
-       struct smc_connection   *conn;          /* socket connection */
-       union smc_host_cursor   cursor; /* tx sndbuf cursor sent */
-       union smc_host_cursor   p_cursor;       /* rx RMBE cursor produced */
-       u16                     ctrl_seq;       /* conn. tx sequence # */
-};
-
 /* handler for send/transmission completion of a CDC msg */
 static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
                               struct smc_link *link,
@@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
 
 int smc_cdc_get_free_slot(struct smc_connection *conn,
                          struct smc_wr_buf **wr_buf,
+                         struct smc_rdma_wr **wr_rdma_buf,
                          struct smc_cdc_tx_pend **pend)
 {
        struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
        int rc;
 
        rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
+                                    wr_rdma_buf,
                                     (struct smc_wr_tx_pend_priv **)pend);
        if (!conn->alert_token_local)
                /* abnormal termination */
@@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn,
                     struct smc_wr_buf *wr_buf,
                     struct smc_cdc_tx_pend *pend)
 {
+       union smc_host_cursor cfed;
        struct smc_link *link;
        int rc;
 
@@ -105,12 +101,10 @@ int smc_cdc_msg_send(struct smc_connection *conn,
 
        conn->tx_cdc_seq++;
        conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
-       smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf,
-                           &conn->local_tx_ctrl, conn);
+       smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, conn, &cfed);
        rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
        if (!rc)
-               smc_curs_copy(&conn->rx_curs_confirmed,
-                             &conn->local_tx_ctrl.cons, conn);
+               smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn);
 
        return rc;
 }
@@ -121,11 +115,14 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn)
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
+       rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend);
        if (rc)
                return rc;
 
-       return smc_cdc_msg_send(conn, wr_buf, pend);
+       spin_lock_bh(&conn->send_lock);
+       rc = smc_cdc_msg_send(conn, wr_buf, pend);
+       spin_unlock_bh(&conn->send_lock);
+       return rc;
 }
 
 int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn)
index b5bfe38c7f9b6a87258adc0aecce58c31c2a164a..f1cdde9d4b890116862a4c9b8212546bfa2b7937 100644 (file)
@@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
 #endif
 }
 
-/* calculate cursor difference between old and new, where old <= new */
+/* calculate cursor difference between old and new, where old <= new and
+ * difference cannot exceed size
+ */
 static inline int smc_curs_diff(unsigned int size,
                                union smc_host_cursor *old,
                                union smc_host_cursor *new)
@@ -185,28 +187,51 @@ static inline int smc_curs_comp(unsigned int size,
        return smc_curs_diff(size, old, new);
 }
 
+/* calculate cursor difference between old and new, where old <= new and
+ * difference may exceed size
+ */
+static inline int smc_curs_diff_large(unsigned int size,
+                                     union smc_host_cursor *old,
+                                     union smc_host_cursor *new)
+{
+       if (old->wrap < new->wrap)
+               return min_t(int,
+                            (size - old->count) + new->count +
+                            (new->wrap - old->wrap - 1) * size,
+                            size);
+
+       if (old->wrap > new->wrap) /* wrap has switched from 0xffff to 0x0000 */
+               return min_t(int,
+                            (size - old->count) + new->count +
+                            (new->wrap + 0xffff - old->wrap) * size,
+                            size);
+
+       return max_t(int, 0, (new->count - old->count));
+}
+
 static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer,
                                          union smc_host_cursor *local,
+                                         union smc_host_cursor *save,
                                          struct smc_connection *conn)
 {
-       union smc_host_cursor temp;
-
-       smc_curs_copy(&temp, local, conn);
-       peer->count = htonl(temp.count);
-       peer->wrap = htons(temp.wrap);
+       smc_curs_copy(save, local, conn);
+       peer->count = htonl(save->count);
+       peer->wrap = htons(save->wrap);
        /* peer->reserved = htons(0); must be ensured by caller */
 }
 
 static inline void smc_host_msg_to_cdc(struct smc_cdc_msg *peer,
-                                      struct smc_host_cdc_msg *local,
-                                      struct smc_connection *conn)
+                                      struct smc_connection *conn,
+                                      union smc_host_cursor *save)
 {
+       struct smc_host_cdc_msg *local = &conn->local_tx_ctrl;
+
        peer->common.type = local->common.type;
        peer->len = local->len;
        peer->seqno = htons(local->seqno);
        peer->token = htonl(local->token);
-       smc_host_cursor_to_cdc(&peer->prod, &local->prod, conn);
-       smc_host_cursor_to_cdc(&peer->cons, &local->cons, conn);
+       smc_host_cursor_to_cdc(&peer->prod, &local->prod, save, conn);
+       smc_host_cursor_to_cdc(&peer->cons, &local->cons, save, conn);
        peer->prod_flags = local->prod_flags;
        peer->conn_state_flags = local->conn_state_flags;
 }
@@ -270,10 +295,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
                smcr_cdc_msg_to_host(local, peer, conn);
 }
 
-struct smc_cdc_tx_pend;
+struct smc_cdc_tx_pend {
+       struct smc_connection   *conn;          /* socket connection */
+       union smc_host_cursor   cursor;         /* tx sndbuf cursor sent */
+       union smc_host_cursor   p_cursor;       /* rx RMBE cursor produced */
+       u16                     ctrl_seq;       /* conn. tx sequence # */
+};
 
 int smc_cdc_get_free_slot(struct smc_connection *conn,
                          struct smc_wr_buf **wr_buf,
+                         struct smc_rdma_wr **wr_rdma_buf,
                          struct smc_cdc_tx_pend **pend);
 void smc_cdc_tx_dismiss_slots(struct smc_connection *conn);
 int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
index 776e9dfc915dd5fb9200a5440862b7bbbc4f5440..d53fd588d1f5a4450819934c83cf960dc29ff46b 100644 (file)
@@ -378,7 +378,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
        vec.iov_len = sizeof(struct smc_clc_msg_decline);
        len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
                             sizeof(struct smc_clc_msg_decline));
-       if (len < sizeof(struct smc_clc_msg_decline))
+       if (len < 0 || len < sizeof(struct smc_clc_msg_decline))
                len = -EPROTO;
        return len > 0 ? 0 : len;
 }
index ea2b87f29469610c1afaf5e043a935c24589425b..e39cadda1bf5a4c48b9c31459b2046a5c921a629 100644 (file)
@@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work)
 
        switch (sk->sk_state) {
        case SMC_INIT:
-               if (atomic_read(&conn->bytes_to_rcv) ||
-                   (rxflags->peer_done_writing &&
-                    !smc_cdc_rxed_any_close(conn))) {
-                       sk->sk_state = SMC_APPCLOSEWAIT1;
-               } else {
-                       sk->sk_state = SMC_CLOSED;
-                       sock_put(sk); /* passive closing */
-               }
+               sk->sk_state = SMC_APPCLOSEWAIT1;
                break;
        case SMC_ACTIVE:
                sk->sk_state = SMC_APPCLOSEWAIT1;
index 35c1cdc93e1c54c3ad0003aea46f0b7597a7e872..aa1c551cee8160ac732399091bdf26c3febaee46 100644 (file)
@@ -128,6 +128,8 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
 {
        struct smc_link_group *lgr = conn->lgr;
 
+       if (!lgr)
+               return;
        write_lock_bh(&lgr->conns_lock);
        if (conn->alert_token_local) {
                __smc_lgr_unregister_conn(conn);
@@ -300,13 +302,13 @@ static void smc_buf_unuse(struct smc_connection *conn,
                conn->sndbuf_desc->used = 0;
        if (conn->rmb_desc) {
                if (!conn->rmb_desc->regerr) {
-                       conn->rmb_desc->used = 0;
                        if (!lgr->is_smcd) {
                                /* unregister rmb with peer */
                                smc_llc_do_delete_rkey(
                                                &lgr->lnk[SMC_SINGLE_LINK],
                                                conn->rmb_desc);
                        }
+                       conn->rmb_desc->used = 0;
                } else {
                        /* buf registration failed, reuse not possible */
                        write_lock_bh(&lgr->rmbs_lock);
@@ -628,6 +630,8 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
                        local_contact = SMC_REUSE_CONTACT;
                        conn->lgr = lgr;
                        smc_lgr_register_conn(conn); /* add smc conn to lgr */
+                       if (delayed_work_pending(&lgr->free_work))
+                               cancel_delayed_work(&lgr->free_work);
                        write_unlock_bh(&lgr->conns_lock);
                        break;
                }
index b00287989a3dea43975ce728df8a9e2885656b71..8806d2afa6edb1178f4ad2904aa1346ee42bcae6 100644 (file)
@@ -52,6 +52,24 @@ enum smc_wr_reg_state {
        FAILED          /* ib_wr_reg_mr response: failure */
 };
 
+struct smc_rdma_sge {                          /* sges for RDMA writes */
+       struct ib_sge           wr_tx_rdma_sge[SMC_IB_MAX_SEND_SGE];
+};
+
+#define SMC_MAX_RDMA_WRITES    2               /* max. # of RDMA writes per
+                                                * message send
+                                                */
+
+struct smc_rdma_sges {                         /* sges per message send */
+       struct smc_rdma_sge     tx_rdma_sge[SMC_MAX_RDMA_WRITES];
+};
+
+struct smc_rdma_wr {                           /* work requests per message
+                                                * send
+                                                */
+       struct ib_rdma_wr       wr_tx_rdma[SMC_MAX_RDMA_WRITES];
+};
+
 struct smc_link {
        struct smc_ib_device    *smcibdev;      /* ib-device */
        u8                      ibport;         /* port - values 1 | 2 */
@@ -64,6 +82,8 @@ struct smc_link {
        struct smc_wr_buf       *wr_tx_bufs;    /* WR send payload buffers */
        struct ib_send_wr       *wr_tx_ibs;     /* WR send meta data */
        struct ib_sge           *wr_tx_sges;    /* WR send gather meta data */
+       struct smc_rdma_sges    *wr_tx_rdma_sges;/*RDMA WRITE gather meta data*/
+       struct smc_rdma_wr      *wr_tx_rdmas;   /* WR RDMA WRITE */
        struct smc_wr_tx_pend   *wr_tx_pends;   /* WR send waiting for CQE */
        /* above four vectors have wr_tx_cnt elements and use the same index */
        dma_addr_t              wr_tx_dma_addr; /* DMA address of wr_tx_bufs */
index e519ef29c0ffcb74baf25753a58048504fedd813..76487a16934ed015a05d9787c682b3df4e253565 100644 (file)
@@ -289,8 +289,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk)
 
 static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
 {
-       struct smc_ib_device *smcibdev =
-               (struct smc_ib_device *)ibevent->device;
+       struct smc_link *lnk = (struct smc_link *)priv;
+       struct smc_ib_device *smcibdev = lnk->smcibdev;
        u8 port_idx;
 
        switch (ibevent->event) {
@@ -298,7 +298,7 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
        case IB_EVENT_GID_CHANGE:
        case IB_EVENT_PORT_ERR:
        case IB_EVENT_QP_ACCESS_ERR:
-               port_idx = ibevent->element.port_num - 1;
+               port_idx = ibevent->element.qp->port - 1;
                set_bit(port_idx, &smcibdev->port_event_mask);
                schedule_work(&smcibdev->port_event_work);
                break;
index a6d3623d06f422073995b5c4e42d31b46088b466..4fd60c522802949e8b0f6931f911fc445765873b 100644 (file)
@@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link,
 {
        int rc;
 
-       rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend);
+       rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
+                                    pend);
        if (rc < 0)
                return rc;
        BUILD_BUG_ON_MSG(
index 7cb3e4f07c10f5da154c0322ef4fae54a6dc85e2..632c3109dee52c20024aeeb47437eb4874c8da87 100644 (file)
@@ -27,7 +27,7 @@
 static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = {
        [SMC_PNETID_NAME] = {
                .type = NLA_NUL_STRING,
-               .len = SMC_MAX_PNETID_LEN - 1
+               .len = SMC_MAX_PNETID_LEN
        },
        [SMC_PNETID_ETHNAME] = {
                .type = NLA_NUL_STRING,
index d8366ed517576ba7f258ad74f0cf91f7fd92d7e0..f93f3580c1006e0638a0c127a631da5cdc7f6b5f 100644 (file)
@@ -165,12 +165,11 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len)
                        conn->local_tx_ctrl.prod_flags.urg_data_pending = 1;
 
                if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) {
+                       if (send_done)
+                               return send_done;
                        rc = smc_tx_wait(smc, msg->msg_flags);
-                       if (rc) {
-                               if (send_done)
-                                       return send_done;
+                       if (rc)
                                goto out_err;
-                       }
                        continue;
                }
 
@@ -267,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len,
 
 /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */
 static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset,
-                            int num_sges, struct ib_sge sges[])
+                            int num_sges, struct ib_rdma_wr *rdma_wr)
 {
        struct smc_link_group *lgr = conn->lgr;
-       struct ib_rdma_wr rdma_wr;
        struct smc_link *link;
        int rc;
 
-       memset(&rdma_wr, 0, sizeof(rdma_wr));
        link = &lgr->lnk[SMC_SINGLE_LINK];
-       rdma_wr.wr.wr_id = smc_wr_tx_get_next_wr_id(link);
-       rdma_wr.wr.sg_list = sges;
-       rdma_wr.wr.num_sge = num_sges;
-       rdma_wr.wr.opcode = IB_WR_RDMA_WRITE;
-       rdma_wr.remote_addr =
+       rdma_wr->wr.wr_id = smc_wr_tx_get_next_wr_id(link);
+       rdma_wr->wr.num_sge = num_sges;
+       rdma_wr->remote_addr =
                lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr +
                /* RMBE within RMB */
                conn->tx_off +
                /* offset within RMBE */
                peer_rmbe_offset;
-       rdma_wr.rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
-       rc = ib_post_send(link->roce_qp, &rdma_wr.wr, NULL);
+       rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
+       rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
        if (rc) {
                conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
                smc_lgr_terminate(lgr);
@@ -314,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn,
 /* SMC-R helper for smc_tx_rdma_writes() */
 static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
                               size_t src_off, size_t src_len,
-                              size_t dst_off, size_t dst_len)
+                              size_t dst_off, size_t dst_len,
+                              struct smc_rdma_wr *wr_rdma_buf)
 {
        dma_addr_t dma_addr =
                sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl);
-       struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
        int src_len_sum = src_len, dst_len_sum = dst_len;
-       struct ib_sge sges[SMC_IB_MAX_SEND_SGE];
        int sent_count = src_off;
        int srcchunk, dstchunk;
        int num_sges;
        int rc;
 
        for (dstchunk = 0; dstchunk < 2; dstchunk++) {
+               struct ib_sge *sge =
+                       wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
+
                num_sges = 0;
                for (srcchunk = 0; srcchunk < 2; srcchunk++) {
-                       sges[srcchunk].addr = dma_addr + src_off;
-                       sges[srcchunk].length = src_len;
-                       sges[srcchunk].lkey = link->roce_pd->local_dma_lkey;
+                       sge[srcchunk].addr = dma_addr + src_off;
+                       sge[srcchunk].length = src_len;
                        num_sges++;
 
                        src_off += src_len;
@@ -344,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
                        src_len = dst_len - src_len; /* remainder */
                        src_len_sum += src_len;
                }
-               rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges);
+               rc = smc_tx_rdma_write(conn, dst_off, num_sges,
+                                      &wr_rdma_buf->wr_tx_rdma[dstchunk]);
                if (rc)
                        return rc;
                if (dst_len_sum == len)
@@ -403,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len,
 /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit;
  * usable snd_wnd as max transmit
  */
-static int smc_tx_rdma_writes(struct smc_connection *conn)
+static int smc_tx_rdma_writes(struct smc_connection *conn,
+                             struct smc_rdma_wr *wr_rdma_buf)
 {
        size_t len, src_len, dst_off, dst_len; /* current chunk values */
        union smc_host_cursor sent, prep, prod, cons;
@@ -464,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
                                         dst_off, dst_len);
        else
                rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len,
-                                        dst_off, dst_len);
+                                        dst_off, dst_len, wr_rdma_buf);
        if (rc)
                return rc;
 
@@ -485,31 +483,30 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
 static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags;
+       struct smc_rdma_wr *wr_rdma_buf;
        struct smc_cdc_tx_pend *pend;
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       spin_lock_bh(&conn->send_lock);
-       rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
+       rc = smc_cdc_get_free_slot(conn, &wr_buf, &wr_rdma_buf, &pend);
        if (rc < 0) {
                if (rc == -EBUSY) {
                        struct smc_sock *smc =
                                container_of(conn, struct smc_sock, conn);
 
-                       if (smc->sk.sk_err == ECONNABORTED) {
-                               rc = sock_error(&smc->sk);
-                               goto out_unlock;
-                       }
+                       if (smc->sk.sk_err == ECONNABORTED)
+                               return sock_error(&smc->sk);
                        rc = 0;
                        if (conn->alert_token_local) /* connection healthy */
                                mod_delayed_work(system_wq, &conn->tx_work,
                                                 SMC_TX_WORK_DELAY);
                }
-               goto out_unlock;
+               return rc;
        }
 
+       spin_lock_bh(&conn->send_lock);
        if (!conn->local_tx_ctrl.prod_flags.urg_data_present) {
-               rc = smc_tx_rdma_writes(conn);
+               rc = smc_tx_rdma_writes(conn, wr_rdma_buf);
                if (rc) {
                        smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK],
                                           (struct smc_wr_tx_pend_priv *)pend);
@@ -536,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
 
        spin_lock_bh(&conn->send_lock);
        if (!pflags->urg_data_present)
-               rc = smc_tx_rdma_writes(conn);
+               rc = smc_tx_rdma_writes(conn, NULL);
        if (!rc)
                rc = smcd_cdc_msg_send(conn);
 
@@ -598,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
        if (to_confirm > conn->rmbe_update_limit) {
                smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn);
                sender_free = conn->rmb_desc->len -
-                             smc_curs_diff(conn->rmb_desc->len, &prod, &cfed);
+                             smc_curs_diff_large(conn->rmb_desc->len,
+                                                 &cfed, &prod);
        }
 
        if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
index c2694750a6a8abe2f1353dae02e95420e5a01b48..253aa75dc2b6818c1a9d4646535c51e1e59bc3f3 100644 (file)
@@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
  * @link:              Pointer to smc_link used to later send the message.
  * @handler:           Send completion handler function pointer.
  * @wr_buf:            Out value returns pointer to message buffer.
+ * @wr_rdma_buf:       Out value returns pointer to rdma work request.
  * @wr_pend_priv:      Out value returns pointer serving as handler context.
  *
  * Return: 0 on success, or -errno on error.
@@ -167,6 +168,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
 int smc_wr_tx_get_free_slot(struct smc_link *link,
                            smc_wr_tx_handler handler,
                            struct smc_wr_buf **wr_buf,
+                           struct smc_rdma_wr **wr_rdma_buf,
                            struct smc_wr_tx_pend_priv **wr_pend_priv)
 {
        struct smc_wr_tx_pend *wr_pend;
@@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
        wr_ib = &link->wr_tx_ibs[idx];
        wr_ib->wr_id = wr_id;
        *wr_buf = &link->wr_tx_bufs[idx];
+       if (wr_rdma_buf)
+               *wr_rdma_buf = &link->wr_tx_rdmas[idx];
        *wr_pend_priv = &wr_pend->priv;
        return 0;
 }
@@ -218,10 +222,10 @@ int smc_wr_tx_put_slot(struct smc_link *link,
                u32 idx = pend->idx;
 
                /* clear the full struct smc_wr_tx_pend including .priv */
-               memset(&link->wr_tx_pends[pend->idx], 0,
-                      sizeof(link->wr_tx_pends[pend->idx]));
-               memset(&link->wr_tx_bufs[pend->idx], 0,
-                      sizeof(link->wr_tx_bufs[pend->idx]));
+               memset(&link->wr_tx_pends[idx], 0,
+                      sizeof(link->wr_tx_pends[idx]));
+               memset(&link->wr_tx_bufs[idx], 0,
+                      sizeof(link->wr_tx_bufs[idx]));
                test_and_clear_bit(idx, link->wr_tx_mask);
                return 1;
        }
@@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk)
                        lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE;
                lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE;
                lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[0].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[1].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[0].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[1].lkey =
+                       lnk->roce_pd->local_dma_lkey;
                lnk->wr_tx_ibs[i].next = NULL;
                lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i];
                lnk->wr_tx_ibs[i].num_sge = 1;
                lnk->wr_tx_ibs[i].opcode = IB_WR_SEND;
                lnk->wr_tx_ibs[i].send_flags =
                        IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list =
+                       lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.sg_list =
+                       lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge;
        }
        for (i = 0; i < lnk->wr_rx_cnt; i++) {
                lnk->wr_rx_sges[i].addr =
@@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk)
        lnk->wr_tx_mask = NULL;
        kfree(lnk->wr_tx_sges);
        lnk->wr_tx_sges = NULL;
+       kfree(lnk->wr_tx_rdma_sges);
+       lnk->wr_tx_rdma_sges = NULL;
        kfree(lnk->wr_rx_sges);
        lnk->wr_rx_sges = NULL;
+       kfree(lnk->wr_tx_rdmas);
+       lnk->wr_tx_rdmas = NULL;
        kfree(lnk->wr_rx_ibs);
        lnk->wr_rx_ibs = NULL;
        kfree(lnk->wr_tx_ibs);
@@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
                                  GFP_KERNEL);
        if (!link->wr_rx_ibs)
                goto no_mem_wr_tx_ibs;
+       link->wr_tx_rdmas = kcalloc(SMC_WR_BUF_CNT,
+                                   sizeof(link->wr_tx_rdmas[0]),
+                                   GFP_KERNEL);
+       if (!link->wr_tx_rdmas)
+               goto no_mem_wr_rx_ibs;
+       link->wr_tx_rdma_sges = kcalloc(SMC_WR_BUF_CNT,
+                                       sizeof(link->wr_tx_rdma_sges[0]),
+                                       GFP_KERNEL);
+       if (!link->wr_tx_rdma_sges)
+               goto no_mem_wr_tx_rdmas;
        link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]),
                                   GFP_KERNEL);
        if (!link->wr_tx_sges)
-               goto no_mem_wr_rx_ibs;
+               goto no_mem_wr_tx_rdma_sges;
        link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
                                   sizeof(link->wr_rx_sges[0]),
                                   GFP_KERNEL);
@@ -579,6 +611,10 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
        kfree(link->wr_rx_sges);
 no_mem_wr_tx_sges:
        kfree(link->wr_tx_sges);
+no_mem_wr_tx_rdma_sges:
+       kfree(link->wr_tx_rdma_sges);
+no_mem_wr_tx_rdmas:
+       kfree(link->wr_tx_rdmas);
 no_mem_wr_rx_ibs:
        kfree(link->wr_rx_ibs);
 no_mem_wr_tx_ibs:
index 1d85bb14fd6f88c455274ef13c5003fb4eb46e28..09bf32fd39596ea241c97f3cd2dcbb8f146d9604 100644 (file)
@@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev);
 
 int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler,
                            struct smc_wr_buf **wr_buf,
+                           struct smc_rdma_wr **wrs,
                            struct smc_wr_tx_pend_priv **wr_pend_priv);
 int smc_wr_tx_put_slot(struct smc_link *link,
                       struct smc_wr_tx_pend_priv *wr_pend_priv);
index e89884e2197babb827b34a345ad8d8625c7071ce..d80d87a395ea99c58624feb204c896e697140bfa 100644 (file)
@@ -941,8 +941,7 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
 EXPORT_SYMBOL(dlci_ioctl_set);
 
 static long sock_do_ioctl(struct net *net, struct socket *sock,
-                         unsigned int cmd, unsigned long arg,
-                         unsigned int ifreq_size)
+                         unsigned int cmd, unsigned long arg)
 {
        int err;
        void __user *argp = (void __user *)arg;
@@ -968,11 +967,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
        } else {
                struct ifreq ifr;
                bool need_copyout;
-               if (copy_from_user(&ifr, argp, ifreq_size))
+               if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
                        return -EFAULT;
                err = dev_ioctl(net, cmd, &ifr, &need_copyout);
                if (!err && need_copyout)
-                       if (copy_to_user(argp, &ifr, ifreq_size))
+                       if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
                                return -EFAULT;
        }
        return err;
@@ -1071,8 +1070,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                        err = open_related_ns(&net->ns, get_net_ns);
                        break;
                default:
-                       err = sock_do_ioctl(net, sock, cmd, arg,
-                                           sizeof(struct ifreq));
+                       err = sock_do_ioctl(net, sock, cmd, arg);
                        break;
                }
        return err;
@@ -2780,8 +2778,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        int err;
 
        set_fs(KERNEL_DS);
-       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv,
-                           sizeof(struct compat_ifreq));
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
        if (!err)
                err = compat_put_timeval(&ktv, up);
@@ -2797,8 +2794,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        int err;
 
        set_fs(KERNEL_DS);
-       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts,
-                           sizeof(struct compat_ifreq));
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
        if (!err)
                err = compat_put_timespec(&kts, up);
@@ -2994,6 +2990,54 @@ static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
        return dev_ioctl(net, cmd, &ifreq, NULL);
 }
 
+static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
+                             unsigned int cmd,
+                             struct compat_ifreq __user *uifr32)
+{
+       struct ifreq __user *uifr;
+       int err;
+
+       /* Handle the fact that while struct ifreq has the same *layout* on
+        * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
+        * which are handled elsewhere, it still has different *size* due to
+        * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
+        * resulting in struct ifreq being 32 and 40 bytes respectively).
+        * As a result, if the struct happens to be at the end of a page and
+        * the next page isn't readable/writable, we get a fault. To prevent
+        * that, copy back and forth to the full size.
+        */
+
+       uifr = compat_alloc_user_space(sizeof(*uifr));
+       if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
+               return -EFAULT;
+
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
+
+       if (!err) {
+               switch (cmd) {
+               case SIOCGIFFLAGS:
+               case SIOCGIFMETRIC:
+               case SIOCGIFMTU:
+               case SIOCGIFMEM:
+               case SIOCGIFHWADDR:
+               case SIOCGIFINDEX:
+               case SIOCGIFADDR:
+               case SIOCGIFBRDADDR:
+               case SIOCGIFDSTADDR:
+               case SIOCGIFNETMASK:
+               case SIOCGIFPFLAGS:
+               case SIOCGIFTXQLEN:
+               case SIOCGMIIPHY:
+               case SIOCGMIIREG:
+               case SIOCGIFNAME:
+                       if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
+                               err = -EFAULT;
+                       break;
+               }
+       }
+       return err;
+}
+
 static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
                        struct compat_ifreq __user *uifr32)
 {
@@ -3109,8 +3153,7 @@ static int routing_ioctl(struct net *net, struct socket *sock,
        }
 
        set_fs(KERNEL_DS);
-       ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r,
-                           sizeof(struct compat_ifreq));
+       ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
        set_fs(old_fs);
 
 out:
@@ -3210,21 +3253,22 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
        case SIOCSIFTXQLEN:
        case SIOCBRADDIF:
        case SIOCBRDELIF:
+       case SIOCGIFNAME:
        case SIOCSIFNAME:
        case SIOCGMIIPHY:
        case SIOCGMIIREG:
        case SIOCSMIIREG:
-       case SIOCSARP:
-       case SIOCGARP:
-       case SIOCDARP:
-       case SIOCATMARK:
        case SIOCBONDENSLAVE:
        case SIOCBONDRELEASE:
        case SIOCBONDSETHWADDR:
        case SIOCBONDCHANGEACTIVE:
-       case SIOCGIFNAME:
-               return sock_do_ioctl(net, sock, cmd, arg,
-                                    sizeof(struct compat_ifreq));
+               return compat_ifreq_ioctl(net, sock, cmd, argp);
+
+       case SIOCSARP:
+       case SIOCGARP:
+       case SIOCDARP:
+       case SIOCATMARK:
+               return sock_do_ioctl(net, sock, cmd, arg);
        }
 
        return -ENOIOCTLCMD;
index 1ff9768f545602dfa1d4db80c630321d4e86f6b8..f3023bbc0b7fcc292793fda4469e0c914b6ece93 100644 (file)
@@ -41,6 +41,9 @@ static unsigned long number_cred_unused;
 
 static struct cred machine_cred = {
        .usage = ATOMIC_INIT(1),
+#ifdef CONFIG_DEBUG_CREDENTIALS
+       .magic = CRED_MAGIC,
+#endif
 };
 
 /*
index dc86713b32b6d832fe840e82332999af119c874c..1531b0219344d9e47a8dc33509355fefa9e05f5c 100644 (file)
@@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        cred_len = p++;
 
        spin_lock(&ctx->gc_seq_lock);
-       req->rq_seqno = ctx->gc_seq++;
+       req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ;
        spin_unlock(&ctx->gc_seq_lock);
+       if (req->rq_seqno == MAXSEQ)
+               goto out_expired;
 
        *p++ = htonl((u32) RPC_GSS_VERSION);
        *p++ = htonl((u32) ctx->gc_proc);
@@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        mic.data = (u8 *)(p + 1);
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
-               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+               goto out_expired;
        } else if (maj_stat != 0) {
-               printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
+               pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
+               task->tk_status = -EIO;
                goto out_put_ctx;
        }
        p = xdr_encode_opaque(p, NULL, mic.len);
        gss_put_ctx(ctx);
        return p;
+out_expired:
+       clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       task->tk_status = -EKEYEXPIRED;
 out_put_ctx:
        gss_put_ctx(ctx);
        return NULL;
index fb6656295204cf6d2fca0451b8ba93a3e5fac057..507105127095a24ca89d49b12118d3e12ce85726 100644 (file)
@@ -44,7 +44,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
                      unsigned char *cksum, unsigned char *buf)
 {
        struct crypto_sync_skcipher *cipher;
-       unsigned char plain[8];
+       unsigned char *plain;
        s32 code;
 
        dprintk("RPC:       %s:\n", __func__);
@@ -52,6 +52,10 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
        if (IS_ERR(cipher))
                return PTR_ERR(cipher);
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
+
        plain[0] = (unsigned char) ((seqnum >> 24) & 0xff);
        plain[1] = (unsigned char) ((seqnum >> 16) & 0xff);
        plain[2] = (unsigned char) ((seqnum >> 8) & 0xff);
@@ -67,6 +71,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
 
        code = krb5_encrypt(cipher, cksum, plain, buf, 8);
 out:
+       kfree(plain);
        crypto_free_sync_skcipher(cipher);
        return code;
 }
@@ -77,12 +82,17 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
                u32 seqnum,
                unsigned char *cksum, unsigned char *buf)
 {
-       unsigned char plain[8];
+       unsigned char *plain;
+       s32 code;
 
        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
                return krb5_make_rc4_seq_num(kctx, direction, seqnum,
                                             cksum, buf);
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
+
        plain[0] = (unsigned char) (seqnum & 0xff);
        plain[1] = (unsigned char) ((seqnum >> 8) & 0xff);
        plain[2] = (unsigned char) ((seqnum >> 16) & 0xff);
@@ -93,7 +103,9 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
        plain[6] = direction;
        plain[7] = direction;
 
-       return krb5_encrypt(key, cksum, plain, buf, 8);
+       code = krb5_encrypt(key, cksum, plain, buf, 8);
+       kfree(plain);
+       return code;
 }
 
 static s32
@@ -101,7 +113,7 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
                     unsigned char *buf, int *direction, s32 *seqnum)
 {
        struct crypto_sync_skcipher *cipher;
-       unsigned char plain[8];
+       unsigned char *plain;
        s32 code;
 
        dprintk("RPC:       %s:\n", __func__);
@@ -113,20 +125,28 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
        if (code)
                goto out;
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain) {
+               code = -ENOMEM;
+               goto out;
+       }
+
        code = krb5_decrypt(cipher, cksum, buf, plain, 8);
        if (code)
-               goto out;
+               goto out_plain;
 
        if ((plain[4] != plain[5]) || (plain[4] != plain[6])
                                   || (plain[4] != plain[7])) {
                code = (s32)KG_BAD_SEQ;
-               goto out;
+               goto out_plain;
        }
 
        *direction = plain[4];
 
        *seqnum = ((plain[0] << 24) | (plain[1] << 16) |
                                        (plain[2] << 8) | (plain[3]));
+out_plain:
+       kfree(plain);
 out:
        crypto_free_sync_skcipher(cipher);
        return code;
@@ -139,7 +159,7 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
               int *direction, u32 *seqnum)
 {
        s32 code;
-       unsigned char plain[8];
+       unsigned char *plain;
        struct crypto_sync_skcipher *key = kctx->seq;
 
        dprintk("RPC:       krb5_get_seq_num:\n");
@@ -147,18 +167,25 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
                return krb5_get_rc4_seq_num(kctx, cksum, buf,
                                            direction, seqnum);
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
 
        if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
-               return code;
+               goto out;
 
        if ((plain[4] != plain[5]) || (plain[4] != plain[6]) ||
-           (plain[4] != plain[7]))
-               return (s32)KG_BAD_SEQ;
+           (plain[4] != plain[7])) {
+               code = (s32)KG_BAD_SEQ;
+               goto out;
+       }
 
        *direction = plain[4];
 
        *seqnum = ((plain[0]) |
                   (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24));
 
-       return 0;
+out:
+       kfree(plain);
+       return code;
 }
index 71d9599b5816591bd12751703d8487a8dda688a4..d7ec6132c046ec409db057d6ace332ab620fa88b 100644 (file)
@@ -1739,14 +1739,10 @@ rpc_xdr_encode(struct rpc_task *task)
        xdr_buf_init(&req->rq_rcv_buf,
                     req->rq_rbuffer,
                     req->rq_rcvsize);
-       req->rq_bytes_sent = 0;
 
        p = rpc_encode_header(task);
-       if (p == NULL) {
-               printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
-               rpc_exit(task, -EIO);
+       if (p == NULL)
                return;
-       }
 
        encode = task->tk_msg.rpc_proc->p_encode;
        if (encode == NULL)
@@ -1771,10 +1767,17 @@ call_encode(struct rpc_task *task)
        /* Did the encode result in an error condition? */
        if (task->tk_status != 0) {
                /* Was the error nonfatal? */
-               if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM)
+               switch (task->tk_status) {
+               case -EAGAIN:
+               case -ENOMEM:
                        rpc_delay(task, HZ >> 4);
-               else
+                       break;
+               case -EKEYEXPIRED:
+                       task->tk_action = call_refresh;
+                       break;
+               default:
                        rpc_exit(task, task->tk_status);
+               }
                return;
        }
 
@@ -2336,7 +2339,8 @@ rpc_encode_header(struct rpc_task *task)
        *p++ = htonl(clnt->cl_vers);    /* program version */
        *p++ = htonl(task->tk_msg.rpc_proc->p_proc);    /* procedure */
        p = rpcauth_marshcred(task, p);
-       req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
+       if (p)
+               req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
        return p;
 }
 
index 45a033329cd4a7156c41509a255e1ca1d969f2df..19bb356230edf521d78a4729e732ead121daaebd 100644 (file)
@@ -146,7 +146,7 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
        rcu_read_lock();
        xprt = rcu_dereference(clnt->cl_xprt);
        /* no "debugfs" dentry? Don't bother with the symlink. */
-       if (!xprt->debugfs) {
+       if (IS_ERR_OR_NULL(xprt->debugfs)) {
                rcu_read_unlock();
                return;
        }
index 73547d17d3c61a844c860c33acaff5259c81d54e..f1ec2110efebe6315523036bd11e30dbdf7c8de4 100644 (file)
@@ -1151,6 +1151,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
        struct rpc_xprt *xprt = req->rq_xprt;
 
        if (xprt_request_need_enqueue_transmit(task, req)) {
+               req->rq_bytes_sent = 0;
                spin_lock(&xprt->queue_lock);
                /*
                 * Requests that carry congestion control credits are added
@@ -1177,7 +1178,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
                                INIT_LIST_HEAD(&req->rq_xmit2);
                                goto out;
                        }
-               } else {
+               } else if (!req->rq_seqno) {
                        list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
                                if (pos->rq_task->tk_owner != task->tk_owner)
                                        continue;
index cf51b8f9b15f5d2806366b116c1226fff1b2fd8b..1f200119268ccdff5674f49eadebbde0de86fdd1 100644 (file)
@@ -537,6 +537,99 @@ void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
                                      DMA_TO_DEVICE);
 }
 
+/* If the xdr_buf has more elements than the device can
+ * transmit in a single RDMA Send, then the reply will
+ * have to be copied into a bounce buffer.
+ */
+static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma,
+                                   struct xdr_buf *xdr,
+                                   __be32 *wr_lst)
+{
+       int elements;
+
+       /* xdr->head */
+       elements = 1;
+
+       /* xdr->pages */
+       if (!wr_lst) {
+               unsigned int remaining;
+               unsigned long pageoff;
+
+               pageoff = xdr->page_base & ~PAGE_MASK;
+               remaining = xdr->page_len;
+               while (remaining) {
+                       ++elements;
+                       remaining -= min_t(u32, PAGE_SIZE - pageoff,
+                                          remaining);
+                       pageoff = 0;
+               }
+       }
+
+       /* xdr->tail */
+       if (xdr->tail[0].iov_len)
+               ++elements;
+
+       /* assume 1 SGE is needed for the transport header */
+       return elements >= rdma->sc_max_send_sges;
+}
+
+/* The device is not capable of sending the reply directly.
+ * Assemble the elements of @xdr into the transport header
+ * buffer.
+ */
+static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma,
+                                     struct svc_rdma_send_ctxt *ctxt,
+                                     struct xdr_buf *xdr, __be32 *wr_lst)
+{
+       unsigned char *dst, *tailbase;
+       unsigned int taillen;
+
+       dst = ctxt->sc_xprt_buf;
+       dst += ctxt->sc_sges[0].length;
+
+       memcpy(dst, xdr->head[0].iov_base, xdr->head[0].iov_len);
+       dst += xdr->head[0].iov_len;
+
+       tailbase = xdr->tail[0].iov_base;
+       taillen = xdr->tail[0].iov_len;
+       if (wr_lst) {
+               u32 xdrpad;
+
+               xdrpad = xdr_padsize(xdr->page_len);
+               if (taillen && xdrpad) {
+                       tailbase += xdrpad;
+                       taillen -= xdrpad;
+               }
+       } else {
+               unsigned int len, remaining;
+               unsigned long pageoff;
+               struct page **ppages;
+
+               ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT);
+               pageoff = xdr->page_base & ~PAGE_MASK;
+               remaining = xdr->page_len;
+               while (remaining) {
+                       len = min_t(u32, PAGE_SIZE - pageoff, remaining);
+
+                       memcpy(dst, page_address(*ppages), len);
+                       remaining -= len;
+                       dst += len;
+                       pageoff = 0;
+               }
+       }
+
+       if (taillen)
+               memcpy(dst, tailbase, taillen);
+
+       ctxt->sc_sges[0].length += xdr->len;
+       ib_dma_sync_single_for_device(rdma->sc_pd->device,
+                                     ctxt->sc_sges[0].addr,
+                                     ctxt->sc_sges[0].length,
+                                     DMA_TO_DEVICE);
+
+       return 0;
+}
+
 /* svc_rdma_map_reply_msg - Map the buffer holding RPC message
  * @rdma: controlling transport
  * @ctxt: send_ctxt for the Send WR
@@ -559,8 +652,10 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        u32 xdr_pad;
        int ret;
 
-       if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-               return -EIO;
+       if (svc_rdma_pull_up_needed(rdma, xdr, wr_lst))
+               return svc_rdma_pull_up_reply_msg(rdma, ctxt, xdr, wr_lst);
+
+       ++ctxt->sc_cur_sge_no;
        ret = svc_rdma_dma_map_buf(rdma, ctxt,
                                   xdr->head[0].iov_base,
                                   xdr->head[0].iov_len);
@@ -591,8 +686,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        while (remaining) {
                len = min_t(u32, PAGE_SIZE - page_off, remaining);
 
-               if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-                       return -EIO;
+               ++ctxt->sc_cur_sge_no;
                ret = svc_rdma_dma_map_page(rdma, ctxt, *ppages++,
                                            page_off, len);
                if (ret < 0)
@@ -606,8 +700,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        len = xdr->tail[0].iov_len;
 tail:
        if (len) {
-               if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-                       return -EIO;
+               ++ctxt->sc_cur_sge_no;
                ret = svc_rdma_dma_map_buf(rdma, ctxt, base, len);
                if (ret < 0)
                        return ret;
index 924c17d46903c9ead94c6a2c33d926ef53469392..57f86c63a46369537c3362dae062da82b554c271 100644 (file)
@@ -419,12 +419,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        /* Transport header, head iovec, tail iovec */
        newxprt->sc_max_send_sges = 3;
        /* Add one SGE per page list entry */
-       newxprt->sc_max_send_sges += svcrdma_max_req_size / PAGE_SIZE;
-       if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) {
-               pr_err("svcrdma: too few Send SGEs available (%d needed)\n",
-                      newxprt->sc_max_send_sges);
-               goto errout;
-       }
+       newxprt->sc_max_send_sges += (svcrdma_max_req_size / PAGE_SIZE) + 1;
+       if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge)
+               newxprt->sc_max_send_sges = dev->attrs.max_send_sge;
        newxprt->sc_max_req_size = svcrdma_max_req_size;
        newxprt->sc_max_requests = svcrdma_max_requests;
        newxprt->sc_max_bc_requests = svcrdma_max_bc_requests;
index 7749a2bf6887764c0956ac404b53f055043c32c3..21113bfd4ecaf6a3cb79329af81fb40168830d35 100644 (file)
@@ -527,7 +527,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
 
        sendcq = ib_alloc_cq(ia->ri_device, NULL,
                             ep->rep_attr.cap.max_send_wr + 1,
-                            1, IB_POLL_WORKQUEUE);
+                            ia->ri_device->num_comp_vectors > 1 ? 1 : 0,
+                            IB_POLL_WORKQUEUE);
        if (IS_ERR(sendcq)) {
                rc = PTR_ERR(sendcq);
                goto out1;
@@ -845,17 +846,13 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
        for (i = 0; i <= buf->rb_sc_last; i++) {
                sc = rpcrdma_sendctx_create(&r_xprt->rx_ia);
                if (!sc)
-                       goto out_destroy;
+                       return -ENOMEM;
 
                sc->sc_xprt = r_xprt;
                buf->rb_sc_ctxs[i] = sc;
        }
 
        return 0;
-
-out_destroy:
-       rpcrdma_sendctxs_destroy(buf);
-       return -ENOMEM;
 }
 
 /* The sendctx queue is not guaranteed to have a size that is a
@@ -1113,8 +1110,10 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
                                                WQ_MEM_RECLAIM | WQ_HIGHPRI,
                                                0,
                        r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]);
-       if (!buf->rb_completion_wq)
+       if (!buf->rb_completion_wq) {
+               rc = -ENOMEM;
                goto out;
+       }
 
        return 0;
 out:
index 13559e6a460bc6f496a9e6dbc3cd5b7eaccad2e8..7754aa3e434f405711cfce8d9bdfece972dfc75c 100644 (file)
@@ -48,6 +48,7 @@
 #include <net/udp.h>
 #include <net/tcp.h>
 #include <linux/bvec.h>
+#include <linux/highmem.h>
 #include <linux/uio.h>
 
 #include <trace/events/sunrpc.h>
@@ -376,6 +377,26 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
        return sock_recvmsg(sock, msg, flags);
 }
 
+#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
+static void
+xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
+{
+       struct bvec_iter bi = {
+               .bi_size = count,
+       };
+       struct bio_vec bv;
+
+       bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
+       for_each_bvec(bv, bvec, bi, bi)
+               flush_dcache_page(bv.bv_page);
+}
+#else
+static inline void
+xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
+{
+}
+#endif
+
 static ssize_t
 xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                struct xdr_buf *buf, size_t count, size_t seek, size_t *read)
@@ -409,6 +430,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                                seek + buf->page_base);
                if (ret <= 0)
                        goto sock_err;
+               xs_flush_bvec(buf->bvec, ret, seek + buf->page_base);
                offset += ret - buf->page_base;
                if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
                        goto out;
index 2792a3cae682205970046d51de55e6ae0e5ab772..85ad5c0678d0447f33e70dd55ff38799c1c9dd97 100644 (file)
@@ -1145,7 +1145,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
        default:
                pr_warn("Dropping received illegal msg type\n");
                kfree_skb(skb);
-               return false;
+               return true;
        };
 }
 
@@ -1425,6 +1425,10 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
                l->rcv_unacked = 0;
        } else {
                /* RESET_MSG or ACTIVATE_MSG */
+               if (mtyp == ACTIVATE_MSG) {
+                       msg_set_dest_session_valid(hdr, 1);
+                       msg_set_dest_session(hdr, l->peer_session);
+               }
                msg_set_max_pkt(hdr, l->advertised_mtu);
                strcpy(data, l->if_name);
                msg_set_size(hdr, INT_H_SIZE + TIPC_MAX_IF_NAME);
@@ -1642,6 +1646,17 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                        rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
                        break;
                }
+
+               /* If this endpoint was re-created while peer was ESTABLISHING
+                * it doesn't know current session number. Force re-synch.
+                */
+               if (mtyp == ACTIVATE_MSG && msg_dest_session_valid(hdr) &&
+                   l->session != msg_dest_session(hdr)) {
+                       if (less(l->session, msg_dest_session(hdr)))
+                               l->session = msg_dest_session(hdr) + 1;
+                       break;
+               }
+
                /* ACTIVATE_MSG serves as PEER_RESET if link is already down */
                if (mtyp == RESET_MSG || !link_is_up(l))
                        rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT);
index a0924956bb61b1aecb100771890c9b9e7bbf9cbe..d7e4b8b93f9d39b8335ab4751c29baea807add66 100644 (file)
@@ -360,6 +360,28 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n)
        msg_set_bits(m, 1, 0, 0xffff, n);
 }
 
+/* Note: reusing bits in word 1 for ACTIVATE_MSG only, to re-synch
+ * link peer session number
+ */
+static inline bool msg_dest_session_valid(struct tipc_msg *m)
+{
+       return msg_bits(m, 1, 16, 0x1);
+}
+
+static inline void msg_set_dest_session_valid(struct tipc_msg *m, bool valid)
+{
+       msg_set_bits(m, 1, 16, 0x1, valid);
+}
+
+static inline u16 msg_dest_session(struct tipc_msg *m)
+{
+       return msg_bits(m, 1, 0, 0xffff);
+}
+
+static inline void msg_set_dest_session(struct tipc_msg *m, u16 n)
+{
+       msg_set_bits(m, 1, 0, 0xffff, n);
+}
 
 /*
  * Word 2
index 40f5cae623a77d73a34f05f1974c8a3292c18f83..4ad3586da8f028c0fb8244382b343a1c7635f6cb 100644 (file)
@@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb)
        return limit;
 }
 
+static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
+{
+       return TLV_GET_LEN(tlv) - TLV_SPACE(0);
+}
+
 static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
 {
        struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);
@@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str)
        return buf;
 }
 
+static inline bool string_is_valid(char *s, int len)
+{
+       return memchr(s, '\0', len) ? true : false;
+}
+
 static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
                                   struct tipc_nl_compat_msg *msg,
                                   struct sk_buff *arg)
@@ -379,6 +389,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_bearer_config *b;
+       int len;
 
        b = (struct tipc_bearer_config *)TLV_DATA(msg->req);
 
@@ -386,6 +397,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(b->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name))
                return -EMSGSIZE;
 
@@ -411,6 +426,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *bearer;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -418,6 +434,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name))
                return -EMSGSIZE;
 
@@ -478,6 +498,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
        struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
        struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
        int err;
+       int len;
 
        if (!attrs[TIPC_NLA_LINK])
                return -EINVAL;
@@ -504,6 +525,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
                return err;
 
        name = (char *)TLV_DATA(msg->req);
+
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
                return 0;
 
@@ -644,6 +670,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *media;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -651,6 +678,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        if (!media)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -671,6 +702,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -678,6 +710,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -726,9 +762,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
        struct tipc_link_config *lc;
        struct tipc_bearer *bearer;
        struct tipc_media *media;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        media = tipc_media_find(lc->name);
        if (media) {
                cmd->doit = &__tipc_nl_media_set;
@@ -750,6 +791,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *link;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -757,6 +799,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
        if (!link)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name))
                return -EMSGSIZE;
 
@@ -778,6 +824,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg)
        };
 
        ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
+       if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query))
+               return -EINVAL;
 
        depth = ntohl(ntq->depth);
 
@@ -904,8 +952,10 @@ static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock)
 
        hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI,
                          TIPC_NL_PUBL_GET);
-       if (!hdr)
+       if (!hdr) {
+               kfree_skb(args);
                return -EMSGSIZE;
+       }
 
        nest = nla_nest_start(args, TIPC_NLA_SOCK);
        if (!nest) {
@@ -1206,7 +1256,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
        }
 
        len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-       if (len && !TLV_OK(msg.req, len)) {
+       if (!len || !TLV_OK(msg.req, len)) {
                msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
                err = -EOPNOTSUPP;
                goto send;
index db2a6c3e0be9180aa0ca7debfb109d0a13d7035e..2dc4919ab23cace02749ddb9b4838c2b64c09152 100644 (file)
@@ -830,15 +830,16 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
        tipc_node_write_lock(n);
        if (!tipc_link_is_establishing(l)) {
                __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr);
-               if (delete) {
-                       kfree(l);
-                       le->link = NULL;
-                       n->link_cnt--;
-               }
        } else {
                /* Defuse pending tipc_node_link_up() */
+               tipc_link_reset(l);
                tipc_link_fsm_evt(l, LINK_RESET_EVT);
        }
+       if (delete) {
+               kfree(l);
+               le->link = NULL;
+               n->link_cnt--;
+       }
        trace_tipc_node_link_down(n, true, "node link down or deleted!");
        tipc_node_write_unlock(n);
        if (delete)
index efb16f69bd2c4c0bc012d5f18c3ad42e71260e81..a457c0fbbef1acfb877cbada5a648364846e5285 100644 (file)
@@ -398,7 +398,7 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con)
        ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT);
        if (ret == -EWOULDBLOCK)
                return -EWOULDBLOCK;
-       if (ret > 0) {
+       if (ret == sizeof(s)) {
                read_lock_bh(&sk->sk_callback_lock);
                ret = tipc_conn_rcv_sub(srv, con, &s);
                read_unlock_bh(&sk->sk_callback_lock);
index 11cdc8f7db63c7d84d1a6befbafb7f4f491eb8c6..bf5b54b513bc70e74f8df3d2554df2b7f87d4b4f 100644 (file)
@@ -439,6 +439,8 @@ static int tls_do_encryption(struct sock *sk,
        struct scatterlist *sge = sk_msg_elem(msg_en, start);
        int rc;
 
+       memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data));
+
        sge->offset += tls_ctx->tx.prepend_size;
        sge->length -= tls_ctx->tx.prepend_size;
 
@@ -448,7 +450,7 @@ static int tls_do_encryption(struct sock *sk,
        aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
        aead_request_set_crypt(aead_req, rec->sg_aead_in,
                               rec->sg_aead_out,
-                              data_len, tls_ctx->tx.iv);
+                              data_len, rec->iv_data);
 
        aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                                  tls_encrypt_done, sk);
@@ -1792,7 +1794,9 @@ void tls_sw_free_resources_tx(struct sock *sk)
        if (atomic_read(&ctx->encrypt_pending))
                crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
 
+       release_sock(sk);
        cancel_delayed_work_sync(&ctx->tx_work.work);
+       lock_sock(sk);
 
        /* Tx whatever records we can transmit and abandon the rest */
        tls_tx_records(sk, -1);
index 5d3cce9e8744d5207753107aeb55518f2848f50a..15eb5d3d475094778cd21cfeeec096cb20a89715 100644 (file)
@@ -75,6 +75,9 @@ static u32 virtio_transport_get_local_cid(void)
 {
        struct virtio_vsock *vsock = virtio_vsock_get();
 
+       if (!vsock)
+               return VMADDR_CID_ANY;
+
        return vsock->guest_cid;
 }
 
@@ -584,10 +587,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
 
        virtio_vsock_update_guest_cid(vsock);
 
-       ret = vsock_core_init(&virtio_transport.transport);
-       if (ret < 0)
-               goto out_vqs;
-
        vsock->rx_buf_nr = 0;
        vsock->rx_buf_max_nr = 0;
        atomic_set(&vsock->queued_replies, 0);
@@ -618,8 +617,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
        mutex_unlock(&the_virtio_vsock_mutex);
        return 0;
 
-out_vqs:
-       vsock->vdev->config->del_vqs(vsock->vdev);
 out:
        kfree(vsock);
        mutex_unlock(&the_virtio_vsock_mutex);
@@ -637,6 +634,9 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
        flush_work(&vsock->event_work);
        flush_work(&vsock->send_pkt_work);
 
+       /* Reset all connected sockets when the device disappear */
+       vsock_for_each_connected_socket(virtio_vsock_reset_sock);
+
        vdev->config->reset(vdev);
 
        mutex_lock(&vsock->rx_lock);
@@ -669,7 +669,6 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
 
        mutex_lock(&the_virtio_vsock_mutex);
        the_virtio_vsock = NULL;
-       vsock_core_exit();
        mutex_unlock(&the_virtio_vsock_mutex);
 
        vdev->config->del_vqs(vdev);
@@ -702,14 +701,28 @@ static int __init virtio_vsock_init(void)
        virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0);
        if (!virtio_vsock_workqueue)
                return -ENOMEM;
+
        ret = register_virtio_driver(&virtio_vsock_driver);
        if (ret)
-               destroy_workqueue(virtio_vsock_workqueue);
+               goto out_wq;
+
+       ret = vsock_core_init(&virtio_transport.transport);
+       if (ret)
+               goto out_vdr;
+
+       return 0;
+
+out_vdr:
+       unregister_virtio_driver(&virtio_vsock_driver);
+out_wq:
+       destroy_workqueue(virtio_vsock_workqueue);
        return ret;
+
 }
 
 static void __exit virtio_vsock_exit(void)
 {
+       vsock_core_exit();
        unregister_virtio_driver(&virtio_vsock_driver);
        destroy_workqueue(virtio_vsock_workqueue);
 }
index c361ce7824123da38ec613361a2ae5fa21197b7b..c3d5ab01fba7ba280a752628788f0f175bf1cd83 100644 (file)
@@ -1651,6 +1651,10 @@ static void vmci_transport_cleanup(struct work_struct *work)
 
 static void vmci_transport_destruct(struct vsock_sock *vsk)
 {
+       /* transport can be NULL if we hit a failure at init() time */
+       if (!vmci_trans(vsk))
+               return;
+
        /* Ensure that the detach callback doesn't use the sk/vsk
         * we are about to destruct.
         */
index 882d97bdc6bfd49ac3acf80f5674821b15f46e35..550ac9d827fe7d7f266f0ac511afec0aa4d8f8c3 100644 (file)
@@ -41,6 +41,8 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
                cfg80211_sched_dfs_chan_update(rdev);
        }
 
+       schedule_work(&cfg80211_disconnect_work);
+
        return err;
 }
 
index 623dfe5e211c6ee41a6a4346d048f7e94f464a22..b36ad8efb5e5271e7ddbf87c72a337bb2d12e0a6 100644 (file)
@@ -1068,6 +1068,8 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
 
        ASSERT_RTNL();
 
+       flush_work(&wdev->pmsr_free_wk);
+
        nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
 
        list_del_rcu(&wdev->list);
index c5d6f341860136a002cf3c5b18c82889c5356afb..f6b40563dc633af1074848f256335902997350aa 100644 (file)
@@ -445,6 +445,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev);
 bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
                                u32 center_freq_khz, u32 bw_khz);
 
+extern struct work_struct cfg80211_disconnect_work;
+
 /**
  * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
  * @wiphy: the wiphy to validate against
index 5e49492d5911d816c85bdec83af843e0a5235c1c..d91a408db113ee2e3475447d3778418f86791478 100644 (file)
@@ -250,7 +250,7 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
        [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
                NLA_POLICY_MAX(NLA_U8, 15),
        [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
-               NLA_POLICY_MAX(NLA_U8, 15),
+               NLA_POLICY_MAX(NLA_U8, 31),
        [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
        [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
        [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
@@ -555,7 +555,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        },
        [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
        [NL80211_ATTR_PEER_MEASUREMENTS] =
-               NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
+               NLA_POLICY_NESTED(NL80211_PMSR_ATTR_MAX,
                                  nl80211_pmsr_attr_policy),
 };
 
index de9286703280a2d8d4306593848676e85d3b1bfe..0216ab555249857daac7990886d832c0acd94856 100644 (file)
@@ -256,8 +256,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
                if (err)
                        goto out_err;
        } else {
-               memcpy(req->mac_addr, nla_data(info->attrs[NL80211_ATTR_MAC]),
-                      ETH_ALEN);
+               memcpy(req->mac_addr, wdev_address(wdev), ETH_ALEN);
                memset(req->mac_addr_mask, 0xff, ETH_ALEN);
        }
 
@@ -272,6 +271,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
 
        req->n_peers = count;
        req->cookie = cfg80211_assign_cookie(rdev);
+       req->nl_portid = info->snd_portid;
 
        err = rdev_start_pmsr(rdev, wdev, req);
        if (err)
@@ -530,14 +530,14 @@ void cfg80211_pmsr_report(struct wireless_dev *wdev,
 }
 EXPORT_SYMBOL_GPL(cfg80211_pmsr_report);
 
-void cfg80211_pmsr_free_wk(struct work_struct *work)
+static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev)
 {
-       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
-                                                pmsr_free_wk);
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
        struct cfg80211_pmsr_request *req, *tmp;
        LIST_HEAD(free_list);
 
+       lockdep_assert_held(&wdev->mtx);
+
        spin_lock_bh(&wdev->pmsr_lock);
        list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) {
                if (req->nl_portid)
@@ -547,14 +547,22 @@ void cfg80211_pmsr_free_wk(struct work_struct *work)
        spin_unlock_bh(&wdev->pmsr_lock);
 
        list_for_each_entry_safe(req, tmp, &free_list, list) {
-               wdev_lock(wdev);
                rdev_abort_pmsr(rdev, wdev, req);
-               wdev_unlock(wdev);
 
                kfree(req);
        }
 }
 
+void cfg80211_pmsr_free_wk(struct work_struct *work)
+{
+       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
+                                                pmsr_free_wk);
+
+       wdev_lock(wdev);
+       cfg80211_pmsr_process_abort(wdev);
+       wdev_unlock(wdev);
+}
+
 void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
 {
        struct cfg80211_pmsr_request *req;
@@ -568,8 +576,8 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
        spin_unlock_bh(&wdev->pmsr_lock);
 
        if (found)
-               schedule_work(&wdev->pmsr_free_wk);
-       flush_work(&wdev->pmsr_free_wk);
+               cfg80211_pmsr_process_abort(wdev);
+
        WARN_ON(!list_empty(&wdev->pmsr_list));
 }
 
index ecfb1a06dbb2be08cfc99028bb9817deaa5fc3a7..dd58b9909ac999ae9683684d05f6744c8a6def9e 100644 (file)
@@ -1024,8 +1024,13 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
        }
 
        rtnl_lock();
-       if (WARN_ON(regdb && !IS_ERR(regdb))) {
-               /* just restore and free new db */
+       if (regdb && !IS_ERR(regdb)) {
+               /* negative case - a bug
+                * positive case - can happen due to race in case of multiple cb's in
+                * queue, due to usage of asynchronous callback
+                *
+                * Either case, just restore and free new db.
+                */
        } else if (set_error) {
                regdb = ERR_PTR(set_error);
        } else if (fw) {
@@ -1255,7 +1260,7 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
  * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"),
  * however it is safe for now to assume that a frequency rule should not be
  * part of a frequency's band if the start freq or end freq are off by more
- * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 10 GHz for the
+ * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 20 GHz for the
  * 60 GHz band.
  * This resolution can be lowered and should be considered as we add
  * regulatory rule support for other "bands".
@@ -1270,7 +1275,7 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
         * with the Channel starting frequency above 45 GHz.
         */
        u32 limit = freq_khz > 45 * ONE_GHZ_IN_KHZ ?
-                       10 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
+                       20 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
        if (abs(freq_khz - freq_range->start_freq_khz) <= limit)
                return true;
        if (abs(freq_khz - freq_range->end_freq_khz) <= limit)
index f741d8376a463b588231550c4cca661e55d2e6b7..7d34cb884840e96d68b43e5f90036d3d3cd306dd 100644 (file)
@@ -667,7 +667,7 @@ static void disconnect_work(struct work_struct *work)
        rtnl_unlock();
 }
 
-static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
+DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
 
 
 /*
index cd48cdd582c070e84375d73d6bcc6d601f3d6996..ec30e3732c7b903904706eeffefd8ddac5155bd6 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2017      Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  */
 #include <linux/export.h>
 #include <linux/bitops.h>
@@ -19,6 +19,7 @@
 #include <linux/mpls.h>
 #include <linux/gcd.h>
 #include <linux/bitfield.h>
+#include <linux/nospec.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -715,20 +716,25 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
 {
        unsigned int dscp;
        unsigned char vlan_priority;
+       unsigned int ret;
 
        /* skb->priority values from 256->263 are magic values to
         * directly indicate a specific 802.1d priority.  This is used
         * to allow 802.1d priority to be passed directly in from VLAN
         * tags, etc.
         */
-       if (skb->priority >= 256 && skb->priority <= 263)
-               return skb->priority - 256;
+       if (skb->priority >= 256 && skb->priority <= 263) {
+               ret = skb->priority - 256;
+               goto out;
+       }
 
        if (skb_vlan_tag_present(skb)) {
                vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK)
                        >> VLAN_PRIO_SHIFT;
-               if (vlan_priority > 0)
-                       return vlan_priority;
+               if (vlan_priority > 0) {
+                       ret = vlan_priority;
+                       goto out;
+               }
        }
 
        switch (skb->protocol) {
@@ -747,8 +753,9 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
                if (!mpls)
                        return 0;
 
-               return (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
+               ret = (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
                        >> MPLS_LS_TC_SHIFT;
+               goto out;
        }
        case htons(ETH_P_80221):
                /* 802.21 is always network control traffic */
@@ -761,18 +768,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
                unsigned int i, tmp_dscp = dscp >> 2;
 
                for (i = 0; i < qos_map->num_des; i++) {
-                       if (tmp_dscp == qos_map->dscp_exception[i].dscp)
-                               return qos_map->dscp_exception[i].up;
+                       if (tmp_dscp == qos_map->dscp_exception[i].dscp) {
+                               ret = qos_map->dscp_exception[i].up;
+                               goto out;
+                       }
                }
 
                for (i = 0; i < 8; i++) {
                        if (tmp_dscp >= qos_map->up[i].low &&
-                           tmp_dscp <= qos_map->up[i].high)
-                               return i;
+                           tmp_dscp <= qos_map->up[i].high) {
+                               ret = i;
+                               goto out;
+                       }
                }
        }
 
-       return dscp >> 5;
+       ret = dscp >> 5;
+out:
+       return array_index_nospec(ret, IEEE80211_NUM_TIDS);
 }
 EXPORT_SYMBOL(cfg80211_classify8021d);
 
index 5121729b8b631f45d81d3e0332b0d2e4346d3c5d..ec3a828672ef53991146bf94a2266932a5f25872 100644 (file)
@@ -352,17 +352,15 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
        unsigned int lci = 1;
        struct sock *sk;
 
-       read_lock_bh(&x25_list_lock);
-
-       while ((sk = __x25_find_socket(lci, nb)) != NULL) {
+       while ((sk = x25_find_socket(lci, nb)) != NULL) {
                sock_put(sk);
                if (++lci == 4096) {
                        lci = 0;
                        break;
                }
+               cond_resched();
        }
 
-       read_unlock_bh(&x25_list_lock);
        return lci;
 }
 
index a264cf2accd0f1c2d5a90019535db8bf736ce311..d4de871e7d4d7fa8f2c426559e92313c33d2655d 100644 (file)
@@ -41,13 +41,20 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
  * not know if the device has more tx queues than rx, or the opposite.
  * This might also change during run time.
  */
-static void xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
-                               u16 queue_id)
+static int xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
+                              u16 queue_id)
 {
+       if (queue_id >= max_t(unsigned int,
+                             dev->real_num_rx_queues,
+                             dev->real_num_tx_queues))
+               return -EINVAL;
+
        if (queue_id < dev->real_num_rx_queues)
                dev->_rx[queue_id].umem = umem;
        if (queue_id < dev->real_num_tx_queues)
                dev->_tx[queue_id].umem = umem;
+
+       return 0;
 }
 
 struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev,
@@ -88,7 +95,10 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev,
                goto out_rtnl_unlock;
        }
 
-       xdp_reg_umem_at_qid(dev, umem, queue_id);
+       err = xdp_reg_umem_at_qid(dev, umem, queue_id);
+       if (err)
+               goto out_rtnl_unlock;
+
        umem->dev = dev;
        umem->queue_id = queue_id;
        if (force_copy)
index 934492bad8e04d2a8600c41627fbaca2370d0f47..ba0a4048c846bbbbde6e0d3320f6d4cfa46da424 100644 (file)
@@ -680,16 +680,6 @@ static void xfrm_hash_resize(struct work_struct *work)
        mutex_unlock(&hash_resize_mutex);
 }
 
-static void xfrm_hash_reset_inexact_table(struct net *net)
-{
-       struct xfrm_pol_inexact_bin *b;
-
-       lockdep_assert_held(&net->xfrm.xfrm_policy_lock);
-
-       list_for_each_entry(b, &net->xfrm.inexact_bins, inexact_bins)
-               INIT_HLIST_HEAD(&b->hhead);
-}
-
 /* Make sure *pol can be inserted into fastbin.
  * Useful to check that later insert requests will be sucessful
  * (provided xfrm_policy_lock is held throughout).
@@ -833,13 +823,13 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
                                              u16 family)
 {
        unsigned int matched_s, matched_d;
-       struct hlist_node *newpos = NULL;
        struct xfrm_policy *policy, *p;
 
        matched_s = 0;
        matched_d = 0;
 
        list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
+               struct hlist_node *newpos = NULL;
                bool matches_s, matches_d;
 
                if (!policy->bydst_reinsert)
@@ -849,16 +839,19 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
 
                policy->bydst_reinsert = false;
                hlist_for_each_entry(p, &n->hhead, bydst) {
-                       if (policy->priority >= p->priority)
+                       if (policy->priority > p->priority)
+                               newpos = &p->bydst;
+                       else if (policy->priority == p->priority &&
+                                policy->pos > p->pos)
                                newpos = &p->bydst;
                        else
                                break;
                }
 
                if (newpos)
-                       hlist_add_behind(&policy->bydst, newpos);
+                       hlist_add_behind_rcu(&policy->bydst, newpos);
                else
-                       hlist_add_head(&policy->bydst, &n->hhead);
+                       hlist_add_head_rcu(&policy->bydst, &n->hhead);
 
                /* paranoia checks follow.
                 * Check that the reinserted policy matches at least
@@ -893,12 +886,13 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                                              struct rb_root *new,
                                              u16 family)
 {
-       struct rb_node **p, *parent = NULL;
        struct xfrm_pol_inexact_node *node;
+       struct rb_node **p, *parent;
 
        /* we should not have another subtree here */
        WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root));
-
+restart:
+       parent = NULL;
        p = &new->rb_node;
        while (*p) {
                u8 prefixlen;
@@ -918,12 +912,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                } else {
                        struct xfrm_policy *tmp;
 
-                       hlist_for_each_entry(tmp, &node->hhead, bydst)
-                               tmp->bydst_reinsert = true;
-                       hlist_for_each_entry(tmp, &n->hhead, bydst)
+                       hlist_for_each_entry(tmp, &n->hhead, bydst) {
                                tmp->bydst_reinsert = true;
+                               hlist_del_rcu(&tmp->bydst);
+                       }
 
-                       INIT_HLIST_HEAD(&node->hhead);
                        xfrm_policy_inexact_list_reinsert(net, node, family);
 
                        if (node->prefixlen == n->prefixlen) {
@@ -935,8 +928,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                        kfree_rcu(n, rcu);
                        n = node;
                        n->prefixlen = prefixlen;
-                       *p = new->rb_node;
-                       parent = NULL;
+                       goto restart;
                }
        }
 
@@ -965,12 +957,11 @@ static void xfrm_policy_inexact_node_merge(struct net *net,
                                                  family);
        }
 
-       hlist_for_each_entry(tmp, &v->hhead, bydst)
-               tmp->bydst_reinsert = true;
-       hlist_for_each_entry(tmp, &n->hhead, bydst)
+       hlist_for_each_entry(tmp, &v->hhead, bydst) {
                tmp->bydst_reinsert = true;
+               hlist_del_rcu(&tmp->bydst);
+       }
 
-       INIT_HLIST_HEAD(&n->hhead);
        xfrm_policy_inexact_list_reinsert(net, n, family);
 }
 
@@ -1235,6 +1226,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
        } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
 
        spin_lock_bh(&net->xfrm.xfrm_policy_lock);
+       write_seqcount_begin(&xfrm_policy_hash_generation);
 
        /* make sure that we can insert the indirect policies again before
         * we start with destructive action.
@@ -1278,10 +1270,14 @@ static void xfrm_hash_rebuild(struct work_struct *work)
        }
 
        /* reset the bydst and inexact table in all directions */
-       xfrm_hash_reset_inexact_table(net);
-
        for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
-               INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
+               struct hlist_node *n;
+
+               hlist_for_each_entry_safe(policy, n,
+                                         &net->xfrm.policy_inexact[dir],
+                                         bydst_inexact_list)
+                       hlist_del_init(&policy->bydst_inexact_list);
+
                hmask = net->xfrm.policy_bydst[dir].hmask;
                odst = net->xfrm.policy_bydst[dir].table;
                for (i = hmask; i >= 0; i--)
@@ -1313,6 +1309,9 @@ static void xfrm_hash_rebuild(struct work_struct *work)
                newpos = NULL;
                chain = policy_hash_bysel(net, &policy->selector,
                                          policy->family, dir);
+
+               hlist_del_rcu(&policy->bydst);
+
                if (!chain) {
                        void *p = xfrm_policy_inexact_insert(policy, dir, 0);
 
@@ -1334,6 +1333,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
 
 out_unlock:
        __xfrm_policy_inexact_flush(net);
+       write_seqcount_end(&xfrm_policy_hash_generation);
        spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        mutex_unlock(&hash_resize_mutex);
@@ -2600,7 +2600,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                dst_copy_metrics(dst1, dst);
 
                if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-                       __u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
+                       __u32 mark = 0;
+
+                       if (xfrm[i]->props.smark.v || xfrm[i]->props.smark.m)
+                               mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
 
                        family = xfrm[i]->props.family;
                        dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
index 277c1c46fe94e17db85f20a4abe3bacae9a1f1b0..c6d26afcf89df4c9327acf3074d042cbbc8eba62 100644 (file)
@@ -1488,10 +1488,15 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
                if (!ut[i].family)
                        ut[i].family = family;
 
-               if ((ut[i].mode == XFRM_MODE_TRANSPORT) &&
-                   (ut[i].family != prev_family))
-                       return -EINVAL;
-
+               switch (ut[i].mode) {
+               case XFRM_MODE_TUNNEL:
+               case XFRM_MODE_BEET:
+                       break;
+               default:
+                       if (ut[i].family != prev_family)
+                               return -EINVAL;
+                       break;
+               }
                if (ut[i].mode >= XFRM_MODE_MAX)
                        return -EINVAL;
 
index 66ae15f27c70d8ecd7c52760e0c84d469b9faf0f..db1a91dfa70253dd6ca90e0bcf0a3c3afd5bb850 100644 (file)
@@ -279,6 +279,7 @@ $(obj)/%.o: $(src)/%.c
                -Wno-gnu-variable-sized-type-not-at-end \
                -Wno-address-of-packed-member -Wno-tautological-compare \
                -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \
+               -I$(srctree)/samples/bpf/ -include asm_goto_workaround.h \
                -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@
 ifeq ($(DWARF2BTF),y)
        $(BTF_PAHOLE) -J $@
diff --git a/samples/bpf/asm_goto_workaround.h b/samples/bpf/asm_goto_workaround.h
new file mode 100644 (file)
index 0000000..5cd7c1d
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 Facebook */
+#ifndef __ASM_GOTO_WORKAROUND_H
+#define __ASM_GOTO_WORKAROUND_H
+
+/* this will bring in asm_volatile_goto macro definition
+ * if enabled by compiler and config options.
+ */
+#include <linux/types.h>
+
+#ifdef asm_volatile_goto
+#undef asm_volatile_goto
+#define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto")
+#endif
+
+#endif
index d7b68ef5ba792ec66d3d8bc26463c61e964c41c3..0bb6507256b77dacd5ffa18f407ffc8a2d021b5d 100644 (file)
@@ -77,7 +77,7 @@ static int test_foo_bar(void)
 
        /* Create cgroup /foo, get fd, and join it */
        foo = create_and_get_cgroup(FOO);
-       if (!foo)
+       if (foo < 0)
                goto err;
 
        if (join_cgroup(FOO))
@@ -94,7 +94,7 @@ static int test_foo_bar(void)
 
        /* Create cgroup /foo/bar, get fd, and join it */
        bar = create_and_get_cgroup(BAR);
-       if (!bar)
+       if (bar < 0)
                goto err;
 
        if (join_cgroup(BAR))
@@ -298,19 +298,19 @@ static int test_multiprog(void)
                goto err;
 
        cg1 = create_and_get_cgroup("/cg1");
-       if (!cg1)
+       if (cg1 < 0)
                goto err;
        cg2 = create_and_get_cgroup("/cg1/cg2");
-       if (!cg2)
+       if (cg2 < 0)
                goto err;
        cg3 = create_and_get_cgroup("/cg1/cg2/cg3");
-       if (!cg3)
+       if (cg3 < 0)
                goto err;
        cg4 = create_and_get_cgroup("/cg1/cg2/cg3/cg4");
-       if (!cg4)
+       if (cg4 < 0)
                goto err;
        cg5 = create_and_get_cgroup("/cg1/cg2/cg3/cg4/cg5");
-       if (!cg5)
+       if (cg5 < 0)
                goto err;
 
        if (join_cgroup("/cg1/cg2/cg3/cg4/cg5"))
index 2259f997a26c7f3e955bcae022d8c83767019a33..f082d6ac59f00b2b1d5c892ee3f173495f156d0f 100644 (file)
@@ -32,7 +32,7 @@ int main(int argc, char **argv)
 
        cg2 = create_and_get_cgroup(CGROUP_PATH);
 
-       if (!cg2)
+       if (cg2 < 0)
                goto err;
 
        if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
index 0a197f86ac43a7a28b281d36efeedb5d423dd8dd..8bfda95c77ad77ade1bc2b553d8940f3da0f60a8 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       ifindex = if_nametoindex(argv[1]);
+       ifindex = if_nametoindex(argv[optind]);
        if (!ifindex) {
                perror("if_nametoindex");
                return 1;
index 33e67bd1dc343cece0573d8dfee9d6e1a3319e9f..32234481ad7dbee128cc9c31531b1843baf672b1 100644 (file)
@@ -117,7 +117,7 @@ static bool mei_init(struct mei *me, const uuid_le *guid,
 
        me->verbose = verbose;
 
-       me->fd = open("/dev/mei", O_RDWR);
+       me->fd = open("/dev/mei0", O_RDWR);
        if (me->fd == -1) {
                mei_err(me, "Cannot establish a handle to the Intel MEI driver\n");
                goto err;
index 525bff667a528404ea887b57b4723096780d59bc..30816037036e605158a2806fea8795ca8ff8dd9e 100644 (file)
@@ -23,10 +23,6 @@ depfile = $(subst $(comma),_,$(dot-target).d)
 # filename of target with directory and extension stripped
 basetarget = $(basename $(notdir $@))
 
-###
-# filename of first prerequisite with directory and extension stripped
-baseprereq = $(basename $(notdir $<))
-
 ###
 # Escape single quote for use in echo statements
 escsq = $(subst $(squote),'\$(squote)',$1)
index de70b8470971e8929a5949174c48a84ab774e0b7..89c47f57d1ce14476ca7c2638e89e31926c3d7fb 100644 (file)
@@ -13,7 +13,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
        for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
                const char *sym;
                rtx body;
-               rtx masked_sp;
+               rtx mask, masked_sp;
 
                /*
                 * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
@@ -33,12 +33,13 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
                 * produces the address of the copy of the stack canary value
                 * stored in struct thread_info
                 */
+               mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
                masked_sp = gen_reg_rtx(Pmode);
 
                emit_insn_before(gen_rtx_SET(masked_sp,
                                             gen_rtx_AND(Pmode,
                                                         stack_pointer_rtx,
-                                                        GEN_INT(sp_mask))),
+                                                        mask)),
                                 insn);
 
                SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp,
@@ -52,6 +53,19 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
 #define NO_GATE
 #include "gcc-generate-rtl-pass.h"
 
+#if BUILDING_GCC_VERSION >= 9000
+static bool no(void)
+{
+       return false;
+}
+
+static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
+{
+       targetm.have_stack_protect_combined_set = no;
+       targetm.have_stack_protect_combined_test = no;
+}
+#endif
+
 __visible int plugin_init(struct plugin_name_args *plugin_info,
                          struct plugin_gcc_version *version)
 {
@@ -99,5 +113,10 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
        register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
                          NULL, &arm_pertask_ssp_rtl_pass_info);
 
+#if BUILDING_GCC_VERSION >= 9000
+       register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
+                         arm_pertask_ssp_start_unit, NULL);
+#endif
+
        return 0;
 }
index c05ab001b54c20383f27efd830e33a29aa86b3f9..181973509a05cc806e5e5ffbd8056dcc8da49494 100644 (file)
@@ -206,4 +206,4 @@ filechk_conf_cfg = $(CONFIG_SHELL) $<
 $(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
        $(call filechk,conf_cfg)
 
-clean-files += conf-cfg
+clean-files += *conf-cfg
index 08c88de0ffdadcb4d68450cff103408cba3a7746..11975ec8d5665957d145ae67f31a03bb41fc77e4 100644 (file)
@@ -1444,7 +1444,10 @@ int aa_change_profile(const char *fqname, int flags)
                        new = aa_label_merge(label, target, GFP_KERNEL);
                if (IS_ERR_OR_NULL(new)) {
                        info = "failed to build target label";
-                       error = PTR_ERR(new);
+                       if (!new)
+                               error = -ENOMEM;
+                       else
+                               error = PTR_ERR(new);
                        new = NULL;
                        perms.allow = 0;
                        goto audit;
index 2c010874329f997559d5c2e786b2bc5031d85a41..8db1731d046ad0b55f594266472308edd0b8217e 100644 (file)
@@ -1599,12 +1599,14 @@ static unsigned int apparmor_ipv4_postroute(void *priv,
        return apparmor_ip_postroute(priv, skb, state);
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
 static unsigned int apparmor_ipv6_postroute(void *priv,
                                            struct sk_buff *skb,
                                            const struct nf_hook_state *state)
 {
        return apparmor_ip_postroute(priv, skb, state);
 }
+#endif
 
 static const struct nf_hook_ops apparmor_nf_ops[] = {
        {
index f1b8d2587639668a84cc3db1c73e71ee79f86134..55bc49027ba97c13c06b4c1076656cef349cee3c 100644 (file)
@@ -1027,6 +1027,13 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 
 void security_cred_free(struct cred *cred)
 {
+       /*
+        * There is a failure case in prepare_creds() that
+        * may result in a call here with ->security being NULL.
+        */
+       if (unlikely(cred->security == NULL))
+               return;
+
        call_void_hook(cred_free, cred);
 }
 
index a50d625e7946f1803bf5e8c7a9f02b734fe46bc9..c1c31e33657ae6d6b9f6247a4c7ac29f6026bc4d 100644 (file)
@@ -732,7 +732,8 @@ static int sens_destroy(void *key, void *datum, void *p)
        kfree(key);
        if (datum) {
                levdatum = datum;
-               ebitmap_destroy(&levdatum->level->cat);
+               if (levdatum->level)
+                       ebitmap_destroy(&levdatum->level->cat);
                kfree(levdatum->level);
        }
        kfree(datum);
index ffda91a4a1aaf3f32b0f72b22ebd4ab068acc6b3..02514fe558b416be1fd2bc407b01a6fb1e0b59b8 100644 (file)
@@ -368,7 +368,9 @@ static int yama_ptrace_access_check(struct task_struct *child,
                        break;
                case YAMA_SCOPE_RELATIONAL:
                        rcu_read_lock();
-                       if (!task_is_descendant(current, child) &&
+                       if (!pid_alive(child))
+                               rc = -EPERM;
+                       if (!rc && !task_is_descendant(current, child) &&
                            !ptracer_exception_found(current, child) &&
                            !ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
                                rc = -EPERM;
index a5b09e75e7874bb6a1facc9a9fd70e6fdac10791..f7d2b373da0aaebd869b06773c24b7994c0cb472 100644 (file)
@@ -541,7 +541,8 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
        /* first let's check the buffer parameter's */
        if (params->buffer.fragment_size == 0 ||
-           params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
+           params->buffer.fragments > INT_MAX / params->buffer.fragment_size ||
+           params->buffer.fragments == 0)
                return -EINVAL;
 
        /* now codec parameters */
index 40013b26f67196b23bcf94d69890b2835cde9f9d..6c0b30391ba99ced198ee7f7c943083899c4b93d 100644 (file)
@@ -2177,16 +2177,11 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
                snd_pcm_update_hw_ptr(substream);
 
        if (!is_playback &&
-           runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
-               if (size >= runtime->start_threshold) {
-                       err = snd_pcm_start(substream);
-                       if (err < 0)
-                               goto _end_unlock;
-               } else {
-                       /* nothing to do */
-                       err = 0;
+           runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+           size >= runtime->start_threshold) {
+               err = snd_pcm_start(substream);
+               if (err < 0)
                        goto _end_unlock;
-               }
        }
 
        avail = snd_pcm_avail(substream);
index 9174f1b3a987f362f783ca545a0f554003240eca..1ec706ced75ca4d0d45c1774bc799c534da71d23 100644 (file)
@@ -115,7 +115,8 @@ static int hda_codec_driver_probe(struct device *dev)
        err = snd_hda_codec_build_controls(codec);
        if (err < 0)
                goto error_module;
-       if (codec->card->registered) {
+       /* only register after the bus probe finished; otherwise it's racy */
+       if (!codec->bus->bus_probing && codec->card->registered) {
                err = snd_card_register(codec->card);
                if (err < 0)
                        goto error_module;
index e784130ea4e0eb2d7fec5357fb86872fb44292fc..e5c49003e75fdd81a62fbea142089500d0eb6eae 100644 (file)
@@ -2185,6 +2185,7 @@ static int azx_probe_continue(struct azx *chip)
        int dev = chip->dev_index;
        int err;
 
+       to_hda_bus(bus)->bus_probing = 1;
        hda->probe_continued = 1;
 
        /* bind with i915 if needed */
@@ -2269,6 +2270,7 @@ static int azx_probe_continue(struct azx *chip)
        if (err < 0)
                hda->init_failed = 1;
        complete_all(&hda->probe_wait);
+       to_hda_bus(bus)->bus_probing = 0;
        return err;
 }
 
index e5bdbc2456822cb835c9644c7bc69468c91a92c7..29882bda763289374069ec4777e62b781b416673 100644 (file)
@@ -8451,8 +8451,10 @@ static void ca0132_free(struct hda_codec *codec)
        ca0132_exit_chip(codec);
 
        snd_hda_power_down(codec);
-       if (IS_ENABLED(CONFIG_PCI) && spec->mem_base)
+#ifdef CONFIG_PCI
+       if (spec->mem_base)
                pci_iounmap(codec->bus->pci, spec->mem_base);
+#endif
        kfree(spec->spec_init_verbs);
        kfree(codec->spec);
 }
index 51cc6589443f5f12e21c5ea6e66a6e30a6a445cc..a4ee7656d9ee904e6f6de6a048cfbbe3a52ce027 100644 (file)
@@ -924,6 +924,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
+       SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
@@ -931,6 +932,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
+       SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
index 0b3e7a18ca78b07548aadcc7ea15a4add9515a30..6df758adff84bcbc15dcc4effc3cbb98f3ea0d9f 100644 (file)
@@ -117,6 +117,7 @@ struct alc_spec {
        int codec_variant;      /* flag for other variants */
        unsigned int has_alc5505_dsp:1;
        unsigned int no_depop_delay:1;
+       unsigned int done_hp_init:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -514,6 +515,15 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
        }
 }
 
+/* get a primary headphone pin if available */
+static hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
+{
+       if (spec->gen.autocfg.hp_pins[0])
+               return spec->gen.autocfg.hp_pins[0];
+       if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
+               return spec->gen.autocfg.line_out_pins[0];
+       return 0;
+}
 
 /*
  * Realtek SSID verification
@@ -724,9 +734,7 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
         * 15   : 1 --> enable the function "Mute internal speaker
         *              when the external headphone out jack is plugged"
         */
-       if (!spec->gen.autocfg.hp_pins[0] &&
-           !(spec->gen.autocfg.line_out_pins[0] &&
-             spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
+       if (!alc_get_hp_pin(spec)) {
                hda_nid_t nid;
                tmp = (ass >> 11) & 0x3;        /* HP to chassis */
                nid = ports[tmp];
@@ -2958,7 +2966,7 @@ static void alc282_restore_default_value(struct hda_codec *codec)
 static void alc282_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
        int coef78;
 
@@ -2995,7 +3003,7 @@ static void alc282_init(struct hda_codec *codec)
 static void alc282_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
        int coef78;
 
@@ -3073,14 +3081,9 @@ static void alc283_restore_default_value(struct hda_codec *codec)
 static void alc283_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
-       if (!spec->gen.autocfg.hp_outs) {
-               if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
-                       hp_pin = spec->gen.autocfg.line_out_pins[0];
-       }
-
        alc283_restore_default_value(codec);
 
        if (!hp_pin)
@@ -3114,14 +3117,9 @@ static void alc283_init(struct hda_codec *codec)
 static void alc283_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
-       if (!spec->gen.autocfg.hp_outs) {
-               if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
-                       hp_pin = spec->gen.autocfg.line_out_pins[0];
-       }
-
        if (!hp_pin) {
                alc269_shutup(codec);
                return;
@@ -3155,7 +3153,7 @@ static void alc283_shutup(struct hda_codec *codec)
 static void alc256_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin)
@@ -3191,7 +3189,7 @@ static void alc256_init(struct hda_codec *codec)
 static void alc256_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin) {
@@ -3227,7 +3225,7 @@ static void alc256_shutup(struct hda_codec *codec)
 static void alc225_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp1_pin_sense, hp2_pin_sense;
 
        if (!hp_pin)
@@ -3270,7 +3268,7 @@ static void alc225_init(struct hda_codec *codec)
 static void alc225_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp1_pin_sense, hp2_pin_sense;
 
        if (!hp_pin) {
@@ -3314,7 +3312,7 @@ static void alc225_shutup(struct hda_codec *codec)
 static void alc_default_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin)
@@ -3343,7 +3341,7 @@ static void alc_default_init(struct hda_codec *codec)
 static void alc_default_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin) {
@@ -3372,6 +3370,48 @@ static void alc_default_shutup(struct hda_codec *codec)
        snd_hda_shutup_pins(codec);
 }
 
+static void alc294_hp_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
+       int i, val;
+
+       if (!hp_pin)
+               return;
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+       msleep(100);
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
+       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
+
+       /* Wait for depop procedure finish  */
+       val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       for (i = 0; i < 20 && val & 0x0080; i++) {
+               msleep(50);
+               val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       }
+       /* Set HP depop to auto mode */
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+       msleep(50);
+}
+
+static void alc294_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (!spec->done_hp_init) {
+               alc294_hp_init(codec);
+               spec->done_hp_init = true;
+       }
+       alc_default_init(codec);
+}
+
 static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
                             unsigned int val)
 {
@@ -4737,7 +4777,7 @@ static void alc_update_headset_mode(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
 
        hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
 
        int new_headset_mode;
 
@@ -5016,7 +5056,7 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
 static void alc_shutup_dell_xps13(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       int hp_pin = spec->gen.autocfg.hp_pins[0];
+       int hp_pin = alc_get_hp_pin(spec);
 
        /* Prevent pop noises when headphones are plugged in */
        snd_hda_codec_write(codec, hp_pin, 0,
@@ -5109,7 +5149,7 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 
        if (action == HDA_FIXUP_ACT_PROBE) {
                int mic_pin = find_ext_mic_pin(codec);
-               int hp_pin = spec->gen.autocfg.hp_pins[0];
+               int hp_pin = alc_get_hp_pin(spec);
 
                if (snd_BUG_ON(!mic_pin || !hp_pin))
                        return;
@@ -5591,6 +5631,7 @@ enum {
        ALC294_FIXUP_ASUS_HEADSET_MIC,
        ALC294_FIXUP_ASUS_SPK,
        ALC225_FIXUP_HEADSET_JACK,
+       ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6537,6 +6578,15 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_headset_jack,
        },
+       [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6715,6 +6765,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -6926,7 +6977,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"},
        {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"},
        {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"},
-       {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"},
+       {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc225-dell1"},
        {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"},
        {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"},
        {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"},
@@ -7373,37 +7424,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
        alc_update_coef_idx(codec, 0x4, 0, 1<<11);
 }
 
-static void alc294_hp_init(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
-       int i, val;
-
-       if (!hp_pin)
-               return;
-
-       snd_hda_codec_write(codec, hp_pin, 0,
-                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
-       msleep(100);
-
-       snd_hda_codec_write(codec, hp_pin, 0,
-                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
-       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
-       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
-
-       /* Wait for depop procedure finish  */
-       val = alc_read_coefex_idx(codec, 0x58, 0x01);
-       for (i = 0; i < 20 && val & 0x0080; i++) {
-               msleep(50);
-               val = alc_read_coefex_idx(codec, 0x58, 0x01);
-       }
-       /* Set HP depop to auto mode */
-       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
-       msleep(50);
-}
-
 /*
  */
 static int patch_alc269(struct hda_codec *codec)
@@ -7529,7 +7549,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC294;
                spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
-               alc294_hp_init(codec);
+               spec->init_hook = alc294_init;
                break;
        case 0x10ec0300:
                spec->codec_variant = ALC269_TYPE_ALC300;
@@ -7541,7 +7561,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC700;
                spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
-               alc294_hp_init(codec);
+               spec->init_hook = alc294_init;
                break;
 
        }
index 022a8912c8a2554eaec61b712fd9f83e474fd6dc..3d58338fa3cf79b3d9c28351cfd9411167fe51a5 100644 (file)
@@ -611,14 +611,16 @@ static int acp3x_audio_probe(struct platform_device *pdev)
        }
        irqflags = *((unsigned int *)(pdev->dev.platform_data));
 
-       adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
-                            GFP_KERNEL);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
                        return -ENODEV;
        }
 
+       adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+       if (!adata)
+               return -ENOMEM;
+
        adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
                                         resource_size(res));
 
index 3ab2949c1dfa454f2df8ebf277dd60d82e56631e..b19d7a3e7a2cc07827808ac2fe92797deac56a37 100644 (file)
@@ -1890,51 +1890,31 @@ static void hdmi_codec_remove(struct snd_soc_component *component)
        pm_runtime_disable(&hdev->dev);
 }
 
-#ifdef CONFIG_PM
-static int hdmi_codec_prepare(struct device *dev)
-{
-       struct hdac_device *hdev = dev_to_hdac_dev(dev);
-
-       pm_runtime_get_sync(&hdev->dev);
-
-       /*
-        * Power down afg.
-        * codec_read is preferred over codec_write to set the power state.
-        * This way verb is send to set the power state and response
-        * is received. So setting power state is ensured without using loop
-        * to read the state.
-        */
-       snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
-                                                       AC_PWRST_D3);
-
-       return 0;
-}
-
-static void hdmi_codec_complete(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int hdmi_codec_resume(struct device *dev)
 {
        struct hdac_device *hdev = dev_to_hdac_dev(dev);
        struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
+       int ret;
 
-       /* Power up afg */
-       snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
-                                                       AC_PWRST_D0);
-
-       hdac_hdmi_skl_enable_all_pins(hdev);
-       hdac_hdmi_skl_enable_dp12(hdev);
-
+       ret = pm_runtime_force_resume(dev);
+       if (ret < 0)
+               return ret;
        /*
         * As the ELD notify callback request is not entertained while the
         * device is in suspend state. Need to manually check detection of
         * all pins here. pin capablity change is not support, so use the
         * already set pin caps.
+        *
+        * NOTE: this is safe to call even if the codec doesn't actually resume.
+        * The pin check involves only with DRM audio component hooks, so it
+        * works even if the HD-audio side is still dreaming peacefully.
         */
        hdac_hdmi_present_sense_all_pins(hdev, hdmi, false);
-
-       pm_runtime_put_sync(&hdev->dev);
+       return 0;
 }
 #else
-#define hdmi_codec_prepare NULL
-#define hdmi_codec_complete NULL
+#define hdmi_codec_resume NULL
 #endif
 
 static const struct snd_soc_component_driver hdmi_hda_codec = {
@@ -2135,75 +2115,6 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
 }
 
 #ifdef CONFIG_PM
-/*
- * Power management sequences
- * ==========================
- *
- * The following explains the PM handling of HDAC HDMI with its parent
- * device SKL and display power usage
- *
- * Probe
- * -----
- * In SKL probe,
- * 1. skl_probe_work() powers up the display (refcount++ -> 1)
- * 2. enumerates the codecs on the link
- * 3. powers down the display  (refcount-- -> 0)
- *
- * In HDAC HDMI probe,
- * 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1)
- * 2. probe the codec
- * 3. put the HDAC HDMI device to runtime suspend
- * 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- *
- * Once children are runtime suspended, SKL device also goes to runtime
- * suspend
- *
- * HDMI Playback
- * -------------
- * Open HDMI device,
- * 1. skl_runtime_resume() invoked
- * 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
- *
- * Close HDMI device,
- * 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- * 2. skl_runtime_suspend() invoked
- *
- * S0/S3 Cycle with playback in progress
- * -------------------------------------
- * When the device is opened for playback, the device is runtime active
- * already and the display refcount is 1 as explained above.
- *
- * Entering to S3,
- * 1. hdmi_codec_prepare() invoke the runtime resume of codec which just
- *    increments the PM runtime usage count of the codec since the device
- *    is in use already
- * 2. skl_suspend() powers down the display (refcount-- -> 0)
- *
- * Wakeup from S3,
- * 1. skl_resume() powers up the display (refcount++ -> 1)
- * 2. hdmi_codec_complete() invokes the runtime suspend of codec which just
- *    decrements the PM runtime usage count of the codec since the device
- *    is in use already
- *
- * Once playback is stopped, the display refcount is set to 0 as explained
- * above in the HDMI playback sequence. The PM handlings are designed in
- * such way that to balance the refcount of display power when the codec
- * device put to S3 while playback is going on.
- *
- * S0/S3 Cycle without playback in progress
- * ----------------------------------------
- * Entering to S3,
- * 1. hdmi_codec_prepare() invoke the runtime resume of codec
- * 2. skl_runtime_resume() invoked
- * 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
- * 4. skl_suspend() powers down the display (refcount-- -> 0)
- *
- * Wakeup from S3,
- * 1. skl_resume() powers up the display (refcount++ -> 1)
- * 2. hdmi_codec_complete() invokes the runtime suspend of codec
- * 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- * 4. skl_runtime_suspend() invoked
- */
 static int hdac_hdmi_runtime_suspend(struct device *dev)
 {
        struct hdac_device *hdev = dev_to_hdac_dev(dev);
@@ -2277,8 +2188,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
 
 static const struct dev_pm_ops hdac_hdmi_pm = {
        SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
-       .prepare = hdmi_codec_prepare,
-       .complete = hdmi_codec_complete,
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume)
 };
 
 static const struct hda_device_id hdmi_list[] = {
index d00734d31e0429bf3df8c12b0bcc118ccefb3ec2..e5b6769b9797724ceef38f3b8132200876f227e8 100644 (file)
@@ -795,6 +795,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
        if (hcd->spdif)
                hcp->daidrv[i] = hdmi_spdif_dai;
 
+       dev_set_drvdata(dev, hcp);
+
        ret = devm_snd_soc_register_component(dev, &hdmi_driver, hcp->daidrv,
                                     dai_count);
        if (ret) {
@@ -802,8 +804,6 @@ static int hdmi_codec_probe(struct platform_device *pdev)
                        __func__, ret);
                return ret;
        }
-
-       dev_set_drvdata(dev, hcp);
        return 0;
 }
 
index 6cb1653be80417ae65ceddbc52791dcc92a4a367..4cc24a5d5c3167cf625a4135e068b6798b12a842 100644 (file)
@@ -1400,24 +1400,20 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
                if (ret != 0) {
                        dev_err(component->dev,
                                "Failed to set digital mute: %d\n", ret);
-                       mutex_unlock(&pcm512x->mutex);
-                       return ret;
+                       goto unlock;
                }
 
                regmap_read_poll_timeout(pcm512x->regmap,
                                         PCM512x_ANALOG_MUTE_DET,
                                         mute_det, (mute_det & 0x3) == 0,
                                         200, 10000);
-
-               mutex_unlock(&pcm512x->mutex);
        } else {
                pcm512x->mute &= ~0x1;
                ret = pcm512x_update_mute(pcm512x);
                if (ret != 0) {
                        dev_err(component->dev,
                                "Failed to update digital mute: %d\n", ret);
-                       mutex_unlock(&pcm512x->mutex);
-                       return ret;
+                       goto unlock;
                }
 
                regmap_read_poll_timeout(pcm512x->regmap,
@@ -1428,9 +1424,10 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
                                         200, 10000);
        }
 
+unlock:
        mutex_unlock(&pcm512x->mutex);
 
-       return 0;
+       return ret;
 }
 
 static const struct snd_soc_dai_ops pcm512x_dai_ops = {
index 0ef966d56bac300f00f1fac7aa92f54fa9949e7e..e2855ab9a2c6b5f84a4e179d254564d62cb6efff 100644 (file)
@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       regmap_read(rt274->regmap,
+       ret = regmap_read(rt274->regmap,
                RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
+       if (ret)
+               return ret;
+
        if (val != RT274_VENDOR_ID) {
                dev_err(&i2c->dev,
                        "Device with ID register %#x is not rt274\n", val);
index 4d46f4567c3a8c69cab55ca45ab1bbbc686b8945..bec2eefa8b0f03efcd518de0c047ac5064221115 100644 (file)
@@ -280,6 +280,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
 
        rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp),
                        GFP_KERNEL);
+       if (!rt5514_dsp)
+               return -ENOMEM;
 
        rt5514_dsp->dev = &rt5514_spi->dev;
        mutex_init(&rt5514_dsp->dma_lock);
index 34cfaf8f6f3452b9839614a03c4b72c9cb82cd17..a9b91bcfcc0967a3d8db46d7e96be88806a93f0e 100644 (file)
@@ -1778,7 +1778,9 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
        {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc},
        {"DAC Stereo1 Filter", NULL, "DAC STO1 ASRC", is_using_asrc},
        {"ADC STO1 ASRC", NULL, "AD ASRC"},
+       {"ADC STO1 ASRC", NULL, "DA ASRC"},
        {"ADC STO1 ASRC", NULL, "CLKDET"},
+       {"DAC STO1 ASRC", NULL, "AD ASRC"},
        {"DAC STO1 ASRC", NULL, "DA ASRC"},
        {"DAC STO1 ASRC", NULL, "CLKDET"},
 
@@ -2512,6 +2514,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
        regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000);
        regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000);
        regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005);
+       regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4);
 
        mutex_unlock(&rt5682->calibrate_mutex);
 
index d82a8301fd745c1206923b3363d1e51ce66746bd..96944cff0ed730b04406036e6b38ddb5499d7726 100644 (file)
 #define RT5682_SCLK_SRC_PLL2                   (0x2 << 13)
 #define RT5682_SCLK_SRC_SDW                    (0x3 << 13)
 #define RT5682_SCLK_SRC_RCCLK                  (0x4 << 13)
-#define RT5682_PLL1_SRC_MASK                   (0x3 << 10)
-#define RT5682_PLL1_SRC_SFT                    10
-#define RT5682_PLL1_SRC_MCLK                   (0x0 << 10)
-#define RT5682_PLL1_SRC_BCLK1                  (0x1 << 10)
-#define RT5682_PLL1_SRC_SDW                    (0x2 << 10)
-#define RT5682_PLL1_SRC_RC                     (0x3 << 10)
-#define RT5682_PLL2_SRC_MASK                   (0x3 << 8)
-#define RT5682_PLL2_SRC_SFT                    8
-#define RT5682_PLL2_SRC_MCLK                   (0x0 << 8)
-#define RT5682_PLL2_SRC_BCLK1                  (0x1 << 8)
-#define RT5682_PLL2_SRC_SDW                    (0x2 << 8)
-#define RT5682_PLL2_SRC_RC                     (0x3 << 8)
+#define RT5682_PLL2_SRC_MASK                   (0x3 << 10)
+#define RT5682_PLL2_SRC_SFT                    10
+#define RT5682_PLL2_SRC_MCLK                   (0x0 << 10)
+#define RT5682_PLL2_SRC_BCLK1                  (0x1 << 10)
+#define RT5682_PLL2_SRC_SDW                    (0x2 << 10)
+#define RT5682_PLL2_SRC_RC                     (0x3 << 10)
+#define RT5682_PLL1_SRC_MASK                   (0x3 << 8)
+#define RT5682_PLL1_SRC_SFT                    8
+#define RT5682_PLL1_SRC_MCLK                   (0x0 << 8)
+#define RT5682_PLL1_SRC_BCLK1                  (0x1 << 8)
+#define RT5682_PLL1_SRC_SDW                    (0x2 << 8)
+#define RT5682_PLL1_SRC_RC                     (0x3 << 8)
 
 
 
index e2b5a11b16d1901775ff0fe8cedce8c2d5c7e5f2..f03195d2ab2ea773b9efa52783c6b5cd7c5f368d 100644 (file)
@@ -822,6 +822,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               /* Initial cold start */
+               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+                       break;
+
                /* Switch off BCLK_N Divider */
                snd_soc_component_update_bits(component, AIC32X4_BCLKN,
                                    AIC32X4_BCLKEN, 0);
index 392d5eef356d3a8a90cb2b4cb52c07d5520ebbc0..99e07b01a2ce9d5fa3d8e1d5bbc72823d399ef4b 100644 (file)
@@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
        if (!buf)
                return -ENOMEM;
 
-       ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
+       ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
                       pdcr, ptcr);
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxFS output from %s, ",
                                audmux_port_string((ptcr >> 27) & 0x7));
        else
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxFS input, ");
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxClk output from %s",
                                audmux_port_string((ptcr >> 22) & 0x7));
        else
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxClk input");
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "Port is symmetric");
        } else {
                if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxFS output from %s, ",
                                        audmux_port_string((ptcr >> 17) & 0x7));
                else
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxFS input, ");
 
                if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxClk output from %s",
                                        audmux_port_string((ptcr >> 12) & 0x7));
                else
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxClk input");
        }
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                        "\nData received from %s\n",
                        audmux_port_string((pdcr >> 13) & 0x7));
 
index 99a62ba409df83424bc84031f067e4e70a0db03d..bd9fd2035c554b9479500113816483b4d128b2c9 100644 (file)
@@ -91,7 +91,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI
 config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
        tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
        default ACPI
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select SND_SST_IPC_ACPI
        select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SOC_ACPI_INTEL_MATCH
index afc5598660955a462f1f2bfdf45fe9905a23e339..91a2436ce9525aea53c537ba1f879456050fcc66 100644 (file)
@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
 {
-       snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       int ret;
+
+       ret =
+               snd_pcm_lib_malloc_pages(substream,
+                               params_buffer_bytes(params));
+       if (ret)
+               return ret;
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
        return 0;
 }
index 68e6543e6cb026aa20b3a339c9f7c3f24c3820f5..99f2a0156ae88cb509b70994cc6784902901161d 100644 (file)
@@ -192,7 +192,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
                .stream_name = "Loopback",
                .cpu_dai_name = "Loopback Pin",
                .platform_name = "haswell-pcm-audio",
-               .dynamic = 0,
+               .dynamic = 1,
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
index c74c4f17316fe898ff29e16a2be4982499d7f612..8f83b182c4f95d283acf52eb04cc70095778d4f4 100644 (file)
@@ -55,39 +55,6 @@ enum {
        GLK_DPCM_AUDIO_HDMI3_PB,
 };
 
-static int platform_clock_control(struct snd_soc_dapm_widget *w,
-                                       struct snd_kcontrol *k, int  event)
-{
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct snd_soc_card *card = dapm->card;
-       struct snd_soc_dai *codec_dai;
-       int ret = 0;
-
-       codec_dai = snd_soc_card_get_codec_dai(card, GLK_REALTEK_CODEC_DAI);
-       if (!codec_dai) {
-               dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
-               return -EIO;
-       }
-
-       if (SND_SOC_DAPM_EVENT_OFF(event)) {
-               ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
-               if (ret)
-                       dev_err(card->dev, "failed to stop sysclk: %d\n", ret);
-       } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
-                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
-               if (ret < 0) {
-                       dev_err(card->dev, "can't set codec pll: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       if (ret)
-               dev_err(card->dev, "failed to start internal clk: %d\n", ret);
-
-       return ret;
-}
-
 static const struct snd_kcontrol_new geminilake_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -102,14 +69,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = {
        SND_SOC_DAPM_SPK("HDMI1", NULL),
        SND_SOC_DAPM_SPK("HDMI2", NULL),
        SND_SOC_DAPM_SPK("HDMI3", NULL),
-       SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-                       platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-                       SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route geminilake_map[] = {
        /* HP jack connectors - unknown if we have jack detection */
-       { "Headphone Jack", NULL, "Platform Clock" },
        { "Headphone Jack", NULL, "HPOL" },
        { "Headphone Jack", NULL, "HPOR" },
 
@@ -117,7 +80,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = {
        { "Spk", NULL, "Speaker" },
 
        /* other jacks */
-       { "Headset Mic", NULL, "Platform Clock" },
        { "IN1P", NULL, "Headset Mic" },
 
        /* digital mics */
@@ -177,6 +139,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_jack *jack;
        int ret;
 
+       ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
+                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
+       if (ret < 0) {
+               dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+               return ret;
+       }
+
        /* Configure sysclk for codec */
        ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
                                        RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
index eab1f439dd3f1ad9a4553d03fa2190d673ec94a3..a4022983a7ce0050b3a5d857b0edd6ed691e0636 100644 (file)
@@ -146,7 +146,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
                .stream_name = "Loopback",
                .cpu_dai_name = "Loopback Pin",
                .platform_name = "haswell-pcm-audio",
-               .dynamic = 0,
+               .dynamic = 1,
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
index 60c94836bf5bc93bb3dde46a237c21abf77e5b6c..4ed5b7e17d44aad3e09e6d6a8726ae3742bc92a1 100644 (file)
@@ -336,9 +336,6 @@ static int skl_suspend(struct device *dev)
                skl->skl_sst->fw_loaded = false;
        }
 
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
-
        return 0;
 }
 
@@ -350,10 +347,6 @@ static int skl_resume(struct device *dev)
        struct hdac_ext_link *hlink = NULL;
        int ret;
 
-       /* Turned OFF in HDMI codec driver after codec reconfiguration */
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
-
        /*
         * resume only when we are not in suspend active, otherwise need to
         * restore the device
@@ -446,8 +439,10 @@ static int skl_free(struct hdac_bus *bus)
        snd_hdac_ext_bus_exit(bus);
 
        cancel_work_sync(&skl->probe_work);
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
                snd_hdac_i915_exit(bus);
+       }
 
        return 0;
 }
@@ -814,7 +809,7 @@ static void skl_probe_work(struct work_struct *work)
        err = skl_platform_register(bus->dev);
        if (err < 0) {
                dev_err(bus->dev, "platform register failed: %d\n", err);
-               return;
+               goto out_err;
        }
 
        err = skl_machine_device_register(skl);
index 5b986b74dd36f96d0a4a37bc8714f0b741c39486..548eb4fa2da64415ccf7f9db83f84575a251093f 100644 (file)
@@ -570,10 +570,10 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
        prtd->audio_client = q6asm_audio_client_alloc(dev,
                                        (q6asm_cb)compress_event_handler,
                                        prtd, stream_id, LEGACY_PCM_MODE);
-       if (!prtd->audio_client) {
+       if (IS_ERR(prtd->audio_client)) {
                dev_err(dev, "Could not allocate memory\n");
-               kfree(prtd);
-               return -ENOMEM;
+               ret = PTR_ERR(prtd->audio_client);
+               goto free_prtd;
        }
 
        size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
@@ -582,7 +582,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
                                  &prtd->dma_buffer);
        if (ret) {
                dev_err(dev, "Cannot allocate buffer(s)\n");
-               return ret;
+               goto free_client;
        }
 
        if (pdata->sid < 0)
@@ -595,6 +595,13 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
        runtime->private_data = prtd;
 
        return 0;
+
+free_client:
+       q6asm_audio_client_free(prtd->audio_client);
+free_prtd:
+       kfree(prtd);
+
+       return ret;
 }
 
 static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
@@ -874,7 +881,7 @@ static int of_q6asm_parse_dai_data(struct device *dev,
 
        for_each_child_of_node(dev->of_node, node) {
                ret = of_property_read_u32(node, "reg", &id);
-               if (ret || id > MAX_SESSIONS || id < 0) {
+               if (ret || id >= MAX_SESSIONS || id < 0) {
                        dev_err(dev, "valid dai id not found:%d\n", ret);
                        continue;
                }
index 1db8ef6682233feaf38145efb07af877c28a1ef2..6f66a58e23caa1178bec669a14eb54c4dec72a95 100644 (file)
@@ -158,17 +158,24 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static void sdm845_jack_free(struct snd_jack *jack)
+{
+       struct snd_soc_component *component = jack->private_data;
+
+       snd_soc_component_set_jack(component, NULL, NULL);
+}
+
 static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_component *component;
-       struct snd_soc_dai_link *dai_link = rtd->dai_link;
        struct snd_soc_card *card = rtd->card;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
-       int i, rval;
+       struct snd_jack *jack;
+       int rval;
 
        if (!pdata->jack_setup) {
-               struct snd_jack *jack;
-
                rval = snd_soc_card_jack_new(card, "Headset Jack",
                                SND_JACK_HEADSET |
                                SND_JACK_HEADPHONE |
@@ -190,16 +197,22 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
                pdata->jack_setup = true;
        }
 
-       for (i = 0 ; i < dai_link->num_codecs; i++) {
-               struct snd_soc_dai *dai = rtd->codec_dais[i];
+       switch (cpu_dai->id) {
+       case PRIMARY_MI2S_RX:
+               jack  = pdata->jack.jack;
+               component = codec_dai->component;
 
-               component = dai->component;
-               rval = snd_soc_component_set_jack(
-                               component, &pdata->jack, NULL);
+               jack->private_data = component;
+               jack->private_free = sdm845_jack_free;
+               rval = snd_soc_component_set_jack(component,
+                                                 &pdata->jack, NULL);
                if (rval != 0 && rval != -ENOTSUPP) {
                        dev_warn(card->dev, "Failed to set jack: %d\n", rval);
                        return rval;
                }
+               break;
+       default:
+               break;
        }
 
        return 0;
index d6c62aa130414369f729bbc5333c82052bdcc9d2..ce00fe2f6aae32d2eb777c2ac7533f3ecdd47a0a 100644 (file)
@@ -700,6 +700,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 {
        struct i2s_dai *i2s = to_info(dai);
        u32 mod, mask = 0, val = 0;
+       struct clk *rclksrc;
        unsigned long flags;
 
        WARN_ON(!pm_runtime_active(dai->dev));
@@ -782,6 +783,10 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 
        i2s->frmclk = params_rate(params);
 
+       rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
+       if (rclksrc && !IS_ERR(rclksrc))
+               i2s->rclk_srcrate = clk_get_rate(rclksrc);
+
        return 0;
 }
 
@@ -886,11 +891,6 @@ static int config_setup(struct i2s_dai *i2s)
                return 0;
 
        if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
-               struct clk *rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
-
-               if (rclksrc && !IS_ERR(rclksrc))
-                       i2s->rclk_srcrate = clk_get_rate(rclksrc);
-
                psr = i2s->rclk_srcrate / i2s->frmclk / rfs;
                writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR);
                dev_dbg(&i2s->pdev->dev,
index 922fb6aa3ed191c5047ae21ecb5d708287a81f35..5aee11c94f2a749f13c2957fb4eeb35c263ed482 100644 (file)
@@ -202,7 +202,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
 
-       pr_debug("PCM data: addr 0x%08ulx len %d\n",
+       pr_debug("PCM data: addr 0x%08lx len %d\n",
                 (u32)runtime->dma_addr, runtime->dma_bytes);
  
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
index 59e250cc2e9df285d778d7939a4812a3c90219df..e819e965e1dbe9254137dfea8c2fd0350542f510 100644 (file)
@@ -1526,14 +1526,14 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
        int ret;
 
        /*
-        * 1) Avoid duplicate register (ex. MIXer case)
-        * 2) re-register if card was rebinded
+        * 1) Avoid duplicate register for DVC with MIX case
+        * 2) Allow duplicate register for MIX
+        * 3) re-register if card was rebinded
         */
        list_for_each_entry(kctrl, &card->controls, list) {
                struct rsnd_kctrl_cfg *c = kctrl->private_data;
 
-               if (strcmp(kctrl->id.name, name) == 0 &&
-                   c->mod == mod)
+               if (c == cfg)
                        return 0;
        }
 
index 45ef295743ecdc2f6042e36b2c2f31edd619a3f9..f5afab631abbc15516fa50427c908a9617e8d82f 100644 (file)
@@ -286,7 +286,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        if (rsnd_ssi_is_multi_slave(mod, io))
                return 0;
 
-       if (ssi->usrcnt > 1) {
+       if (ssi->usrcnt > 0) {
                if (ssi->rate != rate) {
                        dev_err(dev, "SSI parent/child should use same rate\n");
                        return -EINVAL;
index c5934adcfd0155e5a410ecc1d5ea171268f16e8d..c74991dd18abbb459f125529e831e2bbf2d9139c 100644 (file)
@@ -79,7 +79,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
                break;
        case 9:
                for (i = 0; i < 4; i++)
-                       rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << (id * 4));
+                       rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4);
                break;
        }
 
index 0462b3ec977a221a5d7869d3e7afb02e36cd7e5a..50617db05c46b8a5fce3a6553c672e54996c7dfd 100644 (file)
@@ -735,14 +735,19 @@ static struct snd_soc_component *soc_find_component(
        const struct device_node *of_node, const char *name)
 {
        struct snd_soc_component *component;
+       struct device_node *component_of_node;
 
        lockdep_assert_held(&client_mutex);
 
        for_each_component(component) {
                if (of_node) {
-                       if (component->dev->of_node == of_node)
+                       component_of_node = component->dev->of_node;
+                       if (!component_of_node && component->dev->parent)
+                               component_of_node = component->dev->parent->of_node;
+
+                       if (component_of_node == of_node)
                                return component;
-               } else if (strcmp(component->name, name) == 0) {
+               } else if (name && strcmp(component->name, name) == 0) {
                        return component;
                }
        }
@@ -951,7 +956,7 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order)
 {
        int err;
 
-       if (!dai || !dai->probed ||
+       if (!dai || !dai->probed || !dai->driver ||
            dai->driver->remove_order != order)
                return;
 
@@ -1034,17 +1039,18 @@ static int snd_soc_init_platform(struct snd_soc_card *card,
         * this function should be removed in the future
         */
        /* convert Legacy platform link */
-       if (!platform) {
+       if (!platform || dai_link->legacy_platform) {
                platform = devm_kzalloc(card->dev,
                                sizeof(struct snd_soc_dai_link_component),
                                GFP_KERNEL);
                if (!platform)
                        return -ENOMEM;
 
-               dai_link->platform      = platform;
-               platform->name          = dai_link->platform_name;
-               platform->of_node       = dai_link->platform_of_node;
-               platform->dai_name      = NULL;
+               dai_link->platform        = platform;
+               dai_link->legacy_platform = 1;
+               platform->name            = dai_link->platform_name;
+               platform->of_node         = dai_link->platform_of_node;
+               platform->dai_name        = NULL;
        }
 
        /* if there's no platform we match on the empty platform */
@@ -1129,6 +1135,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
                        link->name);
                return -EINVAL;
        }
+
+       /*
+        * Defer card registartion if platform dai component is not added to
+        * component list.
+        */
+       if ((link->platform->of_node || link->platform->name) &&
+           !soc_find_component(link->platform->of_node, link->platform->name))
+               return -EPROBE_DEFER;
+
        /*
         * CPU device may be specified by either name or OF node, but
         * can be left unspecified, and will be matched based on DAI
@@ -1140,6 +1155,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
                        link->name);
                return -EINVAL;
        }
+
+       /*
+        * Defer card registartion if cpu dai component is not added to
+        * component list.
+        */
+       if ((link->cpu_of_node || link->cpu_name) &&
+           !soc_find_component(link->cpu_of_node, link->cpu_name))
+               return -EPROBE_DEFER;
+
        /*
         * At least one of CPU DAI name or CPU device name/node must be
         * specified
@@ -2739,15 +2763,18 @@ int snd_soc_register_card(struct snd_soc_card *card)
        if (!card->name || !card->dev)
                return -EINVAL;
 
+       mutex_lock(&client_mutex);
        for_each_card_prelinks(card, i, link) {
 
                ret = soc_init_dai_link(card, link);
                if (ret) {
                        dev_err(card->dev, "ASoC: failed to init link %s\n",
                                link->name);
+                       mutex_unlock(&client_mutex);
                        return ret;
                }
        }
+       mutex_unlock(&client_mutex);
 
        dev_set_drvdata(card->dev, card);
 
index a5178845065b3586bc1bde669c03580574f1bcb7..20bad755888b119d4102fa030766d492675cf4b8 100644 (file)
@@ -70,12 +70,16 @@ static int dapm_up_seq[] = {
        [snd_soc_dapm_clock_supply] = 1,
        [snd_soc_dapm_supply] = 2,
        [snd_soc_dapm_micbias] = 3,
+       [snd_soc_dapm_vmid] = 3,
        [snd_soc_dapm_dai_link] = 2,
        [snd_soc_dapm_dai_in] = 4,
        [snd_soc_dapm_dai_out] = 4,
        [snd_soc_dapm_aif_in] = 4,
        [snd_soc_dapm_aif_out] = 4,
        [snd_soc_dapm_mic] = 5,
+       [snd_soc_dapm_siggen] = 5,
+       [snd_soc_dapm_input] = 5,
+       [snd_soc_dapm_output] = 5,
        [snd_soc_dapm_mux] = 6,
        [snd_soc_dapm_demux] = 6,
        [snd_soc_dapm_dac] = 7,
@@ -83,11 +87,19 @@ static int dapm_up_seq[] = {
        [snd_soc_dapm_mixer] = 8,
        [snd_soc_dapm_mixer_named_ctl] = 8,
        [snd_soc_dapm_pga] = 9,
+       [snd_soc_dapm_buffer] = 9,
+       [snd_soc_dapm_scheduler] = 9,
+       [snd_soc_dapm_effect] = 9,
+       [snd_soc_dapm_src] = 9,
+       [snd_soc_dapm_asrc] = 9,
+       [snd_soc_dapm_encoder] = 9,
+       [snd_soc_dapm_decoder] = 9,
        [snd_soc_dapm_adc] = 10,
        [snd_soc_dapm_out_drv] = 11,
        [snd_soc_dapm_hp] = 11,
        [snd_soc_dapm_spk] = 11,
        [snd_soc_dapm_line] = 11,
+       [snd_soc_dapm_sink] = 11,
        [snd_soc_dapm_kcontrol] = 12,
        [snd_soc_dapm_post] = 13,
 };
@@ -100,13 +112,25 @@ static int dapm_down_seq[] = {
        [snd_soc_dapm_spk] = 3,
        [snd_soc_dapm_line] = 3,
        [snd_soc_dapm_out_drv] = 3,
+       [snd_soc_dapm_sink] = 3,
        [snd_soc_dapm_pga] = 4,
+       [snd_soc_dapm_buffer] = 4,
+       [snd_soc_dapm_scheduler] = 4,
+       [snd_soc_dapm_effect] = 4,
+       [snd_soc_dapm_src] = 4,
+       [snd_soc_dapm_asrc] = 4,
+       [snd_soc_dapm_encoder] = 4,
+       [snd_soc_dapm_decoder] = 4,
        [snd_soc_dapm_switch] = 5,
        [snd_soc_dapm_mixer_named_ctl] = 5,
        [snd_soc_dapm_mixer] = 5,
        [snd_soc_dapm_dac] = 6,
        [snd_soc_dapm_mic] = 7,
+       [snd_soc_dapm_siggen] = 7,
+       [snd_soc_dapm_input] = 7,
+       [snd_soc_dapm_output] = 7,
        [snd_soc_dapm_micbias] = 8,
+       [snd_soc_dapm_vmid] = 8,
        [snd_soc_dapm_mux] = 9,
        [snd_soc_dapm_demux] = 9,
        [snd_soc_dapm_aif_in] = 10,
@@ -2019,19 +2043,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
                out = is_connected_output_ep(w, NULL, NULL);
        }
 
-       ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
+       ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
                       w->name, w->power ? "On" : "Off",
                       w->force ? " (forced)" : "", in, out);
 
        if (w->reg >= 0)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                " - R%d(0x%x) mask 0x%x",
                                w->reg, w->reg, w->mask << w->shift);
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
        if (w->sname)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
                                w->sname,
                                w->active ? "active" : "inactive");
 
@@ -2044,7 +2068,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
                        if (!p->connect)
                                continue;
 
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        " %s  \"%s\" \"%s\"\n",
                                        (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
                                        p->name ? p->name : "static",
index 045ef136903d63b4a7e3339e137cb5156dedffb7..fc79ec6927e385fbd85ab6182a6788daea610726 100644 (file)
@@ -502,6 +502,7 @@ static void remove_dai(struct snd_soc_component *comp,
 {
        struct snd_soc_dai_driver *dai_drv =
                container_of(dobj, struct snd_soc_dai_driver, dobj);
+       struct snd_soc_dai *dai;
 
        if (pass != SOC_TPLG_PASS_PCM_DAI)
                return;
@@ -509,6 +510,10 @@ static void remove_dai(struct snd_soc_component *comp,
        if (dobj->ops && dobj->ops->dai_unload)
                dobj->ops->dai_unload(comp, dobj);
 
+       list_for_each_entry(dai, &comp->dai_list, list)
+               if (dai->driver == dai_drv)
+                       dai->driver = NULL;
+
        kfree(dai_drv->name);
        list_del(&dobj->list);
        kfree(dai_drv);
index eeda6d5565bccc5bffa00873a9a3c517dcacf41d..a10fcb5963c67a2b41ac02aaf3e6b7fcb329a990 100644 (file)
@@ -108,7 +108,7 @@ struct davinci_mcasp {
        /* Used for comstraint setting on the second stream */
        u32     channels;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        struct davinci_mcasp_context context;
 #endif
 
@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
-{
-       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-       struct davinci_mcasp_context *context = &mcasp->context;
-       u32 reg;
-       int i;
-
-       context->pm_state = pm_runtime_active(mcasp->dev);
-       if (!context->pm_state)
-               pm_runtime_get_sync(mcasp->dev);
-
-       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
-               context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
-
-       if (mcasp->txnumevt) {
-               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-               context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
-       }
-       if (mcasp->rxnumevt) {
-               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-               context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
-       }
-
-       for (i = 0; i < mcasp->num_serializer; i++)
-               context->xrsr_regs[i] = mcasp_get_reg(mcasp,
-                                               DAVINCI_MCASP_XRSRCTL_REG(i));
-
-       pm_runtime_put_sync(mcasp->dev);
-
-       return 0;
-}
-
-static int davinci_mcasp_resume(struct snd_soc_dai *dai)
-{
-       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-       struct davinci_mcasp_context *context = &mcasp->context;
-       u32 reg;
-       int i;
-
-       pm_runtime_get_sync(mcasp->dev);
-
-       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
-               mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
-
-       if (mcasp->txnumevt) {
-               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-               mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
-       }
-       if (mcasp->rxnumevt) {
-               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-               mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
-       }
-
-       for (i = 0; i < mcasp->num_serializer; i++)
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
-                             context->xrsr_regs[i]);
-
-       if (!context->pm_state)
-               pm_runtime_put_sync(mcasp->dev);
-
-       return 0;
-}
-#else
-#define davinci_mcasp_suspend NULL
-#define davinci_mcasp_resume NULL
-#endif
-
 #define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
@@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
        {
                .name           = "davinci-mcasp.0",
                .probe          = davinci_mcasp_dai_probe,
-               .suspend        = davinci_mcasp_suspend,
-               .resume         = davinci_mcasp_resume,
                .playback       = {
                        .channels_min   = 1,
                        .channels_max   = 32 * 16,
@@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        }
 
        mcasp->num_serializer = pdata->num_serializer;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
                                        mcasp->num_serializer, sizeof(u32),
                                        GFP_KERNEL);
@@ -2196,11 +2126,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int davinci_mcasp_runtime_suspend(struct device *dev)
+{
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+       struct davinci_mcasp_context *context = &mcasp->context;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
+               context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
+
+       if (mcasp->txnumevt) {
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
+       }
+       if (mcasp->rxnumevt) {
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
+       }
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               context->xrsr_regs[i] = mcasp_get_reg(mcasp,
+                                               DAVINCI_MCASP_XRSRCTL_REG(i));
+
+       return 0;
+}
+
+static int davinci_mcasp_runtime_resume(struct device *dev)
+{
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+       struct davinci_mcasp_context *context = &mcasp->context;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
+               mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
+
+       if (mcasp->txnumevt) {
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
+       }
+       if (mcasp->rxnumevt) {
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
+       }
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                             context->xrsr_regs[i]);
+
+       return 0;
+}
+
+#endif
+
+static const struct dev_pm_ops davinci_mcasp_pm_ops = {
+       SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend,
+                          davinci_mcasp_runtime_resume,
+                          NULL)
+};
+
 static struct platform_driver davinci_mcasp_driver = {
        .probe          = davinci_mcasp_probe,
        .remove         = davinci_mcasp_remove,
        .driver         = {
                .name   = "davinci-mcasp",
+               .pm     = &davinci_mcasp_pm_ops,
                .of_match_table = mcasp_dt_ids,
        },
 };
index 25e287feb58c33e845db60054e16ed49856e5679..723a583a8d570f625f92f5815f1ffe431624b340 100644 (file)
@@ -1,5 +1,5 @@
 config SND_SOC_XILINX_I2S
-       tristate "Audio support for the the Xilinx I2S"
+       tristate "Audio support for the Xilinx I2S"
        help
          Select this option to enable Xilinx I2S Audio. This enables
          I2S playback and capture using xilinx soft IP. In transmitter
index d4ae9eff41ce51cb2f2777263b5190edf49c3e49..8b353166ad447699480baae7944fe087a3bb79d8 100644 (file)
@@ -1,12 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Xilinx ASoC I2S audio support
- *
- * Copyright (C) 2018 Xilinx, Inc.
- *
- * Author: Praveen Vuppala <praveenv@xilinx.com>
- * Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
- */
+//
+// Xilinx ASoC I2S audio support
+//
+// Copyright (C) 2018 Xilinx, Inc.
+//
+// Author: Praveen Vuppala <praveenv@xilinx.com>
+// Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
 
 #include <linux/io.h>
 #include <linux/module.h>
index 382847154227ef69bb77b477402ed6a3a54f4170..db114f3977e0fb4044e88c028f9dea9bad6382af 100644 (file)
@@ -314,6 +314,9 @@ static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
        return 0;
 }
 
+/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
+ * applies. Returns 1 if a quirk was found.
+ */
 static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                                         struct usb_device *dev,
                                         struct usb_interface_descriptor *altsd,
@@ -384,7 +387,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 
        subs->data_endpoint->sync_master = subs->sync_endpoint;
 
-       return 0;
+       return 1;
 }
 
 static int set_sync_endpoint(struct snd_usb_substream *subs,
@@ -423,6 +426,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
        if (err < 0)
                return err;
 
+       /* endpoint set by quirk */
+       if (err > 0)
+               return 0;
+
        if (altsd->bNumEndpoints < 2)
                return 0;
 
index ebbadb3a7094e0ec5e001c139b614f4a6ed5f7b7..7e65fe853ee3accb793b22cf321cbddeb81e6265 100644 (file)
@@ -1492,6 +1492,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
+       case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
        case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
        case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
@@ -1566,6 +1567,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case 0x20b1:  /* XMOS based devices */
        case 0x152a:  /* Thesycon devices */
        case 0x25ce:  /* Mytek devices */
+       case 0x2ab6:  /* T+A devices */
                if (fp->dsd_raw)
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
index ff91192407d1b3c027257b5e32ac9b6956f8bb13..f599064dd8dc8431fbe705320d9afc7f862f1207 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index 492f0f24e2d36bfde4e12a991610fa71000dd7ca..4ad1f0894d5312ef81e162cc5ecd34f114405725 100644 (file)
@@ -93,9 +93,16 @@ BFD_SRCS = jit_disasm.c
 SRCS = $(filter-out $(BFD_SRCS),$(wildcard *.c))
 
 ifeq ($(feature-libbfd),1)
+  LIBS += -lbfd -ldl -lopcodes
+else ifeq ($(feature-libbfd-liberty),1)
+  LIBS += -lbfd -ldl -lopcodes -liberty
+else ifeq ($(feature-libbfd-liberty-z),1)
+  LIBS += -lbfd -ldl -lopcodes -liberty -lz
+endif
+
+ifneq ($(filter -lbfd,$(LIBS)),)
 CFLAGS += -DHAVE_LIBBFD_SUPPORT
 SRCS += $(BFD_SRCS)
-LIBS += -lbfd -lopcodes
 endif
 
 OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
index 3f0629edbca5986e324f698ed827e31b0196b15a..6ba5f567a9d86778df796b3864c33b646d1db3de 100644 (file)
@@ -82,8 +82,6 @@ static void btf_dumper_bitfield(__u32 nr_bits, __u8 bit_offset,
        int bits_to_copy;
        __u64 print_num;
 
-       data += BITS_ROUNDDOWN_BYTES(bit_offset);
-       bit_offset = BITS_PER_BYTE_MASKED(bit_offset);
        bits_to_copy = bit_offset + nr_bits;
        bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
 
@@ -118,7 +116,9 @@ static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
         * BTF_INT_OFFSET() cannot exceed 64 bits.
         */
        total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
-       btf_dumper_bitfield(nr_bits, total_bits_offset, data, jw,
+       data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+       bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+       btf_dumper_bitfield(nr_bits, bit_offset, data, jw,
                            is_plain_text);
 }
 
@@ -216,11 +216,12 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
                }
 
                jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
+               data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
                if (bitfield_size) {
-                       btf_dumper_bitfield(bitfield_size, bit_offset,
-                                           data, d->jw, d->is_plain_text);
+                       btf_dumper_bitfield(bitfield_size,
+                                           BITS_PER_BYTE_MASKED(bit_offset),
+                                           data_off, d->jw, d->is_plain_text);
                } else {
-                       data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
                        ret = btf_dumper_do_type(d, m[i].type,
                                                 BITS_PER_BYTE_MASKED(bit_offset),
                                                 data_off);
index 897483457bf0306b9831e3dae4f63d4643c2555e..f7261fad45c19cd7859d8d68d87aa26eb71ff128 100644 (file)
@@ -297,10 +297,8 @@ char *get_fdinfo(int fd, const char *key)
        snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
 
        fdi = fopen(path, "r");
-       if (!fdi) {
-               p_err("can't open fdinfo: %s", strerror(errno));
+       if (!fdi)
                return NULL;
-       }
 
        while ((n = getline(&line, &line_n, fdi)) > 0) {
                char *value;
@@ -313,7 +311,6 @@ char *get_fdinfo(int fd, const char *key)
 
                value = strchr(line, '\t');
                if (!value || !value[1]) {
-                       p_err("malformed fdinfo!?");
                        free(line);
                        return NULL;
                }
@@ -326,7 +323,6 @@ char *get_fdinfo(int fd, const char *key)
                return line;
        }
 
-       p_err("key '%s' not found in fdinfo", key);
        free(line);
        fclose(fdi);
        return NULL;
index bff7ee026680481a1f5d33464cf4fad52f3c38cd..6046dcab51cc538b679428def22ff377a6fada7c 100644 (file)
@@ -1,15 +1,10 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * Simple streaming JSON writer
  *
  * This takes care of the annoying bits of JSON syntax like the commas
  * after elements
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
  * Authors:    Stephen Hemminger <stephen@networkplumber.org>
  */
 
index c1ab51aed99c59764a80d69c340dc688c033a06d..cb9a1993681c6e3997e07343b3d5c9a4a68b9e6e 100644 (file)
@@ -5,11 +5,6 @@
  * This takes care of the annoying bits of JSON syntax like the commas
  * after elements
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
  * Authors:    Stephen Hemminger <stephen@networkplumber.org>
  */
 
index 2037e3dc864bae921a62bd9f9071b7a0b5f6342b..1ef1ee2280a28330925acf9aab4bd7dd8ffade3f 100644 (file)
@@ -347,6 +347,20 @@ static char **parse_bytes(char **argv, const char *name, unsigned char *val,
        return argv + i;
 }
 
+/* on per cpu maps we must copy the provided value on all value instances */
+static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
+{
+       unsigned int i, n, step;
+
+       if (!map_is_per_cpu(info->type))
+               return;
+
+       n = get_possible_cpus();
+       step = round_up(info->value_size, 8);
+       for (i = 1; i < n; i++)
+               memcpy(value + i * step, value, info->value_size);
+}
+
 static int parse_elem(char **argv, struct bpf_map_info *info,
                      void *key, void *value, __u32 key_size, __u32 value_size,
                      __u32 *flags, __u32 **value_fd)
@@ -426,6 +440,8 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
                        argv = parse_bytes(argv, "value", value, value_size);
                        if (!argv)
                                return -1;
+
+                       fill_per_cpu_value(info, value);
                }
 
                return parse_elem(argv, info, key, NULL, key_size, value_size,
@@ -497,10 +513,9 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
                                jsonw_uint_field(json_wtr, "owner_prog_type",
                                                 prog_type);
                }
-               if (atoi(owner_jited))
-                       jsonw_bool_field(json_wtr, "owner_jited", true);
-               else
-                       jsonw_bool_field(json_wtr, "owner_jited", false);
+               if (owner_jited)
+                       jsonw_bool_field(json_wtr, "owner_jited",
+                                        !!atoi(owner_jited));
 
                free(owner_prog_type);
                free(owner_jited);
@@ -553,7 +568,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
                char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
                char *owner_jited = get_fdinfo(fd, "owner_jited");
 
-               printf("\n\t");
+               if (owner_prog_type || owner_jited)
+                       printf("\n\t");
                if (owner_prog_type) {
                        unsigned int prog_type = atoi(owner_prog_type);
 
@@ -563,10 +579,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
                        else
                                printf("owner_prog_type %d  ", prog_type);
                }
-               if (atoi(owner_jited))
-                       printf("owner jited");
-               else
-                       printf("owner not jited");
+               if (owner_jited)
+                       printf("owner%s jited",
+                              atoi(owner_jited) ? "" : " not");
 
                free(owner_prog_type);
                free(owner_jited);
index 2d1bb7d6ff5113c0014855b18e0adc4cd44472fa..b54ed82b9589d2135e0592be1035b928727c7cd7 100644 (file)
@@ -78,13 +78,14 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
 
 static int prog_fd_by_tag(unsigned char *tag)
 {
-       struct bpf_prog_info info = {};
-       __u32 len = sizeof(info);
        unsigned int id = 0;
        int err;
        int fd;
 
        while (true) {
+               struct bpf_prog_info info = {};
+               __u32 len = sizeof(info);
+
                err = bpf_prog_get_next_id(id, &id);
                if (err) {
                        p_err("%s", strerror(errno));
index 3040830d779763de73c9fd665ffae1c47d758ad8..84545666a09c4d05ad643aba1e5f55911fcd5a52 100644 (file)
@@ -330,7 +330,7 @@ static const struct option longopts[] = {
 
 int main(int argc, char **argv)
 {
-       unsigned long long num_loops = 2;
+       long long num_loops = 2;
        unsigned long timedelay = 1000000;
        unsigned long buf_len = 128;
 
index fd92ce8388fceb2f30b79bff3a5be86f22dc6568..57aaeaf8e192038ae37eceaa0b60fba82b5f6013 100644 (file)
@@ -15,6 +15,8 @@
 #include "../../arch/ia64/include/uapi/asm/bitsperlong.h"
 #elif defined(__riscv)
 #include "../../arch/riscv/include/uapi/asm/bitsperlong.h"
+#elif defined(__alpha__)
+#include "../../arch/alpha/include/uapi/asm/bitsperlong.h"
 #else
 #include <asm-generic/bitsperlong.h>
 #endif
index f6052e70bf403950eb658cd350337162a100df5f..a55cb8b10165abcf8a07d8228b590bbc1d8a0c08 100644 (file)
@@ -268,7 +268,7 @@ struct sockaddr_in {
 #define        IN_MULTICAST(a)         IN_CLASSD(a)
 #define        IN_MULTICAST_NET        0xe0000000
 
-#define        IN_BADCLASS(a)          ((((long int) (a) ) == 0xffffffff)
+#define        IN_BADCLASS(a)          (((long int) (a) ) == (long int)0xffffffff)
 #define        IN_EXPERIMENTAL(a)      IN_BADCLASS((a))
 
 #define        IN_CLASSE(a)            ((((long int) (a)) & 0xf0000000) == 0xf0000000)
diff --git a/tools/include/uapi/linux/pkt_sched.h b/tools/include/uapi/linux/pkt_sched.h
new file mode 100644 (file)
index 0000000..0d18b1d
--- /dev/null
@@ -0,0 +1,1163 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_SCHED_H
+#define __LINUX_PKT_SCHED_H
+
+#include <linux/types.h>
+
+/* Logical priority bands not depending on specific packet scheduler.
+   Every scheduler will map them to real traffic classes, if it has
+   no more precise mechanism to classify packets.
+
+   These numbers have no special meaning, though their coincidence
+   with obsolete IPv6 values is not occasional :-). New IPv6 drafts
+   preferred full anarchy inspired by diffserv group.
+
+   Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
+   class, actually, as rule it will be handled with more care than
+   filler or even bulk.
+ */
+
+#define TC_PRIO_BESTEFFORT             0
+#define TC_PRIO_FILLER                 1
+#define TC_PRIO_BULK                   2
+#define TC_PRIO_INTERACTIVE_BULK       4
+#define TC_PRIO_INTERACTIVE            6
+#define TC_PRIO_CONTROL                        7
+
+#define TC_PRIO_MAX                    15
+
+/* Generic queue statistics, available for all the elements.
+   Particular schedulers may have also their private records.
+ */
+
+struct tc_stats {
+       __u64   bytes;                  /* Number of enqueued bytes */
+       __u32   packets;                /* Number of enqueued packets   */
+       __u32   drops;                  /* Packets dropped because of lack of resources */
+       __u32   overlimits;             /* Number of throttle events when this
+                                        * flow goes out of allocated bandwidth */
+       __u32   bps;                    /* Current flow byte rate */
+       __u32   pps;                    /* Current flow packet rate */
+       __u32   qlen;
+       __u32   backlog;
+};
+
+struct tc_estimator {
+       signed char     interval;
+       unsigned char   ewma_log;
+};
+
+/* "Handles"
+   ---------
+
+    All the traffic control objects have 32bit identifiers, or "handles".
+
+    They can be considered as opaque numbers from user API viewpoint,
+    but actually they always consist of two fields: major and
+    minor numbers, which are interpreted by kernel specially,
+    that may be used by applications, though not recommended.
+
+    F.e. qdisc handles always have minor number equal to zero,
+    classes (or flows) have major equal to parent qdisc major, and
+    minor uniquely identifying class inside qdisc.
+
+    Macros to manipulate handles:
+ */
+
+#define TC_H_MAJ_MASK (0xFFFF0000U)
+#define TC_H_MIN_MASK (0x0000FFFFU)
+#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
+#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
+#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
+
+#define TC_H_UNSPEC    (0U)
+#define TC_H_ROOT      (0xFFFFFFFFU)
+#define TC_H_INGRESS    (0xFFFFFFF1U)
+#define TC_H_CLSACT    TC_H_INGRESS
+
+#define TC_H_MIN_PRIORITY      0xFFE0U
+#define TC_H_MIN_INGRESS       0xFFF2U
+#define TC_H_MIN_EGRESS                0xFFF3U
+
+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
+enum tc_link_layer {
+       TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */
+       TC_LINKLAYER_ETHERNET,
+       TC_LINKLAYER_ATM,
+};
+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */
+
+struct tc_ratespec {
+       unsigned char   cell_log;
+       __u8            linklayer; /* lower 4 bits */
+       unsigned short  overhead;
+       short           cell_align;
+       unsigned short  mpu;
+       __u32           rate;
+};
+
+#define TC_RTAB_SIZE   1024
+
+struct tc_sizespec {
+       unsigned char   cell_log;
+       unsigned char   size_log;
+       short           cell_align;
+       int             overhead;
+       unsigned int    linklayer;
+       unsigned int    mpu;
+       unsigned int    mtu;
+       unsigned int    tsize;
+};
+
+enum {
+       TCA_STAB_UNSPEC,
+       TCA_STAB_BASE,
+       TCA_STAB_DATA,
+       __TCA_STAB_MAX
+};
+
+#define TCA_STAB_MAX (__TCA_STAB_MAX - 1)
+
+/* FIFO section */
+
+struct tc_fifo_qopt {
+       __u32   limit;  /* Queue length: bytes for bfifo, packets for pfifo */
+};
+
+/* SKBPRIO section */
+
+/*
+ * Priorities go from zero to (SKBPRIO_MAX_PRIORITY - 1).
+ * SKBPRIO_MAX_PRIORITY should be at least 64 in order for skbprio to be able
+ * to map one to one the DS field of IPV4 and IPV6 headers.
+ * Memory allocation grows linearly with SKBPRIO_MAX_PRIORITY.
+ */
+
+#define SKBPRIO_MAX_PRIORITY 64
+
+struct tc_skbprio_qopt {
+       __u32   limit;          /* Queue length in packets. */
+};
+
+/* PRIO section */
+
+#define TCQ_PRIO_BANDS 16
+#define TCQ_MIN_PRIO_BANDS 2
+
+struct tc_prio_qopt {
+       int     bands;                  /* Number of bands */
+       __u8    priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
+};
+
+/* MULTIQ section */
+
+struct tc_multiq_qopt {
+       __u16   bands;                  /* Number of bands */
+       __u16   max_bands;              /* Maximum number of queues */
+};
+
+/* PLUG section */
+
+#define TCQ_PLUG_BUFFER                0
+#define TCQ_PLUG_RELEASE_ONE           1
+#define TCQ_PLUG_RELEASE_INDEFINITE    2
+#define TCQ_PLUG_LIMIT                 3
+
+struct tc_plug_qopt {
+       /* TCQ_PLUG_BUFFER: Inset a plug into the queue and
+        *  buffer any incoming packets
+        * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head
+        *   to beginning of the next plug.
+        * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue.
+        *   Stop buffering packets until the next TCQ_PLUG_BUFFER
+        *   command is received (just act as a pass-thru queue).
+        * TCQ_PLUG_LIMIT: Increase/decrease queue size
+        */
+       int             action;
+       __u32           limit;
+};
+
+/* TBF section */
+
+struct tc_tbf_qopt {
+       struct tc_ratespec rate;
+       struct tc_ratespec peakrate;
+       __u32           limit;
+       __u32           buffer;
+       __u32           mtu;
+};
+
+enum {
+       TCA_TBF_UNSPEC,
+       TCA_TBF_PARMS,
+       TCA_TBF_RTAB,
+       TCA_TBF_PTAB,
+       TCA_TBF_RATE64,
+       TCA_TBF_PRATE64,
+       TCA_TBF_BURST,
+       TCA_TBF_PBURST,
+       TCA_TBF_PAD,
+       __TCA_TBF_MAX,
+};
+
+#define TCA_TBF_MAX (__TCA_TBF_MAX - 1)
+
+
+/* TEQL section */
+
+/* TEQL does not require any parameters */
+
+/* SFQ section */
+
+struct tc_sfq_qopt {
+       unsigned        quantum;        /* Bytes per round allocated to flow */
+       int             perturb_period; /* Period of hash perturbation */
+       __u32           limit;          /* Maximal packets in queue */
+       unsigned        divisor;        /* Hash divisor  */
+       unsigned        flows;          /* Maximal number of flows  */
+};
+
+struct tc_sfqred_stats {
+       __u32           prob_drop;      /* Early drops, below max threshold */
+       __u32           forced_drop;    /* Early drops, after max threshold */
+       __u32           prob_mark;      /* Marked packets, below max threshold */
+       __u32           forced_mark;    /* Marked packets, after max threshold */
+       __u32           prob_mark_head; /* Marked packets, below max threshold */
+       __u32           forced_mark_head;/* Marked packets, after max threshold */
+};
+
+struct tc_sfq_qopt_v1 {
+       struct tc_sfq_qopt v0;
+       unsigned int    depth;          /* max number of packets per flow */
+       unsigned int    headdrop;
+/* SFQRED parameters */
+       __u32           limit;          /* HARD maximal flow queue length (bytes) */
+       __u32           qth_min;        /* Min average length threshold (bytes) */
+       __u32           qth_max;        /* Max average length threshold (bytes) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;
+       __u32           max_P;          /* probability, high resolution */
+/* SFQRED stats */
+       struct tc_sfqred_stats stats;
+};
+
+
+struct tc_sfq_xstats {
+       __s32           allot;
+};
+
+/* RED section */
+
+enum {
+       TCA_RED_UNSPEC,
+       TCA_RED_PARMS,
+       TCA_RED_STAB,
+       TCA_RED_MAX_P,
+       __TCA_RED_MAX,
+};
+
+#define TCA_RED_MAX (__TCA_RED_MAX - 1)
+
+struct tc_red_qopt {
+       __u32           limit;          /* HARD maximal queue length (bytes)    */
+       __u32           qth_min;        /* Min average length threshold (bytes) */
+       __u32           qth_max;        /* Max average length threshold (bytes) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;
+#define TC_RED_ECN             1
+#define TC_RED_HARDDROP                2
+#define TC_RED_ADAPTATIVE      4
+};
+
+struct tc_red_xstats {
+       __u32           early;          /* Early drops */
+       __u32           pdrop;          /* Drops due to queue limits */
+       __u32           other;          /* Drops due to drop() calls */
+       __u32           marked;         /* Marked packets */
+};
+
+/* GRED section */
+
+#define MAX_DPs 16
+
+enum {
+       TCA_GRED_UNSPEC,
+       TCA_GRED_PARMS,
+       TCA_GRED_STAB,
+       TCA_GRED_DPS,
+       TCA_GRED_MAX_P,
+       TCA_GRED_LIMIT,
+       TCA_GRED_VQ_LIST,       /* nested TCA_GRED_VQ_ENTRY */
+       __TCA_GRED_MAX,
+};
+
+#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
+
+enum {
+       TCA_GRED_VQ_ENTRY_UNSPEC,
+       TCA_GRED_VQ_ENTRY,      /* nested TCA_GRED_VQ_* */
+       __TCA_GRED_VQ_ENTRY_MAX,
+};
+#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1)
+
+enum {
+       TCA_GRED_VQ_UNSPEC,
+       TCA_GRED_VQ_PAD,
+       TCA_GRED_VQ_DP,                 /* u32 */
+       TCA_GRED_VQ_STAT_BYTES,         /* u64 */
+       TCA_GRED_VQ_STAT_PACKETS,       /* u32 */
+       TCA_GRED_VQ_STAT_BACKLOG,       /* u32 */
+       TCA_GRED_VQ_STAT_PROB_DROP,     /* u32 */
+       TCA_GRED_VQ_STAT_PROB_MARK,     /* u32 */
+       TCA_GRED_VQ_STAT_FORCED_DROP,   /* u32 */
+       TCA_GRED_VQ_STAT_FORCED_MARK,   /* u32 */
+       TCA_GRED_VQ_STAT_PDROP,         /* u32 */
+       TCA_GRED_VQ_STAT_OTHER,         /* u32 */
+       TCA_GRED_VQ_FLAGS,              /* u32 */
+       __TCA_GRED_VQ_MAX
+};
+
+#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1)
+
+struct tc_gred_qopt {
+       __u32           limit;        /* HARD maximal queue length (bytes)    */
+       __u32           qth_min;      /* Min average length threshold (bytes) */
+       __u32           qth_max;      /* Max average length threshold (bytes) */
+       __u32           DP;           /* up to 2^32 DPs */
+       __u32           backlog;
+       __u32           qave;
+       __u32           forced;
+       __u32           early;
+       __u32           other;
+       __u32           pdrop;
+       __u8            Wlog;         /* log(W)               */
+       __u8            Plog;         /* log(P_max/(qth_max-qth_min)) */
+       __u8            Scell_log;    /* cell size for idle damping */
+       __u8            prio;         /* prio of this VQ */
+       __u32           packets;
+       __u32           bytesin;
+};
+
+/* gred setup */
+struct tc_gred_sopt {
+       __u32           DPs;
+       __u32           def_DP;
+       __u8            grio;
+       __u8            flags;
+       __u16           pad1;
+};
+
+/* CHOKe section */
+
+enum {
+       TCA_CHOKE_UNSPEC,
+       TCA_CHOKE_PARMS,
+       TCA_CHOKE_STAB,
+       TCA_CHOKE_MAX_P,
+       __TCA_CHOKE_MAX,
+};
+
+#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1)
+
+struct tc_choke_qopt {
+       __u32           limit;          /* Hard queue length (packets)  */
+       __u32           qth_min;        /* Min average threshold (packets) */
+       __u32           qth_max;        /* Max average threshold (packets) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;          /* see RED flags */
+};
+
+struct tc_choke_xstats {
+       __u32           early;          /* Early drops */
+       __u32           pdrop;          /* Drops due to queue limits */
+       __u32           other;          /* Drops due to drop() calls */
+       __u32           marked;         /* Marked packets */
+       __u32           matched;        /* Drops due to flow match */
+};
+
+/* HTB section */
+#define TC_HTB_NUMPRIO         8
+#define TC_HTB_MAXDEPTH                8
+#define TC_HTB_PROTOVER                3 /* the same as HTB and TC's major */
+
+struct tc_htb_opt {
+       struct tc_ratespec      rate;
+       struct tc_ratespec      ceil;
+       __u32   buffer;
+       __u32   cbuffer;
+       __u32   quantum;
+       __u32   level;          /* out only */
+       __u32   prio;
+};
+struct tc_htb_glob {
+       __u32 version;          /* to match HTB/TC */
+       __u32 rate2quantum;     /* bps->quantum divisor */
+       __u32 defcls;           /* default class number */
+       __u32 debug;            /* debug flags */
+
+       /* stats */
+       __u32 direct_pkts; /* count of non shaped packets */
+};
+enum {
+       TCA_HTB_UNSPEC,
+       TCA_HTB_PARMS,
+       TCA_HTB_INIT,
+       TCA_HTB_CTAB,
+       TCA_HTB_RTAB,
+       TCA_HTB_DIRECT_QLEN,
+       TCA_HTB_RATE64,
+       TCA_HTB_CEIL64,
+       TCA_HTB_PAD,
+       __TCA_HTB_MAX,
+};
+
+#define TCA_HTB_MAX (__TCA_HTB_MAX - 1)
+
+struct tc_htb_xstats {
+       __u32 lends;
+       __u32 borrows;
+       __u32 giants;   /* unused since 'Make HTB scheduler work with TSO.' */
+       __s32 tokens;
+       __s32 ctokens;
+};
+
+/* HFSC section */
+
+struct tc_hfsc_qopt {
+       __u16   defcls;         /* default class */
+};
+
+struct tc_service_curve {
+       __u32   m1;             /* slope of the first segment in bps */
+       __u32   d;              /* x-projection of the first segment in us */
+       __u32   m2;             /* slope of the second segment in bps */
+};
+
+struct tc_hfsc_stats {
+       __u64   work;           /* total work done */
+       __u64   rtwork;         /* work done by real-time criteria */
+       __u32   period;         /* current period */
+       __u32   level;          /* class level in hierarchy */
+};
+
+enum {
+       TCA_HFSC_UNSPEC,
+       TCA_HFSC_RSC,
+       TCA_HFSC_FSC,
+       TCA_HFSC_USC,
+       __TCA_HFSC_MAX,
+};
+
+#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1)
+
+
+/* CBQ section */
+
+#define TC_CBQ_MAXPRIO         8
+#define TC_CBQ_MAXLEVEL                8
+#define TC_CBQ_DEF_EWMA                5
+
+struct tc_cbq_lssopt {
+       unsigned char   change;
+       unsigned char   flags;
+#define TCF_CBQ_LSS_BOUNDED    1
+#define TCF_CBQ_LSS_ISOLATED   2
+       unsigned char   ewma_log;
+       unsigned char   level;
+#define TCF_CBQ_LSS_FLAGS      1
+#define TCF_CBQ_LSS_EWMA       2
+#define TCF_CBQ_LSS_MAXIDLE    4
+#define TCF_CBQ_LSS_MINIDLE    8
+#define TCF_CBQ_LSS_OFFTIME    0x10
+#define TCF_CBQ_LSS_AVPKT      0x20
+       __u32           maxidle;
+       __u32           minidle;
+       __u32           offtime;
+       __u32           avpkt;
+};
+
+struct tc_cbq_wrropt {
+       unsigned char   flags;
+       unsigned char   priority;
+       unsigned char   cpriority;
+       unsigned char   __reserved;
+       __u32           allot;
+       __u32           weight;
+};
+
+struct tc_cbq_ovl {
+       unsigned char   strategy;
+#define        TC_CBQ_OVL_CLASSIC      0
+#define        TC_CBQ_OVL_DELAY        1
+#define        TC_CBQ_OVL_LOWPRIO      2
+#define        TC_CBQ_OVL_DROP         3
+#define        TC_CBQ_OVL_RCLASSIC     4
+       unsigned char   priority2;
+       __u16           pad;
+       __u32           penalty;
+};
+
+struct tc_cbq_police {
+       unsigned char   police;
+       unsigned char   __res1;
+       unsigned short  __res2;
+};
+
+struct tc_cbq_fopt {
+       __u32           split;
+       __u32           defmap;
+       __u32           defchange;
+};
+
+struct tc_cbq_xstats {
+       __u32           borrows;
+       __u32           overactions;
+       __s32           avgidle;
+       __s32           undertime;
+};
+
+enum {
+       TCA_CBQ_UNSPEC,
+       TCA_CBQ_LSSOPT,
+       TCA_CBQ_WRROPT,
+       TCA_CBQ_FOPT,
+       TCA_CBQ_OVL_STRATEGY,
+       TCA_CBQ_RATE,
+       TCA_CBQ_RTAB,
+       TCA_CBQ_POLICE,
+       __TCA_CBQ_MAX,
+};
+
+#define TCA_CBQ_MAX    (__TCA_CBQ_MAX - 1)
+
+/* dsmark section */
+
+enum {
+       TCA_DSMARK_UNSPEC,
+       TCA_DSMARK_INDICES,
+       TCA_DSMARK_DEFAULT_INDEX,
+       TCA_DSMARK_SET_TC_INDEX,
+       TCA_DSMARK_MASK,
+       TCA_DSMARK_VALUE,
+       __TCA_DSMARK_MAX,
+};
+
+#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1)
+
+/* ATM  section */
+
+enum {
+       TCA_ATM_UNSPEC,
+       TCA_ATM_FD,             /* file/socket descriptor */
+       TCA_ATM_PTR,            /* pointer to descriptor - later */
+       TCA_ATM_HDR,            /* LL header */
+       TCA_ATM_EXCESS,         /* excess traffic class (0 for CLP)  */
+       TCA_ATM_ADDR,           /* PVC address (for output only) */
+       TCA_ATM_STATE,          /* VC state (ATM_VS_*; for output only) */
+       __TCA_ATM_MAX,
+};
+
+#define TCA_ATM_MAX    (__TCA_ATM_MAX - 1)
+
+/* Network emulator */
+
+enum {
+       TCA_NETEM_UNSPEC,
+       TCA_NETEM_CORR,
+       TCA_NETEM_DELAY_DIST,
+       TCA_NETEM_REORDER,
+       TCA_NETEM_CORRUPT,
+       TCA_NETEM_LOSS,
+       TCA_NETEM_RATE,
+       TCA_NETEM_ECN,
+       TCA_NETEM_RATE64,
+       TCA_NETEM_PAD,
+       TCA_NETEM_LATENCY64,
+       TCA_NETEM_JITTER64,
+       TCA_NETEM_SLOT,
+       TCA_NETEM_SLOT_DIST,
+       __TCA_NETEM_MAX,
+};
+
+#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1)
+
+struct tc_netem_qopt {
+       __u32   latency;        /* added delay (us) */
+       __u32   limit;          /* fifo limit (packets) */
+       __u32   loss;           /* random packet loss (0=none ~0=100%) */
+       __u32   gap;            /* re-ordering gap (0 for none) */
+       __u32   duplicate;      /* random packet dup  (0=none ~0=100%) */
+       __u32   jitter;         /* random jitter in latency (us) */
+};
+
+struct tc_netem_corr {
+       __u32   delay_corr;     /* delay correlation */
+       __u32   loss_corr;      /* packet loss correlation */
+       __u32   dup_corr;       /* duplicate correlation  */
+};
+
+struct tc_netem_reorder {
+       __u32   probability;
+       __u32   correlation;
+};
+
+struct tc_netem_corrupt {
+       __u32   probability;
+       __u32   correlation;
+};
+
+struct tc_netem_rate {
+       __u32   rate;   /* byte/s */
+       __s32   packet_overhead;
+       __u32   cell_size;
+       __s32   cell_overhead;
+};
+
+struct tc_netem_slot {
+       __s64   min_delay; /* nsec */
+       __s64   max_delay;
+       __s32   max_packets;
+       __s32   max_bytes;
+       __s64   dist_delay; /* nsec */
+       __s64   dist_jitter; /* nsec */
+};
+
+enum {
+       NETEM_LOSS_UNSPEC,
+       NETEM_LOSS_GI,          /* General Intuitive - 4 state model */
+       NETEM_LOSS_GE,          /* Gilbert Elliot models */
+       __NETEM_LOSS_MAX
+};
+#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
+
+/* State transition probabilities for 4 state model */
+struct tc_netem_gimodel {
+       __u32   p13;
+       __u32   p31;
+       __u32   p32;
+       __u32   p14;
+       __u32   p23;
+};
+
+/* Gilbert-Elliot models */
+struct tc_netem_gemodel {
+       __u32 p;
+       __u32 r;
+       __u32 h;
+       __u32 k1;
+};
+
+#define NETEM_DIST_SCALE       8192
+#define NETEM_DIST_MAX         16384
+
+/* DRR */
+
+enum {
+       TCA_DRR_UNSPEC,
+       TCA_DRR_QUANTUM,
+       __TCA_DRR_MAX
+};
+
+#define TCA_DRR_MAX    (__TCA_DRR_MAX - 1)
+
+struct tc_drr_stats {
+       __u32   deficit;
+};
+
+/* MQPRIO */
+#define TC_QOPT_BITMASK 15
+#define TC_QOPT_MAX_QUEUE 16
+
+enum {
+       TC_MQPRIO_HW_OFFLOAD_NONE,      /* no offload requested */
+       TC_MQPRIO_HW_OFFLOAD_TCS,       /* offload TCs, no queue counts */
+       __TC_MQPRIO_HW_OFFLOAD_MAX
+};
+
+#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
+
+enum {
+       TC_MQPRIO_MODE_DCB,
+       TC_MQPRIO_MODE_CHANNEL,
+       __TC_MQPRIO_MODE_MAX
+};
+
+#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1)
+
+enum {
+       TC_MQPRIO_SHAPER_DCB,
+       TC_MQPRIO_SHAPER_BW_RATE,       /* Add new shapers below */
+       __TC_MQPRIO_SHAPER_MAX
+};
+
+#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
+
+struct tc_mqprio_qopt {
+       __u8    num_tc;
+       __u8    prio_tc_map[TC_QOPT_BITMASK + 1];
+       __u8    hw;
+       __u16   count[TC_QOPT_MAX_QUEUE];
+       __u16   offset[TC_QOPT_MAX_QUEUE];
+};
+
+#define TC_MQPRIO_F_MODE               0x1
+#define TC_MQPRIO_F_SHAPER             0x2
+#define TC_MQPRIO_F_MIN_RATE           0x4
+#define TC_MQPRIO_F_MAX_RATE           0x8
+
+enum {
+       TCA_MQPRIO_UNSPEC,
+       TCA_MQPRIO_MODE,
+       TCA_MQPRIO_SHAPER,
+       TCA_MQPRIO_MIN_RATE64,
+       TCA_MQPRIO_MAX_RATE64,
+       __TCA_MQPRIO_MAX,
+};
+
+#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1)
+
+/* SFB */
+
+enum {
+       TCA_SFB_UNSPEC,
+       TCA_SFB_PARMS,
+       __TCA_SFB_MAX,
+};
+
+#define TCA_SFB_MAX (__TCA_SFB_MAX - 1)
+
+/*
+ * Note: increment, decrement are Q0.16 fixed-point values.
+ */
+struct tc_sfb_qopt {
+       __u32 rehash_interval;  /* delay between hash move, in ms */
+       __u32 warmup_time;      /* double buffering warmup time in ms (warmup_time < rehash_interval) */
+       __u32 max;              /* max len of qlen_min */
+       __u32 bin_size;         /* maximum queue length per bin */
+       __u32 increment;        /* probability increment, (d1 in Blue) */
+       __u32 decrement;        /* probability decrement, (d2 in Blue) */
+       __u32 limit;            /* max SFB queue length */
+       __u32 penalty_rate;     /* inelastic flows are rate limited to 'rate' pps */
+       __u32 penalty_burst;
+};
+
+struct tc_sfb_xstats {
+       __u32 earlydrop;
+       __u32 penaltydrop;
+       __u32 bucketdrop;
+       __u32 queuedrop;
+       __u32 childdrop; /* drops in child qdisc */
+       __u32 marked;
+       __u32 maxqlen;
+       __u32 maxprob;
+       __u32 avgprob;
+};
+
+#define SFB_MAX_PROB 0xFFFF
+
+/* QFQ */
+enum {
+       TCA_QFQ_UNSPEC,
+       TCA_QFQ_WEIGHT,
+       TCA_QFQ_LMAX,
+       __TCA_QFQ_MAX
+};
+
+#define TCA_QFQ_MAX    (__TCA_QFQ_MAX - 1)
+
+struct tc_qfq_stats {
+       __u32 weight;
+       __u32 lmax;
+};
+
+/* CODEL */
+
+enum {
+       TCA_CODEL_UNSPEC,
+       TCA_CODEL_TARGET,
+       TCA_CODEL_LIMIT,
+       TCA_CODEL_INTERVAL,
+       TCA_CODEL_ECN,
+       TCA_CODEL_CE_THRESHOLD,
+       __TCA_CODEL_MAX
+};
+
+#define TCA_CODEL_MAX  (__TCA_CODEL_MAX - 1)
+
+struct tc_codel_xstats {
+       __u32   maxpacket; /* largest packet we've seen so far */
+       __u32   count;     /* how many drops we've done since the last time we
+                           * entered dropping state
+                           */
+       __u32   lastcount; /* count at entry to dropping state */
+       __u32   ldelay;    /* in-queue delay seen by most recently dequeued packet */
+       __s32   drop_next; /* time to drop next packet */
+       __u32   drop_overlimit; /* number of time max qdisc packet limit was hit */
+       __u32   ecn_mark;  /* number of packets we ECN marked instead of dropped */
+       __u32   dropping;  /* are we in dropping state ? */
+       __u32   ce_mark;   /* number of CE marked packets because of ce_threshold */
+};
+
+/* FQ_CODEL */
+
+enum {
+       TCA_FQ_CODEL_UNSPEC,
+       TCA_FQ_CODEL_TARGET,
+       TCA_FQ_CODEL_LIMIT,
+       TCA_FQ_CODEL_INTERVAL,
+       TCA_FQ_CODEL_ECN,
+       TCA_FQ_CODEL_FLOWS,
+       TCA_FQ_CODEL_QUANTUM,
+       TCA_FQ_CODEL_CE_THRESHOLD,
+       TCA_FQ_CODEL_DROP_BATCH_SIZE,
+       TCA_FQ_CODEL_MEMORY_LIMIT,
+       __TCA_FQ_CODEL_MAX
+};
+
+#define TCA_FQ_CODEL_MAX       (__TCA_FQ_CODEL_MAX - 1)
+
+enum {
+       TCA_FQ_CODEL_XSTATS_QDISC,
+       TCA_FQ_CODEL_XSTATS_CLASS,
+};
+
+struct tc_fq_codel_qd_stats {
+       __u32   maxpacket;      /* largest packet we've seen so far */
+       __u32   drop_overlimit; /* number of time max qdisc
+                                * packet limit was hit
+                                */
+       __u32   ecn_mark;       /* number of packets we ECN marked
+                                * instead of being dropped
+                                */
+       __u32   new_flow_count; /* number of time packets
+                                * created a 'new flow'
+                                */
+       __u32   new_flows_len;  /* count of flows in new list */
+       __u32   old_flows_len;  /* count of flows in old list */
+       __u32   ce_mark;        /* packets above ce_threshold */
+       __u32   memory_usage;   /* in bytes */
+       __u32   drop_overmemory;
+};
+
+struct tc_fq_codel_cl_stats {
+       __s32   deficit;
+       __u32   ldelay;         /* in-queue delay seen by most recently
+                                * dequeued packet
+                                */
+       __u32   count;
+       __u32   lastcount;
+       __u32   dropping;
+       __s32   drop_next;
+};
+
+struct tc_fq_codel_xstats {
+       __u32   type;
+       union {
+               struct tc_fq_codel_qd_stats qdisc_stats;
+               struct tc_fq_codel_cl_stats class_stats;
+       };
+};
+
+/* FQ */
+
+enum {
+       TCA_FQ_UNSPEC,
+
+       TCA_FQ_PLIMIT,          /* limit of total number of packets in queue */
+
+       TCA_FQ_FLOW_PLIMIT,     /* limit of packets per flow */
+
+       TCA_FQ_QUANTUM,         /* RR quantum */
+
+       TCA_FQ_INITIAL_QUANTUM,         /* RR quantum for new flow */
+
+       TCA_FQ_RATE_ENABLE,     /* enable/disable rate limiting */
+
+       TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */
+
+       TCA_FQ_FLOW_MAX_RATE,   /* per flow max rate */
+
+       TCA_FQ_BUCKETS_LOG,     /* log2(number of buckets) */
+
+       TCA_FQ_FLOW_REFILL_DELAY,       /* flow credit refill delay in usec */
+
+       TCA_FQ_ORPHAN_MASK,     /* mask applied to orphaned skb hashes */
+
+       TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */
+
+       TCA_FQ_CE_THRESHOLD,    /* DCTCP-like CE-marking threshold */
+
+       __TCA_FQ_MAX
+};
+
+#define TCA_FQ_MAX     (__TCA_FQ_MAX - 1)
+
+struct tc_fq_qd_stats {
+       __u64   gc_flows;
+       __u64   highprio_packets;
+       __u64   tcp_retrans;
+       __u64   throttled;
+       __u64   flows_plimit;
+       __u64   pkts_too_long;
+       __u64   allocation_errors;
+       __s64   time_next_delayed_flow;
+       __u32   flows;
+       __u32   inactive_flows;
+       __u32   throttled_flows;
+       __u32   unthrottle_latency_ns;
+       __u64   ce_mark;                /* packets above ce_threshold */
+};
+
+/* Heavy-Hitter Filter */
+
+enum {
+       TCA_HHF_UNSPEC,
+       TCA_HHF_BACKLOG_LIMIT,
+       TCA_HHF_QUANTUM,
+       TCA_HHF_HH_FLOWS_LIMIT,
+       TCA_HHF_RESET_TIMEOUT,
+       TCA_HHF_ADMIT_BYTES,
+       TCA_HHF_EVICT_TIMEOUT,
+       TCA_HHF_NON_HH_WEIGHT,
+       __TCA_HHF_MAX
+};
+
+#define TCA_HHF_MAX    (__TCA_HHF_MAX - 1)
+
+struct tc_hhf_xstats {
+       __u32   drop_overlimit; /* number of times max qdisc packet limit
+                                * was hit
+                                */
+       __u32   hh_overlimit;   /* number of times max heavy-hitters was hit */
+       __u32   hh_tot_count;   /* number of captured heavy-hitters so far */
+       __u32   hh_cur_count;   /* number of current heavy-hitters */
+};
+
+/* PIE */
+enum {
+       TCA_PIE_UNSPEC,
+       TCA_PIE_TARGET,
+       TCA_PIE_LIMIT,
+       TCA_PIE_TUPDATE,
+       TCA_PIE_ALPHA,
+       TCA_PIE_BETA,
+       TCA_PIE_ECN,
+       TCA_PIE_BYTEMODE,
+       __TCA_PIE_MAX
+};
+#define TCA_PIE_MAX   (__TCA_PIE_MAX - 1)
+
+struct tc_pie_xstats {
+       __u32 prob;             /* current probability */
+       __u32 delay;            /* current delay in ms */
+       __u32 avg_dq_rate;      /* current average dq_rate in bits/pie_time */
+       __u32 packets_in;       /* total number of packets enqueued */
+       __u32 dropped;          /* packets dropped due to pie_action */
+       __u32 overlimit;        /* dropped due to lack of space in queue */
+       __u32 maxq;             /* maximum queue size */
+       __u32 ecn_mark;         /* packets marked with ecn*/
+};
+
+/* CBS */
+struct tc_cbs_qopt {
+       __u8 offload;
+       __u8 _pad[3];
+       __s32 hicredit;
+       __s32 locredit;
+       __s32 idleslope;
+       __s32 sendslope;
+};
+
+enum {
+       TCA_CBS_UNSPEC,
+       TCA_CBS_PARMS,
+       __TCA_CBS_MAX,
+};
+
+#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+
+
+/* ETF */
+struct tc_etf_qopt {
+       __s32 delta;
+       __s32 clockid;
+       __u32 flags;
+#define TC_ETF_DEADLINE_MODE_ON        BIT(0)
+#define TC_ETF_OFFLOAD_ON      BIT(1)
+};
+
+enum {
+       TCA_ETF_UNSPEC,
+       TCA_ETF_PARMS,
+       __TCA_ETF_MAX,
+};
+
+#define TCA_ETF_MAX (__TCA_ETF_MAX - 1)
+
+
+/* CAKE */
+enum {
+       TCA_CAKE_UNSPEC,
+       TCA_CAKE_PAD,
+       TCA_CAKE_BASE_RATE64,
+       TCA_CAKE_DIFFSERV_MODE,
+       TCA_CAKE_ATM,
+       TCA_CAKE_FLOW_MODE,
+       TCA_CAKE_OVERHEAD,
+       TCA_CAKE_RTT,
+       TCA_CAKE_TARGET,
+       TCA_CAKE_AUTORATE,
+       TCA_CAKE_MEMORY,
+       TCA_CAKE_NAT,
+       TCA_CAKE_RAW,
+       TCA_CAKE_WASH,
+       TCA_CAKE_MPU,
+       TCA_CAKE_INGRESS,
+       TCA_CAKE_ACK_FILTER,
+       TCA_CAKE_SPLIT_GSO,
+       __TCA_CAKE_MAX
+};
+#define TCA_CAKE_MAX   (__TCA_CAKE_MAX - 1)
+
+enum {
+       __TCA_CAKE_STATS_INVALID,
+       TCA_CAKE_STATS_PAD,
+       TCA_CAKE_STATS_CAPACITY_ESTIMATE64,
+       TCA_CAKE_STATS_MEMORY_LIMIT,
+       TCA_CAKE_STATS_MEMORY_USED,
+       TCA_CAKE_STATS_AVG_NETOFF,
+       TCA_CAKE_STATS_MIN_NETLEN,
+       TCA_CAKE_STATS_MAX_NETLEN,
+       TCA_CAKE_STATS_MIN_ADJLEN,
+       TCA_CAKE_STATS_MAX_ADJLEN,
+       TCA_CAKE_STATS_TIN_STATS,
+       TCA_CAKE_STATS_DEFICIT,
+       TCA_CAKE_STATS_COBALT_COUNT,
+       TCA_CAKE_STATS_DROPPING,
+       TCA_CAKE_STATS_DROP_NEXT_US,
+       TCA_CAKE_STATS_P_DROP,
+       TCA_CAKE_STATS_BLUE_TIMER_US,
+       __TCA_CAKE_STATS_MAX
+};
+#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
+
+enum {
+       __TCA_CAKE_TIN_STATS_INVALID,
+       TCA_CAKE_TIN_STATS_PAD,
+       TCA_CAKE_TIN_STATS_SENT_PACKETS,
+       TCA_CAKE_TIN_STATS_SENT_BYTES64,
+       TCA_CAKE_TIN_STATS_DROPPED_PACKETS,
+       TCA_CAKE_TIN_STATS_DROPPED_BYTES64,
+       TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS,
+       TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64,
+       TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS,
+       TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64,
+       TCA_CAKE_TIN_STATS_BACKLOG_PACKETS,
+       TCA_CAKE_TIN_STATS_BACKLOG_BYTES,
+       TCA_CAKE_TIN_STATS_THRESHOLD_RATE64,
+       TCA_CAKE_TIN_STATS_TARGET_US,
+       TCA_CAKE_TIN_STATS_INTERVAL_US,
+       TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS,
+       TCA_CAKE_TIN_STATS_WAY_MISSES,
+       TCA_CAKE_TIN_STATS_WAY_COLLISIONS,
+       TCA_CAKE_TIN_STATS_PEAK_DELAY_US,
+       TCA_CAKE_TIN_STATS_AVG_DELAY_US,
+       TCA_CAKE_TIN_STATS_BASE_DELAY_US,
+       TCA_CAKE_TIN_STATS_SPARSE_FLOWS,
+       TCA_CAKE_TIN_STATS_BULK_FLOWS,
+       TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS,
+       TCA_CAKE_TIN_STATS_MAX_SKBLEN,
+       TCA_CAKE_TIN_STATS_FLOW_QUANTUM,
+       __TCA_CAKE_TIN_STATS_MAX
+};
+#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1)
+#define TC_CAKE_MAX_TINS (8)
+
+enum {
+       CAKE_FLOW_NONE = 0,
+       CAKE_FLOW_SRC_IP,
+       CAKE_FLOW_DST_IP,
+       CAKE_FLOW_HOSTS,    /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */
+       CAKE_FLOW_FLOWS,
+       CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_TRIPLE,   /* = CAKE_FLOW_HOSTS  | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_MAX,
+};
+
+enum {
+       CAKE_DIFFSERV_DIFFSERV3 = 0,
+       CAKE_DIFFSERV_DIFFSERV4,
+       CAKE_DIFFSERV_DIFFSERV8,
+       CAKE_DIFFSERV_BESTEFFORT,
+       CAKE_DIFFSERV_PRECEDENCE,
+       CAKE_DIFFSERV_MAX
+};
+
+enum {
+       CAKE_ACK_NONE = 0,
+       CAKE_ACK_FILTER,
+       CAKE_ACK_AGGRESSIVE,
+       CAKE_ACK_MAX
+};
+
+enum {
+       CAKE_ATM_NONE = 0,
+       CAKE_ATM_ATM,
+       CAKE_ATM_PTM,
+       CAKE_ATM_MAX
+};
+
+
+/* TAPRIO */
+enum {
+       TC_TAPRIO_CMD_SET_GATES = 0x00,
+       TC_TAPRIO_CMD_SET_AND_HOLD = 0x01,
+       TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02,
+};
+
+enum {
+       TCA_TAPRIO_SCHED_ENTRY_UNSPEC,
+       TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */
+       TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */
+       TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */
+       TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */
+       __TCA_TAPRIO_SCHED_ENTRY_MAX,
+};
+#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1)
+
+/* The format for schedule entry list is:
+ * [TCA_TAPRIO_SCHED_ENTRY_LIST]
+ *   [TCA_TAPRIO_SCHED_ENTRY]
+ *     [TCA_TAPRIO_SCHED_ENTRY_CMD]
+ *     [TCA_TAPRIO_SCHED_ENTRY_GATES]
+ *     [TCA_TAPRIO_SCHED_ENTRY_INTERVAL]
+ */
+enum {
+       TCA_TAPRIO_SCHED_UNSPEC,
+       TCA_TAPRIO_SCHED_ENTRY,
+       __TCA_TAPRIO_SCHED_MAX,
+};
+
+#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
+
+enum {
+       TCA_TAPRIO_ATTR_UNSPEC,
+       TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
+       TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */
+       TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */
+       TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
+       TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
+       TCA_TAPRIO_PAD,
+       __TCA_TAPRIO_ATTR_MAX,
+};
+
+#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
+
+#endif
index f81e549ddfdb18e6e3c86d063bb131cfcbadb810..4db74758c6743e2a32800eef302f9cdeddc8a2ee 100644 (file)
@@ -1,2 +1,3 @@
 libbpf_version.h
 FEATURE-DUMP.libbpf
+test_libbpf
index 056f383107226082d5a7e693f8f888651a84520b..607aae40f4edaa95514bc76403ea42d8ed580748 100644 (file)
@@ -132,6 +132,20 @@ For example, if current state of ``libbpf.map`` is:
 Format of version script and ways to handle ABI changes, including
 incompatible ones, described in details in [1].
 
+Stand-alone build
+=================
+
+Under https://github.com/libbpf/libbpf there is a (semi-)automated
+mirror of the mainline's version of libbpf for a stand-alone build.
+
+However, all changes to libbpf's code base must be upstreamed through
+the mainline kernel tree.
+
+License
+=======
+
+libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause.
+
 Links
 =====
 
index 3caaa3428774427e451b50a682845b5ceb8eba18..88cbd110ae5807091b2a1c7b5227abd1940d996f 100644 (file)
@@ -65,6 +65,17 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
        return syscall(__NR_bpf, cmd, attr, size);
 }
 
+static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
+{
+       int fd;
+
+       do {
+               fd = sys_bpf(BPF_PROG_LOAD, attr, size);
+       } while (fd < 0 && errno == EAGAIN);
+
+       return fd;
+}
+
 int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
 {
        __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0;
@@ -232,7 +243,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        memcpy(attr.prog_name, load_attr->name,
               min(name_len, BPF_OBJ_NAME_LEN - 1));
 
-       fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       fd = sys_bpf_prog_load(&attr, sizeof(attr));
        if (fd >= 0)
                return fd;
 
@@ -269,7 +280,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
                        break;
                }
 
-               fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+               fd = sys_bpf_prog_load(&attr, sizeof(attr));
 
                if (fd >= 0)
                        goto done;
@@ -283,7 +294,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        attr.log_size = log_buf_sz;
        attr.log_level = 1;
        log_buf[0] = 0;
-       fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       fd = sys_bpf_prog_load(&attr, sizeof(attr));
 done:
        free(finfo);
        free(linfo);
@@ -328,7 +339,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
        attr.kern_version = kern_version;
        attr.prog_flags = prog_flags;
 
-       return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       return sys_bpf_prog_load(&attr, sizeof(attr));
 }
 
 int bpf_map_update_elem(int fd, const void *key, const void *value,
index 095aebdc5bb733d5a0615e67f60f4069ac1a0135..e6150f21267d69a8ec8e34b9d14b8bb91701bf74 100644 (file)
@@ -19,8 +19,11 @@ C2C stands for Cache To Cache.
 The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows
 you to track down the cacheline contentions.
 
-The tool is based on x86's load latency and precise store facility events
-provided by Intel CPUs. These events provide:
+On x86, the tool is based on load latency and precise store facility events
+provided by Intel CPUs. On PowerPC, the tool uses random instruction sampling
+with thresholding feature.
+
+These events provide:
   - memory address of the access
   - type of the access (load and store details)
   - latency (in cycles) of the load access
@@ -46,7 +49,7 @@ RECORD OPTIONS
 
 -l::
 --ldlat::
-       Configure mem-loads latency.
+       Configure mem-loads latency. (x86 only)
 
 -k::
 --all-kernel::
@@ -119,11 +122,16 @@ Following perf record options are configured by default:
   -W,-d,--phys-data,--sample-cpu
 
 Unless specified otherwise with '-e' option, following events are monitored by
-default:
+default on x86:
 
   cpu/mem-loads,ldlat=30/P
   cpu/mem-stores/P
 
+and following on PowerPC:
+
+  cpu/mem-loads/
+  cpu/mem-stores/
+
 User can pass any 'perf record' option behind '--' mark, like (to enable
 callchains and system wide monitoring):
 
index f8d2167cf3e7a2221b8688aff0f0fa55968db369..199ea0f0a6c0c41f64ed91f7ffb1ad3d402a1160 100644 (file)
@@ -82,7 +82,7 @@ RECORD OPTIONS
        Be more verbose (show counter open errors, etc)
 
 --ldlat <n>::
-       Specify desired latency for loads event.
+       Specify desired latency for loads event. (x86 only)
 
 In addition, for report all perf report options are valid, and for record
 all perf record options.
index 1076393e6f43e2ef1d694918ba433ea625339263..e18a3556f5e315849854bc9fe6a8f42c52cd64f6 100644 (file)
@@ -63,7 +63,8 @@ static const char *reg_names[] = {
        [PERF_REG_POWERPC_TRAP] = "trap",
        [PERF_REG_POWERPC_DAR] = "dar",
        [PERF_REG_POWERPC_DSISR] = "dsisr",
-       [PERF_REG_POWERPC_SIER] = "sier"
+       [PERF_REG_POWERPC_SIER] = "sier",
+       [PERF_REG_POWERPC_MMCRA] = "mmcra"
 };
 
 static inline const char *perf_reg_name(int id)
index 2e6595310420104a40fe4ee813f41ee0bc213349..ba98bd00648809f6d1b1bddf9ade824a59af3e90 100644 (file)
@@ -2,6 +2,7 @@ libperf-y += header.o
 libperf-y += sym-handling.o
 libperf-y += kvm-stat.o
 libperf-y += perf_regs.o
+libperf-y += mem-events.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/mem-events.c b/tools/perf/arch/powerpc/util/mem-events.c
new file mode 100644 (file)
index 0000000..d08311f
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "mem-events.h"
+
+/* PowerPC does not support 'ldlat' parameter. */
+char *perf_mem_events__name(int i)
+{
+       if (i == PERF_MEM_EVENTS__LOAD)
+               return (char *) "cpu/mem-loads/";
+
+       return (char *) "cpu/mem-stores/";
+}
index 07fcd977d93e4e713c3492274c77f4b70606fa08..34d5134681d96c9716ed1937f835a3b125d6dfa5 100644 (file)
@@ -53,6 +53,7 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dar, PERF_REG_POWERPC_DAR),
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG(sier, PERF_REG_POWERPC_SIER),
+       SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
        SMPL_REG_END
 };
 
index d079f36d342d4ca6024b46a52de349b1ea95ac4a..ac221f137ed2aa96665add3861d5a2655e8c18c6 100644 (file)
@@ -1681,13 +1681,8 @@ static void perf_sample__fprint_metric(struct perf_script *script,
                .force_header = false,
        };
        struct perf_evsel *ev2;
-       static bool init;
        u64 val;
 
-       if (!init) {
-               perf_stat__init_shadow_stats();
-               init = true;
-       }
        if (!evsel->stats)
                perf_evlist__alloc_stats(script->session->evlist, false);
        if (evsel_script(evsel->leader)->gnum++ == 0)
@@ -1794,7 +1789,7 @@ static void process_event(struct perf_script *script,
                return;
        }
 
-       if (PRINT_FIELD(TRACE)) {
+       if (PRINT_FIELD(TRACE) && sample->raw_data) {
                event_format__fprintf(evsel->tp_format, sample->cpu,
                                      sample->raw_data, sample->raw_size, fp);
        }
@@ -2359,6 +2354,8 @@ static int __cmd_script(struct perf_script *script)
 
        signal(SIGINT, sig_handler);
 
+       perf_stat__init_shadow_stats();
+
        /* override event processing functions */
        if (script->show_task_events) {
                script->tool.comm = process_comm_event;
index ed4583128b9ce2bd17a25c105c908a38f28a8eed..b36061cd1ab86887af34ef8cc345419b9cebc238 100644 (file)
@@ -2514,19 +2514,30 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
 
 static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
 {
-       struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
+       bool found = false;
+       struct perf_evsel *evsel, *tmp;
+       struct parse_events_error err = { .idx = 0, };
+       int ret = parse_events(evlist, "probe:vfs_getname*", &err);
 
-       if (IS_ERR(evsel))
+       if (ret)
                return false;
 
-       if (perf_evsel__field(evsel, "pathname") == NULL) {
+       evlist__for_each_entry_safe(evlist, evsel, tmp) {
+               if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname"))
+                       continue;
+
+               if (perf_evsel__field(evsel, "pathname")) {
+                       evsel->handler = trace__vfs_getname;
+                       found = true;
+                       continue;
+               }
+
+               list_del_init(&evsel->node);
+               evsel->evlist = NULL;
                perf_evsel__delete(evsel);
-               return false;
        }
 
-       evsel->handler = trace__vfs_getname;
-       perf_evlist__add(evlist, evsel);
-       return true;
+       return found;
 }
 
 static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
index 44090a9a19f3b9f33b0ae8eee972941a919fca4c..e952127e4fb0b453eab36540d9dff023128edf02 100644 (file)
@@ -1,6 +1,8 @@
 #! /usr/bin/python
 # SPDX-License-Identifier: GPL-2.0
 
+from __future__ import print_function
+
 import os
 import sys
 import glob
@@ -8,7 +10,11 @@ import optparse
 import tempfile
 import logging
 import shutil
-import ConfigParser
+
+try:
+    import configparser
+except ImportError:
+    import ConfigParser as configparser
 
 def data_equal(a, b):
     # Allow multiple values in assignment separated by '|'
@@ -100,20 +106,20 @@ class Event(dict):
     def equal(self, other):
         for t in Event.terms:
             log.debug("      [%s] %s %s" % (t, self[t], other[t]));
-            if not self.has_key(t) or not other.has_key(t):
+            if t not in self or t not in other:
                 return False
             if not data_equal(self[t], other[t]):
                 return False
         return True
 
     def optional(self):
-        if self.has_key('optional') and self['optional'] == '1':
+        if 'optional' in self and self['optional'] == '1':
             return True
         return False
 
     def diff(self, other):
         for t in Event.terms:
-            if not self.has_key(t) or not other.has_key(t):
+            if t not in self or t not in other:
                 continue
             if not data_equal(self[t], other[t]):
                 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
@@ -134,7 +140,7 @@ class Event(dict):
 #   - expected values assignments
 class Test(object):
     def __init__(self, path, options):
-        parser = ConfigParser.SafeConfigParser()
+        parser = configparser.SafeConfigParser()
         parser.read(path)
 
         log.warning("running '%s'" % path)
@@ -193,7 +199,7 @@ class Test(object):
         return True
 
     def load_events(self, path, events):
-        parser_event = ConfigParser.SafeConfigParser()
+        parser_event = configparser.SafeConfigParser()
         parser_event.read(path)
 
         # The event record section header contains 'event' word,
@@ -207,7 +213,7 @@ class Test(object):
             # Read parent event if there's any
             if (':' in section):
                 base = section[section.index(':') + 1:]
-                parser_base = ConfigParser.SafeConfigParser()
+                parser_base = configparser.SafeConfigParser()
                 parser_base.read(self.test_dir + '/' + base)
                 base_items = parser_base.items('event')
 
@@ -322,9 +328,9 @@ def run_tests(options):
     for f in glob.glob(options.test_dir + '/' + options.test):
         try:
             Test(f, options).run()
-        except Unsup, obj:
+        except Unsup as obj:
             log.warning("unsupp  %s" % obj.getMsg())
-        except Notest, obj:
+        except Notest as obj:
             log.warning("skipped %s" % obj.getMsg())
 
 def setup_log(verbose):
@@ -363,7 +369,7 @@ def main():
     parser.add_option("-p", "--perf",
                       action="store", type="string", dest="perf")
     parser.add_option("-v", "--verbose",
-                      action="count", dest="verbose")
+                      default=0, action="count", dest="verbose")
 
     options, args = parser.parse_args()
     if args:
@@ -373,7 +379,7 @@ def main():
     setup_log(options.verbose)
 
     if not options.test_dir:
-        print 'FAILED no -d option specified'
+        print('FAILED no -d option specified')
         sys.exit(-1)
 
     if not options.test:
@@ -382,8 +388,8 @@ def main():
     try:
         run_tests(options)
 
-    except Fail, obj:
-        print "FAILED %s" % obj.getMsg();
+    except Fail as obj:
+        print("FAILED %s" % obj.getMsg())
         sys.exit(-1)
 
     sys.exit(0)
index 5f8501c68da49d56d8dee911b1760cbcb17d2d99..5cbba70bcdd0b5ff19c913ade3032f4a858dfe94 100644 (file)
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
                return -1;
        }
 
-       is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
+       is_signed = !!(field->flags & TEP_FIELD_IS_SIGNED);
        if (should_be_signed && !is_signed) {
                pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
                         evsel->name, name, is_signed, should_be_signed);
index 1d00e5ec7906ebaf23b57a5d9e1471ed1cbab465..82e16bf84466001e950690e41e2b555824fdef6a 100644 (file)
@@ -224,20 +224,24 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)
        return ret;
 }
 
-static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
+static double disasm__cmp(struct annotation_line *a, struct annotation_line *b,
+                                                 int percent_type)
 {
        int i;
 
        for (i = 0; i < a->data_nr; i++) {
-               if (a->data[i].percent == b->data[i].percent)
+               if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type])
                        continue;
-               return a->data[i].percent < b->data[i].percent;
+               return a->data[i].percent[percent_type] -
+                          b->data[i].percent[percent_type];
        }
        return 0;
 }
 
-static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
+static void disasm_rb_tree__insert(struct annotate_browser *browser,
+                               struct annotation_line *al)
 {
+       struct rb_root *root = &browser->entries;
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
        struct annotation_line *l;
@@ -246,7 +250,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line
                parent = *p;
                l = rb_entry(parent, struct annotation_line, rb_node);
 
-               if (disasm__cmp(al, l))
+               if (disasm__cmp(al, l, browser->opts->percent_type) < 0)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
@@ -329,7 +333,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
                        RB_CLEAR_NODE(&pos->al.rb_node);
                        continue;
                }
-               disasm_rb_tree__insert(&browser->entries, &pos->al);
+               disasm_rb_tree__insert(browser, &pos->al);
        }
        pthread_mutex_unlock(&notes->lock);
 
index 89512504551b0b198a44ebe30e81d0972b86ce77..39c0004f288663a579b701a802ef3348906dda70 100644 (file)
@@ -160,7 +160,7 @@ getBPFObjectFromModule(llvm::Module *Module)
        }
        PM.run(*Module);
 
-       return std::move(Buffer);
+       return Buffer;
 }
 
 }
index 1ccbd334206942f7b489041b8418972508162fe9..383674f448fcd67997afe9f07ae0a7fbb48f2f45 100644 (file)
@@ -134,7 +134,12 @@ struct cpu_map *cpu_map__new(const char *cpu_list)
        if (!cpu_list)
                return cpu_map__read_all_cpu_map();
 
-       if (!isdigit(*cpu_list))
+       /*
+        * must handle the case of empty cpumap to cover
+        * TOPOLOGY header for NUMA nodes with no CPU
+        * ( e.g., because of CPU hotplug)
+        */
+       if (!isdigit(*cpu_list) && *cpu_list != '\0')
                goto out;
 
        while (isdigit(*cpu_list)) {
@@ -181,8 +186,10 @@ struct cpu_map *cpu_map__new(const char *cpu_list)
 
        if (nr_cpus > 0)
                cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
-       else
+       else if (*cpu_list != '\0')
                cpus = cpu_map__default_new();
+       else
+               cpus = cpu_map__dummy_new();
 invalid:
        free(tmp_cpus);
 out:
index 93f74d8d3cdd96c97ea22354e9d38abfa518476e..42c3e5a229d24bae0719e4f2ad0e1e5e4b3770aa 100644 (file)
@@ -28,7 +28,7 @@ struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
 static char mem_loads_name[100];
 static bool mem_loads_name__init;
 
-char *perf_mem_events__name(int i)
+char * __weak perf_mem_events__name(int i)
 {
        if (i == PERF_MEM_EVENTS__LOAD) {
                if (!mem_loads_name__init) {
index 897589507d97cba2c09ccb6676bd25e02212c9d8..ea523d3b248fe9bdfb2ded5bca9f88bc966b31b1 100644 (file)
@@ -391,8 +391,10 @@ void ordered_events__free(struct ordered_events *oe)
         * Current buffer might not have all the events allocated
         * yet, we need to free only allocated ones ...
         */
-       list_del(&oe->buffer->list);
-       ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
+       if (oe->buffer) {
+               list_del(&oe->buffer->list);
+               ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
+       }
 
        /* ... and continue with the rest */
        list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
index 63f758c655d5b64c34e44c635eccc0f04cc653a4..64d1f36dee99fb41f05c8ab4a030808f110ed5f0 100644 (file)
@@ -17,6 +17,8 @@ if cc == "clang":
             vars[var] = sub("-mcet", "", vars[var])
         if not clang_has_option("-fcf-protection"):
             vars[var] = sub("-fcf-protection", "", vars[var])
+        if not clang_has_option("-fstack-clash-protection"):
+            vars[var] = sub("-fstack-clash-protection", "", vars[var])
 
 from distutils.core import setup, Extension
 
index 66a84d5846c88ed912aff027943c6f8e9ff78ff2..dca7dfae69ad2b2884103aeb054b3634905e6fb8 100644 (file)
 #define EM_AARCH64     183  /* ARM 64 bit */
 #endif
 
+#ifndef ELF32_ST_VISIBILITY
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+#endif
+
+/* For ELF64 the definitions are the same.  */
+#ifndef ELF64_ST_VISIBILITY
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+#endif
+
+/* How to extract information held in the st_other field.  */
+#ifndef GELF_ST_VISIBILITY
+#define GELF_ST_VISIBILITY(val)        ELF64_ST_VISIBILITY (val)
+#endif
+
 typedef Elf64_Nhdr GElf_Nhdr;
 
 #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
@@ -87,6 +101,11 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
        return GELF_ST_TYPE(sym->st_info);
 }
 
+static inline uint8_t elf_sym__visibility(const GElf_Sym *sym)
+{
+       return GELF_ST_VISIBILITY(sym->st_other);
+}
+
 #ifndef STT_GNU_IFUNC
 #define STT_GNU_IFUNC 10
 #endif
@@ -111,7 +130,9 @@ static inline int elf_sym__is_label(const GElf_Sym *sym)
        return elf_sym__type(sym) == STT_NOTYPE &&
                sym->st_name != 0 &&
                sym->st_shndx != SHN_UNDEF &&
-               sym->st_shndx != SHN_ABS;
+               sym->st_shndx != SHN_ABS &&
+               elf_sym__visibility(sym) != STV_HIDDEN &&
+               elf_sym__visibility(sym) != STV_INTERNAL;
 }
 
 static bool elf_sym__filter(GElf_Sym *sym)
index e752384045556cba86811d0b1a5e1dd66aca03fa..2d4baf57822fae8e7111a89e63fa047f4d0638ec 100644 (file)
@@ -18,8 +18,8 @@ ssize_t security_show(struct device *dev,
         * For the test version we need to poll the "hardware" in order
         * to get the updated status for unlock testing.
         */
-       nvdimm->sec.state = nvdimm_security_state(nvdimm, false);
-       nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, true);
+       nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
+       nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
 
        switch (nvdimm->sec.state) {
        case NVDIMM_SECURITY_DISABLED:
index 1a2bd15c5b6e53be68ac9f37ee6b6cf2de582424..400ee81a304332ba308397c9540ed5829f1bee39 100644 (file)
@@ -10,6 +10,7 @@ TARGETS += drivers/dma-buf
 TARGETS += efivarfs
 TARGETS += exec
 TARGETS += filesystems
+TARGETS += filesystems/binderfs
 TARGETS += firmware
 TARGETS += ftrace
 TARGETS += futex
index 4a9785043a3914959fef99de25983fe3b5b256f3..dd093bd91aa980e68e706437e6d8c6cec41a2c4c 100644 (file)
@@ -28,3 +28,4 @@ flow_dissector_load
 test_netcnt
 test_section_names
 test_tcpnotify_user
+test_libbpf
index 73aa6d8f4a2f8717493641411b77f5e3900346e4..41ab7a3668b383a0d58767e4015d86e3e90a507d 100644 (file)
@@ -55,7 +55,10 @@ TEST_PROGS := test_kmod.sh \
        test_flow_dissector.sh \
        test_xdp_vlan.sh
 
-TEST_PROGS_EXTENDED := with_addr.sh
+TEST_PROGS_EXTENDED := with_addr.sh \
+       with_tunnels.sh \
+       tcp_client.py \
+       tcp_server.py
 
 # Compile but not part of 'make run_tests'
 TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
index 315a44fa32af3353bf6eb90fd3d324121319d319..84fd6f1bf33e7fd2b38d89c9c876bd35139eb94c 100644 (file)
@@ -13,7 +13,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
        unsigned int start, end, possible_cpus = 0;
        char buff[128];
        FILE *fp;
-       int n;
+       int len, n, i, j = 0;
 
        fp = fopen(fcpu, "r");
        if (!fp) {
@@ -21,17 +21,27 @@ static inline unsigned int bpf_num_possible_cpus(void)
                exit(1);
        }
 
-       while (fgets(buff, sizeof(buff), fp)) {
-               n = sscanf(buff, "%u-%u", &start, &end);
-               if (n == 0) {
-                       printf("Failed to retrieve # possible CPUs!\n");
-                       exit(1);
-               } else if (n == 1) {
-                       end = start;
+       if (!fgets(buff, sizeof(buff), fp)) {
+               printf("Failed to read %s!\n", fcpu);
+               exit(1);
+       }
+
+       len = strlen(buff);
+       for (i = 0; i <= len; i++) {
+               if (buff[i] == ',' || buff[i] == '\0') {
+                       buff[i] = '\0';
+                       n = sscanf(&buff[j], "%u-%u", &start, &end);
+                       if (n <= 0) {
+                               printf("Failed to retrieve # possible CPUs!\n");
+                               exit(1);
+                       } else if (n == 1) {
+                               end = start;
+                       }
+                       possible_cpus += end - start + 1;
+                       j = i + 1;
                }
-               possible_cpus = start == 0 ? end + 1 : 0;
-               break;
        }
+
        fclose(fp);
 
        return possible_cpus;
index cf16948aad4adb1e32d33d21f0742ddf724e524e..6692a40a6979eac0b48665e77566e6beef066d17 100644 (file)
@@ -155,7 +155,7 @@ void cleanup_cgroup_environment(void)
  * This function creates a cgroup under the top level workdir and returns the
  * file descriptor. It is idempotent.
  *
- * On success, it returns the file descriptor. On failure it returns 0.
+ * On success, it returns the file descriptor. On failure it returns -1.
  * If there is a failure, it prints the error to stderr.
  */
 int create_and_get_cgroup(const char *path)
@@ -166,13 +166,13 @@ int create_and_get_cgroup(const char *path)
        format_cgroup_path(cgroup_path, path);
        if (mkdir(cgroup_path, 0777) && errno != EEXIST) {
                log_err("mkdiring cgroup %s .. %s", path, cgroup_path);
-               return 0;
+               return -1;
        }
 
        fd = open(cgroup_path, O_RDONLY);
        if (fd < 0) {
                log_err("Opening Cgroup");
-               return 0;
+               return -1;
        }
 
        return fd;
index 8bcd380105826f6a3c7e2cf7769c451241432963..91420fa83b088e7e3ec4d63a0781bdcb40a070a9 100644 (file)
@@ -1881,13 +1881,12 @@ static struct btf_raw_test raw_tests[] = {
 },
 
 {
-       .descr = "func proto (CONST=>TYPEDEF=>FUNC_PROTO)",
+       .descr = "func proto (TYPEDEF=>FUNC_PROTO)",
        .raw_types = {
                BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
                BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),               /* [2] */
-               BTF_CONST_ENC(4),                               /* [3] */
-               BTF_TYPEDEF_ENC(NAME_TBD, 5),                   /* [4] */
-               BTF_FUNC_PROTO_ENC(0, 2),                       /* [5] */
+               BTF_TYPEDEF_ENC(NAME_TBD, 4),                   /* [3] */
+               BTF_FUNC_PROTO_ENC(0, 2),                       /* [4] */
                        BTF_FUNC_PROTO_ARG_ENC(0, 1),
                        BTF_FUNC_PROTO_ARG_ENC(0, 2),
                BTF_END_RAW,
@@ -1901,8 +1900,6 @@ static struct btf_raw_test raw_tests[] = {
        .key_type_id = 1,
        .value_type_id = 1,
        .max_entries = 4,
-       .btf_load_err = true,
-       .err_str = "Invalid type_id",
 },
 
 {
@@ -3526,6 +3523,8 @@ struct pprint_mapv {
                ENUM_TWO,
                ENUM_THREE,
        } aenum;
+       uint32_t ui32b;
+       uint32_t bits2c:2;
 };
 
 static struct btf_raw_test pprint_test_template[] = {
@@ -3568,7 +3567,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, 0),        /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, 32),       /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, 64),       /* int32_t si32 */
@@ -3577,9 +3576,11 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 6, 126),       /* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, 128),             /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, 192),      /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, 224),      /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 6, 256),       /* bits2c */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3628,7 +3629,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),  /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
@@ -3637,9 +3638,11 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 126)), /* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),       /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),        /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),        /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3690,7 +3693,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),  /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
@@ -3699,13 +3702,15 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 19, BTF_MEMBER_OFFSET(2, 126)),/* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),       /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),        /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),        /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 256)),        /* bits2c */
                /* typedef unsigned int ___int */       /* [17] */
                BTF_TYPEDEF_ENC(NAME_TBD, 18),
                BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6),      /* [18] */
                BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15),        /* [19] */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0___int"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3793,6 +3798,8 @@ static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
                v->unused_bits2b = 3;
                v->ui64 = i;
                v->aenum = i & 0x03;
+               v->ui32b = 4;
+               v->bits2c = 1;
                v = (void *)v + rounded_value_size;
        }
 }
@@ -3955,7 +3962,8 @@ static int do_test_pprint(int test_num)
 
                        nexpected_line = snprintf(expected_line, sizeof(expected_line),
                                                  "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
-                                                 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
+                                                 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s,"
+                                                 "%u,0x%x}\n",
                                                  percpu_map ? "\tcpu" : "",
                                                  percpu_map ? cpu : next_key,
                                                  cmapv->ui32, cmapv->si32,
@@ -3967,7 +3975,9 @@ static int do_test_pprint(int test_num)
                                                  cmapv->ui8a[2], cmapv->ui8a[3],
                                                  cmapv->ui8a[4], cmapv->ui8a[5],
                                                  cmapv->ui8a[6], cmapv->ui8a[7],
-                                                 pprint_enum_str[cmapv->aenum]);
+                                                 pprint_enum_str[cmapv->aenum],
+                                                 cmapv->ui32b,
+                                                 cmapv->bits2c);
 
                        err = check_line(expected_line, nexpected_line,
                                         sizeof(expected_line), line);
index f44834155f25e420270f28a49ece2376c1a95b5a..2fc4625c1a1502b5926614874253fd86715242c7 100644 (file)
@@ -81,7 +81,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 9c8b50bac7e01fd60dc436a5f986e384e2343b43..76e4993b7c16a45404c8a9bc7d7149a34b5796b0 100644 (file)
@@ -43,7 +43,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 44ed7f29f8ab6cec40c83c02c01d28ca36c36492..c1da5404454a1551b792c642938050d6c427fda9 100644 (file)
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 126fc624290d22b4d834b475356de2226dbea3a8..25f0083a9b2e7c87d1efbadae3cc00c97e0c5560 100644 (file)
@@ -1188,7 +1188,9 @@ static void test_stacktrace_build_id(void)
        int i, j;
        struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
        int build_id_matches = 0;
+       int retry = 1;
 
+retry:
        err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
        if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
                goto out;
@@ -1301,6 +1303,19 @@ static void test_stacktrace_build_id(void)
                previous_key = key;
        } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
 
+       /* stack_map_get_build_id_offset() is racy and sometimes can return
+        * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
+        * try it one more time.
+        */
+       if (build_id_matches < 1 && retry--) {
+               ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
+               close(pmu_fd);
+               bpf_object__close(obj);
+               printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
+                      __func__);
+               goto retry;
+       }
+
        if (CHECK(build_id_matches < 1, "build id match",
                  "Didn't find expected build ID from the map\n"))
                goto disable_pmu;
@@ -1341,7 +1356,9 @@ static void test_stacktrace_build_id_nmi(void)
        int i, j;
        struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
        int build_id_matches = 0;
+       int retry = 1;
 
+retry:
        err = bpf_prog_load(file, BPF_PROG_TYPE_PERF_EVENT, &obj, &prog_fd);
        if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
                return;
@@ -1436,6 +1453,19 @@ static void test_stacktrace_build_id_nmi(void)
                previous_key = key;
        } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
 
+       /* stack_map_get_build_id_offset() is racy and sometimes can return
+        * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
+        * try it one more time.
+        */
+       if (build_id_matches < 1 && retry--) {
+               ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
+               close(pmu_fd);
+               bpf_object__close(obj);
+               printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
+                      __func__);
+               goto retry;
+       }
+
        if (CHECK(build_id_matches < 1, "build id match",
                  "Didn't find expected build ID from the map\n"))
                goto disable_pmu;
index c121cc59f31429d4805bcf205dea79cbe1121609..9220747c069db6518b29cd0b3e106c6fafecbd01 100644 (file)
@@ -164,7 +164,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CGROUP_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CGROUP_PATH))
index b8ebe2f580741a5cb4aae39e604affc313b31ff4..561ffb6d643349f794ff8dc9b00ee570c3dd369b 100644 (file)
@@ -458,7 +458,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index 73b7493d4120991527b61a2a33a9c0784542176b..3f110eaaf29cea214844ff98211697c764b8a870 100644 (file)
@@ -44,6 +44,7 @@
 #define SERV6_V4MAPPED_IP      "::ffff:192.168.0.4"
 #define SRC6_IP                        "::1"
 #define SRC6_REWRITE_IP                "::6"
+#define WILDCARD6_IP           "::"
 #define SERV6_PORT             6060
 #define SERV6_REWRITE_PORT     6666
 
@@ -85,12 +86,14 @@ static int bind4_prog_load(const struct sock_addr_test *test);
 static int bind6_prog_load(const struct sock_addr_test *test);
 static int connect4_prog_load(const struct sock_addr_test *test);
 static int connect6_prog_load(const struct sock_addr_test *test);
+static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
+static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
 
 static struct sock_addr_test tests[] = {
        /* bind */
@@ -462,6 +465,34 @@ static struct sock_addr_test tests[] = {
                SRC6_REWRITE_IP,
                SYSCALL_ENOTSUPP,
        },
+       {
+               "sendmsg6: set dst IP = [::] (BSD'ism)",
+               sendmsg6_rw_wildcard_prog_load,
+               BPF_CGROUP_UDP6_SENDMSG,
+               BPF_CGROUP_UDP6_SENDMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               SERV6_IP,
+               SERV6_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SRC6_REWRITE_IP,
+               SUCCESS,
+       },
+       {
+               "sendmsg6: preserve dst IP = [::] (BSD'ism)",
+               sendmsg_allow_prog_load,
+               BPF_CGROUP_UDP6_SENDMSG,
+               BPF_CGROUP_UDP6_SENDMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               WILDCARD6_IP,
+               SERV6_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_PORT,
+               SRC6_IP,
+               SUCCESS,
+       },
        {
                "sendmsg6: deny call",
                sendmsg_deny_prog_load,
@@ -734,16 +765,27 @@ static int connect6_prog_load(const struct sock_addr_test *test)
        return load_path(test, CONNECT6_PROG_PATH);
 }
 
-static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
+static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
+                                     int32_t rc)
 {
        struct bpf_insn insns[] = {
-               /* return 0 */
-               BPF_MOV64_IMM(BPF_REG_0, 0),
+               /* return rc */
+               BPF_MOV64_IMM(BPF_REG_0, rc),
                BPF_EXIT_INSN(),
        };
        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 }
 
+static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg_ret_only_prog_load(test, /*rc*/ 1);
+}
+
+static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg_ret_only_prog_load(test, /*rc*/ 0);
+}
+
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
 {
        struct sockaddr_in dst4_rw_addr;
@@ -864,6 +906,11 @@ static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
 }
 
+static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
+}
+
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 {
        return load_path(test, SENDMSG6_PROG_PATH);
@@ -1395,7 +1442,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index b6c2c605d8c050794cef847c73f779e40378b0ab..fc7832ee566b8e2310f323ec3f6738a67122e759 100644 (file)
@@ -202,7 +202,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index e6eebda7d112b771de662c5b970c0848186595ef..716b4e3be5813d5c2ab37000cb1883aa45728c45 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
                goto err;
 
        cg_fd = create_and_get_cgroup(cg_path);
-       if (!cg_fd)
+       if (cg_fd < 0)
                goto err;
 
        if (join_cgroup(cg_path))
index ff3c4522aed6823b2af492454b889aa79b3bbc2b..4e4353711a86b5cf9e0ad7902377e481c1d98ebd 100644 (file)
@@ -115,7 +115,7 @@ int main(int argc, char **argv)
                goto err;
 
        cg_fd = create_and_get_cgroup(cg_path);
-       if (!cg_fd)
+       if (cg_fd < 0)
                goto err;
 
        if (join_cgroup(cg_path))
index 10d44446e8013a19d8c01e5e15a94a919bae94cb..2fd90d4568926d13542783c870507d43a6d6bb64 100644 (file)
@@ -6933,6 +6933,126 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .retval = 1,
        },
+       {
+               "map access: mixing value pointer and scalar, 1",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different pointers or scalars",
+               .retval = 0,
+       },
+       {
+               "map access: mixing value pointer and scalar, 2",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different maps or paths",
+               .retval = 0,
+       },
+       {
+               "sanitation: alu with different scalars",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       BPF_MOV64_IMM(BPF_REG_2, 42),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100001),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .retval = 0x100000,
+       },
        {
                "map access: value_ptr += known scalar, upper oob arith, test 1",
                .insns = {
index bab13dd025a63a9344445985391d70581a2e7815..0d26b5e3f9667bf94b3acf6610f16f6a422277b0 100755 (executable)
@@ -37,6 +37,10 @@ prerequisite()
                exit $ksft_skip
        fi
 
+       present_cpus=`cat $SYSFS/devices/system/cpu/present`
+       present_max=${present_cpus##*-}
+       echo "present_cpus = $present_cpus present_max = $present_max"
+
        echo -e "\t Cpus in online state: $online_cpus"
 
        offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -151,6 +155,8 @@ online_cpus=0
 online_max=0
 offline_cpus=0
 offline_max=0
+present_cpus=0
+present_max=0
 
 while getopts e:ahp: opt; do
        case $opt in
@@ -190,9 +196,10 @@ if [ $allcpus -eq 0 ]; then
        online_cpu_expect_success $online_max
 
        if [[ $offline_cpus -gt 0 ]]; then
-               echo -e "\t offline to online to offline: cpu $offline_max"
-               online_cpu_expect_success $offline_max
-               offline_cpu_expect_success $offline_max
+               echo -e "\t offline to online to offline: cpu $present_max"
+               online_cpu_expect_success $present_max
+               offline_cpu_expect_success $present_max
+               online_cpu $present_max
        fi
        exit 0
 else
index 94fdbf215c145ecd4814e99cd235044801703dac..c4cf6e6d800ebe3d2d595805397ce1b3f70e7de3 100755 (executable)
@@ -25,6 +25,7 @@ ALL_TESTS="
        lag_unlink_slaves_test
        lag_dev_deletion_test
        vlan_interface_uppers_test
+       bridge_extern_learn_test
        devlink_reload_test
 "
 NUM_NETIFS=2
@@ -541,6 +542,25 @@ vlan_interface_uppers_test()
        ip link del dev br0
 }
 
+bridge_extern_learn_test()
+{
+       # Test that externally learned entries added from user space are
+       # marked as offloaded
+       RET=0
+
+       ip link add name br0 type bridge
+       ip link set dev $swp1 master br0
+
+       bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn
+
+       bridge fdb show brport $swp1 | grep de:ad:be:ef:13:37 | grep -q offload
+       check_err $? "fdb entry not marked as offloaded when should"
+
+       log_test "externally learned fdb entry"
+
+       ip link del dev br0
+}
+
 devlink_reload_test()
 {
        # Test that after executing all the above configuration tests, a
index dcf9f4e913e076cabcc1cebe83705ae1583eb20c..ae6146ec5afd2a68f99803eb59fc590d18399913 100755 (executable)
@@ -847,6 +847,24 @@ sanitization_vlan_aware_test()
 
        log_test "vlan-aware - failed enslavement to vlan-aware bridge"
 
+       bridge vlan del vid 10 dev vxlan20
+       bridge vlan add vid 20 dev vxlan20 pvid untagged
+
+       # Test that offloading of an unsupported tunnel fails when it is
+       # triggered by addition of VLAN to a local port
+       RET=0
+
+       # TOS must be set to inherit
+       ip link set dev vxlan10 type vxlan tos 42
+
+       ip link set dev $swp1 master br0
+       bridge vlan add vid 10 dev $swp1 &> /dev/null
+       check_fail $?
+
+       log_test "vlan-aware - failed vlan addition to a local port"
+
+       ip link set dev vxlan10 type vxlan tos inherit
+
        ip link del dev vxlan20
        ip link del dev vxlan10
        ip link del dev br0
diff --git a/tools/testing/selftests/filesystems/binderfs/.gitignore b/tools/testing/selftests/filesystems/binderfs/.gitignore
new file mode 100644 (file)
index 0000000..8a5d9bf
--- /dev/null
@@ -0,0 +1 @@
+binderfs_test
diff --git a/tools/testing/selftests/filesystems/binderfs/Makefile b/tools/testing/selftests/filesystems/binderfs/Makefile
new file mode 100644 (file)
index 0000000..58cb659
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS += -I../../../../../usr/include/
+TEST_GEN_PROGS := binderfs_test
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
new file mode 100644 (file)
index 0000000..8c2ed96
--- /dev/null
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/android/binder.h>
+#include <linux/android/binderfs.h>
+#include "../../kselftest.h"
+
+static ssize_t write_nointr(int fd, const void *buf, size_t count)
+{
+       ssize_t ret;
+again:
+       ret = write(fd, buf, count);
+       if (ret < 0 && errno == EINTR)
+               goto again;
+
+       return ret;
+}
+
+static void write_to_file(const char *filename, const void *buf, size_t count,
+                         int allowed_errno)
+{
+       int fd, saved_errno;
+       ssize_t ret;
+
+       fd = open(filename, O_WRONLY | O_CLOEXEC);
+       if (fd < 0)
+               ksft_exit_fail_msg("%s - Failed to open file %s\n",
+                                  strerror(errno), filename);
+
+       ret = write_nointr(fd, buf, count);
+       if (ret < 0) {
+               if (allowed_errno && (errno == allowed_errno)) {
+                       close(fd);
+                       return;
+               }
+
+               goto on_error;
+       }
+
+       if ((size_t)ret != count)
+               goto on_error;
+
+       close(fd);
+       return;
+
+on_error:
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to write to file %s\n",
+                                  strerror(errno), filename);
+
+       ksft_exit_fail_msg("Failed to write to file %s\n", filename);
+}
+
+static void change_to_userns(void)
+{
+       int ret;
+       uid_t uid;
+       gid_t gid;
+       /* {g,u}id_map files only allow a max of 4096 bytes written to them */
+       char idmap[4096];
+
+       uid = getuid();
+       gid = getgid();
+
+       ret = unshare(CLONE_NEWUSER);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unshare user namespace\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/setgroups", "deny", strlen("deny"), ENOENT);
+
+       ret = snprintf(idmap, sizeof(idmap), "0 %d 1", uid);
+       if (ret < 0 || (size_t)ret >= sizeof(idmap))
+               ksft_exit_fail_msg("%s - Failed to prepare uid mapping\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/uid_map", idmap, strlen(idmap), 0);
+
+       ret = snprintf(idmap, sizeof(idmap), "0 %d 1", gid);
+       if (ret < 0 || (size_t)ret >= sizeof(idmap))
+               ksft_exit_fail_msg("%s - Failed to prepare uid mapping\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/gid_map", idmap, strlen(idmap), 0);
+
+       ret = setgid(0);
+       if (ret)
+               ksft_exit_fail_msg("%s - Failed to setgid(0)\n",
+                                  strerror(errno));
+
+       ret = setuid(0);
+       if (ret)
+               ksft_exit_fail_msg("%s - Failed to setgid(0)\n",
+                                  strerror(errno));
+}
+
+static void change_to_mountns(void)
+{
+       int ret;
+
+       ret = unshare(CLONE_NEWNS);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unshare mount namespace\n",
+                                  strerror(errno));
+
+       ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to mount / as private\n",
+                                  strerror(errno));
+}
+
+static void rmdir_protect_errno(const char *dir)
+{
+       int saved_errno = errno;
+       (void)rmdir(dir);
+       errno = saved_errno;
+}
+
+static void __do_binderfs_test(void)
+{
+       int fd, ret, saved_errno;
+       size_t len;
+       ssize_t wret;
+       bool keep = false;
+       struct binderfs_device device = { 0 };
+       struct binder_version version = { 0 };
+
+       change_to_mountns();
+
+       ret = mkdir("/dev/binderfs", 0755);
+       if (ret < 0) {
+               if (errno != EEXIST)
+                       ksft_exit_fail_msg(
+                               "%s - Failed to create binderfs mountpoint\n",
+                               strerror(errno));
+
+               keep = true;
+       }
+
+       ret = mount(NULL, "/dev/binderfs", "binder", 0, 0);
+       if (ret < 0) {
+               if (errno != ENODEV)
+                       ksft_exit_fail_msg("%s - Failed to mount binderfs\n",
+                                          strerror(errno));
+
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_skip(
+                       "The Android binderfs filesystem is not available\n");
+       }
+
+       /* binderfs mount test passed */
+       ksft_inc_pass_cnt();
+
+       memcpy(device.name, "my-binder", strlen("my-binder"));
+
+       fd = open("/dev/binderfs/binder-control", O_RDONLY | O_CLOEXEC);
+       if (fd < 0)
+               ksft_exit_fail_msg(
+                       "%s - Failed to open binder-control device\n",
+                       strerror(errno));
+
+       ret = ioctl(fd, BINDER_CTL_ADD, &device);
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to allocate new binder device\n",
+                       strerror(errno));
+       }
+
+       ksft_print_msg(
+               "Allocated new binder device with major %d, minor %d, and name %s\n",
+               device.major, device.minor, device.name);
+
+       /* binder device allocation test passed */
+       ksft_inc_pass_cnt();
+
+       fd = open("/dev/binderfs/my-binder", O_CLOEXEC | O_RDONLY);
+       if (fd < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("%s - Failed to open my-binder device\n",
+                                  strerror(errno));
+       }
+
+       ret = ioctl(fd, BINDER_VERSION, &version);
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to open perform BINDER_VERSION request\n",
+                       strerror(errno));
+       }
+
+       ksft_print_msg("Detected binder version: %d\n",
+                      version.protocol_version);
+
+       /* binder transaction with binderfs binder device passed */
+       ksft_inc_pass_cnt();
+
+       ret = unlink("/dev/binderfs/my-binder");
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("%s - Failed to delete binder device\n",
+                                  strerror(errno));
+       }
+
+       /* binder device removal passed */
+       ksft_inc_pass_cnt();
+
+       ret = unlink("/dev/binderfs/binder-control");
+       if (!ret) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("Managed to delete binder-control device\n");
+       } else if (errno != EPERM) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to delete binder-control device but exited with unexpected error code\n",
+                       strerror(errno));
+       }
+
+       /* binder-control device removal failed as expected */
+       ksft_inc_xfail_cnt();
+
+on_error:
+       ret = umount2("/dev/binderfs", MNT_DETACH);
+       keep ?: rmdir_protect_errno("/dev/binderfs");
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unmount binderfs\n",
+                                  strerror(errno));
+
+       /* binderfs unmount test passed */
+       ksft_inc_pass_cnt();
+}
+
+static void binderfs_test_privileged()
+{
+       if (geteuid() != 0)
+               ksft_print_msg(
+                       "Tests are not run as root. Skipping privileged tests\n");
+       else
+               __do_binderfs_test();
+}
+
+static void binderfs_test_unprivileged()
+{
+       change_to_userns();
+       __do_binderfs_test();
+}
+
+int main(int argc, char *argv[])
+{
+       binderfs_test_privileged();
+       binderfs_test_unprivileged();
+       ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/filesystems/binderfs/config b/tools/testing/selftests/filesystems/binderfs/config
new file mode 100644 (file)
index 0000000..02dd6cc
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDERFS=y
+CONFIG_ANDROID_BINDER_IPC=y
index f8d468f54e986dd00aa82ba1aa29370896f656ee..aaa1e9f083c372153836764e85feb7a358f0a273 100644 (file)
@@ -37,7 +37,7 @@ static int get_debugfs(char **path)
        struct libmnt_table *tb;
        struct libmnt_iter *itr = NULL;
        struct libmnt_fs *fs;
-       int found = 0;
+       int found = 0, ret;
 
        cxt = mnt_new_context();
        if (!cxt)
@@ -58,8 +58,11 @@ static int get_debugfs(char **path)
                        break;
                }
        }
-       if (found)
-               asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+       if (found) {
+               ret = asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+               if (ret < 0)
+                       err(EXIT_FAILURE, "failed to format string");
+       }
 
        mnt_free_iter(itr);
        mnt_free_context(cxt);
index f4ba8eb84b951890c00aa179b6b3453722f4ea80..ad06489c22a566aeba8f79456d31a862a2859a8a 100644 (file)
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 TEST_PROGS := ir_loopback.sh
 TEST_GEN_PROGS_EXTENDED := ir_loopback
+APIDIR := ../../../include/uapi
+CFLAGS += -Wall -O2 -I$(APIDIR)
 
 include ../lib.mk
index 23022e9d32eb816d9a9955d94f08078a6d5fdfd8..b52cfdefecbfe9f760b569baf757d2228fe0c6af 100644 (file)
@@ -571,7 +571,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
         * already exist.
         */
        region = (struct userspace_mem_region *) userspace_mem_region_find(
-               vm, guest_paddr, guest_paddr + npages * vm->page_size);
+               vm, guest_paddr, (guest_paddr + npages * vm->page_size) - 1);
        if (region != NULL)
                TEST_ASSERT(false, "overlapping userspace_mem_region already "
                        "exists\n"
@@ -587,15 +587,10 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
                region = region->next) {
                if (region->region.slot == slot)
                        break;
-               if ((guest_paddr <= (region->region.guest_phys_addr
-                               + region->region.memory_size))
-                       && ((guest_paddr + npages * vm->page_size)
-                               >= region->region.guest_phys_addr))
-                       break;
        }
        if (region != NULL)
                TEST_ASSERT(false, "A mem region with the requested slot "
-                       "or overlapping physical memory range already exists.\n"
+                       "already exists.\n"
                        "  requested slot: %u paddr: 0x%lx npages: 0x%lx\n"
                        "  existing slot: %u paddr: 0x%lx size: 0x%lx",
                        slot, guest_paddr, npages,
index ea3c73e8f4f6e7a97303e1801a674c12dc01219d..c49c2a28b0eb290ccd6c51498a0b9fd716b58b07 100644 (file)
@@ -103,6 +103,12 @@ int main(int argc, char *argv[])
 
        vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
 
+       /* KVM should return supported EVMCS version range */
+       TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
+                   (evmcs_ver & 0xff) > 0,
+                   "Incorrect EVMCS version range: %x:%x\n",
+                   evmcs_ver & 0xff, evmcs_ver >> 8);
+
        run = vcpu_state(vm, VCPU_ID);
 
        vcpu_regs_get(vm, VCPU_ID, &regs1);
index f8f3e90700c0ebc2437ffdd96398caee1b39fa4a..1e6d14d2825cca3fa7349ea14fc1fbecd26ca9d0 100644 (file)
@@ -21,6 +21,6 @@ TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
 KSFT_KHDR_INSTALL := 1
 include ../lib.mk
 
-$(OUTPUT)/reuseport_bpf_numa: LDFLAGS += -lnuma
+$(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
 $(OUTPUT)/tcp_mmap: LDFLAGS += -lpthread
 $(OUTPUT)/tcp_inq: LDFLAGS += -lpthread
index d8313d0438b7422df129f2fe5868236119eca991..b90dff8d3a94bf41640564513e4bb73e54f7bcdc 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
-ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding"
+ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding vlan_deletion extern_learn"
 NUM_NETIFS=4
 CHECK_TC="yes"
 source lib.sh
@@ -96,6 +96,51 @@ flooding()
        flood_test $swp2 $h1 $h2
 }
 
+vlan_deletion()
+{
+       # Test that the deletion of a VLAN on a bridge port does not affect
+       # the PVID VLAN
+       log_info "Add and delete a VLAN on bridge port $swp1"
+
+       bridge vlan add vid 10 dev $swp1
+       bridge vlan del vid 10 dev $swp1
+
+       ping_ipv4
+       ping_ipv6
+}
+
+extern_learn()
+{
+       local mac=de:ad:be:ef:13:37
+       local ageing_time
+
+       # Test that externally learned FDB entries can roam, but not age out
+       RET=0
+
+       bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn vlan 1
+
+       bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
+       check_err $? "Did not find FDB entry when should"
+
+       # Wait for 10 seconds after the ageing time to make sure the FDB entry
+       # was not aged out
+       ageing_time=$(bridge_ageing_time_get br0)
+       sleep $((ageing_time + 10))
+
+       bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
+       check_err $? "FDB entry was aged out when should not"
+
+       $MZ $h2 -c 1 -p 64 -a $mac -t ip -q
+
+       bridge fdb show brport $swp2 | grep -q de:ad:be:ef:13:37
+       check_err $? "FDB entry did not roam when should"
+
+       log_test "Externally learned FDB entry - ageing & roaming"
+
+       bridge fdb del de:ad:be:ef:13:37 dev $swp2 master vlan 1 &> /dev/null
+       bridge fdb del de:ad:be:ef:13:37 dev $swp1 master vlan 1 &> /dev/null
+}
+
 trap cleanup EXIT
 
 setup_prepare
index 56cef3b1c194628d5efb18f74fc67806562c8d84..bb10e33690b25a763d3de18cce207a098baf7351 100755 (executable)
@@ -629,7 +629,7 @@ __test_ecn_decap()
        RET=0
 
        tc filter add dev $h1 ingress pref 77 prot ip \
-               flower ip_tos $decapped_tos action pass
+               flower ip_tos $decapped_tos action drop
        sleep 1
        vxlan_encapped_ping_test v2 v1 192.0.2.17 \
                                 $orig_inner_tos $orig_outer_tos \
index 61ae2782388e9d0921b06a4589c5d5662cb02e8e..5d56cc0838f627b44afc0ce225bdb2330fbcbe2a 100644 (file)
@@ -203,6 +203,7 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
 {
        struct ip *iphdr = (struct ip *)ip_frame;
        struct ip6_hdr *ip6hdr = (struct ip6_hdr *)ip_frame;
+       const bool ipv4 = !ipv6;
        int res;
        int offset;
        int frag_len;
@@ -239,19 +240,53 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
                iphdr->ip_sum = 0;
        }
 
+       /* Occasionally test in-order fragments. */
+       if (!cfg_overlap && (rand() % 100 < 15)) {
+               offset = 0;
+               while (offset < (UDP_HLEN + payload_len)) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               return;
+       }
+
+       /* Occasionally test IPv4 "runs" (see net/ipv4/ip_fragment.c) */
+       if (ipv4 && !cfg_overlap && (rand() % 100 < 20) &&
+                       (payload_len > 9 * max_frag_len)) {
+               offset = 6 * max_frag_len;
+               while (offset < (UDP_HLEN + payload_len)) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               offset = 3 * max_frag_len;
+               while (offset < 6 * max_frag_len) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               offset = 0;
+               while (offset < 3 * max_frag_len) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               return;
+       }
+
        /* Odd fragments. */
        offset = max_frag_len;
        while (offset < (UDP_HLEN + payload_len)) {
                send_fragment(fd_raw, addr, alen, offset, ipv6);
+               /* IPv4 ignores duplicates, so randomly send a duplicate. */
+               if (ipv4 && (1 == rand() % 100))
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
                offset += 2 * max_frag_len;
        }
 
        if (cfg_overlap) {
                /* Send an extra random fragment. */
-               offset = rand() % (UDP_HLEN + payload_len - 1);
-               /* sendto() returns EINVAL if offset + frag_len is too small. */
                if (ipv6) {
                        struct ip6_frag *fraghdr = (struct ip6_frag *)(ip_frame + IP6_HLEN);
+                       /* sendto() returns EINVAL if offset + frag_len is too small. */
+                       offset = rand() % (UDP_HLEN + payload_len - 1);
                        frag_len = max_frag_len + rand() % 256;
                        /* In IPv6 if !!(frag_len % 8), the fragment is dropped. */
                        frag_len &= ~0x7;
@@ -259,13 +294,29 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
                        ip6hdr->ip6_plen = htons(frag_len);
                        frag_len += IP6_HLEN;
                } else {
-                       frag_len = IP4_HLEN + UDP_HLEN + rand() % 256;
+                       /* In IPv4, duplicates and some fragments completely inside
+                        * previously sent fragments are dropped/ignored. So
+                        * random offset and frag_len can result in a dropped
+                        * fragment instead of a dropped queue/packet. So we
+                        * hard-code offset and frag_len.
+                        *
+                        * See ade446403bfb ("net: ipv4: do not handle duplicate
+                        * fragments as overlapping").
+                        */
+                       if (max_frag_len * 4 < payload_len || max_frag_len < 16) {
+                               /* not enough payload to play with random offset and frag_len. */
+                               offset = 8;
+                               frag_len = IP4_HLEN + UDP_HLEN + max_frag_len;
+                       } else {
+                               offset = rand() % (payload_len / 2);
+                               frag_len = 2 * max_frag_len + 1 + rand() % 256;
+                       }
                        iphdr->ip_off = htons(offset / 8 | IP4_MF);
                        iphdr->ip_len = htons(frag_len);
                }
                res = sendto(fd_raw, ip_frame, frag_len, 0, addr, alen);
                if (res < 0)
-                       error(1, errno, "sendto overlap");
+                       error(1, errno, "sendto overlap: %d", frag_len);
                if (res != frag_len)
                        error(1, 0, "sendto overlap: %d vs %d", (int)res, frag_len);
                frag_counter++;
@@ -275,6 +326,9 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
        offset = 0;
        while (offset < (UDP_HLEN + payload_len)) {
                send_fragment(fd_raw, addr, alen, offset, ipv6);
+               /* IPv4 ignores duplicates, so randomly send a duplicate. */
+               if (ipv4 && (1 == rand() % 100))
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
                offset += 2 * max_frag_len;
        }
 }
@@ -282,7 +336,11 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
 static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
 {
        int fd_tx_raw, fd_rx_udp;
-       struct timeval tv = { .tv_sec = 0, .tv_usec = 10 * 1000 };
+       /* Frag queue timeout is set to one second in the calling script;
+        * socket timeout should be just a bit longer to avoid tests interfering
+        * with each other.
+        */
+       struct timeval tv = { .tv_sec = 1, .tv_usec = 10 };
        int idx;
        int min_frag_len = ipv6 ? 1280 : 8;
 
@@ -308,12 +366,32 @@ static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
                        payload_len += (rand() % 4096)) {
                if (cfg_verbose)
                        printf("payload_len: %d\n", payload_len);
-               max_frag_len = min_frag_len;
-               do {
+
+               if (cfg_overlap) {
+                       /* With overlaps, one send/receive pair below takes
+                        * at least one second (== timeout) to run, so there
+                        * is not enough test time to run a nested loop:
+                        * the full overlap test takes 20-30 seconds.
+                        */
+                       max_frag_len = min_frag_len +
+                               rand() % (1500 - FRAG_HLEN - min_frag_len);
                        send_udp_frags(fd_tx_raw, addr, alen, ipv6);
                        recv_validate_udp(fd_rx_udp);
-                       max_frag_len += 8 * (rand() % 8);
-               } while (max_frag_len < (1500 - FRAG_HLEN) && max_frag_len <= payload_len);
+               } else {
+                       /* Without overlaps, each packet reassembly (== one
+                        * send/receive pair below) takes very little time to
+                        * run, so we can easily afford more thourough testing
+                        * with a nested loop: the full non-overlap test takes
+                        * less than one second).
+                        */
+                       max_frag_len = min_frag_len;
+                       do {
+                               send_udp_frags(fd_tx_raw, addr, alen, ipv6);
+                               recv_validate_udp(fd_rx_udp);
+                               max_frag_len += 8 * (rand() % 8);
+                       } while (max_frag_len < (1500 - FRAG_HLEN) &&
+                                max_frag_len <= payload_len);
+               }
        }
 
        /* Cleanup. */
index f34672796044952a9a7b7b02496ac08ed29bd885..7dd79a9efb1772945f7b9415d080e0fec5f55a71 100755 (executable)
@@ -11,10 +11,17 @@ readonly NETNS="ns-$(mktemp -u XXXXXX)"
 setup() {
        ip netns add "${NETNS}"
        ip -netns "${NETNS}" link set lo up
+
        ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_high_thresh=9000000 >/dev/null 2>&1
        ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_low_thresh=7000000 >/dev/null 2>&1
+       ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_time=1 >/dev/null 2>&1
+
        ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_high_thresh=9000000 >/dev/null 2>&1
        ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_low_thresh=7000000 >/dev/null 2>&1
+       ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_time=1 >/dev/null 2>&1
+
+       # DST cache can get full with a lot of frags, with GC not keeping up with the test.
+       ip netns exec "${NETNS}" sysctl -w net.ipv6.route.max_size=65536 >/dev/null 2>&1
 }
 
 cleanup() {
@@ -27,7 +34,6 @@ setup
 echo "ipv4 defrag"
 ip netns exec "${NETNS}" ./ip_defrag -4
 
-
 echo "ipv4 defrag with overlaps"
 ip netns exec "${NETNS}" ./ip_defrag -4o
 
@@ -37,3 +43,4 @@ ip netns exec "${NETNS}" ./ip_defrag -6
 echo "ipv6 defrag with overlaps"
 ip netns exec "${NETNS}" ./ip_defrag -6o
 
+echo "all tests done"
index 8db35b99457c65966fb8c81524c7a7b87119449a..71d7fdc513c1bbe270688d732a415c390007ec45 100755 (executable)
@@ -28,6 +28,19 @@ KEY_AES=0x0123456789abcdef0123456789012345
 SPI1=0x1
 SPI2=0x2
 
+do_esp_policy() {
+    local ns=$1
+    local me=$2
+    local remote=$3
+    local lnet=$4
+    local rnet=$5
+
+    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
+    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow
+    # to fwd decrypted packets after esp processing:
+    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow
+}
+
 do_esp() {
     local ns=$1
     local me=$2
@@ -40,10 +53,59 @@ do_esp() {
     ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in  enc aes $KEY_AES  auth sha1 $KEY_SHA  mode tunnel sel src $rnet dst $lnet
     ip -net $ns xfrm state add src $me  dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
 
-    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
-    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow
-    # to fwd decrypted packets after esp processing:
-    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow
+    do_esp_policy $ns $me $remote $lnet $rnet
+}
+
+# add policies with different netmasks, to make sure kernel carries
+# the policies contained within new netmask over when search tree is
+# re-built.
+# peer netns that are supposed to be encapsulated via esp have addresses
+# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively.
+#
+# Adding a policy for '10.0.1.0/23' will make it necessary to
+# alter the prefix of 10.0.1.0 subnet.
+# In case new prefix overlaps with existing node, the node and all
+# policies it carries need to be merged with the existing one(s).
+#
+# Do that here.
+do_overlap()
+{
+    local ns=$1
+
+    # adds new nodes to tree (neither network exists yet in policy database).
+    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
+
+    # adds a new node in the 10.0.0.0/24 tree (dst node exists).
+    ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
+
+    # adds a 10.2.0.0/23 node, but for different dst.
+    ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block
+
+    # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd.
+    # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23.
+    # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node
+    # also has to be merged too, including source-sorted subtrees.
+    # old:
+    # 10.0.0.0/24 (node 1 in dst tree of the bin)
+    #    10.1.0.0/24 (node in src tree of dst node 1)
+    #    10.2.0.0/24 (node in src tree of dst node 1)
+    # 10.0.1.0/24 (node 2 in dst tree of the bin)
+    #    10.0.2.0/24 (node in src tree of dst node 2)
+    #    10.2.0.0/24 (node in src tree of dst node 2)
+    #
+    # The next 'policy add' adds dst '10.0.0.0/23', which means
+    # that dst node 1 and dst node 2 have to be merged including
+    # the sub-tree.  As no duplicates are allowed, policies in
+    # the two '10.0.2.0/24' are also merged.
+    #
+    # after the 'add', internal search tree should look like this:
+    # 10.0.0.0/23 (node in dst tree of bin)
+    #     10.0.2.0/24 (node in src tree of dst node)
+    #     10.1.0.0/24 (node in src tree of dst node)
+    #     10.2.0.0/24 (node in src tree of dst node)
+    #
+    # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
+    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
 }
 
 do_esp_policy_get_check() {
@@ -160,6 +222,41 @@ check_xfrm() {
        return $lret
 }
 
+check_exceptions()
+{
+       logpostfix="$1"
+       local lret=0
+
+       # ping to .254 should be excluded from the tunnel (exception is in place).
+       check_xfrm 0 254
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .254 to fail ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)"
+       fi
+
+       # ping to .253 should use use ipsec due to direct policy exception.
+       check_xfrm 1 253
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: direct policy matches ($logpostfix)"
+       fi
+
+       # ping to .2 should use ipsec.
+       check_xfrm 1 2
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: policy matches ($logpostfix)"
+       fi
+
+       return $lret
+}
+
 #check for needed privileges
 if [ "$(id -u)" -ne 0 ];then
        echo "SKIP: Need root privileges"
@@ -270,33 +367,45 @@ do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28
 do_exception ns3 dead:3::1 dead:3::10 dead:2::fd  dead:2:f0::/96
 do_exception ns4 dead:3::10 dead:3::1 dead:1::fd  dead:1:f0::/96
 
-# ping to .254 should now be excluded from the tunnel
-check_xfrm 0 254
+check_exceptions "exceptions"
 if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .254 to fail"
        ret=1
-else
-       echo "PASS: ping to .254 bypassed ipsec tunnel"
 fi
 
-# ping to .253 should use use ipsec due to direct policy exception.
-check_xfrm 1 253
-if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .253 to use ipsec tunnel"
-       ret=1
-else
-       echo "PASS: direct policy matches"
-fi
+# insert block policies with adjacent/overlapping netmasks
+do_overlap ns3
 
-# ping to .2 should use ipsec.
-check_xfrm 1 2
+check_exceptions "exceptions and block policies"
 if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .2 to use ipsec tunnel"
        ret=1
-else
-       echo "PASS: policy matches"
 fi
 
+for n in ns3 ns4;do
+       ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125
+       sleep $((RANDOM%5))
+done
+
+check_exceptions "exceptions and block policies after hresh changes"
+
+# full flush of policy db, check everything gets freed incl. internal meta data
+ip -net ns3 xfrm policy flush
+
+do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24
+do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
+
+# move inexact policies to hash table
+ip -net ns3 xfrm policy set hthresh4 16 16
+
+sleep $((RANDOM%5))
+check_exceptions "exceptions and block policies after hthresh change in ns3"
+
+# restore original hthresh settings -- move policies back to tables
+for n in ns3 ns4;do
+       ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
+       sleep $((RANDOM%5))
+done
+check_exceptions "exceptions and block policies after hresh change to normal"
+
 for i in 1 2 3 4;do ip netns del ns$i;done
 
 exit $ret
index 47ed6cef93fb8ff860f944223a176026821fbd54..c9ff2b47bd1ca3a2f70ee0683cb2b79b170c74f5 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for netfilter selftests
 
-TEST_PROGS := nft_trans_stress.sh
+TEST_PROGS := nft_trans_stress.sh nft_nat.sh
 
 include ../lib.mk
index 1017313e41a85e160f62a815d693836aaf1d4521..59caa8f71cd80e133b11acde1fb969077eebfecf 100644 (file)
@@ -1,2 +1,2 @@
 CONFIG_NET_NS=y
-NF_TABLES_INET=y
+CONFIG_NF_TABLES_INET=y
diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh
new file mode 100755 (executable)
index 0000000..8ec7668
--- /dev/null
@@ -0,0 +1,762 @@
+#!/bin/bash
+#
+# This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
+#
+
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+ret=0
+
+nft --version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without nft tool"
+       exit $ksft_skip
+fi
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+
+ip netns add ns0
+ip netns add ns1
+ip netns add ns2
+
+ip link add veth0 netns ns0 type veth peer name eth0 netns ns1
+ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
+
+ip -net ns0 link set lo up
+ip -net ns0 link set veth0 up
+ip -net ns0 addr add 10.0.1.1/24 dev veth0
+ip -net ns0 addr add dead:1::1/64 dev veth0
+
+ip -net ns0 link set veth1 up
+ip -net ns0 addr add 10.0.2.1/24 dev veth1
+ip -net ns0 addr add dead:2::1/64 dev veth1
+
+for i in 1 2; do
+  ip -net ns$i link set lo up
+  ip -net ns$i link set eth0 up
+  ip -net ns$i addr add 10.0.$i.99/24 dev eth0
+  ip -net ns$i route add default via 10.0.$i.1
+  ip -net ns$i addr add dead:$i::99/64 dev eth0
+  ip -net ns$i route add default via dead:$i::1
+done
+
+bad_counter()
+{
+       local ns=$1
+       local counter=$2
+       local expect=$3
+
+       echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
+       ip netns exec $ns nft list counter inet filter $counter 1>&2
+}
+
+check_counters()
+{
+       ns=$1
+       local lret=0
+
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0in "packets 1 bytes 84"
+               lret=1
+       fi
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0out "packets 1 bytes 84"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0in6 "$expect"
+               lret=1
+       fi
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0out6 "$expect"
+               lret=1
+       fi
+
+       return $lret
+}
+
+check_ns0_counters()
+{
+       local ns=$1
+       local lret=0
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0in "packets 0 bytes 0"
+               lret=1
+       fi
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0in6 "packets 0 bytes 0"
+               lret=1
+       fi
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0out "packets 0 bytes 0"
+               lret=1
+       fi
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0out6 "packets 0 bytes 0"
+               lret=1
+       fi
+
+       for dir in "in" "out" ; do
+               expect="packets 1 bytes 84"
+               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 $ns$dir "$expect"
+                       lret=1
+               fi
+
+               expect="packets 1 bytes 104"
+               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 $ns$dir6 "$expect"
+                       lret=1
+               fi
+       done
+
+       return $lret
+}
+
+reset_counters()
+{
+       for i in 0 1 2;do
+               ip netns exec ns$i nft reset counters inet > /dev/null
+       done
+}
+
+test_local_dnat6()
+{
+       local lret=0
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain output {
+               type nat hook output priority 0; policy accept;
+               ip6 daddr dead:1::99 dnat to dead:2::99
+       }
+}
+EOF
+       if [ $? -ne 0 ]; then
+               echo "SKIP: Could not add add ip6 dnat hook"
+               return $ksft_skip
+       fi
+
+       # ping netns1, expect rewrite to netns2
+       ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping6 failed"
+               return $lret
+       fi
+
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 count in ns1
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 packet in ns2
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was NATted to ns2"
+       ip netns exec ns0 nft flush chain ip6 nat output
+
+       return $lret
+}
+
+test_local_dnat()
+{
+       local lret=0
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain output {
+               type nat hook output priority 0; policy accept;
+               ip daddr 10.0.1.99 dnat to 10.0.2.99
+       }
+}
+EOF
+       # ping netns1, expect rewrite to netns2
+       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping failed"
+               return $lret
+       fi
+
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 count in ns1
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 packet in ns2
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ping to ns1 was NATted to ns2"
+
+       ip netns exec ns0 nft flush chain ip nat output
+
+       reset_counters
+       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping failed"
+               return $lret
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 count in ns1
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 packet in ns2
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ping to ns1 OK after nat output chain flush"
+
+       return $lret
+}
+
+
+test_masquerade6()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 via ipv6"
+               return 1
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add masquerading rule
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain postrouting {
+               type nat hook postrouting priority 0; policy accept;
+               meta oif veth0 masquerade
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerading"
+               lret=1
+       fi
+
+       # ns1 should have seen packets from ns0, due to masquerade
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns1 should not have seen packets from ns2, due to masquerade
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft flush chain ip6 nat postrouting
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not flush ip6 nat postrouting" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IPv6 masquerade for ns2"
+
+       return $lret
+}
+
+test_masquerade()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: canot ping ns1 from ns2"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add masquerading rule
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain postrouting {
+               type nat hook postrouting priority 0; policy accept;
+               meta oif veth0 masquerade
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip masquerading"
+               lret=1
+       fi
+
+       # ns1 should have seen packets from ns0, due to masquerade
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns1 should not have seen packets from ns2, due to masquerade
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft flush chain ip nat postrouting
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not flush nat postrouting" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IP masquerade for ns2"
+
+       return $lret
+}
+
+test_redirect6()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add redirect rule
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain prerouting {
+               type nat hook prerouting priority 0; policy accept;
+               meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip6 redirect"
+               lret=1
+       fi
+
+       # ns1 should have seen no packets from ns2, due to redirection
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns0 should have seen packets from ns2, due to masquerade
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft delete table ip6 nat
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not delete ip6 nat table" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IPv6 redirection for ns2"
+
+       return $lret
+}
+
+test_redirect()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add redirect rule
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain prerouting {
+               type nat hook prerouting priority 0; policy accept;
+               meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip redirect"
+               lret=1
+       fi
+
+       # ns1 should have seen no packets from ns2, due to redirection
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns0 should have seen packets from ns2, due to masquerade
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft delete table ip nat
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not delete nat table" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IP redirection for ns2"
+
+       return $lret
+}
+
+
+# ip netns exec ns0 ping -c 1 -q 10.0.$i.99
+for i in 0 1 2; do
+ip netns exec ns$i nft -f - <<EOF
+table inet filter {
+       counter ns0in {}
+       counter ns1in {}
+       counter ns2in {}
+
+       counter ns0out {}
+       counter ns1out {}
+       counter ns2out {}
+
+       counter ns0in6 {}
+       counter ns1in6 {}
+       counter ns2in6 {}
+
+       counter ns0out6 {}
+       counter ns1out6 {}
+       counter ns2out6 {}
+
+       map nsincounter {
+               type ipv4_addr : counter
+               elements = { 10.0.1.1 : "ns0in",
+                            10.0.2.1 : "ns0in",
+                            10.0.1.99 : "ns1in",
+                            10.0.2.99 : "ns2in" }
+       }
+
+       map nsincounter6 {
+               type ipv6_addr : counter
+               elements = { dead:1::1 : "ns0in6",
+                            dead:2::1 : "ns0in6",
+                            dead:1::99 : "ns1in6",
+                            dead:2::99 : "ns2in6" }
+       }
+
+       map nsoutcounter {
+               type ipv4_addr : counter
+               elements = { 10.0.1.1 : "ns0out",
+                            10.0.2.1 : "ns0out",
+                            10.0.1.99: "ns1out",
+                            10.0.2.99: "ns2out" }
+       }
+
+       map nsoutcounter6 {
+               type ipv6_addr : counter
+               elements = { dead:1::1 : "ns0out6",
+                            dead:2::1 : "ns0out6",
+                            dead:1::99 : "ns1out6",
+                            dead:2::99 : "ns2out6" }
+       }
+
+       chain input {
+               type filter hook input priority 0; policy accept;
+               counter name ip saddr map @nsincounter
+               icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
+       }
+       chain output {
+               type filter hook output priority 0; policy accept;
+               counter name ip daddr map @nsoutcounter
+               icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
+       }
+}
+EOF
+done
+
+sleep 3
+# test basic connectivity
+for i in 1 2; do
+  ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
+  if [ $? -ne 0 ];then
+       echo "ERROR: Could not reach other namespace(s)" 1>&2
+       ret=1
+  fi
+
+  ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
+  if [ $? -ne 0 ];then
+       echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
+       ret=1
+  fi
+  check_counters ns$i
+  if [ $? -ne 0 ]; then
+       ret=1
+  fi
+
+  check_ns0_counters ns$i
+  if [ $? -ne 0 ]; then
+       ret=1
+  fi
+  reset_counters
+done
+
+if [ $ret -eq 0 ];then
+       echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
+fi
+
+reset_counters
+test_local_dnat
+test_local_dnat6
+
+reset_counters
+test_masquerade
+test_masquerade6
+
+reset_counters
+test_redirect
+test_redirect6
+
+for i in 0 1 2; do ip netns del ns$i;done
+
+exit $ret
index 9050eeea5f5f29531c304f8a36f2f9959f6b1cd3..1de8bd8ccf5dd7c801964b2957cc09fdf335d080 100644 (file)
@@ -9,6 +9,3 @@ all: $(TEST_PROGS)
 top_srcdir = ../../../../..
 KSFT_KHDR_INSTALL := 1
 include ../../lib.mk
-
-clean:
-       rm -fr $(TEST_GEN_FILES)
index 2e563d17cf0c1ccaa12a59e182488f39657000b7..d1bbafb16f476df49fa9b4f0c3277d677286e4b0 100644 (file)
@@ -240,7 +240,7 @@ static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
                            cm->cmsg_type == IP_RECVERR) ||
                           (cm->cmsg_level == SOL_IPV6 &&
                            cm->cmsg_type == IPV6_RECVERR) ||
-                          (cm->cmsg_level = SOL_PACKET &&
+                          (cm->cmsg_level == SOL_PACKET &&
                            cm->cmsg_type == PACKET_TX_TIMESTAMP)) {
                        serr = (void *) CMSG_DATA(cm);
                        if (serr->ee_errno != ENOMSG ||
index 82121a81681f7720a16709d659c6e7c53e6a3fa3..29bac5ef9a93dda0b1964223ba77f39c23e75a72 100644 (file)
@@ -10,4 +10,5 @@
 /proc-uptime-002
 /read
 /self
+/setns-dcache
 /thread-self
index 1c12c34cf85d801b09c6adbfe1fb1067c55283e8..434d033ee06774aa4a14b75c8dfed7dacf2f75a4 100644 (file)
@@ -14,6 +14,7 @@ TEST_GEN_PROGS += proc-uptime-001
 TEST_GEN_PROGS += proc-uptime-002
 TEST_GEN_PROGS += read
 TEST_GEN_PROGS += self
+TEST_GEN_PROGS += setns-dcache
 TEST_GEN_PROGS += thread-self
 
 include ../lib.mk
diff --git a/tools/testing/selftests/proc/setns-dcache.c b/tools/testing/selftests/proc/setns-dcache.c
new file mode 100644 (file)
index 0000000..60ab197
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright Â© 2019 Alexey Dobriyan <adobriyan@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Test that setns(CLONE_NEWNET) points to new /proc/net content even
+ * if old one is in dcache.
+ *
+ * FIXME /proc/net/unix is under CONFIG_UNIX which can be disabled.
+ */
+#undef NDEBUG
+#include <assert.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+static pid_t pid = -1;
+
+static void f(void)
+{
+       if (pid > 0) {
+               kill(pid, SIGTERM);
+       }
+}
+
+int main(void)
+{
+       int fd[2];
+       char _ = 0;
+       int nsfd;
+
+       atexit(f);
+
+       /* Check for priviledges and syscall availability straight away. */
+       if (unshare(CLONE_NEWNET) == -1) {
+               if (errno == ENOSYS || errno == EPERM) {
+                       return 4;
+               }
+               return 1;
+       }
+       /* Distinguisher between two otherwise empty net namespaces. */
+       if (socket(AF_UNIX, SOCK_STREAM, 0) == -1) {
+               return 1;
+       }
+
+       if (pipe(fd) == -1) {
+               return 1;
+       }
+
+       pid = fork();
+       if (pid == -1) {
+               return 1;
+       }
+
+       if (pid == 0) {
+               if (unshare(CLONE_NEWNET) == -1) {
+                       return 1;
+               }
+
+               if (write(fd[1], &_, 1) != 1) {
+                       return 1;
+               }
+
+               pause();
+
+               return 0;
+       }
+
+       if (read(fd[0], &_, 1) != 1) {
+               return 1;
+       }
+
+       {
+               char buf[64];
+               snprintf(buf, sizeof(buf), "/proc/%u/ns/net", pid);
+               nsfd = open(buf, O_RDONLY);
+               if (nsfd == -1) {
+                       return 1;
+               }
+       }
+
+       /* Reliably pin dentry into dcache. */
+       (void)open("/proc/net/unix", O_RDONLY);
+
+       if (setns(nsfd, CLONE_NEWNET) == -1) {
+               return 1;
+       }
+
+       kill(pid, SIGTERM);
+       pid = 0;
+
+       {
+               char buf[4096];
+               ssize_t rv;
+               int fd;
+
+               fd = open("/proc/net/unix", O_RDONLY);
+               if (fd == -1) {
+                       return 1;
+               }
+
+#define S "Num       RefCount Protocol Flags    Type St Inode Path\n"
+               rv = read(fd, buf, sizeof(buf));
+
+               assert(rv == strlen(S));
+               assert(memcmp(buf, S, strlen(S)) == 0);
+       }
+
+       return 0;
+}
index e20b017e70731c13a8128dbf8396ddfb2f861958..b2065536d40757eeac0487aff3a95c5fcec9467d 100644 (file)
@@ -145,15 +145,12 @@ TEST_F(rtc, alarm_alm_set) {
 
        rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
        ASSERT_NE(-1, rc);
-       EXPECT_NE(0, rc);
+       ASSERT_NE(0, rc);
 
        /* Disable alarm interrupts */
        rc = ioctl(self->fd, RTC_AIE_OFF, 0);
        ASSERT_NE(-1, rc);
 
-       if (rc == 0)
-               return;
-
        rc = read(self->fd, &data, sizeof(unsigned long));
        ASSERT_NE(-1, rc);
        TH_LOG("data: %lx", data);
@@ -202,7 +199,109 @@ TEST_F(rtc, alarm_wkalm_set) {
 
        rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
        ASSERT_NE(-1, rc);
-       EXPECT_NE(0, rc);
+       ASSERT_NE(0, rc);
+
+       rc = read(self->fd, &data, sizeof(unsigned long));
+       ASSERT_NE(-1, rc);
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       new = timegm((struct tm *)&tm);
+       ASSERT_EQ(new, secs);
+}
+
+TEST_F(rtc, alarm_alm_set_minute) {
+       struct timeval tv = { .tv_sec = 62 };
+       unsigned long data;
+       struct rtc_time tm;
+       fd_set readfds;
+       time_t secs, new;
+       int rc;
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec;
+       gmtime_r(&secs, (struct tm *)&tm);
+
+       rc = ioctl(self->fd, RTC_ALM_SET, &tm);
+       if (rc == -1) {
+               ASSERT_EQ(EINVAL, errno);
+               TH_LOG("skip alarms are not supported.");
+               return;
+       }
+
+       rc = ioctl(self->fd, RTC_ALM_READ, &tm);
+       ASSERT_NE(-1, rc);
+
+       TH_LOG("Alarm time now set to %02d:%02d:%02d.",
+              tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+       /* Enable alarm interrupts */
+       rc = ioctl(self->fd, RTC_AIE_ON, 0);
+       ASSERT_NE(-1, rc);
+
+       FD_ZERO(&readfds);
+       FD_SET(self->fd, &readfds);
+
+       rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
+       ASSERT_NE(-1, rc);
+       ASSERT_NE(0, rc);
+
+       /* Disable alarm interrupts */
+       rc = ioctl(self->fd, RTC_AIE_OFF, 0);
+       ASSERT_NE(-1, rc);
+
+       rc = read(self->fd, &data, sizeof(unsigned long));
+       ASSERT_NE(-1, rc);
+       TH_LOG("data: %lx", data);
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       new = timegm((struct tm *)&tm);
+       ASSERT_EQ(new, secs);
+}
+
+TEST_F(rtc, alarm_wkalm_set_minute) {
+       struct timeval tv = { .tv_sec = 62 };
+       struct rtc_wkalrm alarm = { 0 };
+       struct rtc_time tm;
+       unsigned long data;
+       fd_set readfds;
+       time_t secs, new;
+       int rc;
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
+       ASSERT_NE(-1, rc);
+
+       secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec;
+       gmtime_r(&secs, (struct tm *)&alarm.time);
+
+       alarm.enabled = 1;
+
+       rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
+       if (rc == -1) {
+               ASSERT_EQ(EINVAL, errno);
+               TH_LOG("skip alarms are not supported.");
+               return;
+       }
+
+       rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
+       ASSERT_NE(-1, rc);
+
+       TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
+              alarm.time.tm_mday, alarm.time.tm_mon + 1,
+              alarm.time.tm_year + 1900, alarm.time.tm_hour,
+              alarm.time.tm_min, alarm.time.tm_sec);
+
+       FD_ZERO(&readfds);
+       FD_SET(self->fd, &readfds);
+
+       rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
+       ASSERT_NE(-1, rc);
+       ASSERT_NE(0, rc);
 
        rc = read(self->fd, &data, sizeof(unsigned long));
        ASSERT_NE(-1, rc);
index fce7f4ce069251a675c05f30f412c5361c4dbde3..1760b3e397306ce951498688692776a506e5fd10 100644 (file)
@@ -9,7 +9,7 @@ BINARIES := seccomp_bpf seccomp_benchmark
 CFLAGS += -Wl,-no-as-needed -Wall
 
 seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
-       $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
+       $(CC) $(CFLAGS) $(LDFLAGS) $< -lpthread -o $@
 
 TEST_PROGS += $(BINARIES)
 EXTRA_CLEAN := $(BINARIES)
index 067cb4607d6cd519793b4ea2d26a5ef96f446e89..7e632b465ab48eea860ab32e2a2cb9b2ea1d0a4f 100644 (file)
@@ -1608,7 +1608,16 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 #ifdef SYSCALL_NUM_RET_SHARE_REG
 # define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(-1, action)
 #else
-# define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(val, action)
+# define EXPECT_SYSCALL_RETURN(val, action)            \
+       do {                                            \
+               errno = 0;                              \
+               if (val < 0) {                          \
+                       EXPECT_EQ(-1, action);          \
+                       EXPECT_EQ(-(val), errno);       \
+               } else {                                \
+                       EXPECT_EQ(val, action);         \
+               }                                       \
+       } while (0)
 #endif
 
 /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
@@ -1647,7 +1656,7 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
 
 /* Architecture-specific syscall changing routine. */
 void change_syscall(struct __test_metadata *_metadata,
-                   pid_t tracee, int syscall)
+                   pid_t tracee, int syscall, int result)
 {
        int ret;
        ARCH_REGS regs;
@@ -1706,7 +1715,7 @@ void change_syscall(struct __test_metadata *_metadata,
 #ifdef SYSCALL_NUM_RET_SHARE_REG
                TH_LOG("Can't modify syscall return on this architecture");
 #else
-               regs.SYSCALL_RET = EPERM;
+               regs.SYSCALL_RET = result;
 #endif
 
 #ifdef HAVE_GETREGS
@@ -1734,14 +1743,19 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
        case 0x1002:
                /* change getpid to getppid. */
                EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
-               change_syscall(_metadata, tracee, __NR_getppid);
+               change_syscall(_metadata, tracee, __NR_getppid, 0);
                break;
        case 0x1003:
-               /* skip gettid. */
+               /* skip gettid with valid return code. */
                EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
-               change_syscall(_metadata, tracee, -1);
+               change_syscall(_metadata, tracee, -1, 45000);
                break;
        case 0x1004:
+               /* skip openat with error. */
+               EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
+               change_syscall(_metadata, tracee, -1, -ESRCH);
+               break;
+       case 0x1005:
                /* do nothing (allow getppid) */
                EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
                break;
@@ -1774,9 +1788,11 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
        nr = get_syscall(_metadata, tracee);
 
        if (nr == __NR_getpid)
-               change_syscall(_metadata, tracee, __NR_getppid);
+               change_syscall(_metadata, tracee, __NR_getppid, 0);
+       if (nr == __NR_gettid)
+               change_syscall(_metadata, tracee, -1, 45000);
        if (nr == __NR_openat)
-               change_syscall(_metadata, tracee, -1);
+               change_syscall(_metadata, tracee, -1, -ESRCH);
 }
 
 FIXTURE_DATA(TRACE_syscall) {
@@ -1793,8 +1809,10 @@ FIXTURE_SETUP(TRACE_syscall)
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
                BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
        };
 
@@ -1842,15 +1860,26 @@ TEST_F(TRACE_syscall, ptrace_syscall_redirected)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, ptrace_syscall_dropped)
+TEST_F(TRACE_syscall, ptrace_syscall_errno)
+{
+       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+       teardown_trace_fixture(_metadata, self->tracer);
+       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+                                          true);
+
+       /* Tracer should skip the open syscall, resulting in ESRCH. */
+       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, ptrace_syscall_faked)
 {
        /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
        teardown_trace_fixture(_metadata, self->tracer);
        self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
                                           true);
 
-       /* Tracer should skip the open syscall, resulting in EPERM. */
-       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_openat));
+       /* Tracer should skip the gettid syscall, resulting fake pid. */
+       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, syscall_allowed)
@@ -1883,7 +1912,21 @@ TEST_F(TRACE_syscall, syscall_redirected)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, syscall_dropped)
+TEST_F(TRACE_syscall, syscall_errno)
+{
+       long ret;
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       /* openat has been skipped and an errno return. */
+       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, syscall_faked)
 {
        long ret;
 
@@ -1894,8 +1937,7 @@ TEST_F(TRACE_syscall, syscall_dropped)
        ASSERT_EQ(0, ret);
 
        /* gettid has been skipped and an altered return value stored. */
-       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
-       EXPECT_NE(self->mytid, syscall(__NR_gettid));
+       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, skip_after_RET_TRACE)
@@ -3044,7 +3086,7 @@ TEST(user_notification_basic)
        /* Check that the basic notification machinery works */
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /* Installing a second listener in the chain should EBUSY */
        EXPECT_EQ(user_trap_syscall(__NR_getpid,
@@ -3103,7 +3145,7 @@ TEST(user_notification_kill_in_middle)
 
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /*
         * Check that nothing bad happens when we kill the task in the middle
@@ -3152,7 +3194,7 @@ TEST(user_notification_signal)
 
        listener = user_trap_syscall(__NR_gettid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        pid = fork();
        ASSERT_GE(pid, 0);
@@ -3215,7 +3257,7 @@ TEST(user_notification_closed_listener)
 
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /*
         * Check that we get an ENOSYS when the listener is closed.
@@ -3376,7 +3418,7 @@ TEST(seccomp_get_notif_sizes)
 {
        struct seccomp_notif_sizes sizes;
 
-       EXPECT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
+       ASSERT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
        EXPECT_EQ(sizes.seccomp_notif, sizeof(struct seccomp_notif));
        EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp));
 }
index 637ea0219617f3beb9a69016e5b613bf173f5ada..0da3545cabdb6239190c8e916d28e25a882b78d2 100644 (file)
@@ -17,7 +17,7 @@
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -41,7 +41,7 @@
         "cmdUnderTest": "$TC actions add action ife encode use mark 10 pipe index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -65,7 +65,7 @@
         "cmdUnderTest": "$TC actions add action ife encode allow mark continue index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*allow mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*allow mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -89,7 +89,7 @@
         "cmdUnderTest": "$TC actions add action ife encode use mark 789 drop index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*use mark 789.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*use mark 789.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 656768 reclassify index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use mark 656768.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use mark 656768.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 65 jump 1 index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action jump 1.*type 0xED3E.*use mark 65.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action jump 1.*type 0[xX]ED3E.*use mark 65.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 4294967295 reclassify index 90",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 90",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use mark 4294967295.*index 90",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use mark 4294967295.*index 90",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 4294967295999 pipe index 90",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 90",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use mark 4294967295999.*index 90",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use mark 4294967295999.*index 90",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio pass index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow prio.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow prio.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 7 pipe index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use prio 7.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use prio 7.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 3 continue index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use prio 3.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use prio 3.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow prio drop index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*allow prio.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*allow prio.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 998877 reclassify index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 998877.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 998877.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 998877 jump 10 index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action jump 10.*type 0xED3E.*use prio 998877.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action jump 10.*type 0[xX]ED3E.*use prio 998877.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 4294967295 reclassify index 99",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 99",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 4294967295.*index 99",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 4294967295.*index 99",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 4294967298 pipe index 99",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 99",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use prio 4294967298.*index 99",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use prio 4294967298.*index 99",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow tcindex.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow tcindex.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 111 pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use tcindex 111.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use tcindex 111.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 1 continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use tcindex 1.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use tcindex 1.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 1 continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use tcindex 1.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use tcindex 1.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex drop index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex reclassify index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex jump 999 index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action jump 999.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action jump 999.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 65535 pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*use tcindex 65535.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*use tcindex 65535.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 65539 pipe index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use tcindex 65539.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use tcindex 65539.*index 1",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow mark src 00:11:22:33:44:55 pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow mark src 00:11:22:33:44:55.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow mark src 00:11:22:33:44:55.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 9876 dst 00:11:22:33:44:55 reclassify index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 9876 dst 00:11:22:33:44:55.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 9876 dst 00:11:22:33:44:55.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex src 00:aa:bb:cc:dd:ee dst 00:11:22:33:44:55 pass index 11",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 11",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow tcindex dst 00:11:22:33:44:55 src 00:aa:bb:cc:dd:ee .*index 11",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow tcindex dst 00:11:22:33:44:55 src 00:aa:bb:cc:dd:ee .*index 11",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 7 type 0xfefe pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xFEFE.*use mark 7.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]FEFE.*use mark 7.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 444 type 0xabba pipe index 21",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 21",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xABBA.*use prio 444.*index 21",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ABBA.*use prio 444.*index 21",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 5000 type 0xabcd reclassify index 21",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 21",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xABCD.*use tcindex 5000.*index 21",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ABCD.*use tcindex 5000.*index 21",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
     },
     {
         "id": "fac3",
-        "name": "Create valid ife encode action with index at 32-bit maximnum",
+        "name": "Create valid ife encode action with index at 32-bit maximum",
         "category": [
             "actions",
             "ife"
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 4294967295",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 4294967295",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 4294967295",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 4294967295",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action pass.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action pass.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action pipe.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action pipe.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action continue.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action continue.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode drop index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action drop.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action drop.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode reclassify index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action reclassify.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action reclassify.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode jump 10 index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action jump 10.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action jump 10.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 4294967295999",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4294967295999",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 4294967295999",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 4294967295999",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow mark kuka index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action kuka.*type 0xED3E.*allow mark.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action kuka.*type 0[xX]ED3E.*allow mark.*index 4",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio pipe index 4 cookie aabbccddeeff112233445566778800a1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow prio.*index 4.*cookie aabbccddeeff112233445566778800a1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow prio.*index 4.*cookie aabbccddeeff112233445566778800a1",
         "matchCount": "1",
         "teardown": [
            "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow foo pipe index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow foo.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow foo.*index 4",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio type 70000 pipe index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0x11170.*allow prio.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]11170.*allow prio.*index 4",
         "matchCount": "0",
         "teardown": []
     },
index 10b2d894e43628bb1f8e330448539dffbbb16b32..e7e15a7336b6dfd1516e0276343f4afa735b41dd 100644 (file)
            ]
         ]
     },
-    {
-        "id": "ba4e",
-        "name": "Add tunnel_key set action with missing mandatory id parameter",
-        "category": [
-            "actions",
-            "tunnel_key"
-        ],
-        "setup": [
-            [
-                "$TC actions flush action tunnel_key",
-                0,
-                1,
-                255
-            ]
-        ],
-        "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 20.20.20.2",
-        "expExitCode": "255",
-        "verifyCmd": "$TC actions list action tunnel_key",
-        "matchPattern": "action order [0-9]+: tunnel_key set.*src_ip 10.10.10.1.*dst_ip 20.20.20.2",
-        "matchCount": "0",
-        "teardown": [
-           [
-               "$TC actions flush action tunnel_key",
-               0,
-               1,
-               255
-           ]
-        ]
-    },
     {
         "id": "a5e0",
         "name": "Add tunnel_key set action with invalid src_ip parameter",
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 10.10.10.2 id 7 index 4 cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action tunnel_key index 4",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 10.10.10.2.*key_id 7.*dst_port 0.*csum pipe.*index 4 ref.*cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 10.10.10.2.*key_id 7.*csum pipe.*index 4 ref.*cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action tunnel_key"
index c02683cfb6c9a9f403bbc330fc124d8f8c8e9751..7656c7ce79d905f1b35c112996c8c292618a4c9a 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS += -O3 -Wl,-no-as-needed -Wall
-LDFLAGS += -lrt -lpthread -lm
+LDLIBS += -lrt -lpthread -lm
 
 # these are all "safe" tests that don't modify
 # system time or require escalated privileges
index 880b96fc80d4cabea168a1fb4e9bc5e828c4b0d5..c0534e298b5128d9bc2800abb5b59d7d5379f75e 100644 (file)
@@ -25,6 +25,7 @@ struct gup_benchmark {
        __u64 size;
        __u32 nr_pages_per_call;
        __u32 flags;
+       __u64 expansion[10];    /* For future use */
 };
 
 int main(int argc, char **argv)
index 50f7e92724813a3525154ede4f2b282af7e5a839..bf1bb15b6fbe3e2831a302a01586de6605b242e2 100644 (file)
@@ -1503,7 +1503,7 @@ void check_mpx_insns_and_tables(void)
                exit(20);
        }
        if (successes != total_nr_tests) {
-               eprintf("ERROR: succeded fewer than number of tries (%d != %d)\n",
+               eprintf("ERROR: succeeded fewer than number of tries (%d != %d)\n",
                                successes, total_nr_tests);
                exit(21);
        }
index 460b4bdf4c1edff9d5dfa0d451dbaa393d53b80c..5d546dcdbc805b93516e73ea1dd0757fd1449aff 100644 (file)
@@ -1133,6 +1133,21 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
        pkey_assert(err);
 }
 
+void become_child(void)
+{
+       pid_t forkret;
+
+       forkret = fork();
+       pkey_assert(forkret >= 0);
+       dprintf3("[%d] fork() ret: %d\n", getpid(), forkret);
+
+       if (!forkret) {
+               /* in the child */
+               return;
+       }
+       exit(0);
+}
+
 /* Assumes that all pkeys other than 'pkey' are unallocated */
 void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
 {
@@ -1141,7 +1156,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
        int nr_allocated_pkeys = 0;
        int i;
 
-       for (i = 0; i < NR_PKEYS*2; i++) {
+       for (i = 0; i < NR_PKEYS*3; i++) {
                int new_pkey;
                dprintf1("%s() alloc loop: %d\n", __func__, i);
                new_pkey = alloc_pkey();
@@ -1152,20 +1167,26 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
                if ((new_pkey == -1) && (errno == ENOSPC)) {
                        dprintf2("%s() failed to allocate pkey after %d tries\n",
                                __func__, nr_allocated_pkeys);
-                       break;
+               } else {
+                       /*
+                        * Ensure the number of successes never
+                        * exceeds the number of keys supported
+                        * in the hardware.
+                        */
+                       pkey_assert(nr_allocated_pkeys < NR_PKEYS);
+                       allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
                }
-               pkey_assert(nr_allocated_pkeys < NR_PKEYS);
-               allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
+
+               /*
+                * Make sure that allocation state is properly
+                * preserved across fork().
+                */
+               if (i == NR_PKEYS*2)
+                       become_child();
        }
 
        dprintf3("%s()::%d\n", __func__, __LINE__);
 
-       /*
-        * ensure it did not reach the end of the loop without
-        * failure:
-        */
-       pkey_assert(i < NR_PKEYS*2);
-
        /*
         * There are 16 pkeys supported in hardware.  Three are
         * allocated by the time we get here:
index 00a26a82fa98b1eec4f82046b9a88517ceb8c7e4..97311333700e7154e19c86f5b5de29208332b429 100644 (file)
@@ -44,7 +44,6 @@ int main()
 #include <stdbool.h>
 #include <sys/ptrace.h>
 #include <sys/user.h>
-#include <sys/ucontext.h>
 #include <link.h>
 #include <sys/auxv.h>
 #include <dlfcn.h>
index 9e350fd3450456a927ac2a0889ccaf2cfe6d6030..9c486fad3f9f8289e2d8989928a34459bb2dd105 100644 (file)
@@ -626,6 +626,13 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
                /* Awaken to handle a signal, request we sleep again later. */
                kvm_make_request(KVM_REQ_SLEEP, vcpu);
        }
+
+       /*
+        * Make sure we will observe a potential reset request if we've
+        * observed a change to the power state. Pairs with the smp_wmb() in
+        * kvm_psci_vcpu_on().
+        */
+       smp_rmb();
 }
 
 static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
@@ -639,6 +646,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
                if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
                        vcpu_req_sleep(vcpu);
 
+               if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
+                       kvm_reset_vcpu(vcpu);
+
                /*
                 * Clear IRQ_PENDING requests that were made to guarantee
                 * that a VCPU sees new virtual interrupts.
index fbdf3ac2f001069f35c92e6ef4c6be878e01221d..30251e2886298ea30489d106712c8fe958f48fb8 100644 (file)
@@ -1695,11 +1695,14 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
        vma_pagesize = vma_kernel_pagesize(vma);
        /*
-        * PUD level may not exist for a VM but PMD is guaranteed to
-        * exist.
+        * The stage2 has a minimum of 2 level table (For arm64 see
+        * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can
+        * use PMD_SIZE huge mappings (even when the PMD is folded into PGD).
+        * As for PUD huge maps, we must make sure that we have at least
+        * 3 levels, i.e, PMD is not folded.
         */
        if ((vma_pagesize == PMD_SIZE ||
-            (vma_pagesize == PUD_SIZE && kvm_stage2_has_pud(kvm))) &&
+            (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) &&
            !force_pte) {
                gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
        }
index 9b73d3ad918a4520a3a7ecf6897836abc0887f9c..34d08ee637471762529017a8341152468a5bdfd4 100644 (file)
@@ -104,12 +104,10 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
 
 static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 {
+       struct vcpu_reset_state *reset_state;
        struct kvm *kvm = source_vcpu->kvm;
        struct kvm_vcpu *vcpu = NULL;
-       struct swait_queue_head *wq;
        unsigned long cpu_id;
-       unsigned long context_id;
-       phys_addr_t target_pc;
 
        cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
        if (vcpu_mode_is_32bit(source_vcpu))
@@ -130,32 +128,30 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
                        return PSCI_RET_INVALID_PARAMS;
        }
 
-       target_pc = smccc_get_arg2(source_vcpu);
-       context_id = smccc_get_arg3(source_vcpu);
+       reset_state = &vcpu->arch.reset_state;
 
-       kvm_reset_vcpu(vcpu);
-
-       /* Gracefully handle Thumb2 entry point */
-       if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
-               target_pc &= ~((phys_addr_t) 1);
-               vcpu_set_thumb(vcpu);
-       }
+       reset_state->pc = smccc_get_arg2(source_vcpu);
 
        /* Propagate caller endianness */
-       if (kvm_vcpu_is_be(source_vcpu))
-               kvm_vcpu_set_be(vcpu);
+       reset_state->be = kvm_vcpu_is_be(source_vcpu);
 
-       *vcpu_pc(vcpu) = target_pc;
        /*
         * NOTE: We always update r0 (or x0) because for PSCI v0.1
         * the general puspose registers are undefined upon CPU_ON.
         */
-       smccc_set_retval(vcpu, context_id, 0, 0, 0);
-       vcpu->arch.power_off = false;
-       smp_mb();               /* Make sure the above is visible */
+       reset_state->r0 = smccc_get_arg3(source_vcpu);
+
+       WRITE_ONCE(reset_state->reset, true);
+       kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
 
-       wq = kvm_arch_vcpu_wq(vcpu);
-       swake_up_one(wq);
+       /*
+        * Make sure the reset request is observed if the change to
+        * power_state is observed.
+        */
+       smp_wmb();
+
+       vcpu->arch.power_off = false;
+       kvm_vcpu_wake_up(vcpu);
 
        return PSCI_RET_SUCCESS;
 }
index 07aa900bac56a3aa5d85dadc462225905c2c4f0f..1f62f2b8065de78dfaf30d2ccb157ce42b4ad9b2 100644 (file)
@@ -251,9 +251,9 @@ static int vgic_debug_show(struct seq_file *s, void *v)
                return 0;
        }
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        print_irq_state(s, irq, vcpu);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        vgic_put_irq(kvm, irq);
        return 0;
index c0c0b88af1d58c0e1c3015424be66272f4873845..3bdb31eaed641d721ba2b3df3b694d291caf2e9a 100644 (file)
@@ -64,7 +64,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
        struct vgic_dist *dist = &kvm->arch.vgic;
 
        INIT_LIST_HEAD(&dist->lpi_list_head);
-       spin_lock_init(&dist->lpi_list_lock);
+       raw_spin_lock_init(&dist->lpi_list_lock);
 }
 
 /* CREATION */
@@ -171,7 +171,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
 
                irq->intid = i + VGIC_NR_PRIVATE_IRQS;
                INIT_LIST_HEAD(&irq->ap_list);
-               spin_lock_init(&irq->irq_lock);
+               raw_spin_lock_init(&irq->irq_lock);
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu0;
                kref_init(&irq->refcount);
@@ -206,7 +206,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
        vgic_cpu->sgi_iodev.base_addr = VGIC_ADDR_UNDEF;
 
        INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
-       spin_lock_init(&vgic_cpu->ap_list_lock);
+       raw_spin_lock_init(&vgic_cpu->ap_list_lock);
 
        /*
         * Enable and configure all SGIs to be edge-triggered and
@@ -216,7 +216,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
 
                INIT_LIST_HEAD(&irq->ap_list);
-               spin_lock_init(&irq->irq_lock);
+               raw_spin_lock_init(&irq->irq_lock);
                irq->intid = i;
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu;
@@ -231,13 +231,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                        irq->config = VGIC_CONFIG_LEVEL;
                }
 
-               /*
-                * GICv3 can only be created via the KVM_DEVICE_CREATE API and
-                * so we always know the emulation type at this point as it's
-                * either explicitly configured as GICv3, or explicitly
-                * configured as GICv2, or not configured yet which also
-                * implies GICv2.
-                */
                if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
                        irq->group = 1;
                else
@@ -281,7 +274,7 @@ int vgic_init(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct kvm_vcpu *vcpu;
-       int ret = 0, i;
+       int ret = 0, i, idx;
 
        if (vgic_initialized(kvm))
                return 0;
@@ -298,6 +291,19 @@ int vgic_init(struct kvm *kvm)
        if (ret)
                goto out;
 
+       /* Initialize groups on CPUs created before the VGIC type was known */
+       kvm_for_each_vcpu(idx, vcpu, kvm) {
+               struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+               for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+                       struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+                       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+                               irq->group = 1;
+                       else
+                               irq->group = 0;
+               }
+       }
+
        if (vgic_has_its(kvm)) {
                ret = vgic_v4_init(kvm);
                if (ret)
index eb2a390a6c864393b9cba89eaa544ec1972bda8d..ab3f47745d9caaedf263577c4a7263d6386f70b5 100644 (file)
@@ -65,7 +65,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
 
        INIT_LIST_HEAD(&irq->lpi_list);
        INIT_LIST_HEAD(&irq->ap_list);
-       spin_lock_init(&irq->irq_lock);
+       raw_spin_lock_init(&irq->irq_lock);
 
        irq->config = VGIC_CONFIG_EDGE;
        kref_init(&irq->refcount);
@@ -73,7 +73,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        irq->target_vcpu = vcpu;
        irq->group = 1;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        /*
         * There could be a race with another vgic_add_lpi(), so we need to
@@ -101,7 +101,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        dist->lpi_list_count++;
 
 out_unlock:
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        /*
         * We "cache" the configuration table entries in our struct vgic_irq's.
@@ -287,7 +287,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
        if (ret)
                return ret;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (!filter_vcpu || filter_vcpu == irq->target_vcpu) {
                irq->priority = LPI_PROP_PRIORITY(prop);
@@ -299,7 +299,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
                }
        }
 
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw)
                return its_prop_update_vlpi(irq->host_irq, prop, needs_inv);
@@ -332,7 +332,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
        if (!intids)
                return -ENOMEM;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (i == irq_count)
                        break;
@@ -341,7 +341,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
                        continue;
                intids[i++] = irq->intid;
        }
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        *intid_ptr = intids;
        return i;
@@ -352,9 +352,9 @@ static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
        int ret = 0;
        unsigned long flags;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->target_vcpu = vcpu;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw) {
                struct its_vlpi_map map;
@@ -455,7 +455,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
                }
 
                irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->pending_latch = pendmask & (1U << bit_nr);
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                vgic_put_irq(vcpu->kvm, irq);
@@ -612,7 +612,7 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
                return irq_set_irqchip_state(irq->host_irq,
                                             IRQCHIP_STATE_PENDING, true);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->pending_latch = true;
        vgic_queue_irq_unlock(kvm, irq, flags);
 
index 738b65d2d0e76587d24fa0a44f7107c05400cc49..b535fffc740089f0215259cd5080fd6eca3f081b 100644 (file)
@@ -147,7 +147,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
 
                irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->pending_latch = true;
                irq->source |= 1U << source_vcpu->vcpu_id;
 
@@ -191,13 +191,13 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
                int target;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->targets = (val >> (i * 8)) & cpu_mask;
                target = irq->targets ? __ffs(irq->targets) : 0;
                irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -230,13 +230,13 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->source &= ~((val >> (i * 8)) & 0xff);
                if (!irq->source)
                        irq->pending_latch = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -252,7 +252,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->source |= (val >> (i * 8)) & 0xff;
 
@@ -260,7 +260,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
                        irq->pending_latch = true;
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
                vgic_put_irq(vcpu->kvm, irq);
        }
index b3d1f098511787766b4fbd3567fb87779f5725b2..4a12322bf7df81215d705eb3f7b5ab825d625fdc 100644 (file)
@@ -169,13 +169,13 @@ static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
        if (!irq)
                return;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        /* We only care about and preserve Aff0, Aff1 and Aff2. */
        irq->mpidr = val & GENMASK(23, 0);
        irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
 
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 }
 
@@ -281,7 +281,7 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (test_bit(i, &val)) {
                        /*
                         * pending_latch is set irrespective of irq type
@@ -292,7 +292,7 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
                        irq->pending_latch = false;
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
 
                vgic_put_irq(vcpu->kvm, irq);
@@ -957,7 +957,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
 
                irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                /*
                 * An access targetting Group0 SGIs can only generate
@@ -968,7 +968,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
                        irq->pending_latch = true;
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
 
                vgic_put_irq(vcpu->kvm, irq);
index ceeda7e04a4d9aa57932adeb1140e9d9348e2a0d..7de42fba05b5c7f11a4f254ca69c346d7e48e5d6 100644 (file)
@@ -77,7 +77,7 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->group = !!(val & BIT(i));
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -120,7 +120,7 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->enabled = true;
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -139,11 +139,11 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->enabled = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -160,10 +160,10 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
                unsigned long flags;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq_is_pending(irq))
                        value |= (1U << i);
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -215,7 +215,7 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq->hw)
                        vgic_hw_irq_spending(vcpu, irq, is_uaccess);
                else
@@ -262,14 +262,14 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (irq->hw)
                        vgic_hw_irq_cpending(vcpu, irq, is_uaccess);
                else
                        irq->pending_latch = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -311,7 +311,7 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        unsigned long flags;
        struct kvm_vcpu *requester_vcpu = vgic_get_mmio_requester_vcpu();
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (irq->hw) {
                vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
@@ -342,7 +342,7 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        if (irq->active)
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
        else
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 }
 
 /*
@@ -485,10 +485,10 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                /* Narrow the priority range to what we actually support */
                irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -534,14 +534,14 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
                        continue;
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (test_bit(i * 2 + 1, &val))
                        irq->config = VGIC_CONFIG_EDGE;
                else
                        irq->config = VGIC_CONFIG_LEVEL;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -590,12 +590,12 @@ void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
                 * restore irq config before line level.
                 */
                new_level = !!(val & (1U << i));
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->line_level = new_level;
                if (new_level)
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                else
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
index 69b892abd7dc6faec17e820fe6f4c0f95800ecb3..d91a8938aa7c4eea3c3ee9567be54e5531410e5c 100644 (file)
@@ -84,7 +84,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & GICH_LR_ACTIVE_BIT);
@@ -127,7 +127,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
index 9c0dd234ebe8112f601e81083de436d5547b5c55..4ee0aeb9a9058165bce669c92217cbe73fce1fe6 100644 (file)
@@ -76,7 +76,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                if (!irq)       /* An LPI could have been unmapped. */
                        continue;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & ICH_LR_ACTIVE_BIT);
@@ -119,7 +119,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
@@ -347,9 +347,9 @@ int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq)
 
        status = val & (1 << bit_nr);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        if (irq->target_vcpu != vcpu) {
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                goto retry;
        }
        irq->pending_latch = status;
index 870b1185173b610c9d7fdd42363efe6fdee08868..abd9c735267784a3085b797d33133a579dc629c6 100644 (file)
@@ -54,11 +54,11 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = {
  * When taking more than one ap_list_lock at the same time, always take the
  * lowest numbered VCPU's ap_list_lock first, so:
  *   vcpuX->vcpu_id < vcpuY->vcpu_id:
- *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
- *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ *     raw_spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     raw_spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
  *
  * Since the VGIC must support injecting virtual interrupts from ISRs, we have
- * to use the spin_lock_irqsave/spin_unlock_irqrestore versions of outer
+ * to use the raw_spin_lock_irqsave/raw_spin_unlock_irqrestore versions of outer
  * spinlocks for any lock that may be taken while injecting an interrupt.
  */
 
@@ -72,7 +72,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        struct vgic_irq *irq = NULL;
        unsigned long flags;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (irq->intid != intid)
@@ -88,7 +88,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        irq = NULL;
 
 out_unlock:
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        return irq;
 }
@@ -138,15 +138,15 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
        if (irq->intid < VGIC_MIN_LPI)
                return;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
        if (!kref_put(&irq->refcount, vgic_irq_release)) {
-               spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+               raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
                return;
        };
 
        list_del(&irq->lpi_list);
        dist->lpi_list_count--;
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        kfree(irq);
 }
@@ -244,8 +244,8 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        bool penda, pendb;
        int ret;
 
-       spin_lock(&irqa->irq_lock);
-       spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
+       raw_spin_lock(&irqa->irq_lock);
+       raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
 
        if (irqa->active || irqb->active) {
                ret = (int)irqb->active - (int)irqa->active;
@@ -263,8 +263,8 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        /* Both pending and enabled, sort by priority */
        ret = irqa->priority - irqb->priority;
 out:
-       spin_unlock(&irqb->irq_lock);
-       spin_unlock(&irqa->irq_lock);
+       raw_spin_unlock(&irqb->irq_lock);
+       raw_spin_unlock(&irqa->irq_lock);
        return ret;
 }
 
@@ -325,7 +325,7 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
                 * not need to be inserted into an ap_list and there is also
                 * no more work for us to do.
                 */
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                /*
                 * We have to kick the VCPU here, because we could be
@@ -347,12 +347,12 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
         * We must unlock the irq lock to take the ap_list_lock where
         * we are going to insert this new pending interrupt.
         */
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        /* someone can do stuff here, which we re-check below */
 
-       spin_lock_irqsave(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
-       spin_lock(&irq->irq_lock);
+       raw_spin_lock_irqsave(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+       raw_spin_lock(&irq->irq_lock);
 
        /*
         * Did something change behind our backs?
@@ -367,10 +367,11 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
         */
 
        if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
-               spin_unlock(&irq->irq_lock);
-               spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock,
+                                          flags);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                goto retry;
        }
 
@@ -382,8 +383,8 @@ bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq,
        list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
        irq->vcpu = vcpu;
 
-       spin_unlock(&irq->irq_lock);
-       spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+       raw_spin_unlock(&irq->irq_lock);
+       raw_spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
 
        kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
        kvm_vcpu_kick(vcpu);
@@ -430,11 +431,11 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
        if (!irq)
                return -EINVAL;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (!vgic_validate_injection(irq, level, owner)) {
                /* Nothing to see here, move along... */
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(kvm, irq);
                return 0;
        }
@@ -494,9 +495,9 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
 
        BUG_ON(!irq);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        ret = kvm_vgic_map_irq(vcpu, irq, host_irq, get_input_level);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return ret;
@@ -519,11 +520,11 @@ void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid)
        if (!irq->hw)
                goto out;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->active = false;
        irq->pending_latch = false;
        irq->line_level = false;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 out:
        vgic_put_irq(vcpu->kvm, irq);
 }
@@ -539,9 +540,9 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
        irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
        BUG_ON(!irq);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        kvm_vgic_unmap_irq(irq);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return 0;
@@ -571,12 +572,12 @@ int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner)
                return -EINVAL;
 
        irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        if (irq->owner && irq->owner != owner)
                ret = -EEXIST;
        else
                irq->owner = owner;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        return ret;
 }
@@ -597,13 +598,13 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
 retry:
-       spin_lock(&vgic_cpu->ap_list_lock);
+       raw_spin_lock(&vgic_cpu->ap_list_lock);
 
        list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
                struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
                bool target_vcpu_needs_kick = false;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                BUG_ON(vcpu != irq->vcpu);
 
@@ -616,7 +617,7 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
                         */
                        list_del(&irq->ap_list);
                        irq->vcpu = NULL;
-                       spin_unlock(&irq->irq_lock);
+                       raw_spin_unlock(&irq->irq_lock);
 
                        /*
                         * This vgic_put_irq call matches the
@@ -631,14 +632,14 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
 
                if (target_vcpu == vcpu) {
                        /* We're on the right CPU */
-                       spin_unlock(&irq->irq_lock);
+                       raw_spin_unlock(&irq->irq_lock);
                        continue;
                }
 
                /* This interrupt looks like it has to be migrated. */
 
-               spin_unlock(&irq->irq_lock);
-               spin_unlock(&vgic_cpu->ap_list_lock);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vgic_cpu->ap_list_lock);
 
                /*
                 * Ensure locking order by always locking the smallest
@@ -652,10 +653,10 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
                        vcpuB = vcpu;
                }
 
-               spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
-               spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
-                                SINGLE_DEPTH_NESTING);
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+               raw_spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
+                                     SINGLE_DEPTH_NESTING);
+               raw_spin_lock(&irq->irq_lock);
 
                /*
                 * If the affinity has been preserved, move the
@@ -675,9 +676,9 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
                        target_vcpu_needs_kick = true;
                }
 
-               spin_unlock(&irq->irq_lock);
-               spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
-               spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
 
                if (target_vcpu_needs_kick) {
                        kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
@@ -687,7 +688,7 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
                goto retry;
        }
 
-       spin_unlock(&vgic_cpu->ap_list_lock);
+       raw_spin_unlock(&vgic_cpu->ap_list_lock);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
@@ -741,10 +742,10 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
                int w;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
                /* GICv2 SGIs can count for more than one... */
                w = vgic_irq_get_lr_count(irq);
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                count += w;
                *multi_sgi |= (w > 1);
@@ -770,7 +771,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
        count = 0;
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /*
                 * If we have multi-SGIs in the pipeline, we need to
@@ -780,7 +781,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                 * the AP list has been sorted already.
                 */
                if (multi_sgi && irq->priority > prio) {
-                       spin_unlock(&irq->irq_lock);
+                       _raw_spin_unlock(&irq->irq_lock);
                        break;
                }
 
@@ -791,7 +792,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                                prio = irq->priority;
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                if (count == kvm_vgic_global_state.nr_lr) {
                        if (!list_is_last(&irq->ap_list,
@@ -872,9 +873,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
-       spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+       raw_spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
        vgic_flush_lr_state(vcpu);
-       spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+       raw_spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 
        if (can_access_vgic_from_kernel())
                vgic_restore_state(vcpu);
@@ -918,20 +919,20 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
        vgic_get_vmcr(vcpu, &vmcr);
 
-       spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
+       raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
                pending = irq_is_pending(irq) && irq->enabled &&
                          !irq->active &&
                          irq->priority < vmcr.pmr;
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                if (pending)
                        break;
        }
 
-       spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
+       raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
 
        return pending;
 }
@@ -963,11 +964,10 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
                return false;
 
        irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        map_is_active = irq->hw && irq->active;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return map_is_active;
 }
-
index 5ecea812cb6a24056ee5ab42aa585cb7f5ce15ab..585845203db89e5d2bc90722fd75bfcf595671d9 100644 (file)
@@ -3000,8 +3000,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
        if (ops->init)
                ops->init(dev);
 
+       kvm_get_kvm(kvm);
        ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
        if (ret < 0) {
+               kvm_put_kvm(kvm);
                mutex_lock(&kvm->lock);
                list_del(&dev->vm_node);
                mutex_unlock(&kvm->lock);
@@ -3009,7 +3011,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
                return ret;
        }
 
-       kvm_get_kvm(kvm);
        cd->fd = ret;
        return 0;
 }