Merge branches 'x86/cache', 'x86/debug' and 'x86/irq' into x86/urgent
authorIngo Molnar <mingo@kernel.org>
Mon, 20 Feb 2017 13:16:58 +0000 (14:16 +0100)
committerIngo Molnar <mingo@kernel.org>
Mon, 20 Feb 2017 13:16:58 +0000 (14:16 +0100)
Pick up simple singular commits from their topic branches.

Signed-off-by: Ingo Molnar <mingo@kernel.org>
1338 files changed:
.mailmap
CREDITS
Documentation/ABI/testing/sysfs-devices-deferred_probe [deleted file]
Documentation/admin-guide/kernel-parameters.txt
Documentation/devicetree/bindings/i2c/i2c.txt
Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt
Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
Documentation/devicetree/bindings/mtd/tango-nand.txt
Documentation/devicetree/bindings/net/mediatek-net.txt
Documentation/devicetree/bindings/net/phy.txt
Documentation/devicetree/bindings/net/ti,dp83867.txt
Documentation/devicetree/bindings/power/supply/tps65217_charger.txt
Documentation/devicetree/bindings/spi/sh-msiof.txt
Documentation/driver-api/infrastructure.rst
Documentation/filesystems/proc.txt
Documentation/media/uapi/cec/cec-func-close.rst
Documentation/media/uapi/cec/cec-func-ioctl.rst
Documentation/media/uapi/cec/cec-func-open.rst
Documentation/media/uapi/cec/cec-func-poll.rst
Documentation/media/uapi/cec/cec-intro.rst
Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst
Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst
Documentation/media/uapi/cec/cec-ioc-adap-g-phys-addr.rst
Documentation/media/uapi/cec/cec-ioc-dqevent.rst
Documentation/media/uapi/cec/cec-ioc-g-mode.rst
Documentation/media/uapi/cec/cec-ioc-receive.rst
Documentation/media/uapi/v4l/pixfmt-007.rst
Documentation/power/states.txt
Documentation/vfio-mediated-device.txt
Documentation/vm/page_frags [new file with mode: 0644]
Documentation/x86/intel_rdt_ui.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/include/asm/cache.h
arch/arc/include/asm/delay.h
arch/arc/include/asm/entry-arcv2.h
arch/arc/include/asm/module.h
arch/arc/include/asm/ptrace.h
arch/arc/include/asm/setup.h
arch/arc/kernel/head.S
arch/arc/kernel/intc-arcv2.c
arch/arc/kernel/intc-compact.c
arch/arc/kernel/mcip.c
arch/arc/kernel/module.c
arch/arc/kernel/smp.c
arch/arc/kernel/unaligned.c
arch/arc/mm/cache.c
arch/arc/mm/init.c
arch/arm/Kconfig
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-bone-common.dtsi
arch/arm/boot/dts/am335x-icev2.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am571x-idk.dts
arch/arm/boot/dts/am572x-idk.dts
arch/arm/boot/dts/am57xx-idk-common.dtsi
arch/arm/boot/dts/bcm-nsp.dtsi
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/dm814x.dtsi
arch/arm/boot/dts/dm816x.dtsi
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra72-evm-revc.dts
arch/arm/boot/dts/dra72-evm-tps65917.dtsi
arch/arm/boot/dts/imx1.dtsi
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx25.dtsi
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx31.dtsi
arch/arm/boot/dts/imx35.dtsi
arch/arm/boot/dts/imx50.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6dl.dtsi
arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/imx6ul.dtsi
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
arch/arm/boot/dts/omap2.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/orion5x-linkstation-lschl.dts [new file with mode: 0644]
arch/arm/boot/dts/orion5x-lschl.dts [deleted file]
arch/arm/boot/dts/qcom-apq8064.dtsi
arch/arm/boot/dts/qcom-mdm9615.dtsi
arch/arm/boot/dts/stih407-family.dtsi
arch/arm/boot/dts/sun6i-a31-hummingbird.dts
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/configs/ezx_defconfig
arch/arm/configs/imote2_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/s3c2410_defconfig
arch/arm/include/asm/cputype.h
arch/arm/include/asm/ftrace.h
arch/arm/include/asm/types.h [deleted file]
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/virt.h
arch/arm/include/uapi/asm/types.h [new file with mode: 0644]
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/smp_tlb.c
arch/arm/kvm/arm.c
arch/arm/lib/getuser.S
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/clock.h
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/usb-da8xx.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-imx/mach-imx1.c
arch/arm/mach-imx/mmdc.c
arch/arm/mach-omap1/dma.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/gpio.c [deleted file]
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_common_data.h
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-s3c24xx/common.c
arch/arm/mach-ux500/pm.c
arch/arm/mm/fault.c
arch/arm/mm/fault.h
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
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.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
arch/arm64/boot/dts/exynos/exynos5433.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts
arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
arch/arm64/boot/dts/xilinx/zynqmp.dtsi
arch/arm64/configs/defconfig
arch/arm64/crypto/aes-modes.S
arch/arm64/include/asm/assembler.h
arch/arm64/include/asm/current.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/virt.h
arch/arm64/include/uapi/asm/ptrace.h
arch/arm64/kernel/entry.S
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/topology.c
arch/arm64/kernel/traps.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/fault.c
arch/arm64/mm/hugetlbpage.c
arch/arm64/mm/init.c
arch/frv/include/asm/atomic.h
arch/mips/kvm/entry.c
arch/mips/kvm/mips.c
arch/mn10300/include/asm/switch_to.h
arch/parisc/include/asm/bitops.h
arch/parisc/include/uapi/asm/bitsperlong.h
arch/parisc/include/uapi/asm/swab.h
arch/powerpc/Kconfig
arch/powerpc/include/asm/book3s/64/hash-4k.h
arch/powerpc/include/asm/book3s/64/hash.h
arch/powerpc/include/asm/cpu_has_feature.h
arch/powerpc/include/asm/hugetlb.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/nohash/pgtable.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/perf_event_server.h
arch/powerpc/include/asm/pgtable-be-types.h
arch/powerpc/include/asm/pgtable-types.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/stackprotector.h [deleted file]
arch/powerpc/include/asm/xics.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/module_64.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage-hash64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/init-common.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/mm/tlb-radix.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/perf/power9-events-list.h
arch/powerpc/perf/power9-pmu.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/sysdev/xics/icp-opal.c
arch/s390/configs/default_defconfig
arch/s390/configs/gcov_defconfig
arch/s390/configs/performance_defconfig
arch/s390/defconfig
arch/s390/include/asm/ctl_reg.h
arch/s390/kernel/ptrace.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/pgtable.c
arch/sparc/include/asm/mmu_context_64.h
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/sstate.c
arch/sparc/kernel/traps_64.c
arch/tile/kernel/ptrace.c
arch/x86/boot/string.c
arch/x86/boot/string.h
arch/x86/crypto/aesni-intel_glue.c
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/events/amd/ibs.c
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/cstate.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/rapl.c
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_intel.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/stacktrace.h
arch/x86/include/asm/switch_to.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/fpu/core.c
arch/x86/kernel/hpet.c
arch/x86/kernel/pci-swiotlb.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/tsc.c
arch/x86/kernel/tsc_sync.c
arch/x86/kernel/unwind_frame.c
arch/x86/kernel/vm86_32.c
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/dump_pagetables.c
arch/x86/mm/mpx.c
arch/x86/net/bpf_jit_comp.c
arch/x86/pci/acpi.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/quirks.c
arch/x86/platform/intel-mid/device_libs/Makefile
arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c [new file with mode: 0644]
arch/x86/platform/intel-mid/device_libs/platform_spidev.c [deleted file]
arch/x86/xen/pci-swiotlb-xen.c
arch/x86/xen/setup.c
arch/xtensa/kernel/setup.c
block/blk-lib.c
block/blk-mq.c
block/blk-zoned.c
block/cfq-iosched.c
block/partition-generic.c
crypto/algapi.c
crypto/algif_aead.c
drivers/acpi/acpi_watchdog.c
drivers/acpi/acpica/tbdata.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/glue.c
drivers/acpi/internal.h
drivers/acpi/nfit/core.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/acpi/video_detect.c
drivers/ata/libata-core.c
drivers/ata/sata_mv.c
drivers/auxdisplay/Kconfig
drivers/base/base.h
drivers/base/core.c
drivers/base/dd.c
drivers/base/firmware_class.c
drivers/base/memory.c
drivers/base/power/domain.c
drivers/base/power/runtime.c
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon.c
drivers/bcma/driver_mips.c
drivers/block/nbd.c
drivers/block/virtio_blk.c
drivers/block/xen-blkfront.c
drivers/block/zram/zram_drv.c
drivers/char/hw_random/core.c
drivers/char/mem.c
drivers/char/ppdev.c
drivers/char/virtio_console.c
drivers/clk/clk-stm32f4.c
drivers/clk/renesas/clk-mstp.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clocksource/exynos_mct.c
drivers/cpufreq/brcmstb-avs-cpufreq.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/intel_pstate.c
drivers/crypto/ccp/ccp-dev-v5.c
drivers/crypto/ccp/ccp-dev.h
drivers/crypto/ccp/ccp-dmaengine.c
drivers/crypto/chelsio/chcr_algo.c
drivers/crypto/chelsio/chcr_core.c
drivers/crypto/chelsio/chcr_crypto.h
drivers/crypto/qat/qat_c62x/adf_drv.c
drivers/crypto/qat/qat_common/adf_accel_devices.h
drivers/crypto/qat/qat_common/qat_hal.c
drivers/devfreq/devfreq.c
drivers/devfreq/exynos-bus.c
drivers/dma/cppi41.c
drivers/dma/dw/Kconfig
drivers/dma/ioat/hw.h
drivers/dma/ioat/init.c
drivers/dma/omap-dma.c
drivers/dma/pl330.c
drivers/dma/sh/rcar-dmac.c
drivers/dma/stm32-dma.c
drivers/dma/ti-dma-crossbar.c
drivers/extcon/extcon.c
drivers/firmware/arm_scpi.c
drivers/firmware/efi/fake_mem.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c
drivers/firmware/efi/memmap.c
drivers/firmware/psci_checker.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
drivers/gpu/drm/amd/amdgpu/si_dpm.c
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_post.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/cirrus/Kconfig
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/etnaviv/etnaviv_mmu.c
drivers/gpu/drm/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/i915/gvt/aperture_gm.c
drivers/gpu/drm/i915/gvt/cfg_space.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/execlist.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/gtt.h
drivers/gpu/drm/i915/gvt/gvt.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mmio.c
drivers/gpu/drm/i915/gvt/mmio.h
drivers/gpu/drm/i915/gvt/opregion.c
drivers/gpu/drm/i915/gvt/reg.h
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/scheduler.h
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_internal.c
drivers/gpu/drm/i915/i915_gem_request.h
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_atomic_plane.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dpll_mgr.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/meson/meson_venc.c
drivers/gpu/drm/meson/meson_venc_cvbs.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_ringbuffer.c
drivers/gpu/drm/nouveau/dispnv04/hw.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/nouveau/nouveau_led.h
drivers/gpu/drm/nouveau/nouveau_usif.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv84_fence.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vc4/vc4_render_cl.c
drivers/gpu/drm/virtio/virtgpu_fb.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
drivers/hid/hid-core.c
drivers/hid/hid-corsair.c
drivers/hid/hid-cp2112.c
drivers/hid/hid-cypress.c
drivers/hid/hid-ids.h
drivers/hid/hid-lg.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hv/ring_buffer.c
drivers/hwmon/lm90.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-imx-lpi2c.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/Kconfig
drivers/iio/adc/palmas_gpadc.c
drivers/iio/common/st_sensors/st_sensors_buffer.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/counter/104-quad-8.c
drivers/iio/health/afe4403.c
drivers/iio/health/afe4404.c
drivers/iio/health/max30100.c
drivers/iio/humidity/dht11.c
drivers/iio/imu/bmi160/bmi160_core.c
drivers/iio/light/max44000.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/umem.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/cxgb4/provider.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/cxgb4/t4.h
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/qedr_cm.c
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
drivers/infiniband/sw/rxe/rxe_mr.c
drivers/infiniband/sw/rxe/rxe_net.c
drivers/infiniband/sw/rxe/rxe_qp.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/joydev.c
drivers/input/joystick/xpad.c
drivers/input/misc/adxl34x-i2c.c
drivers/input/misc/uinput.c
drivers/input/mouse/alps.h
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/synaptics_i2c.c
drivers/input/rmi4/Kconfig
drivers/input/rmi4/rmi_driver.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/touchscreen/elants_i2c.c
drivers/input/touchscreen/wm97xx-core.c
drivers/iommu/amd_iommu.c
drivers/iommu/dmar.c
drivers/iommu/intel-iommu.c
drivers/irqchip/irq-keystone.c
drivers/irqchip/irq-mxs.c
drivers/isdn/hardware/eicon/message.c
drivers/md/dm-crypt.c
drivers/md/dm-mpath.c
drivers/md/dm-rq.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5-cache.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/cec/cec-adap.c
drivers/media/dvb-core/dvb_net.c
drivers/media/i2c/Kconfig
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/i2c/tvp5150.c
drivers/media/i2c/tvp5150_reg.h
drivers/media/pci/cobalt/cobalt-driver.c
drivers/media/pci/cobalt/cobalt-driver.h
drivers/media/usb/dvb-usb/pctv452e.c
drivers/media/usb/siano/smsusb.c
drivers/memstick/core/memstick.c
drivers/misc/mei/bus-fixup.c
drivers/misc/mei/bus.c
drivers/misc/mei/client.c
drivers/misc/mei/debugfs.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hw.h
drivers/misc/mei/mei_dev.h
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/sdhci-acpi.c
drivers/mmc/host/sdhci.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/lpc32xx_mlc.c
drivers/mtd/nand/tango_nand.c
drivers/mtd/nand/xway_nand.c
drivers/net/appletalk/ipddp.c
drivers/net/can/c_can/c_can_pci.c
drivers/net/can/ti_hecc.c
drivers/net/dsa/bcm_sf2.c
drivers/net/ethernet/adaptec/starfire.c
drivers/net/ethernet/amd/xgbe/xgbe-common.h
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/amd/xgbe/xgbe-pci.c
drivers/net/ethernet/amd/xgbe/xgbe.h
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.h
drivers/net/ethernet/cavium/thunder/thunder_xcv.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/catas.c
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/intf.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
drivers/net/ethernet/mellanox/mlx5/core/vport.c
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_ll2.h
drivers/net/ethernet/qlogic/qed/qed_roce.c
drivers/net/ethernet/qualcomm/emac/emac-phy.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/gtp.c
drivers/net/hamradio/mkiss.c
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ieee802154/atusb.c
drivers/net/loopback.c
drivers/net/macvtap.c
drivers/net/phy/Kconfig
drivers/net/phy/bcm63xx.c
drivers/net/phy/dp83848.c
drivers/net/phy/dp83867.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-bcm-iproc.c
drivers/net/phy/micrel.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phy_led_triggers.c
drivers/net/tun.c
drivers/net/usb/catc.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/pegasus.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/rtl8150.c
drivers/net/usb/sierra_net.c
drivers/net/virtio_net.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wireless/intel/iwlwifi/iwl-8000.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
drivers/net/wireless/intersil/orinoco/mic.c
drivers/net/wireless/intersil/orinoco/mic.h
drivers/net/wireless/intersil/orinoco/orinoco.h
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/realtek/rtlwifi/usb.c
drivers/net/xen-netback/common.h
drivers/net/xen-netback/interface.c
drivers/net/xen-netback/xenbus.c
drivers/net/xen-netfront.c
drivers/ntb/hw/intel/ntb_hw_intel.c
drivers/ntb/ntb_transport.c
drivers/ntb/test/ntb_perf.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/pfn_devs.c
drivers/nvdimm/pmem.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/configfs.c
drivers/nvme/target/core.c
drivers/nvme/target/fc.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/rdma.c
drivers/nvmem/core.c
drivers/nvmem/imx-ocotp.c
drivers/nvmem/qfprom.c
drivers/parport/parport_gsc.c
drivers/pci/host/pci-xgene-msi.c
drivers/pci/host/pcie-designware.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/pme.c
drivers/pci/probe.c
drivers/pinctrl/berlin/berlin-bg4ct.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-broxton.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/pinctrl/intel/pinctrl-merrifield.c
drivers/pinctrl/meson/pinctrl-meson-gxbb.c
drivers/pinctrl/meson/pinctrl-meson-gxl.c
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/samsung/pinctrl-exynos.c
drivers/pinctrl/samsung/pinctrl-exynos.h
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.c
drivers/platform/x86/Kconfig
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_mid_powerbtn.c
drivers/platform/x86/mlx-platform.c
drivers/platform/x86/surface3-wmi.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/fixed.c
drivers/regulator/twl6030-regulator.c
drivers/remoteproc/remoteproc_core.c
drivers/reset/core.c
drivers/rpmsg/rpmsg_core.c
drivers/rtc/Kconfig
drivers/rtc/rtc-jz4740.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_bsg.c
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/mpt3sas/mpt3sas_base.h
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/qedi/Kconfig
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_nx.h
drivers/scsi/qla2xxx/qla_nx2.c
drivers/scsi/qla2xxx/qla_nx2.h
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/qla_tmpl.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/ses.c
drivers/scsi/sg.c
drivers/scsi/snic/snic_main.c
drivers/scsi/virtio_scsi.c
drivers/soc/ti/wkup_m3_ipc.c
drivers/spi/Kconfig
drivers/spi/spi-armada-3700.c
drivers/spi/spi-axi-spi-engine.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mid.c
drivers/spi/spi-dw.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-sh-msiof.c
drivers/staging/greybus/timesync_platform.c
drivers/staging/lustre/lustre/llite/llite_mmap.c
drivers/staging/octeon/ethernet.c
drivers/target/target_core_device.c
drivers/target/target_core_sbc.c
drivers/target/target_core_transport.c
drivers/target/target_core_xcopy.c
drivers/target/target_core_xcopy.h
drivers/thermal/rockchip_thermal.c
drivers/thermal/thermal_core.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/atmel_serial.c
drivers/tty/sysrq.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/params.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/atmel_usba_udc.h
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-mtk.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/blackfin.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_debugfs.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musbhsdma.h
drivers/usb/serial/ch341.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/f81534.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/storage/unusual_devs.h
drivers/usb/wusbcore/crypto.c
drivers/vfio/mdev/mdev_core.c
drivers/vfio/mdev/mdev_private.h
drivers/vfio/mdev/mdev_sysfs.c
drivers/vfio/mdev/vfio_mdev.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_rdwr.c
drivers/vfio/vfio_iommu_spapr_tce.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/scsi.c
drivers/vhost/vhost.c
drivers/vhost/vsock.c
drivers/video/fbdev/core/fbcmap.c
drivers/virtio/virtio_mmio.c
drivers/vme/bridges/vme_ca91cx42.c
drivers/xen/arm-device.c
drivers/xen/events/events_fifo.c
drivers/xen/evtchn.c
drivers/xen/platform-pci.c
drivers/xen/swiotlb-xen.c
drivers/xen/xenbus/xenbus_comms.h
drivers/xen/xenbus/xenbus_dev_frontend.c
fs/Kconfig
fs/aio.c
fs/binfmt_elf.c
fs/block_dev.c
fs/btrfs/async-thread.c
fs/btrfs/compression.c
fs/btrfs/extent-tree.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/tree-log.c
fs/btrfs/uuid-tree.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/cifs/readdir.c
fs/coredump.c
fs/dax.c
fs/dcache.c
fs/direct-io.c
fs/ext2/Kconfig
fs/ext4/Kconfig
fs/f2fs/segment.c
fs/f2fs/super.c
fs/fscache/cookie.c
fs/fscache/netfs.c
fs/fscache/object.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/iomap.c
fs/libfs.c
fs/namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/pnfs.c
fs/nfsd/nfs4layouts.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/state.h
fs/notify/mark.c
fs/ocfs2/dlmglue.c
fs/ocfs2/stackglue.c
fs/ocfs2/stackglue.h
fs/overlayfs/namei.c
fs/posix_acl.c
fs/proc/base.c
fs/proc/page.c
fs/proc/proc_sysctl.c
fs/pstore/ram.c
fs/romfs/super.c
fs/splice.c
fs/ubifs/Kconfig
fs/ubifs/dir.c
fs/ubifs/ioctl.c
fs/ubifs/journal.c
fs/ubifs/tnc.c
fs/userfaultfd.c
fs/xfs/libxfs/xfs_ag_resv.c
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.h
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_bmap_btree.c
fs/xfs/libxfs/xfs_dir2.c
fs/xfs/libxfs/xfs_dir2.h
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/libxfs/xfs_ialloc_btree.h
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/libxfs/xfs_sb.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_dquot.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_linux.h
fs/xfs/xfs_log.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_qm.c
include/asm-generic/asm-prototypes.h
include/asm-generic/export.h
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_connector.h
include/drm/drm_mode_config.h
include/dt-bindings/mfd/tps65217.h [deleted file]
include/kvm/arm_arch_timer.h
include/linux/blkdev.h
include/linux/bpf-cgroup.h
include/linux/bpf.h
include/linux/buffer_head.h
include/linux/can/core.h
include/linux/coredump.h
include/linux/cpuhotplug.h
include/linux/cpumask.h
include/linux/efi.h
include/linux/export.h
include/linux/filter.h
include/linux/fscache-cache.h
include/linux/fsnotify_backend.h
include/linux/gfp.h
include/linux/gpio/driver.h
include/linux/hyperv.h
include/linux/i2c.h
include/linux/iio/common/st_sensors.h
include/linux/irq.h
include/linux/jump_label_ratelimit.h
include/linux/kernel.h
include/linux/log2.h
include/linux/mdev.h
include/linux/memcontrol.h
include/linux/memory_hotplug.h
include/linux/micrel_phy.h
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mmzone.h
include/linux/module.h
include/linux/netdevice.h
include/linux/nfs4.h
include/linux/nmi.h
include/linux/percpu-refcount.h
include/linux/perf_event.h
include/linux/phy.h
include/linux/phy_led_triggers.h
include/linux/radix-tree.h
include/linux/rcupdate.h
include/linux/remoteproc.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/svc_xprt.h
include/linux/suspend.h
include/linux/swap.h
include/linux/swiotlb.h
include/linux/tcp.h
include/linux/timerfd.h
include/linux/virtio_net.h
include/net/cipso_ipv4.h
include/net/ipv6.h
include/net/lwtunnel.h
include/net/netfilter/nf_tables.h
include/net/netfilter/nft_fib.h
include/net/sock.h
include/rdma/ib_verbs.h
include/scsi/libfc.h
include/soc/arc/mcip.h
include/sound/hdmi-codec.h
include/sound/soc.h
include/target/target_core_base.h
include/trace/events/btrfs.h
include/trace/events/mmflags.h
include/trace/events/swiotlb.h
include/uapi/linux/Kbuild
include/uapi/linux/bpf.h
include/uapi/linux/cec-funcs.h
include/uapi/linux/ethtool.h
include/uapi/linux/l2tp.h
include/uapi/linux/netfilter/nf_log.h
include/uapi/linux/netfilter/nf_tables.h
include/uapi/linux/nl80211.h
include/uapi/linux/pkt_cls.h
include/uapi/linux/seg6.h
include/uapi/linux/tc_act/tc_bpf.h
include/uapi/linux/timerfd.h [new file with mode: 0644]
include/uapi/linux/usb/functionfs.h
include/uapi/linux/videodev2.h
include/uapi/rdma/Kbuild
include/uapi/rdma/cxgb3-abi.h
include/uapi/rdma/ib_user_verbs.h
init/Kconfig
ipc/sem.c
kernel/audit_tree.c
kernel/bpf/arraymap.c
kernel/bpf/cgroup.c
kernel/bpf/core.c
kernel/bpf/hashtab.c
kernel/bpf/stackmap.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/capability.c
kernel/cgroup.c
kernel/cpu.c
kernel/events/core.c
kernel/futex.c
kernel/irq/irqdomain.c
kernel/jump_label.c
kernel/memremap.c
kernel/module.c
kernel/panic.c
kernel/pid_namespace.c
kernel/power/suspend.c
kernel/printk/printk.c
kernel/rcu/rcu.h
kernel/rcu/tiny.c
kernel/rcu/tiny_plugin.h
kernel/rcu/tree.c
kernel/rcu/tree_exp.h
kernel/rcu/tree_plugin.h
kernel/rcu/update.c
kernel/signal.c
kernel/stacktrace.c
kernel/sysctl.c
kernel/time/tick-broadcast.c
kernel/time/timekeeping_debug.c
kernel/trace/trace_hwlat.c
kernel/trace/trace_kprobe.c
kernel/ucount.c
kernel/watchdog.c
kernel/watchdog_hld.c
lib/Kconfig.debug
lib/ioremap.c
lib/iov_iter.c
lib/radix-tree.c
lib/swiotlb.c
mm/filemap.c
mm/huge_memory.c
mm/hugetlb.c
mm/kasan/report.c
mm/khugepaged.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/slub.c
mm/swapfile.c
mm/vmscan.c
mm/workingset.c
mm/zswap.c
net/Kconfig
net/ax25/ax25_subr.c
net/batman-adv/fragmentation.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_netlink.c
net/can/af_can.c
net/can/af_can.h
net/can/bcm.c
net/can/gw.c
net/can/raw.c
net/ceph/crypto.c
net/core/datagram.c
net/core/dev.c
net/core/ethtool.c
net/core/flow_dissector.c
net/core/lwt_bpf.c
net/core/lwtunnel.c
net/core/neighbour.c
net/core/skbuff.c
net/core/sock.c
net/dccp/input.c
net/dccp/ipv6.c
net/dsa/dsa2.c
net/dsa/slave.c
net/ethernet/eth.c
net/ipv4/arp.c
net/ipv4/cipso_ipv4.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_tunnel_core.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/netfilter/nf_reject_ipv4.c
net/ipv4/netfilter/nft_fib_ipv4.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_fastopen.c
net/ipv4/tcp_input.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_output.c
net/ipv4/tcp_probe.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/datagram.c
net/ipv6/exthdrs.c
net/ipv6/ila/ila_lwt.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/mcast.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/netfilter/nf_reject_ipv6.c
net/ipv6/netfilter/nft_fib_ipv6.c
net/ipv6/route.c
net/ipv6/seg6.c
net/ipv6/seg6_hmac.c
net/ipv6/seg6_iptunnel.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/irda/irqueue.c
net/iucv/af_iucv.c
net/kcm/kcmsock.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/llc/llc_conn.c
net/llc/llc_sap.c
net/mac80211/chan.c
net/mac80211/fils_aead.c
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/tx.c
net/mac80211/vht.c
net/mpls/af_mpls.c
net/mpls/mpls_iptunnel.c
net/netfilter/Kconfig
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_log.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_dynset.c
net/netfilter/nft_log.c
net/netfilter/nft_lookup.c
net/netfilter/nft_objref.c
net/netfilter/nft_payload.c
net/netfilter/nft_queue.c
net/netfilter/nft_quota.c
net/netfilter/nft_set_hash.c
net/netfilter/nft_set_rbtree.c
net/netlabel/netlabel_kapi.c
net/openvswitch/conntrack.c
net/packet/af_packet.c
net/qrtr/qrtr.c
net/sched/act_api.c
net/sched/act_bpf.c
net/sched/cls_bpf.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sctp/ipv6.c
net/sctp/offload.c
net/sctp/outqueue.c
net/sctp/socket.c
net/socket.c
net/sunrpc/auth_gss/gss_rpc_xdr.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/clnt.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc_xprt.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/tipc/discover.c
net/tipc/link.c
net/tipc/msg.c
net/tipc/msg.h
net/tipc/name_distr.c
net/tipc/node.c
net/tipc/server.c
net/tipc/subscr.c
net/tipc/subscr.h
net/unix/af_unix.c
net/wireless/nl80211.c
samples/Kconfig
samples/Makefile
samples/bpf/sock_example.h
samples/bpf/tc_l2_redirect_kern.c
samples/bpf/test_cgrp2_attach.c
samples/bpf/test_cgrp2_attach2.c
samples/bpf/test_cgrp2_sock.c
samples/bpf/test_cgrp2_sock2.c
samples/bpf/trace_output_user.c
samples/bpf/xdp_tx_iptunnel_kern.c
samples/vfio-mdev/Makefile
samples/vfio-mdev/mtty.c
scripts/Makefile.build
scripts/genksyms/genksyms.c
scripts/kallsyms.c
scripts/mod/modpost.c
security/selinux/hooks.c
sound/core/seq/seq_memory.c
sound/core/seq/seq_queue.c
sound/firewire/fireworks/fireworks_stream.c
sound/firewire/tascam/tascam-stream.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/nau8825.c
sound/soc/codecs/nau8825.h
sound/soc/codecs/rt5645.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/wm_adsp.c
sound/soc/dwc/designware_i2s.c
sound/soc/fsl/fsl_ssi.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/intel/skylake/skl-sst.c
sound/soc/sh/rcar/core.c
sound/soc/soc-core.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/line6/driver.c
sound/usb/pcm.c
sound/usb/quirks.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf.h
tools/lib/subcmd/parse-options.c
tools/lib/subcmd/parse-options.h
tools/lib/traceevent/plugin_sched_switch.c
tools/objtool/arch/x86/decode.c
tools/perf/Documentation/perf-record.txt
tools/perf/Makefile.perf
tools/perf/builtin-diff.c
tools/perf/builtin-kmem.c
tools/perf/builtin-record.c
tools/perf/builtin-sched.c
tools/perf/ui/hist.c
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/symbol-elf.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/test_kmod.sh
tools/testing/selftests/bpf/test_lru_map.c
tools/testing/selftests/net/run_netsocktests
tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c
tools/testing/selftests/x86/protection_keys.c
tools/virtio/ringtest/main.h
tools/virtio/ringtest/run-on-all.sh
usr/Makefile
virt/kvm/arm/arch_timer.c
virt/kvm/arm/hyp/timer-sr.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/lib/irqbypass.c

index 02d261407683dcfa483cf15247b2cf31cff0432a..67dc22ffc9a80cb4fd6abeeba3d2ec7f7ae2ba19 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -137,6 +137,7 @@ Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
 Rudolf Marek <R.Marek@sh.cvut.cz>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Sachin P Sant <ssant@in.ibm.com>
+Sarangdhar Joshi <spjoshi@codeaurora.org>
 Sam Ravnborg <sam@mars.ravnborg.org>
 Santosh Shilimkar <ssantosh@kernel.org>
 Santosh Shilimkar <santosh.shilimkar@oracle.org>
@@ -150,10 +151,13 @@ Shuah Khan <shuah@kernel.org> <shuah.kh@samsung.com>
 Simon Kelley <simon@thekelleys.org.uk>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
 Stephen Hemminger <shemminger@osdl.org>
+Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+Subhash Jadavani <subhashj@codeaurora.org>
 Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
 Sumit Semwal <sumit.semwal@ti.com>
 Tejun Heo <htejun@gmail.com>
 Thomas Graf <tgraf@suug.ch>
+Thomas Pedersen <twp@codeaurora.org>
 Tony Luck <tony.luck@intel.com>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
 Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
diff --git a/CREDITS b/CREDITS
index c58560701d13158f535046c09fd4b825922ced94..c5626bf06264e41e136fbe0c0420881e72de0ce2 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2478,12 +2478,11 @@ S: D-90453 Nuernberg
 S: Germany
 
 N: Arnaldo Carvalho de Melo
-E: acme@ghostprotocols.net
+E: acme@kernel.org
 E: arnaldo.melo@gmail.com
 E: acme@redhat.com
-W: http://oops.ghostprotocols.net:81/blog/
 P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
-D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
+D: tools/, IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
 S: Brazil
 
 N: Karsten Merker
diff --git a/Documentation/ABI/testing/sysfs-devices-deferred_probe b/Documentation/ABI/testing/sysfs-devices-deferred_probe
deleted file mode 100644 (file)
index 58553d7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-What:          /sys/devices/.../deferred_probe
-Date:          August 2016
-Contact:       Ben Hutchings <ben.hutchings@codethink.co.uk>
-Description:
-               The /sys/devices/.../deferred_probe attribute is
-               present for all devices.  If a driver detects during
-               probing a device that a related device is not yet
-               ready, it may defer probing of the first device.  The
-               kernel will retry probing the first device after any
-               other device is successfully probed.  This attribute
-               reads as 1 if probing of this device is currently
-               deferred, or 0 otherwise.
index 21e2d88637050b7a33f141e558fff43d3f23d0c9..be7c0d9506b12072219f0396ceb9072eeea03df8 100644 (file)
                        use by PCI
                        Format: <irq>,<irq>...
 
+       acpi_mask_gpe=  [HW,ACPI]
+                       Due to the existence of _Lxx/_Exx, some GPEs triggered
+                       by unsupported hardware/firmware features can result in
+                        GPE floodings that cannot be automatically disabled by
+                        the GPE dispatcher.
+                       This facility can be used to prevent such uncontrolled
+                       GPE floodings.
+                       Format: <int>
+                       Support masking of GPEs numbered from 0x00 to 0x7f.
+
        acpi_no_auto_serialize  [HW,ACPI]
                        Disable auto-serialization of AML methods
                        AML control methods that contain the opcodes to create
                        it if 0 is given (See Documentation/cgroup-v1/memory.txt)
 
        swiotlb=        [ARM,IA-64,PPC,MIPS,X86]
-                       Format: { <int> | force }
+                       Format: { <int> | force | noforce }
                        <int> -- Number of I/O TLB slabs
                        force -- force using of bounce buffers even if they
                                 wouldn't be automatically used by the kernel
+                       noforce -- Never use bounce buffers (for debugging)
 
        switches=       [HW,M68k]
 
index 5fa691e6f6388320acd4199995ef0072e9e70faa..cee9d5055fa27c7593f5a9da09661c4f7eed9647 100644 (file)
@@ -62,6 +62,9 @@ wants to support one of the below features, it should adapt the bindings below.
        "irq" and "wakeup" names are recognized by I2C core, other names are
        left to individual drivers.
 
+- host-notify
+       device uses SMBus host notify protocol instead of interrupt line.
+
 - multi-master
        states that there is another master active on this bus. The OS can use
        this information to adapt power management to keep the arbitration awake
@@ -81,6 +84,11 @@ Binding may contain optional "interrupts" property, describing interrupts
 used by the device. I2C core will assign "irq" interrupt (or the very first
 interrupt if not using interrupt names) as primary interrupt for the slave.
 
+Alternatively, devices supporting SMbus Host Notify, and connected to
+adapters that support this feature, may use "host-notify" property. I2C
+core will create a virtual interrupt for Host Notify and assign it as
+primary interrupt for the slave.
+
 Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
 interrupt for the device. If "wakeup" interrupt name is not present in the
 binding, then primary interrupt will be used as wakeup interrupt.
index 3e5b9793341f4e10679f792c8e19e9fbb55027e1..8682ab6d4a50f86d0d352f6b5b4e8a337c5511c4 100644 (file)
@@ -8,8 +8,9 @@ This driver provides a simple power button event via an Interrupt.
 Required properties:
 - compatible: should be "ti,tps65217-pwrbutton" or "ti,tps65218-pwrbutton"
 
-Required properties for TPS65218:
+Required properties:
 - interrupts: should be one of the following
+   - <2>: For controllers compatible with tps65217
    - <3 IRQ_TYPE_EDGE_BOTH>: For controllers compatible with tps65218
 
 Examples:
@@ -17,6 +18,7 @@ Examples:
 &tps {
        tps65217-pwrbutton {
                compatible = "ti,tps65217-pwrbutton";
+               interrupts = <2>;
        };
 };
 
index 0dcb7c7d3e40bdda3bea51c03729808ae2ac1427..944657684d73cc009bb42b0f7b50eeb1adb7f044 100644 (file)
@@ -15,6 +15,9 @@ Properties:
   Second cell specifies the irq distribution mode to cores
      0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
 
+  The second cell in interrupts property is deprecated and may be ignored by
+  the kernel.
+
   intc accessed via the special ARC AUX register interface, hence "reg" property
   is not specified.
 
index ad5a02f2ac8c9da32eb72192ba9f313fa82d2e4b..cd1bf2ac9055fc3561dbf6da805c8aa5ca3ea49c 100644 (file)
@@ -5,7 +5,7 @@ Required properties:
 - compatible: "sigma,smp8758-nand"
 - reg: address/size of nfc_reg, nfc_mem, and pbus_reg
 - dmas: reference to the DMA channel used by the controller
-- dma-names: "nfc_sbox"
+- dma-names: "rxtx"
 - clocks: reference to the system clock
 - #address-cells: <1>
 - #size-cells: <0>
@@ -17,9 +17,9 @@ Example:
 
        nandc: nand-controller@2c000 {
                compatible = "sigma,smp8758-nand";
-               reg = <0x2c000 0x30 0x2d000 0x800 0x20000 0x1000>;
+               reg = <0x2c000 0x30>, <0x2d000 0x800>, <0x20000 0x1000>;
                dmas = <&dma0 3>;
-               dma-names = "nfc_sbox";
+               dma-names = "rxtx";
                clocks = <&clkgen SYS_CLK>;
                #address-cells = <1>;
                #size-cells = <0>;
index c010fafc66a8e4d6f0b1543104ac352f82ec992f..c7194e87d5f4b7d9b61927a430479e39f52ddca8 100644 (file)
@@ -7,7 +7,7 @@ have dual GMAC each represented by a child node..
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt7623-eth"
+- compatible: Should be "mediatek,mt2701-eth"
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
        order. These are fe_int0, fe_int1 and fe_int2.
index ff1bc4b1bb3b5e1d91a1747fcc73c24d587cd1a8..fb5056b22685c249c9bf812a1ada038070d8c03d 100644 (file)
@@ -19,8 +19,9 @@ Optional Properties:
   specifications. If neither of these are specified, the default is to
   assume clause 22.
 
-  If the phy's identifier is known then the list may contain an entry
-  of the form: "ethernet-phy-idAAAA.BBBB" where
+  If the PHY reports an incorrect ID (or none at all) then the
+  "compatible" list may contain an entry with the correct PHY ID in the
+  form: "ethernet-phy-idAAAA.BBBB" where
      AAAA - The value of the 16 bit Phy Identifier 1 register as
             4 hex digits. This is the chip vendor OUI bits 3:18
      BBBB - The value of the 16 bit Phy Identifier 2 register as
index 85bf945b898f0d156702f16d76be315c9108e1aa..afe9630a5e7de1ff01806675d6a8908cc200d465 100644 (file)
@@ -3,9 +3,11 @@
 Required properties:
        - reg - The ID number for the phy, usually a small integer
        - ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
-               for applicable values
+               for applicable values. Required only if interface type is
+               PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_RXID
        - ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
-               for applicable values
+               for applicable values. Required only if interface type is
+               PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID
        - ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
                for applicable values
 
index 98d131acee95dbff1631e63a5c01db39c2b3def1..a11072c5a8660d362958995a6fd27123c296b2fa 100644 (file)
@@ -2,11 +2,16 @@ TPS65217 Charger
 
 Required Properties:
 -compatible: "ti,tps65217-charger"
+-interrupts: TPS65217 interrupt numbers for the AC and USB charger input change.
+             Should be <0> for the USB charger and <1> for the AC adapter.
+-interrupt-names: Should be "USB" and "AC"
 
 This node is a subnode of the tps65217 PMIC.
 
 Example:
 
        tps65217-charger {
-               compatible = "ti,tps65090-charger";
+               compatible = "ti,tps65217-charger";
+               interrupts = <0>, <1>;
+               interrupt-names = "USB", "AC";
        };
index da6614c6379604bb209156cea87a4e3b27a7d1b8..dc975064fa273c3600eee7d822c94eb5fea73502 100644 (file)
@@ -1,17 +1,23 @@
 Renesas MSIOF spi controller
 
 Required properties:
-- compatible           : "renesas,msiof-<soctype>" for SoCs,
-                        "renesas,sh-msiof" for SuperH, or
-                        "renesas,sh-mobile-msiof" for SH Mobile series.
-                        Examples with soctypes are:
-                        "renesas,msiof-r8a7790" (R-Car H2)
+- compatible           : "renesas,msiof-r8a7790" (R-Car H2)
                         "renesas,msiof-r8a7791" (R-Car M2-W)
                         "renesas,msiof-r8a7792" (R-Car V2H)
                         "renesas,msiof-r8a7793" (R-Car M2-N)
                         "renesas,msiof-r8a7794" (R-Car E2)
                         "renesas,msiof-r8a7796" (R-Car M3-W)
                         "renesas,msiof-sh73a0" (SH-Mobile AG5)
+                        "renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device)
+                        "renesas,rcar-gen2-msiof" (generic R-Car Gen2 compatible device)
+                        "renesas,rcar-gen3-msiof" (generic R-Car Gen3 compatible device)
+                        "renesas,sh-msiof"      (deprecated)
+
+                        When compatible with the generic version, nodes
+                        must list the SoC-specific version corresponding
+                        to the platform first followed by the generic
+                        version.
+
 - reg                  : A list of offsets and lengths of the register sets for
                         the device.
                         If only one register set is present, it is to be used
@@ -61,7 +67,8 @@ Documentation/devicetree/bindings/pinctrl/renesas,*.
 Example:
 
        msiof0: spi@e6e20000 {
-               compatible = "renesas,msiof-r8a7791";
+               compatible = "renesas,msiof-r8a7791",
+                            "renesas,rcar-gen2-msiof";
                reg = <0 0xe6e20000 0 0x0064>;
                interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
index 0bb0b5fc951236f28c79d85a17f32e19710155da..6d9ff316b608db48b46de6413d9503e23b51536a 100644 (file)
@@ -55,21 +55,6 @@ Device Drivers DMA Management
 .. kernel-doc:: drivers/base/dma-mapping.c
    :export:
 
-Device Drivers Power Management
--------------------------------
-
-.. kernel-doc:: drivers/base/power/main.c
-   :export:
-
-Device Drivers ACPI Support
----------------------------
-
-.. kernel-doc:: drivers/acpi/scan.c
-   :export:
-
-.. kernel-doc:: drivers/acpi/scan.c
-   :internal:
-
 Device drivers PnP support
 --------------------------
 
index 72624a16b79284c0f2484741144e6b90ac084064..c94b4675d021ffd374de22d7d83df61dbb6c34dd 100644 (file)
@@ -212,10 +212,11 @@ asynchronous manner and the value may not be very precise. To see a precise
 snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
 It's slow but very precise.
 
-Table 1-2: Contents of the status files (as of 4.1)
+Table 1-2: Contents of the status files (as of 4.8)
 ..............................................................................
  Field                       Content
  Name                        filename of the executable
+ Umask                       file mode creation mask
  State                       state (R is running, S is sleeping, D is sleeping
                              in an uninterruptible wait, Z is zombie,
                             T is traced or stopped)
@@ -226,7 +227,6 @@ Table 1-2: Contents of the status files (as of 4.1)
  TracerPid                   PID of process tracing this process (0 if not)
  Uid                         Real, effective, saved set, and  file system UIDs
  Gid                         Real, effective, saved set, and  file system GIDs
- Umask                       file mode creation mask
  FDSize                      number of file descriptor slots currently allocated
  Groups                      supplementary group list
  NStgid                      descendant namespace thread group ID hierarchy
@@ -236,6 +236,7 @@ Table 1-2: Contents of the status files (as of 4.1)
  VmPeak                      peak virtual memory size
  VmSize                      total program size
  VmLck                       locked memory size
+ VmPin                       pinned memory size
  VmHWM                       peak resident set size ("high water mark")
  VmRSS                       size of memory portions. It contains the three
                              following parts (VmRSS = RssAnon + RssFile + RssShmem)
index 8267c31b317dc9ac8e86007c56de62c0f79ebcba..895d9c2d1c04302f9452350b7fffe3678af1ee61 100644 (file)
@@ -33,11 +33,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 Closes the cec device. Resources associated with the file descriptor are
 freed. The device configuration remain unchanged.
 
index 9e8dbb118d6a3d518391caa1a086f05a545b57c2..7dcfd178fb243c33f6ba23bb331236496018809c 100644 (file)
@@ -39,11 +39,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 The :c:func:`ioctl()` function manipulates cec device parameters. The
 argument ``fd`` must be an open file descriptor.
 
index af3f5b5c24c646dfe61dea9b8afed05a9cb84228..0304388cd15976a7ff00eb46ca9bc9ef5f0a3c94 100644 (file)
@@ -46,11 +46,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To open a cec device applications call :c:func:`open()` with the
 desired device name. The function has no side effects; the device
 configuration remain unchanged.
index cfb73e6027a55734747255df676619e2e55441f7..6a863cfda6e05172be7e60e930fbd0ff885b3ce4 100644 (file)
@@ -39,11 +39,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 With the :c:func:`poll()` function applications can wait for CEC
 events.
 
index 4a19ea5323a97d6ac577b62caf015e6cf2653f63..07ee2b8f89d6a320d66f1a9ed3d20977aa60c34b 100644 (file)
@@ -3,11 +3,6 @@
 Introduction
 ============
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 HDMI connectors provide a single pin for use by the Consumer Electronics
 Control protocol. This protocol allows different devices connected by an
 HDMI cable to communicate. The protocol for CEC version 1.4 is defined
@@ -31,3 +26,15 @@ control just the CEC pin.
 Drivers that support CEC will create a CEC device node (/dev/cecX) to
 give userspace access to the CEC adapter. The
 :ref:`CEC_ADAP_G_CAPS` ioctl will tell userspace what it is allowed to do.
+
+In order to check the support and test it, it is suggested to download
+the `v4l-utils <https://git.linuxtv.org/v4l-utils.git/>`_ package. It
+provides three tools to handle CEC:
+
+- cec-ctl: the Swiss army knife of CEC. Allows you to configure, transmit
+  and monitor CEC messages.
+
+- cec-compliance: does a CEC compliance test of a remote CEC device to
+  determine how compliant the CEC implementation is.
+
+- cec-follower: emulates a CEC follower.
index 2b0ddb14b280e6fddcd8aae1bc67f60560e8a9e4..a0e961f11017c74d9d8ca36fa57124910cd6dbdd 100644 (file)
@@ -29,11 +29,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 All cec devices must support :ref:`ioctl CEC_ADAP_G_CAPS <CEC_ADAP_G_CAPS>`. To query
 device information, applications call the ioctl with a pointer to a
 struct :c:type:`cec_caps`. The driver fills the structure and
index b878637e91b3d8dc78aebf0ccb94823ef6b96ac5..09f09bbe28d4ffb1d5b3291221c4b678e4e38c6e 100644 (file)
@@ -35,11 +35,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To query the current CEC logical addresses, applications call
 :ref:`ioctl CEC_ADAP_G_LOG_ADDRS <CEC_ADAP_G_LOG_ADDRS>` with a pointer to a
 struct :c:type:`cec_log_addrs` where the driver stores the logical addresses.
index 3357deb43c85afb7c577a2fe34127f210903ae73..a3cdc75cec3e3c0754027869cee43ad8ca019260 100644 (file)
@@ -35,11 +35,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To query the current physical address applications call
 :ref:`ioctl CEC_ADAP_G_PHYS_ADDR <CEC_ADAP_G_PHYS_ADDR>` with a pointer to a __u16 where the
 driver stores the physical address.
index e256c6605de7f7b7242a1ad4fbd303d5b5309369..6e589a1fae1704c0eea188c662537d37ea6142b5 100644 (file)
@@ -30,11 +30,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 CEC devices can send asynchronous events. These can be retrieved by
 calling :c:func:`CEC_DQEVENT`. If the file descriptor is in
 non-blocking mode and no event is pending, then it will return -1 and
index 4f5818b9d27724163781713a14241dca38dca0cb..e4ded9df0a84a3be52a4f2a5fb09359e1d4fe285 100644 (file)
@@ -31,11 +31,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 By default any filehandle can use :ref:`CEC_TRANSMIT`, but in order to prevent
 applications from stepping on each others toes it must be possible to
 obtain exclusive access to the CEC adapter. This ioctl sets the
index bdf015b1d1dc0a677b89cdc05b7637687370a496..dc2adb391c0a2d2183e3e00bc90af520e727c6dd 100644 (file)
@@ -34,11 +34,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To receive a CEC message the application has to fill in the
 ``timeout`` field of struct :c:type:`cec_msg` and pass it to
 :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
index 44bb5a7059b38212cbecf33f530355b64459f7dd..95a23a28c59521625f0dbdc0d37eac8c84f4f92a 100644 (file)
@@ -211,7 +211,13 @@ Colorspace sRGB (V4L2_COLORSPACE_SRGB)
 The :ref:`srgb` standard defines the colorspace used by most webcams
 and computer graphics. The default transfer function is
 ``V4L2_XFER_FUNC_SRGB``. The default Y'CbCr encoding is
-``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is full range.
+``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited range.
+
+Note that the :ref:`sycc` standard specifies full range quantization,
+however all current capture hardware supported by the kernel convert
+R'G'B' to limited range Y'CbCr. So choosing full range as the default
+would break how applications interpret the quantization range.
+
 The chromaticities of the primary colors and the white reference are:
 
 
@@ -276,7 +282,7 @@ the following ``V4L2_YCBCR_ENC_601`` encoding as defined by :ref:`sycc`:
 
 Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range
 [-0.5…0.5]. This transform is identical to one defined in SMPTE
-170M/BT.601. The Y'CbCr quantization is full range.
+170M/BT.601. The Y'CbCr quantization is limited range.
 
 
 .. _col-adobergb:
@@ -288,10 +294,15 @@ The :ref:`adobergb` standard defines the colorspace used by computer
 graphics that use the AdobeRGB colorspace. This is also known as the
 :ref:`oprgb` standard. The default transfer function is
 ``V4L2_XFER_FUNC_ADOBERGB``. The default Y'CbCr encoding is
-``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is full
-range. The chromaticities of the primary colors and the white reference
-are:
+``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited
+range.
+
+Note that the :ref:`oprgb` standard specifies full range quantization,
+however all current capture hardware supported by the kernel convert
+R'G'B' to limited range Y'CbCr. So choosing full range as the default
+would break how applications interpret the quantization range.
 
+The chromaticities of the primary colors and the white reference are:
 
 
 .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
@@ -344,7 +355,7 @@ the following ``V4L2_YCBCR_ENC_601`` encoding:
 
 Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range
 [-0.5…0.5]. This transform is identical to one defined in SMPTE
-170M/BT.601. The Y'CbCr quantization is full range.
+170M/BT.601. The Y'CbCr quantization is limited range.
 
 
 .. _col-bt2020:
index 8a39ce45d8a01c298ec3b62b878e2623cba5a958..008ecb588317bc1d354bb5f50513605d6154237c 100644 (file)
@@ -35,9 +35,7 @@ only one way to cause the system to go into the Suspend-To-RAM state (write
 The default suspend mode (ie. the one to be used without writing anything into
 /sys/power/mem_sleep) is either "deep" (if Suspend-To-RAM is supported) or
 "s2idle", but it can be overridden by the value of the "mem_sleep_default"
-parameter in the kernel command line.  On some ACPI-based systems, depending on
-the information in the FADT, the default may be "s2idle" even if Suspend-To-RAM
-is supported.
+parameter in the kernel command line.
 
 The properties of all of the sleep states are described below.
 
index b38afec35edc2b1ea3f49cce804b0d67667b0c97..d226c7a5ba8bee46aeded6bfd181b840259fd4bb 100644 (file)
@@ -127,22 +127,22 @@ the VFIO when devices are unbound from the driver.
 Physical Device Driver Interface
 --------------------------------
 
-The physical device driver interface provides the parent_ops[3] structure to
-define the APIs to manage work in the mediated core driver that is related to
-the physical device.
+The physical device driver interface provides the mdev_parent_ops[3] structure
+to define the APIs to manage work in the mediated core driver that is related
+to the physical device.
 
-The structures in the parent_ops structure are as follows:
+The structures in the mdev_parent_ops structure are as follows:
 
 * dev_attr_groups: attributes of the parent device
 * mdev_attr_groups: attributes of the mediated device
 * supported_config: attributes to define supported configurations
 
-The functions in the parent_ops structure are as follows:
+The functions in the mdev_parent_ops structure are as follows:
 
 * create: allocate basic resources in a driver for a mediated device
 * remove: free resources in a driver when a mediated device is destroyed
 
-The callbacks in the parent_ops structure are as follows:
+The callbacks in the mdev_parent_ops structure are as follows:
 
 * open: open callback of mediated device
 * close: close callback of mediated device
@@ -151,14 +151,14 @@ The callbacks in the parent_ops structure are as follows:
 * write: write emulation callback
 * mmap: mmap emulation callback
 
-A driver should use the parent_ops structure in the function call to register
-itself with the mdev core driver:
+A driver should use the mdev_parent_ops structure in the function call to
+register itself with the mdev core driver:
 
 extern int  mdev_register_device(struct device *dev,
-                                 const struct parent_ops *ops);
+                                 const struct mdev_parent_ops *ops);
 
-However, the parent_ops structure is not required in the function call that a
-driver should use to unregister itself with the mdev core driver:
+However, the mdev_parent_ops structure is not required in the function call
+that a driver should use to unregister itself with the mdev core driver:
 
 extern void mdev_unregister_device(struct device *dev);
 
@@ -223,6 +223,9 @@ Directories and files under the sysfs for Each Physical Device
 
        sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
 
+  (or using mdev_parent_dev(mdev) to arrive at the parent device outside
+   of the core mdev code)
+
 * device_api
 
   This attribute should show which device API is being created, for example,
@@ -394,5 +397,5 @@ References
 
 [1] See Documentation/vfio.txt for more information on VFIO.
 [2] struct mdev_driver in include/linux/mdev.h
-[3] struct parent_ops in include/linux/mdev.h
+[3] struct mdev_parent_ops in include/linux/mdev.h
 [4] struct vfio_iommu_driver_ops in include/linux/vfio.h
diff --git a/Documentation/vm/page_frags b/Documentation/vm/page_frags
new file mode 100644 (file)
index 0000000..a671456
--- /dev/null
@@ -0,0 +1,42 @@
+Page fragments
+--------------
+
+A page fragment is an arbitrary-length arbitrary-offset area of memory
+which resides within a 0 or higher order compound page.  Multiple
+fragments within that page are individually refcounted, in the page's
+reference counter.
+
+The page_frag functions, page_frag_alloc and page_frag_free, provide a
+simple allocation framework for page fragments.  This is used by the
+network stack and network device drivers to provide a backing region of
+memory for use as either an sk_buff->head, or to be used in the "frags"
+portion of skb_shared_info.
+
+In order to make use of the page fragment APIs a backing page fragment
+cache is needed.  This provides a central point for the fragment allocation
+and tracks allows multiple calls to make use of a cached page.  The
+advantage to doing this is that multiple calls to get_page can be avoided
+which can be expensive at allocation time.  However due to the nature of
+this caching it is required that any calls to the cache be protected by
+either a per-cpu limitation, or a per-cpu limitation and forcing interrupts
+to be disabled when executing the fragment allocation.
+
+The network stack uses two separate caches per CPU to handle fragment
+allocation.  The netdev_alloc_cache is used by callers making use of the
+__netdev_alloc_frag and __netdev_alloc_skb calls.  The napi_alloc_cache is
+used by callers of the __napi_alloc_frag and __napi_alloc_skb calls.  The
+main difference between these two calls is the context in which they may be
+called.  The "netdev" prefixed functions are usable in any context as these
+functions will disable interrupts, while the "napi" prefixed functions are
+only usable within the softirq context.
+
+Many network device drivers use a similar methodology for allocating page
+fragments, but the page fragments are cached at the ring or descriptor
+level.  In order to enable these cases it is necessary to provide a generic
+way of tearing down a page cache.  For this reason __page_frag_cache_drain
+was implemented.  It allows for freeing multiple references from a single
+page via a single call.  The advantage to doing this is that it allows for
+cleaning up the multiple references that were added to a page in order to
+avoid calling get_page per allocation.
+
+Alexander Duyck, Nov 29, 2016.
index d918d268cd72bd6e8c7ec839dc9235e75233a72b..51cf6fa5591f9e99d95e73212e19372821ae4d7f 100644 (file)
@@ -212,3 +212,117 @@ Finally we move core 4-7 over to the new group and make sure that the
 kernel and the tasks running there get 50% of the cache.
 
 # echo C0 > p0/cpus
+
+4) Locking between applications
+
+Certain operations on the resctrl filesystem, composed of read/writes
+to/from multiple files, must be atomic.
+
+As an example, the allocation of an exclusive reservation of L3 cache
+involves:
+
+  1. Read the cbmmasks from each directory
+  2. Find a contiguous set of bits in the global CBM bitmask that is clear
+     in any of the directory cbmmasks
+  3. Create a new directory
+  4. Set the bits found in step 2 to the new directory "schemata" file
+
+If two applications attempt to allocate space concurrently then they can
+end up allocating the same bits so the reservations are shared instead of
+exclusive.
+
+To coordinate atomic operations on the resctrlfs and to avoid the problem
+above, the following locking procedure is recommended:
+
+Locking is based on flock, which is available in libc and also as a shell
+script command
+
+Write lock:
+
+ A) Take flock(LOCK_EX) on /sys/fs/resctrl
+ B) Read/write the directory structure.
+ C) funlock
+
+Read lock:
+
+ A) Take flock(LOCK_SH) on /sys/fs/resctrl
+ B) If success read the directory structure.
+ C) funlock
+
+Example with bash:
+
+# Atomically read directory structure
+$ flock -s /sys/fs/resctrl/ find /sys/fs/resctrl
+
+# Read directory contents and create new subdirectory
+
+$ cat create-dir.sh
+find /sys/fs/resctrl/ > output.txt
+mask = function-of(output.txt)
+mkdir /sys/fs/resctrl/newres/
+echo mask > /sys/fs/resctrl/newres/schemata
+
+$ flock /sys/fs/resctrl/ ./create-dir.sh
+
+Example with C:
+
+/*
+ * Example code do take advisory locks
+ * before accessing resctrl filesystem
+ */
+#include <sys/file.h>
+#include <stdlib.h>
+
+void resctrl_take_shared_lock(int fd)
+{
+       int ret;
+
+       /* take shared lock on resctrl filesystem */
+       ret = flock(fd, LOCK_SH);
+       if (ret) {
+               perror("flock");
+               exit(-1);
+       }
+}
+
+void resctrl_take_exclusive_lock(int fd)
+{
+       int ret;
+
+       /* release lock on resctrl filesystem */
+       ret = flock(fd, LOCK_EX);
+       if (ret) {
+               perror("flock");
+               exit(-1);
+       }
+}
+
+void resctrl_release_lock(int fd)
+{
+       int ret;
+
+       /* take shared lock on resctrl filesystem */
+       ret = flock(fd, LOCK_UN);
+       if (ret) {
+               perror("flock");
+               exit(-1);
+       }
+}
+
+void main(void)
+{
+       int fd, ret;
+
+       fd = open("/sys/fs/resctrl", O_DIRECTORY);
+       if (fd == -1) {
+               perror("open");
+               exit(-1);
+       }
+       resctrl_take_shared_lock(fd);
+       /* code to read directory contents */
+       resctrl_release_lock(fd);
+
+       resctrl_take_exclusive_lock(fd);
+       /* code to read and write directory contents */
+       resctrl_release_lock(fd);
+}
index ea11bb03f550eb41e6de2e1b5cc9f8087a31b3bd..527d13759eccf6670c8402c80e918c11f80530f7 100644 (file)
@@ -81,7 +81,6 @@ Descriptions of section entries:
        Q: Patchwork web based patch tracking system site
        T: SCM tree type and location.
           Type is one of: git, hg, quilt, stgit, topgit
-       B: Bug tracking system location.
        S: Status, one of the following:
           Supported:   Someone is actually paid to look after this.
           Maintained:  Someone actually looks after it.
@@ -878,8 +877,8 @@ S:  Odd fixes
 F:     drivers/hwmon/applesmc.c
 
 APPLETALK NETWORK LAYER
-M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
-S:     Maintained
+L:     netdev@vger.kernel.org
+S:     Odd fixes
 F:     drivers/net/appletalk/
 F:     net/appletalk/
 
@@ -977,6 +976,7 @@ M:  Russell King <linux@armlinux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.armlinux.org.uk/
 S:     Maintained
+T:     git git://git.armlinux.org.uk/~rmk/linux-arm.git
 F:     arch/arm/
 
 ARM SUB-ARCHITECTURES
@@ -1091,7 +1091,7 @@ F:        arch/arm/boot/dts/aspeed-*
 F:     drivers/*/*aspeed*
 
 ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 M:     Alexandre Belloni <alexandre.belloni@free-electrons.com>
 M:     Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1154,6 +1154,7 @@ ARM/CLKDEV SUPPORT
 M:     Russell King <linux@armlinux.org.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
+T:     git git://git.armlinux.org.uk/~rmk/linux-arm.git clkdev
 F:     arch/arm/include/asm/clkdev.h
 F:     drivers/clk/clkdev.c
 
@@ -1689,6 +1690,7 @@ M:        Krzysztof Kozlowski <krzk@kernel.org>
 R:     Javier Martinez Canillas <javier@osg.samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+Q:     https://patchwork.kernel.org/project/linux-samsung-soc/list/
 S:     Maintained
 F:     arch/arm/boot/dts/s3c*
 F:     arch/arm/boot/dts/s5p*
@@ -1771,7 +1773,7 @@ F:        drivers/soc/renesas/
 F:     include/linux/soc/renesas/
 
 ARM/SOCFPGA ARCHITECTURE
-M:     Dinh Nguyen <dinguyen@opensource.altera.com>
+M:     Dinh Nguyen <dinguyen@kernel.org>
 S:     Maintained
 F:     arch/arm/mach-socfpga/
 F:     arch/arm/boot/dts/socfpga*
@@ -1781,7 +1783,7 @@ W:        http://www.rocketboards.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
 
 ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
-M:     Dinh Nguyen <dinguyen@opensource.altera.com>
+M:     Dinh Nguyen <dinguyen@kernel.org>
 S:     Maintained
 F:     drivers/clk/socfpga/
 
@@ -2173,64 +2175,56 @@ F:      include/linux/atm*
 F:     include/uapi/linux/atm*
 
 ATMEL AT91 / AT32 MCI DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 S:     Maintained
 F:     drivers/mmc/host/atmel-mci.c
 
 ATMEL AT91 SAMA5D2-Compatible Shutdown Controller
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 S:     Supported
 F:     drivers/power/reset/at91-sama5d2_shdwc.c
 
 ATMEL SAMA5D2 ADC DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 L:     linux-iio@vger.kernel.org
 S:     Supported
 F:     drivers/iio/adc/at91-sama5d2_adc.c
 
 ATMEL Audio ALSA driver
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/atmel
 
-ATMEL DMA DRIVER
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Supported
-F:     drivers/dma/at_hdmac.c
-F:     drivers/dma/at_hdmac_regs.h
-F:     include/linux/platform_data/dma-atmel.h
-
 ATMEL XDMA DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     dmaengine@vger.kernel.org
 S:     Supported
 F:     drivers/dma/at_xdmac.c
 
 ATMEL I2C DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 L:     linux-i2c@vger.kernel.org
 S:     Supported
 F:     drivers/i2c/busses/i2c-at91.c
 
 ATMEL ISI DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
 F:     drivers/media/platform/soc_camera/atmel-isi.c
 F:     include/media/atmel-isi.h
 
 ATMEL LCDFB DRIVER
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 L:     linux-fbdev@vger.kernel.org
 S:     Maintained
 F:     drivers/video/fbdev/atmel_lcdfb.c
 F:     include/video/atmel_lcdc.h
 
 ATMEL MACB ETHERNET DRIVER
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 S:     Supported
 F:     drivers/net/ethernet/cadence/
 
@@ -2242,32 +2236,32 @@ S:      Supported
 F:     drivers/mtd/nand/atmel_nand*
 
 ATMEL SDMMC DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 L:     linux-mmc@vger.kernel.org
 S:     Supported
 F:     drivers/mmc/host/sdhci-of-at91.c
 
 ATMEL SPI DRIVER
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 S:     Supported
 F:     drivers/spi/spi-atmel.*
 
 ATMEL SSC DRIVER
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/misc/atmel-ssc.c
 F:     include/linux/atmel-ssc.h
 
 ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/misc/atmel_tclib.c
 F:     drivers/clocksource/tcb_clksrc.c
 
 ATMEL USBA UDC DRIVER
-M:     Nicolas Ferre <nicolas.ferre@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/usb/gadget/udc/atmel_usba_udc.*
@@ -3573,7 +3567,7 @@ F:        drivers/infiniband/hw/cxgb3/
 F:     include/uapi/rdma/cxgb3-abi.h
 
 CXGB4 ETHERNET DRIVER (CXGB4)
-M:     Hariprasad S <hariprasad@chelsio.com>
+M:     Ganesh Goudar <ganeshgr@chelsio.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
@@ -3800,6 +3794,7 @@ F:        include/linux/devcoredump.h
 DEVICE FREQUENCY (DEVFREQ)
 M:     MyungJoo Ham <myungjoo.ham@samsung.com>
 M:     Kyungmin Park <kyungmin.park@samsung.com>
+R:     Chanwoo Choi <cw00.choi@samsung.com>
 L:     linux-pm@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git
 S:     Maintained
@@ -4105,18 +4100,24 @@ F:      drivers/gpu/drm/bridge/
 
 DRM DRIVER FOR BOCHS VIRTUAL GPU
 M:     Gerd Hoffmann <kraxel@redhat.com>
-S:     Odd Fixes
+L:     virtualization@lists.linux-foundation.org
+T:     git git://git.kraxel.org/linux drm-qemu
+S:     Maintained
 F:     drivers/gpu/drm/bochs/
 
 DRM DRIVER FOR QEMU'S CIRRUS DEVICE
 M:     Dave Airlie <airlied@redhat.com>
-S:     Odd Fixes
+M:     Gerd Hoffmann <kraxel@redhat.com>
+L:     virtualization@lists.linux-foundation.org
+T:     git git://git.kraxel.org/linux drm-qemu
+S:     Obsolete
+W:     https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
 F:     drivers/gpu/drm/cirrus/
 
 RADEON and AMDGPU DRM DRIVERS
 M:     Alex Deucher <alexander.deucher@amd.com>
 M:     Christian König <christian.koenig@amd.com>
-L:     dri-devel@lists.freedesktop.org
+L:     amd-gfx@lists.freedesktop.org
 T:     git git://people.freedesktop.org/~agd5f/linux
 S:     Supported
 F:     drivers/gpu/drm/radeon/
@@ -4152,7 +4153,7 @@ F:        Documentation/gpu/i915.rst
 INTEL GVT-g DRIVERS (Intel GPU Virtualization)
 M:      Zhenyu Wang <zhenyuw@linux.intel.com>
 M:      Zhi Wang <zhi.a.wang@intel.com>
-L:      igvt-g-dev@lists.01.org
+L:      intel-gvt-dev@lists.freedesktop.org
 L:      intel-gfx@lists.freedesktop.org
 W:      https://01.org/igvt-g
 T:      git https://github.com/01org/gvt-linux.git
@@ -4303,7 +4304,10 @@ F:       Documentation/devicetree/bindings/display/renesas,du.txt
 
 DRM DRIVER FOR QXL VIRTUAL GPU
 M:     Dave Airlie <airlied@redhat.com>
-S:     Odd Fixes
+M:     Gerd Hoffmann <kraxel@redhat.com>
+L:     virtualization@lists.linux-foundation.org
+T:     git git://git.kraxel.org/linux drm-qemu
+S:     Maintained
 F:     drivers/gpu/drm/qxl/
 F:     include/uapi/drm/qxl_drm.h
 
@@ -5506,6 +5510,7 @@ M:        Alex Elder <elder@kernel.org>
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 S:     Maintained
 F:     drivers/staging/greybus/
+L:     greybus-dev@lists.linaro.org
 
 GREYBUS AUDIO PROTOCOLS DRIVERS
 M:     Vaibhav Agarwal <vaibhav.sr@gmail.com>
@@ -5963,6 +5968,7 @@ F:        drivers/media/platform/sti/hva
 Hyper-V CORE AND DRIVERS
 M:     "K. Y. Srinivasan" <kys@microsoft.com>
 M:     Haiyang Zhang <haiyangz@microsoft.com>
+M:     Stephen Hemminger <sthemmin@microsoft.com>
 L:     devel@linuxdriverproject.org
 S:     Maintained
 F:     arch/x86/include/asm/mshyperv.h
@@ -6721,9 +6727,8 @@ S:        Odd Fixes
 F:     drivers/tty/ipwireless/
 
 IPX NETWORK LAYER
-M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Odd fixes
 F:     include/net/ipx.h
 F:     include/uapi/linux/ipx.h
 F:     net/ipx/
@@ -7495,8 +7500,8 @@ S:        Maintained
 F:     drivers/misc/lkdtm*
 
 LLC (802.2)
-M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
-S:     Maintained
+L:     netdev@vger.kernel.org
+S:     Odd fixes
 F:     include/linux/llc.h
 F:     include/uapi/linux/llc.h
 F:     include/net/llc*
@@ -7703,8 +7708,10 @@ F:       drivers/net/dsa/mv88e6xxx/
 F:     Documentation/devicetree/bindings/net/dsa/marvell.txt
 
 MARVELL ARMADA DRM SUPPORT
-M:     Russell King <rmk+kernel@armlinux.org.uk>
+M:     Russell King <linux@armlinux.org.uk>
 S:     Maintained
+T:     git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-armada-devel
+T:     git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-armada-fixes
 F:     drivers/gpu/drm/armada/
 F:     include/uapi/drm/armada_drm.h
 F:     Documentation/devicetree/bindings/display/armada/
@@ -8176,6 +8183,15 @@ S:       Maintained
 F:     drivers/tty/serial/atmel_serial.c
 F:     include/linux/atmel_serial.h
 
+MICROCHIP / ATMEL DMA DRIVER
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     dmaengine@vger.kernel.org
+S:     Supported
+F:     drivers/dma/at_hdmac.c
+F:     drivers/dma/at_hdmac_regs.h
+F:     include/linux/platform_data/dma-atmel.h
+
 MICROCHIP / ATMEL ISC DRIVER
 M:     Songjun Wu <songjun.wu@microchip.com>
 L:     linux-media@vger.kernel.org
@@ -8900,8 +8916,10 @@ S:       Supported
 F:     drivers/nfc/nxp-nci
 
 NXP TDA998X DRM DRIVER
-M:     Russell King <rmk+kernel@armlinux.org.uk>
+M:     Russell King <linux@armlinux.org.uk>
 S:     Supported
+T:     git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-devel
+T:     git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-fixes
 F:     drivers/gpu/drm/i2c/tda998x_drv.c
 F:     include/drm/i2c/tda998x.h
 
@@ -9717,7 +9735,7 @@ S:        Maintained
 F:     drivers/pinctrl/pinctrl-at91.*
 
 PIN CONTROLLER - ATMEL AT91 PIO4
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+M:     Ludovic Desroches <ludovic.desroches@microchip.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-gpio@vger.kernel.org
 S:     Supported
@@ -9849,7 +9867,7 @@ M:        Mark Rutland <mark.rutland@arm.com>
 M:     Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
 L:     linux-arm-kernel@lists.infradead.org
 S:     Maintained
-F:     drivers/firmware/psci.c
+F:     drivers/firmware/psci*.c
 F:     include/linux/psci.h
 F:     include/uapi/linux/psci.h
 
@@ -10176,7 +10194,6 @@ F:      drivers/media/tuners/qt1010*
 QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
 M:     QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
 L:     linux-wireless@vger.kernel.org
-L:     ath9k-devel@lists.ath9k.org
 W:     http://wireless.kernel.org/en/users/Drivers/ath9k
 S:     Supported
 F:     drivers/net/wireless/ath/ath9k/
@@ -13047,7 +13064,7 @@ F:      drivers/input/serio/userio.c
 F:     include/uapi/linux/userio.h
 
 VIRTIO CONSOLE DRIVER
-M:     Amit Shah <amit.shah@redhat.com>
+M:     Amit Shah <amit@kernel.org>
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
 F:     drivers/char/virtio_console.c
@@ -13082,6 +13099,7 @@ M:      David Airlie <airlied@linux.ie>
 M:     Gerd Hoffmann <kraxel@redhat.com>
 L:     dri-devel@lists.freedesktop.org
 L:     virtualization@lists.linux-foundation.org
+T:     git git://git.kraxel.org/linux drm-qemu
 S:     Maintained
 F:     drivers/gpu/drm/virtio/
 F:     include/uapi/linux/virtio_gpu.h
@@ -13354,10 +13372,8 @@ S:     Maintained
 F:     drivers/input/misc/wistron_btns.c
 
 WL3501 WIRELESS PCMCIA CARD DRIVER
-M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     linux-wireless@vger.kernel.org
-W:     http://oops.ghostprotocols.net:81/blog
-S:     Maintained
+S:     Odd fixes
 F:     drivers/net/wireless/wl3501*
 
 WOLFSON MICROELECTRONICS DRIVERS
@@ -13433,6 +13449,7 @@ F:      arch/x86/
 
 X86 PLATFORM DRIVERS
 M:     Darren Hart <dvhart@infradead.org>
+M:     Andy Shevchenko <andy@infradead.org>
 L:     platform-driver-x86@vger.kernel.org
 T:     git git://git.infradead.org/users/dvhart/linux-platform-drivers-x86.git
 S:     Maintained
@@ -13604,6 +13621,7 @@ F:      drivers/net/hamradio/z8530.h
 
 ZBUD COMPRESSED PAGE ALLOCATOR
 M:     Seth Jennings <sjenning@redhat.com>
+M:     Dan Streetman <ddstreet@ieee.org>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zbud.c
@@ -13659,6 +13677,7 @@ F:      Documentation/vm/zsmalloc.txt
 
 ZSWAP COMPRESSED SWAP CACHING
 M:     Seth Jennings <sjenning@redhat.com>
+M:     Dan Streetman <ddstreet@ieee.org>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zswap.c
index 5470d599384a5ba676a60490e19baf81a1068b65..f1e6a02a0c199c861665d9eaa61d89473001e33a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 4
 PATCHLEVEL = 10
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
-NAME = Roaring Lionus
+EXTRAVERSION =
+NAME = Fearless Coyote
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -797,7 +797,7 @@ KBUILD_CFLAGS   += $(call cc-option,-Werror=incompatible-pointer-types)
 KBUILD_ARFLAGS := $(call ar-option,D)
 
 # check for 'asm goto'
-ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
+ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
        KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
        KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
 endif
index c75d29077e4a654276219883629444deec89c955..283099c9560aa296377d588e0402d5e0b49884b4 100644 (file)
@@ -29,7 +29,7 @@ config ARC
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_MEMBLOCK
-       select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND
+       select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_OPROFILE
        select HAVE_PERF_EVENTS
        select HANDLE_DOMAIN_IRQ
index b3410ff6a62dbcc589ffa411f326d6954c8ba80c..5008021fba9894c0ba44251ddfd41a716d6c6cca 100644 (file)
@@ -67,7 +67,7 @@ extern unsigned long perip_base, perip_end;
 #define ARC_REG_IC_PTAG_HI     0x1F
 
 /* Bit val in IC_CTRL */
-#define IC_CTRL_CACHE_DISABLE   0x1
+#define IC_CTRL_DIS            0x1
 
 /* Data cache related Auxiliary registers */
 #define ARC_REG_DC_BCR         0x72    /* Build Config reg */
@@ -80,8 +80,9 @@ extern unsigned long perip_base, perip_end;
 #define ARC_REG_DC_PTAG_HI     0x5F
 
 /* Bit val in DC_CTRL */
-#define DC_CTRL_INV_MODE_FLUSH  0x40
-#define DC_CTRL_FLUSH_STATUS    0x100
+#define DC_CTRL_DIS            0x001
+#define DC_CTRL_INV_MODE_FLUSH 0x040
+#define DC_CTRL_FLUSH_STATUS   0x100
 
 /*System-level cache (L2 cache) related Auxiliary registers */
 #define ARC_REG_SLC_CFG                0x901
@@ -92,8 +93,8 @@ extern unsigned long perip_base, perip_end;
 #define ARC_REG_SLC_RGN_END    0x916
 
 /* Bit val in SLC_CONTROL */
+#define SLC_CTRL_DIS           0x001
 #define SLC_CTRL_IM            0x040
-#define SLC_CTRL_DISABLE       0x001
 #define SLC_CTRL_BUSY          0x100
 #define SLC_CTRL_RGN_OP_INV    0x200
 
index a36e8601114d2ca2970f257f9f8d7e5c03ec08a2..d5da2115d78a678e343da2abec51f6c8efbbe0a4 100644 (file)
@@ -26,7 +26,9 @@ static inline void __delay(unsigned long loops)
        "       lp  1f                  \n"
        "       nop                     \n"
        "1:                             \n"
-       : : "r"(loops));
+       :
+        : "r"(loops)
+        : "lp_count");
 }
 
 extern void __bad_udelay(void);
index b5ff87e6f4b71352fc8990624114c025b6c5ccb0..aee1a77934cf694e37ae579347a37bc167e43762 100644 (file)
@@ -16,6 +16,7 @@
        ;
        ; Now manually save: r12, sp, fp, gp, r25
 
+       PUSH    r30
        PUSH    r12
 
        ; Saving pt_regs->sp correctly requires some extra work due to the way
@@ -72,6 +73,7 @@
        POPAX   AUX_USER_SP
 1:
        POP     r12
+       POP     r30
 
 .endm
 
index 6e91d8b339c3616b59d7b389353c477acba8a418..567590ea8f6c9166d7cef4643529ae621910ddce 100644 (file)
 
 #include <asm-generic/module.h>
 
-#ifdef CONFIG_ARC_DW2_UNWIND
 struct mod_arch_specific {
+#ifdef CONFIG_ARC_DW2_UNWIND
        void *unw_info;
        int unw_sec_idx;
+#endif
        const char *secstr;
 };
-#endif
 
 #define MODULE_PROC_FAMILY "ARC700"
 
index 69095da1fcfd1e35f16234aaf473896194064d38..47111d565a959d117ab9e2c7c9eea3b852137971 100644 (file)
@@ -84,7 +84,7 @@ struct pt_regs {
        unsigned long fp;
        unsigned long sp;       /* user/kernel sp depending on where we came from  */
 
-       unsigned long r12;
+       unsigned long r12, r30;
 
        /*------- Below list auto saved by h/w -----------*/
        unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
index cb954cdab07087bc6b49e72c8d117c77b905595c..c568a9df82b1a397d73d3fa3c0c523804a2856f2 100644 (file)
@@ -31,6 +31,7 @@ extern int root_mountflags, end_mem;
 
 void setup_processor(void);
 void __init setup_arch_memory(void);
+long __init arc_get_mem_sz(void);
 
 /* Helpers used in arc_*_mumbojumbo routines */
 #define IS_AVAIL1(v, s)                ((v) ? s : "")
index 689dd867fdff53eeafa0d01d980ecf425f66a759..8b90d25a15cca8ebd334402848d98aa22f07b8bf 100644 (file)
@@ -71,14 +71,14 @@ ENTRY(stext)
        GET_CPU_ID  r5
        cmp     r5, 0
        mov.nz  r0, r5
-#ifdef CONFIG_ARC_SMP_HALT_ON_RESET
-       ; Non-Master can proceed as system would be booted sufficiently
-       jnz     first_lines_of_secondary
-#else
+       bz      .Lmaster_proceed
+
        ; Non-Masters wait for Master to boot enough and bring them up
-       jnz     arc_platform_smp_wait_to_boot
-#endif
-       ; Master falls thru
+       ; when they resume, tail-call to entry point
+       mov     blink, @first_lines_of_secondary
+       j       arc_platform_smp_wait_to_boot
+
+.Lmaster_proceed:
 #endif
 
        ; Clear BSS before updating any globals
index 994dca7014db645b32cfb22753cb25bae4c46566..ecef0fb0b66c37d814b2adc2cc207ef178903bef 100644 (file)
@@ -77,20 +77,20 @@ void arc_init_IRQ(void)
 
 static void arcv2_irq_mask(struct irq_data *data)
 {
-       write_aux_reg(AUX_IRQ_SELECT, data->irq);
+       write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
        write_aux_reg(AUX_IRQ_ENABLE, 0);
 }
 
 static void arcv2_irq_unmask(struct irq_data *data)
 {
-       write_aux_reg(AUX_IRQ_SELECT, data->irq);
+       write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
        write_aux_reg(AUX_IRQ_ENABLE, 1);
 }
 
 void arcv2_irq_enable(struct irq_data *data)
 {
        /* set default priority */
-       write_aux_reg(AUX_IRQ_SELECT, data->irq);
+       write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
        write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
 
        /*
index ce9deb953ca90e1a0309ccd69f9608e8fd32cf70..8c1fd5c007822409ff9bc07e7dbec4eaa9fdad09 100644 (file)
@@ -57,7 +57,7 @@ static void arc_irq_mask(struct irq_data *data)
        unsigned int ienb;
 
        ienb = read_aux_reg(AUX_IENABLE);
-       ienb &= ~(1 << data->irq);
+       ienb &= ~(1 << data->hwirq);
        write_aux_reg(AUX_IENABLE, ienb);
 }
 
@@ -66,7 +66,7 @@ static void arc_irq_unmask(struct irq_data *data)
        unsigned int ienb;
 
        ienb = read_aux_reg(AUX_IENABLE);
-       ienb |= (1 << data->irq);
+       ienb |= (1 << data->hwirq);
        write_aux_reg(AUX_IENABLE, ienb);
 }
 
index 560c4afc2af4882f7e64191350be90efef808754..9f6b68fd4f3bcfc6df3741f5206bf38ebb304ce7 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/smp.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/spinlock.h>
 #include <soc/arc/mcip.h>
 #include <asm/irqflags-arcv2.h>
@@ -92,11 +93,10 @@ static void mcip_probe_n_setup(void)
        READ_BCR(ARC_REG_MCIP_BCR, mp);
 
        sprintf(smp_cpuinfo_buf,
-               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s%s\n",
+               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n",
                mp.ver, mp.num_cores,
                IS_AVAIL1(mp.ipi, "IPI "),
                IS_AVAIL1(mp.idu, "IDU "),
-               IS_AVAIL1(mp.llm, "LLM "),
                IS_AVAIL1(mp.dbg, "DEBUG "),
                IS_AVAIL1(mp.gfrc, "GFRC"));
 
@@ -174,7 +174,6 @@ static void idu_irq_unmask(struct irq_data *data)
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
 }
 
-#ifdef CONFIG_SMP
 static int
 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
                     bool force)
@@ -204,12 +203,27 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 
        return IRQ_SET_MASK_OK;
 }
-#endif
+
+static void idu_irq_enable(struct irq_data *data)
+{
+       /*
+        * By default send all common interrupts to all available online CPUs.
+        * The affinity of common interrupts in IDU must be set manually since
+        * in some cases the kernel will not call irq_set_affinity() by itself:
+        *   1. When the kernel is not configured with support of SMP.
+        *   2. When the kernel is configured with support of SMP but upper
+        *      interrupt controllers does not support setting of the affinity
+        *      and cannot propagate it to IDU.
+        */
+       idu_irq_set_affinity(data, cpu_online_mask, false);
+       idu_irq_unmask(data);
+}
 
 static struct irq_chip idu_irq_chip = {
        .name                   = "MCIP IDU Intc",
        .irq_mask               = idu_irq_mask,
        .irq_unmask             = idu_irq_unmask,
+       .irq_enable             = idu_irq_enable,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = idu_irq_set_affinity,
 #endif
@@ -221,10 +235,13 @@ static irq_hw_number_t idu_first_hwirq;
 static void idu_cascade_isr(struct irq_desc *desc)
 {
        struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+       struct irq_chip *core_chip = irq_desc_get_chip(desc);
        irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
        irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
 
+       chained_irq_enter(core_chip, desc);
        generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
+       chained_irq_exit(core_chip, desc);
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
@@ -239,36 +256,14 @@ static int idu_irq_xlate(struct irq_domain *d, struct device_node *n,
                         const u32 *intspec, unsigned int intsize,
                         irq_hw_number_t *out_hwirq, unsigned int *out_type)
 {
-       irq_hw_number_t hwirq = *out_hwirq = intspec[0];
-       int distri = intspec[1];
-       unsigned long flags;
-
+       /*
+        * Ignore value of interrupt distribution mode for common interrupts in
+        * IDU which resides in intspec[1] since setting an affinity using value
+        * from Device Tree is deprecated in ARC.
+        */
+       *out_hwirq = intspec[0];
        *out_type = IRQ_TYPE_NONE;
 
-       /* XXX: validate distribution scheme again online cpu mask */
-       if (distri == 0) {
-               /* 0 - Round Robin to all cpus, otherwise 1 bit per core */
-               raw_spin_lock_irqsave(&mcip_lock, flags);
-               idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
-               idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
-               raw_spin_unlock_irqrestore(&mcip_lock, flags);
-       } else {
-               /*
-                * DEST based distribution for Level Triggered intr can only
-                * have 1 CPU, so generalize it to always contain 1 cpu
-                */
-               int cpu = ffs(distri);
-
-               if (cpu != fls(distri))
-                       pr_warn("IDU irq %lx distri mode set to cpu %x\n",
-                               hwirq, cpu);
-
-               raw_spin_lock_irqsave(&mcip_lock, flags);
-               idu_set_dest(hwirq, cpu);
-               idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
-               raw_spin_unlock_irqrestore(&mcip_lock, flags);
-       }
-
        return 0;
 }
 
index 42e964db29677877438f8b9bc8e6225cc5f64174..3d99a60913325d1ac5229b7b6e5933caddb0cbbc 100644 (file)
@@ -32,8 +32,8 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
 #ifdef CONFIG_ARC_DW2_UNWIND
        mod->arch.unw_sec_idx = 0;
        mod->arch.unw_info = NULL;
-       mod->arch.secstr = secstr;
 #endif
+       mod->arch.secstr = secstr;
        return 0;
 }
 
@@ -113,8 +113,10 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 
        }
 
+#ifdef CONFIG_ARC_DW2_UNWIND
        if (strcmp(module->arch.secstr+sechdrs[tgtsec].sh_name, ".eh_frame") == 0)
                module->arch.unw_sec_idx = tgtsec;
+#endif
 
        return 0;
 
index 88674d972c9d056f33f87205aa77049c11006129..2afbafadb6ab529ebaa7af4e367d733fc7837e1e 100644 (file)
@@ -90,22 +90,37 @@ void __init smp_cpus_done(unsigned int max_cpus)
  */
 static volatile int wake_flag;
 
+#ifdef CONFIG_ISA_ARCOMPACT
+
+#define __boot_read(f)         f
+#define __boot_write(f, v)     f = v
+
+#else
+
+#define __boot_read(f)         arc_read_uncached_32(&f)
+#define __boot_write(f, v)     arc_write_uncached_32(&f, v)
+
+#endif
+
 static void arc_default_smp_cpu_kick(int cpu, unsigned long pc)
 {
        BUG_ON(cpu == 0);
-       wake_flag = cpu;
+
+       __boot_write(wake_flag, cpu);
 }
 
 void arc_platform_smp_wait_to_boot(int cpu)
 {
-       while (wake_flag != cpu)
+       /* for halt-on-reset, we've waited already */
+       if (IS_ENABLED(CONFIG_ARC_SMP_HALT_ON_RESET))
+               return;
+
+       while (__boot_read(wake_flag) != cpu)
                ;
 
-       wake_flag = 0;
-       __asm__ __volatile__("j @first_lines_of_secondary       \n");
+       __boot_write(wake_flag, 0);
 }
 
-
 const char *arc_platform_smp_cpuinfo(void)
 {
        return plat_smp_ops.info ? : "";
index abd961f3e7639f13fb7954da68885ed0215f432c..5f69c3bd59bba47babf92c97a9c7e5a0174c5648 100644 (file)
@@ -241,8 +241,9 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs,
        if (state.fault)
                goto fault;
 
+       /* clear any remanants of delay slot */
        if (delay_mode(regs)) {
-               regs->ret = regs->bta;
+               regs->ret = regs->bta & ~1U;
                regs->status32 &= ~STATUS_DE_MASK;
        } else {
                regs->ret += state.instr_len;
index ec86ac0e33213b889cd6100e10e95fda8f3c31e4..d408fa21a07c9937a0e2956a6e12a7895ffef684 100644 (file)
@@ -23,7 +23,7 @@
 
 static int l2_line_sz;
 static int ioc_exists;
-int slc_enable = 1, ioc_enable = 0;
+int slc_enable = 1, ioc_enable = 1;
 unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */
 unsigned long perip_end = 0xFFFFFFFF; /* legacy value */
 
@@ -271,7 +271,11 @@ void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr,
 
 /*
  * For ARC700 MMUv3 I-cache and D-cache flushes
- * Also reused for HS38 aliasing I-cache configuration
+ *  - ARC700 programming model requires paddr and vaddr be passed in seperate
+ *    AUX registers (*_IV*L and *_PTAG respectively) irrespective of whether the
+ *    caches actually alias or not.
+ * -  For HS38, only the aliasing I-cache configuration uses the PTAG reg
+ *    (non aliasing I-cache version doesn't; while D-cache can't possibly alias)
  */
 static inline
 void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
@@ -458,6 +462,21 @@ static inline void __dc_entire_op(const int op)
        __after_dc_op(op);
 }
 
+static inline void __dc_disable(void)
+{
+       const int r = ARC_REG_DC_CTRL;
+
+       __dc_entire_op(OP_FLUSH_N_INV);
+       write_aux_reg(r, read_aux_reg(r) | DC_CTRL_DIS);
+}
+
+static void __dc_enable(void)
+{
+       const int r = ARC_REG_DC_CTRL;
+
+       write_aux_reg(r, read_aux_reg(r) & ~DC_CTRL_DIS);
+}
+
 /* For kernel mappings cache operation: index is same as paddr */
 #define __dc_line_op_k(p, sz, op)      __dc_line_op(p, p, sz, op)
 
@@ -483,6 +502,8 @@ static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr,
 #else
 
 #define __dc_entire_op(op)
+#define __dc_disable()
+#define __dc_enable()
 #define __dc_line_op(paddr, vaddr, sz, op)
 #define __dc_line_op_k(paddr, sz, op)
 
@@ -597,6 +618,40 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op)
 #endif
 }
 
+noinline static void slc_entire_op(const int op)
+{
+       unsigned int ctrl, r = ARC_REG_SLC_CTRL;
+
+       ctrl = read_aux_reg(r);
+
+       if (!(op & OP_FLUSH))           /* i.e. OP_INV */
+               ctrl &= ~SLC_CTRL_IM;   /* clear IM: Disable flush before Inv */
+       else
+               ctrl |= SLC_CTRL_IM;
+
+       write_aux_reg(r, ctrl);
+
+       write_aux_reg(ARC_REG_SLC_INVALIDATE, 1);
+
+       /* Important to wait for flush to complete */
+       while (read_aux_reg(r) & SLC_CTRL_BUSY);
+}
+
+static inline void arc_slc_disable(void)
+{
+       const int r = ARC_REG_SLC_CTRL;
+
+       slc_entire_op(OP_FLUSH_N_INV);
+       write_aux_reg(r, read_aux_reg(r) | SLC_CTRL_DIS);
+}
+
+static inline void arc_slc_enable(void)
+{
+       const int r = ARC_REG_SLC_CTRL;
+
+       write_aux_reg(r, read_aux_reg(r) & ~SLC_CTRL_DIS);
+}
+
 /***********************************************************
  * Exported APIs
  */
@@ -923,21 +978,54 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
        return 0;
 }
 
-void arc_cache_init(void)
+/*
+ * IO-Coherency (IOC) setup rules:
+ *
+ * 1. Needs to be at system level, so only once by Master core
+ *    Non-Masters need not be accessing caches at that time
+ *    - They are either HALT_ON_RESET and kick started much later or
+ *    - if run on reset, need to ensure that arc_platform_smp_wait_to_boot()
+ *      doesn't perturb caches or coherency unit
+ *
+ * 2. caches (L1 and SLC) need to be purged (flush+inv) before setting up IOC,
+ *    otherwise any straggler data might behave strangely post IOC enabling
+ *
+ * 3. All Caches need to be disabled when setting up IOC to elide any in-flight
+ *    Coherency transactions
+ */
+noinline void __init arc_ioc_setup(void)
 {
-       unsigned int __maybe_unused cpu = smp_processor_id();
-       char str[256];
+       unsigned int ap_sz;
 
-       printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
+       /* Flush + invalidate + disable L1 dcache */
+       __dc_disable();
+
+       /* Flush + invalidate SLC */
+       if (read_aux_reg(ARC_REG_SLC_BCR))
+               slc_entire_op(OP_FLUSH_N_INV);
+
+       /* IOC Aperture start: TDB: handle non default CONFIG_LINUX_LINK_BASE */
+       write_aux_reg(ARC_REG_IO_COH_AP0_BASE, 0x80000);
 
        /*
-        * Only master CPU needs to execute rest of function:
-        *  - Assume SMP so all cores will have same cache config so
-        *    any geomtry checks will be same for all
-        *  - IOC setup / dma callbacks only need to be setup once
+        * IOC Aperture size:
+        *   decoded as 2 ^ (SIZE + 2) KB: so setting 0x11 implies 512M
+        * TBD: fix for PGU + 1GB of low mem
+        * TBD: fix for PAE
         */
-       if (cpu)
-               return;
+       ap_sz = order_base_2(arc_get_mem_sz()/1024) - 2;
+       write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, ap_sz);
+
+       write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
+       write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
+
+       /* Re-enable L1 dcache */
+       __dc_enable();
+}
+
+void __init arc_cache_init_master(void)
+{
+       unsigned int __maybe_unused cpu = smp_processor_id();
 
        if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
                struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
@@ -985,30 +1073,14 @@ void arc_cache_init(void)
                }
        }
 
-       if (is_isa_arcv2() && l2_line_sz && !slc_enable) {
-
-               /* IM set : flush before invalidate */
-               write_aux_reg(ARC_REG_SLC_CTRL,
-                       read_aux_reg(ARC_REG_SLC_CTRL) | SLC_CTRL_IM);
+       /* Note that SLC disable not formally supported till HS 3.0 */
+       if (is_isa_arcv2() && l2_line_sz && !slc_enable)
+               arc_slc_disable();
 
-               write_aux_reg(ARC_REG_SLC_INVALIDATE, 1);
-
-               /* Important to wait for flush to complete */
-               while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY);
-               write_aux_reg(ARC_REG_SLC_CTRL,
-                       read_aux_reg(ARC_REG_SLC_CTRL) | SLC_CTRL_DISABLE);
-       }
+       if (is_isa_arcv2() && ioc_enable)
+               arc_ioc_setup();
 
        if (is_isa_arcv2() && ioc_enable) {
-               /* IO coherency base - 0x8z */
-               write_aux_reg(ARC_REG_IO_COH_AP0_BASE, 0x80000);
-               /* IO coherency aperture size - 512Mb: 0x8z-0xAz */
-               write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, 0x11);
-               /* Enable partial writes */
-               write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
-               /* Enable IO coherency */
-               write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
-
                __dma_cache_wback_inv = __dma_cache_wback_inv_ioc;
                __dma_cache_inv = __dma_cache_inv_ioc;
                __dma_cache_wback = __dma_cache_wback_ioc;
@@ -1022,3 +1094,20 @@ void arc_cache_init(void)
                __dma_cache_wback = __dma_cache_wback_l1;
        }
 }
+
+void __ref arc_cache_init(void)
+{
+       unsigned int __maybe_unused cpu = smp_processor_id();
+       char str[256];
+
+       printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
+
+       /*
+        * Only master CPU needs to execute rest of function:
+        *  - Assume SMP so all cores will have same cache config so
+        *    any geomtry checks will be same for all
+        *  - IOC setup / dma callbacks only need to be setup once
+        */
+       if (!cpu)
+               arc_cache_init_master();
+}
index 399e2f223d25303f1294c35b52862e584fbcb1eb..8c9415ed62804d0a8b4a35df176f1b43e6c1be44 100644 (file)
@@ -40,6 +40,11 @@ struct pglist_data node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 #endif
 
+long __init arc_get_mem_sz(void)
+{
+       return low_mem_sz;
+}
+
 /* User can over-ride above with "mem=nnn[KkMm]" in cmdline */
 static int __init setup_mem_sz(char *str)
 {
index 5fab553fd03ade24fdc1a69a83e5092b791b8a01..186c4c214e0a756b4468b597d5680093408c28c3 100644 (file)
@@ -1502,8 +1502,7 @@ source kernel/Kconfig.preempt
 
 config HZ_FIXED
        int
-       default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
-               ARCH_S5PV210 || ARCH_EXYNOS4
+       default 200 if ARCH_EBSA110
        default 128 if SOC_AT91RM9200
        default 0
 
index cccdbcb557b6d29b2e45a0c0b9fb792a469cf1fe..01d178a2009f598f133e890a46c3e3e99efcc63c 100644 (file)
@@ -501,6 +501,7 @@ dtb-$(CONFIG_ARCH_OMAP3) += \
        am3517-evm.dtb \
        am3517_mt_ventoux.dtb \
        logicpd-torpedo-37xx-devkit.dtb \
+       logicpd-som-lv-37xx-devkit.dtb \
        omap3430-sdp.dtb \
        omap3-beagle.dtb \
        omap3-beagle-xm.dtb \
@@ -616,7 +617,7 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
        orion5x-lacie-ethernet-disk-mini-v2.dtb \
        orion5x-linkstation-lsgl.dtb \
        orion5x-linkstation-lswtgl.dtb \
-       orion5x-lschl.dtb \
+       orion5x-linkstation-lschl.dtb \
        orion5x-lswsgl.dtb \
        orion5x-maxtor-shared-storage-2.dtb \
        orion5x-netgear-wnr854t.dtb \
@@ -845,6 +846,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
        sun8i-a83t-allwinner-h8homlet-v2.dtb \
        sun8i-a83t-cubietruck-plus.dtb \
        sun8i-h3-bananapi-m2-plus.dtb \
+       sun8i-h3-nanopi-m1.dtb  \
        sun8i-h3-nanopi-neo.dtb \
        sun8i-h3-orangepi-2.dtb \
        sun8i-h3-orangepi-lite.dtb \
index dc561d505bbe2ce10054c7bc19452b0b4b76fc4f..3e32dd18fd25f5720ca5449ce494c0a3282d4fc4 100644 (file)
@@ -6,8 +6,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <dt-bindings/mfd/tps65217.h>
-
 / {
        cpus {
                cpu@0 {
        ti,pmic-shutdown-controller;
 
        charger {
-               interrupts = <TPS65217_IRQ_AC>, <TPS65217_IRQ_USB>;
-               interrupts-names = "AC", "USB";
+               interrupts = <0>, <1>;
+               interrupt-names = "USB", "AC";
                status = "okay";
        };
 
        pwrbutton {
-               interrupts = <TPS65217_IRQ_PB>;
+               interrupts = <2>;
                status = "okay";
        };
 
index 1463df3b5b195544f7fafc97f3a7dc62efa01f4f..8ed46f9d79b75f1f64e466eba59beb254dbd1f48 100644 (file)
                        AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
                        AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
                        AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
-                       AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */
                >;
        };
 
index 64c8aa9057a3366b746078a51e662f76a35e8f4b..18d72a245e889ac28561b34417680702fb0e10e1 100644 (file)
@@ -16,6 +16,7 @@
        interrupt-parent = <&intc>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c0;
index ac55f93fc91e997deef1815adeb9d9dee9e2c555..2df9e6050c2f382fea2d09f6a95e634210d3a88f 100644 (file)
@@ -16,6 +16,7 @@
        interrupt-parent = <&wakeupgen>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        memory@0 {
                device_type = "memory";
index d6e43e5184c1829483a3b5b0fb1cc99268a0d611..ad68d1eb3bc3d2a4feec75053323f4ed90d394e4 100644 (file)
                        linux,default-trigger = "mmc0";
                };
        };
-
-       extcon_usb2: extcon_usb2 {
-            compatible = "linux,extcon-usb-gpio";
-            id-gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
-       };
 };
 
 &mmc1 {
@@ -79,3 +74,8 @@
 &omap_dwc3_2 {
        extcon = <&extcon_usb2>;
 };
+
+&extcon_usb2 {
+       id-gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
+       vbus-gpio = <&gpio7 22 GPIO_ACTIVE_HIGH>;
+};
index 27d9149cedba78c81c7025a2404d3f80b14524f6..8350b4b34b085231663c9235b570e487827a5000 100644 (file)
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
-       extcon_usb2: extcon_usb2 {
-               compatible = "linux,extcon-usb-gpio";
-               id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
-       };
-
        status-leds {
                compatible = "gpio-leds";
                cpu0-led {
        extcon = <&extcon_usb2>;
 };
 
+&extcon_usb2 {
+       id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+       vbus-gpio = <&gpio3 26 GPIO_ACTIVE_HIGH>;
+};
+
 &mmc1 {
        status = "okay";
        vmmc-supply = <&v3_3d>;
@@ -87,3 +87,7 @@
 &sn65hvs882 {
        load-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
 };
+
+&pcie1 {
+       gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+};
index 555ae21f2b9adcf2ad811b5541a3f865997bb098..814a720d5c3db5a9d1a5c94719fdf89207c435e2 100644 (file)
                        gpio-controller;
                        #gpio-cells = <2>;
                };
+
+               extcon_usb2: tps659038_usb {
+                       compatible = "ti,palmas-usb-vid";
+                       ti,enable-vbus-detection;
+                       ti,enable-id-detection;
+                       /* ID & VBUS GPIOs provided in board dts */
+               };
        };
 };
 
 };
 
 &usb2 {
-       dr_mode = "otg";
+       dr_mode = "peripheral";
 };
 
 &mmc2 {
index b6142bda661e1a701c66c6590970553ce5255fcb..15f07f9af3b3df082f8fd0676ebc843c5b097ab5 100644 (file)
 
        axi {
                compatible = "simple-bus";
-               ranges = <0x00000000 0x18000000 0x0011c40a>;
+               ranges = <0x00000000 0x18000000 0x0011c40c>;
                #address-cells = <1>;
                #size-cells = <1>;
 
index 41de15fe15a2f0dfa241748b2b49ef90be48b323..78492a0bbbab94ffec665bc36a205e48c21e0070 100644 (file)
@@ -99,6 +99,7 @@
                                #size-cells = <1>;
                                compatible = "m25p64";
                                spi-max-frequency = <30000000>;
+                               m25p,fast-read;
                                reg = <0>;
                                partition@0 {
                                        label = "U-Boot-SPL";
index 1facc5f12cef700acf90e0b2f2e8594096a9bf9a..81b8cecb58206d8c98d9d986a1995e67e17fe7ed 100644 (file)
@@ -12,6 +12,7 @@
        interrupt-parent = <&intc>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c1;
index 61dd2f6b02bcfe47d7d6a5ddd5734de0e5687e89..6db652ae9bd558021ac99a6a8bcb954a5c94b806 100644 (file)
@@ -12,6 +12,7 @@
        interrupt-parent = <&intc>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c1;
index addb7530cfbe0dcece696c2e84fbb5ea8896ceb2..5ba161679e01f97c868266aee23b34c62d079c3a 100644 (file)
@@ -18,6 +18,7 @@
 
        compatible = "ti,dra7xx";
        interrupt-parent = <&crossbar_mpu>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c1;
                        phy-names = "sata-phy";
                        clocks = <&sata_ref_clk>;
                        ti,hwmods = "sata";
+                       ports-implemented = <0x1>;
                };
 
                rtc: rtc@48838000 {
index c3d939c9666cabb03752806cab94c002073a4d65..3f808a47df03dfad2b892fd6f833d57f2b18b439 100644 (file)
@@ -75,6 +75,6 @@
                ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
                ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
                ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
-               ti,min-output-imepdance;
+               ti,min-output-impedance;
        };
 };
index ee6dac44edf1ada06b65a48d213ec9d8d966119b..e6df676886c0c35052921669039ae31fd446ccbf 100644 (file)
                ti,palmas-long-press-seconds = <6>;
        };
 };
+
+&usb2_phy1 {
+       phy-supply = <&ldo4_reg>;
+};
+
+&usb2_phy2 {
+       phy-supply = <&ldo4_reg>;
+};
+
+&dss {
+       vdda_video-supply = <&ldo5_reg>;
+};
+
+&mmc1 {
+       vmmc_aux-supply = <&ldo1_reg>;
+};
index b792eee3899b25e7a7a206d16f5737f5fd631a9d..2ee40bc9ec21aafb9833bef482e344c2213273a9 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                gpio0 = &gpio1;
index ac2a9da62b6ce81e4130c44185300ac95c31b2ca..43ccbbf754a340ab552a10ae0578badc59287aa4 100644 (file)
        #size-cells = <1>;
 
        interrupt-parent = <&icoll>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                gpio0 = &gpio0;
index 831d09a28155c5caa0b26ee6be42c20986067536..acd475659156bd05a0cfa9c94eeb778578a480d6 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
index 9d8b5969ee3b0d9455afee96c666e77cae1cc713..b397384248f4b90876f8983ed95881e6caa1cb7d 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
index 3aabf65a6a5224f5681d6ba189087a550824e964..d6a2190b60ef4d52a19d87e140d878c826a1b7ad 100644 (file)
        #size-cells = <1>;
 
        interrupt-parent = <&icoll>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &mac0;
index 685916e3d8a1eaefb083d2a7a81583c18a360168..23b0d2cf9acdcde0180b50b0b7635a52ddd92ecc 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                serial0 = &uart1;
                };
        };
 
-       avic: avic-interrupt-controller@60000000 {
+       avic: interrupt-controller@68000000 {
                compatible = "fsl,imx31-avic", "fsl,avic";
                interrupt-controller;
                #interrupt-cells = <1>;
-               reg = <0x60000000 0x100000>;
+               reg = <0x68000000 0x100000>;
        };
 
        soc {
index 9f40e6229189f3c6cb72c99bc11c351598e7f0e3..d0496c65cea2695772f0477b4d153c3bd3e6fa4d 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
index fe0221e4cbf7b108f81c2695507a9450653b53f8..ceae909e2201f729e8ed64a2f9baaa3103d3d968 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
index 33526cade73582766f68972301d349c72fccb9a6..1ee1d542d9ad088c0bb94a55d66829d6ac1d92b9 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
index ca51dc03e327b3f89b3836ea8ba41d55359af58e..2e516f4985e4cd2e470f8ddb0195a34821a1d09d 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
index 1ade1951e620da007041882b467ebfbe3e530a7c..7aa120fbdc71ea0e4a2776312bc8aedfe5617f16 100644 (file)
 &gpio4 {
        gpio-ranges = <&iomuxc  5 136 1>, <&iomuxc  6 145 1>, <&iomuxc  7 150 1>,
                      <&iomuxc  8 146 1>, <&iomuxc  9 151 1>, <&iomuxc 10 147 1>,
-                     <&iomuxc 11 151 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
+                     <&iomuxc 11 152 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
                      <&iomuxc 14 149 1>, <&iomuxc 15 154 1>, <&iomuxc 16  39 7>,
                      <&iomuxc 23  56 1>, <&iomuxc 24  61 7>, <&iomuxc 31  46 1>;
 };
index 34887a10c5f1712e62c0b953405ef330676a6940..47ba97229a48f23b247a0bd8bc2e874fa5c14c73 100644 (file)
                compatible = "fsl,imx6q-nitrogen6_max-sgtl5000",
                             "fsl,imx-audio-sgtl5000";
                model = "imx6q-nitrogen6_max-sgtl5000";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_sgtl5000>;
                ssi-controller = <&ssi1>;
                audio-codec = <&codec>;
                audio-routing =
 
        codec: sgtl5000@0a {
                compatible = "fsl,sgtl5000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_sgtl5000>;
                reg = <0x0a>;
                clocks = <&clks IMX6QDL_CLK_CKO>;
                VDDA-supply = <&reg_2p5v>;
index d80f21abea62b5bfbd15c4999b01f282b269e973..31d4cc62dbc71bc3b5a8e6aa4a327d9b356fbfed 100644 (file)
                compatible = "fsl,imx6q-nitrogen6_som2-sgtl5000",
                             "fsl,imx-audio-sgtl5000";
                model = "imx6q-nitrogen6_som2-sgtl5000";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_sgtl5000>;
                ssi-controller = <&ssi1>;
                audio-codec = <&codec>;
                audio-routing =
 
        codec: sgtl5000@0a {
                compatible = "fsl,sgtl5000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_sgtl5000>;
                reg = <0x0a>;
                clocks = <&clks IMX6QDL_CLK_CKO>;
                VDDA-supply = <&reg_2p5v>;
index e476d01959ea3f337eb966559c241b3ef82f7fba..26d0604847282879f2286ac9c7242a84b8ac271b 100644 (file)
                                MX6QDL_PAD_SD2_DAT1__SD2_DATA1          0x17071
                                MX6QDL_PAD_SD2_DAT2__SD2_DATA2          0x17071
                                MX6QDL_PAD_SD2_DAT3__SD2_DATA3          0x17071
-                               MX6QDL_PAD_NANDF_CS2__GPIO6_IO15        0x000b0
                        >;
                };
 
index 53e6e63cbb0235d634f108f12ad1fd75001817dd..e7d30f45b161ebb09f9d904f690638ec46c20ce7 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
                                interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6QDL_CLK_EIM_SLOW>;
                                fsl,weim-cs-gpr = <&gpr>;
+                               status = "disabled";
                        };
 
                        ocotp: ocotp@021bc000 {
index 4fd6de29f07db21ba1c4552b8d4e37c59858699f..cc9572ea2860a5b619ce27bce26ed78de0c4c13c 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec;
                                reg = <0x021b8000 0x4000>;
                                interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
                                fsl,weim-cs-gpr = <&gpr>;
+                               status = "disabled";
                        };
 
                        ocotp: ocotp@021bc000 {
index 076a30f9bcae26d8e62b119ee92fd71d1944e922..dd4ec85ecbaaff534c2128997da4215e5b0f93bc 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                can0 = &flexcan1;
                                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_EIM_SLOW>;
                                fsl,weim-cs-gpr = <&gpr>;
+                               status = "disabled";
                        };
 
                        ocotp: ocotp@021bc000 {
index 39845a7e046303e6448e506d7199a49b7530de74..53d3f8e41e9b8e99a15888cb63a50fc19aa591d4 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                ethernet0 = &fec1;
index 8ff2cbdd8f0df26e59805a12dcb0ee871cc3ca73..be33dfc86838ea16dd09201c60cfcdfe00d3c054 100644 (file)
 / {
        #address-cells = <1>;
        #size-cells = <1>;
+       /*
+        * The decompressor and also some bootloaders rely on a
+        * pre-existing /chosen node to be available to insert the
+        * command line and merge other ATAGS info.
+        * Also for U-Boot there must be a pre-existing /memory node.
+        */
+       chosen {};
+       memory { device_type = "memory"; reg = <0 0>; };
 
        aliases {
                gpio0 = &gpio1;
index da8598402ab8b33137a74fac30a69432155fac17..38faa90007d7f0c7e3042a90aef486321cc4bfa0 100644 (file)
 &mmc1 {
        interrupts-extended = <&intc 83 &omap3_pmx_core 0x11a>;
        pinctrl-names = "default";
-       pinctrl-0 = <&mmc1_pins &mmc1_cd>;
+       pinctrl-0 = <&mmc1_pins>;
        wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;                /* gpio_126 */
        cd-gpios = <&gpio4 14 IRQ_TYPE_LEVEL_LOW>;              /* gpio_110 */
        vmmc-supply = <&vmmc1>;
                        OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT | MUX_MODE0)        /* sdmmc1_dat1.sdmmc1_dat1 */
                        OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT | MUX_MODE0)        /* sdmmc1_dat2.sdmmc1_dat2 */
                        OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT | MUX_MODE0)        /* sdmmc1_dat3.sdmmc1_dat3 */
-                       OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_strobe.gpio_126 sdmmc1_wp*/
+                       OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_strobe.gpio_126 */
+                       OMAP3_CORE1_IOPAD(0x212c, PIN_INPUT_PULLUP | MUX_MODE4) /* cam_d11.gpio_110 */
                >;
        };
 
                        OMAP3_WKUP_IOPAD(0x2a16, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4)       /* sys_boot6.gpio_8 */
                >;
        };
-
-       mmc1_cd: pinmux_mmc1_cd {
-               pinctrl-single,pins = <
-                       OMAP3_WKUP_IOPAD(0x212c, PIN_INPUT_PULLUP | MUX_MODE4)  /* cam_d11.gpio_110 */
-               >;
-       };
 };
 
 
index 4f793a025a721b03f3a5e1f074c4c531033cf62f..f1d6de8b3c193eee0d88b0465f33de4e122ba266 100644 (file)
@@ -17,6 +17,7 @@
        interrupt-parent = <&intc>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        aliases {
                serial0 = &uart1;
index 87ca50b53002b9cf244b9dca24a0f2fbdca3dabc..4d448f145ed1c2941bda6d76e91d7573c0a37568 100644 (file)
        vmmc_aux-supply = <&vsim>;
        bus-width = <8>;
        non-removable;
+       no-sdio;
+       no-sd;
 };
 
 &mmc3 {
index ecf5eb584c75058598b9c90bc3f3568bf3a7ce7e..a3ff4933dbc173936bbec5a222aba6642e70564d 100644 (file)
@@ -17,6 +17,7 @@
        interrupt-parent = <&intc>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c1;
index 8087456b5fbec60c9379e5937b299ce820a7cb03..578c53f08309090069454261e09bb0f1617e4a98 100644 (file)
@@ -15,6 +15,7 @@
        interrupt-parent = <&wakeupgen>;
        #address-cells = <1>;
        #size-cells = <1>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c1;
index 968c67a49dbd158b3b3ca24ad2bd85b6f45687d6..0844737b72b27c53b0c8ed88940abf5d2937d637 100644 (file)
@@ -17,6 +17,7 @@
 
        compatible = "ti,omap5";
        interrupt-parent = <&wakeupgen>;
+       chosen { };
 
        aliases {
                i2c0 = &i2c1;
                        phy-names = "sata-phy";
                        clocks = <&sata_ref_clk>;
                        ti,hwmods = "sata";
+                       ports-implemented = <0x1>;
                };
 
                dss: dss@58000000 {
diff --git a/arch/arm/boot/dts/orion5x-linkstation-lschl.dts b/arch/arm/boot/dts/orion5x-linkstation-lschl.dts
new file mode 100644 (file)
index 0000000..ea6c881
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Device Tree file for Buffalo Linkstation LS-CHLv3
+ *
+ * Copyright (C) 2016 Ash Hughes <ashley.hughes@blueyonder.co.uk>
+ * Copyright (C) 2015-2017
+ * Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file 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 file 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.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "orion5x-linkstation.dtsi"
+#include "mvebu-linkstation-gpio-simple.dtsi"
+#include "mvebu-linkstation-fan.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Buffalo Linkstation LiveV3 (LS-CHL)";
+       compatible = "buffalo,lschl", "marvell,orion5x-88f5182", "marvell,orion5x";
+
+       memory { /* 128 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       gpio_keys {
+               func {
+                       label = "Function Button";
+                       linux,code = <KEY_OPTION>;
+                       gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+               };
+
+               power-on-switch {
+                       gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
+               };
+
+               power-auto-switch {
+                       gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio_leds {
+               pinctrl-0 = <&pmx_led_power &pmx_led_alarm &pmx_led_info &pmx_led_func>;
+               blue-power-led {
+                       gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+               };
+
+               red-alarm-led {
+                       gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+               };
+
+               amber-info-led {
+                       gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+               };
+
+               func {
+                       label = "lschl:func:blue:top";
+                       gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio_fan {
+               gpios = <&gpio0 14 GPIO_ACTIVE_LOW
+                        &gpio0 16 GPIO_ACTIVE_LOW>;
+
+               alarm-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&pinctrl {
+       pmx_led_power: pmx-leds {
+               marvell,pins = "mpp0";
+               marvell,function = "gpio";
+       };
+
+       pmx_power_hdd: pmx-power-hdd {
+               marvell,pins = "mpp1";
+               marvell,function = "gpio";
+       };
+
+       pmx_led_alarm: pmx-leds {
+               marvell,pins = "mpp2";
+               marvell,function = "gpio";
+       };
+
+       pmx_led_info: pmx-leds {
+               marvell,pins = "mpp3";
+               marvell,function = "gpio";
+       };
+
+       pmx_fan_lock: pmx-fan-lock {
+               marvell,pins = "mpp6";
+               marvell,function = "gpio";
+       };
+
+       pmx_power_switch: pmx-power-switch {
+               marvell,pins = "mpp8", "mpp10", "mpp15";
+               marvell,function = "gpio";
+       };
+
+       pmx_power_usb: pmx-power-usb {
+               marvell,pins = "mpp9";
+               marvell,function = "gpio";
+       };
+
+       pmx_fan_high: pmx-fan-high {
+               marvell,pins = "mpp14";
+               marvell,function = "gpio";
+       };
+
+       pmx_fan_low: pmx-fan-low {
+               marvell,pins = "mpp16";
+               marvell,function = "gpio";
+       };
+
+       pmx_led_func: pmx-leds {
+               marvell,pins = "mpp17";
+               marvell,function = "gpio";
+       };
+
+       pmx_sw_init: pmx-sw-init {
+               marvell,pins = "mpp7";
+               marvell,function = "gpio";
+       };
+};
+
+&hdd_power {
+       gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+};
+
+&usb_power {
+       gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
+};
+
diff --git a/arch/arm/boot/dts/orion5x-lschl.dts b/arch/arm/boot/dts/orion5x-lschl.dts
deleted file mode 100644 (file)
index 9474092..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Device Tree file for Buffalo Linkstation LS-CHLv3
- *
- * Copyright (C) 2016 Ash Hughes <ashley.hughes@blueyonder.co.uk>
- * Copyright (C) 2015, 2016
- * Roger Shimizu <rogershimizu@gmail.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file 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 file 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.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/dts-v1/;
-
-#include "orion5x-linkstation.dtsi"
-#include "mvebu-linkstation-gpio-simple.dtsi"
-#include "mvebu-linkstation-fan.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-
-/ {
-       model = "Buffalo Linkstation Live v3 (LS-CHL)";
-       compatible = "buffalo,lschl", "marvell,orion5x-88f5182", "marvell,orion5x";
-
-       memory { /* 128 MB */
-               device_type = "memory";
-               reg = <0x00000000 0x8000000>;
-       };
-
-       gpio_keys {
-               func {
-                       label = "Function Button";
-                       linux,code = <KEY_OPTION>;
-                       gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
-               };
-
-               power-on-switch {
-                       gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
-               };
-
-               power-auto-switch {
-                       gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
-               };
-       };
-
-       gpio_leds {
-               pinctrl-0 = <&pmx_led_power &pmx_led_alarm &pmx_led_info &pmx_led_func>;
-               blue-power-led {
-                       gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
-               };
-
-               red-alarm-led {
-                       gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
-               };
-
-               amber-info-led {
-                       gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
-               };
-
-               func {
-                       label = "lschl:func:blue:top";
-                       gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
-               };
-       };
-
-       gpio_fan {
-               gpios = <&gpio0 14 GPIO_ACTIVE_LOW
-                        &gpio0 16 GPIO_ACTIVE_LOW>;
-
-               alarm-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
-       };
-};
-
-&pinctrl {
-       pmx_led_power: pmx-leds {
-               marvell,pins = "mpp0";
-               marvell,function = "gpio";
-       };
-
-       pmx_power_hdd: pmx-power-hdd {
-               marvell,pins = "mpp1";
-               marvell,function = "gpio";
-       };
-
-       pmx_led_alarm: pmx-leds {
-               marvell,pins = "mpp2";
-               marvell,function = "gpio";
-       };
-
-       pmx_led_info: pmx-leds {
-               marvell,pins = "mpp3";
-               marvell,function = "gpio";
-       };
-
-       pmx_fan_lock: pmx-fan-lock {
-               marvell,pins = "mpp6";
-               marvell,function = "gpio";
-       };
-
-       pmx_power_switch: pmx-power-switch {
-               marvell,pins = "mpp8", "mpp10", "mpp15";
-               marvell,function = "gpio";
-       };
-
-       pmx_power_usb: pmx-power-usb {
-               marvell,pins = "mpp9";
-               marvell,function = "gpio";
-       };
-
-       pmx_fan_high: pmx-fan-high {
-               marvell,pins = "mpp14";
-               marvell,function = "gpio";
-       };
-
-       pmx_fan_low: pmx-fan-low {
-               marvell,pins = "mpp16";
-               marvell,function = "gpio";
-       };
-
-       pmx_led_func: pmx-leds {
-               marvell,pins = "mpp17";
-               marvell,function = "gpio";
-       };
-
-       pmx_sw_init: pmx-sw-init {
-               marvell,pins = "mpp7";
-               marvell,function = "gpio";
-       };
-};
-
-&hdd_power {
-       gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
-};
-
-&usb_power {
-       gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
-};
-
index 268bd470c865e6022d907ca495b6913acfd7c1ef..407a4610f4a7e055a488defe3fc52c05f1b3fa63 100644 (file)
@@ -4,6 +4,7 @@
 #include <dt-bindings/clock/qcom,gcc-msm8960.h>
 #include <dt-bindings/reset/qcom,gcc-msm8960.h>
 #include <dt-bindings/clock/qcom,mmcc-msm8960.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
 #include <dt-bindings/soc/qcom,gsbi.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
        firmware {
                scm {
                        compatible = "qcom,scm-apq8064";
+
+                       clocks = <&rpmcc RPM_DAYTONA_FABRIC_CLK>;
+                       clock-names = "core";
                };
        };
 
index 5ae4ec59e6ea4533ec35485a0a0bb361acdfffaf..c852b69229c977281a6f7e7192d88c3275e80817 100644 (file)
                };
 
                amba {
-                       compatible = "arm,amba-bus";
+                       compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
index c8b2944e304ac6dfdfdacbc3d1b63ab12e7ad73f..ace97e8576dbd9ae34d112b4aa8ec991647134e5 100644 (file)
                                phy-names       = "usb2-phy", "usb3-phy";
                                phys            = <&usb2_picophy0>,
                                                  <&phy_port2 PHY_TYPE_USB3>;
+                               snps,dis_u3_susphy_quirk;
                        };
                };
 
index 735914f6ae446a4766f484ab888826efc99eefb1..7cae328398b12f962421cdaa774b5892246032a6 100644 (file)
        cpu-supply = <&reg_dcdc3>;
 };
 
+&de {
+       status = "okay";
+};
+
 &ehci0 {
        status = "okay";
 };
index 2b26175d55d1b7e3cc27611eb5883f4bc913d575..e78faaf9243c862d6eba52d43851f9451cfd0476 100644 (file)
        de: display-engine {
                compatible = "allwinner,sun6i-a31-display-engine";
                allwinner,pipelines = <&fe0>;
+               status = "disabled";
        };
 
        soc@01c00000 {
index 5ea4915f6d75b93eb06c974ab1b6abd009f7f769..10d307408f237f21d15fdbe2bf84de5b4db40f0a 100644 (file)
@@ -56,7 +56,7 @@
 };
 
 &pio {
-       mmc2_pins_nrst: mmc2@0 {
+       mmc2_pins_nrst: mmc2-rst-pin {
                allwinner,pins = "PC16";
                allwinner,function = "gpio_out";
                allwinner,drive = <SUN4I_PINCTRL_10_MA>;
index 102838fcc5880ca0f4fbb90a23098191004d9386..15f4fd3f469561caa7fba30fed8c6a10c18c6668 100644 (file)
@@ -81,7 +81,7 @@
                #address-cells = <0>;
                interrupt-controller;
                reg = <0 0x2c001000 0 0x1000>,
-                     <0 0x2c002000 0 0x1000>,
+                     <0 0x2c002000 0 0x2000>,
                      <0 0x2c004000 0 0x2000>,
                      <0 0x2c006000 0 0x2000>;
                interrupts = <1 9 0xf04>;
index 45d08cc37b0134c71b11bb580fb574386b46c47b..bd107c5a02267f33a02e31e0e5fd116672684d73 100644 (file)
                #address-cells = <0>;
                interrupt-controller;
                reg = <0 0x2c001000 0 0x1000>,
-                     <0 0x2c002000 0 0x1000>,
+                     <0 0x2c002000 0 0x2000>,
                      <0 0x2c004000 0 0x2000>,
                      <0 0x2c006000 0 0x2000>;
                interrupts = <1 9 0xf04>;
index 7ea617e47fe41123193bc10a9cb331d9687e015a..958b4c42d32040105fd545ee2e62ceaadb0b682c 100644 (file)
                                        switch0phy1: switch1phy0@1 {
                                                reg = <1>;
                                                interrupt-parent = <&switch0>;
-                                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;                                   };
+                                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
                                        switch0phy2: switch1phy0@2 {
                                                reg = <2>;
                                                interrupt-parent = <&switch0>;
index ea316c4b890efadb31df9f90df5ae382c94d4228..d3f1768840e28aa6a4e1ccba8cb3313bfbe78324 100644 (file)
@@ -64,8 +64,8 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
index 18e59feaa3071593936ca4f0ff3d3b021eea9b08..7f479cdb34797c36219fe37bf8cdac79e94c3b8b 100644 (file)
@@ -56,8 +56,8 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
index b01a4385129472ef83fb1bdbb90513a4b357a312..f57ec511e7ae41d8d3d35351b11a15d708f0647e 100644 (file)
@@ -471,7 +471,7 @@ CONFIG_MESON_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
-CONFIG_BCM47XX_WATCHDOG=y
+CONFIG_BCM47XX_WDT=y
 CONFIG_BCM7038_WDT=m
 CONFIG_BCM_KONA_WDT=y
 CONFIG_MFD_ACT8945A=y
@@ -824,6 +824,7 @@ CONFIG_QCOM_SMSM=y
 CONFIG_QCOM_WCNSS_CTRL=m
 CONFIG_ROCKCHIP_PM_DOMAINS=y
 CONFIG_COMMON_CLK_QCOM=y
+CONFIG_QCOM_CLK_RPM=y
 CONFIG_CHROME_PLATFORMS=y
 CONFIG_STAGING_BOARD=y
 CONFIG_CROS_EC_CHARDEV=m
@@ -893,7 +894,7 @@ CONFIG_BCM2835_MBOX=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
 CONFIG_EFI_VARS=m
 CONFIG_EFI_CAPSULE_LOADER=m
-CONFIG_CONFIG_BCM47XX_NVRAM=y
+CONFIG_BCM47XX_NVRAM=y
 CONFIG_BCM47XX_SPROM=y
 CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
index 4364040ed69689dcc1d4c9a25aab9c8308e1b77c..1e6c48dd7b11830acc9a03a8bd700a47f8dbcc01 100644 (file)
@@ -86,9 +86,9 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
index 522b5feb4eaa34dcbd0e66b7f417a6e857076db8..b62eaeb147aa9a0b8caa73bf96a73a1d02e5f708 100644 (file)
@@ -94,6 +94,9 @@
 #define ARM_CPU_XSCALE_ARCH_V2         0x4000
 #define ARM_CPU_XSCALE_ARCH_V3         0x6000
 
+/* Qualcomm implemented cores */
+#define ARM_CPU_PART_SCORPION          0x510002d0
+
 extern unsigned int processor_id;
 
 #ifdef CONFIG_CPU_CP15
index bfe2a2f5a644e80a9f80f71b49d727604c41e728..22b73112b75f2070e440068184f9655cff781afe 100644 (file)
@@ -54,6 +54,24 @@ static inline void *return_address(unsigned int level)
 
 #define ftrace_return_address(n) return_address(n)
 
+#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+
+static inline bool arch_syscall_match_sym_name(const char *sym,
+                                              const char *name)
+{
+       if (!strcmp(sym, "sys_mmap2"))
+               sym = "sys_mmap_pgoff";
+       else if (!strcmp(sym, "sys_statfs64_wrapper"))
+               sym = "sys_statfs64";
+       else if (!strcmp(sym, "sys_fstatfs64_wrapper"))
+               sym = "sys_fstatfs64";
+       else if (!strcmp(sym, "sys_arm_fadvise64_64"))
+               sym = "sys_fadvise64_64";
+
+       /* Ignore case since sym may start with "SyS" instead of "sys" */
+       return !strcasecmp(sym, name);
+}
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* _ASM_ARM_FTRACE */
diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h
deleted file mode 100644 (file)
index a53cdb8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _ASM_TYPES_H
-#define _ASM_TYPES_H
-
-#include <asm-generic/int-ll64.h>
-
-/*
- * The C99 types uintXX_t that are usually defined in 'stdint.h' are not as
- * unambiguous on ARM as you would expect. For the types below, there is a
- * difference on ARM between GCC built for bare metal ARM, GCC built for glibc
- * and the kernel itself, which results in build errors if you try to build with
- * -ffreestanding and include 'stdint.h' (such as when you include 'arm_neon.h'
- * in order to use NEON intrinsics)
- *
- * As the typedefs for these types in 'stdint.h' are based on builtin defines
- * supplied by GCC, we can tweak these to align with the kernel's idea of those
- * types, so 'linux/types.h' and 'stdint.h' can be safely included from the same
- * source file (provided that -ffreestanding is used).
- *
- *                    int32_t         uint32_t               uintptr_t
- * bare metal GCC     long            unsigned long          unsigned int
- * glibc GCC          int             unsigned int           unsigned int
- * kernel             int             unsigned int           unsigned long
- */
-
-#ifdef __INT32_TYPE__
-#undef __INT32_TYPE__
-#define __INT32_TYPE__         int
-#endif
-
-#ifdef __UINT32_TYPE__
-#undef __UINT32_TYPE__
-#define __UINT32_TYPE__        unsigned int
-#endif
-
-#ifdef __UINTPTR_TYPE__
-#undef __UINTPTR_TYPE__
-#define __UINTPTR_TYPE__       unsigned long
-#endif
-
-#endif /* _ASM_TYPES_H */
index 1f59ea051bab814132074b09f55d3a57c800a471..b7e0125c0bbf2014a447800a383426b62d5147b8 100644 (file)
@@ -478,11 +478,10 @@ extern unsigned long __must_check
 arm_copy_from_user(void *to, const void __user *from, unsigned long n);
 
 static inline unsigned long __must_check
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__arch_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
        unsigned int __ua_flags;
 
-       check_object_size(to, n, false);
        __ua_flags = uaccess_save_and_enable();
        n = arm_copy_from_user(to, from, n);
        uaccess_restore(__ua_flags);
@@ -495,18 +494,15 @@ extern unsigned long __must_check
 __copy_to_user_std(void __user *to, const void *from, unsigned long n);
 
 static inline unsigned long __must_check
-__copy_to_user(void __user *to, const void *from, unsigned long n)
+__arch_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 #ifndef CONFIG_UACCESS_WITH_MEMCPY
        unsigned int __ua_flags;
-
-       check_object_size(from, n, true);
        __ua_flags = uaccess_save_and_enable();
        n = arm_copy_to_user(to, from, n);
        uaccess_restore(__ua_flags);
        return n;
 #else
-       check_object_size(from, n, true);
        return arm_copy_to_user(to, from, n);
 #endif
 }
@@ -526,25 +522,49 @@ __clear_user(void __user *addr, unsigned long n)
 }
 
 #else
-#define __copy_from_user(to, from, n)  (memcpy(to, (void __force *)from, n), 0)
-#define __copy_to_user(to, from, n)    (memcpy((void __force *)to, from, n), 0)
+#define __arch_copy_from_user(to, from, n)     \
+                                       (memcpy(to, (void __force *)from, n), 0)
+#define __arch_copy_to_user(to, from, n)       \
+                                       (memcpy((void __force *)to, from, n), 0)
 #define __clear_user(addr, n)          (memset((void __force *)addr, 0, n), 0)
 #endif
 
-static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
+static inline unsigned long __must_check
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+       check_object_size(to, n, false);
+       return __arch_copy_from_user(to, from, n);
+}
+
+static inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long n)
 {
        unsigned long res = n;
+
+       check_object_size(to, n, false);
+
        if (likely(access_ok(VERIFY_READ, from, n)))
-               res = __copy_from_user(to, from, n);
+               res = __arch_copy_from_user(to, from, n);
        if (unlikely(res))
                memset(to + (n - res), 0, res);
        return res;
 }
 
-static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
+static inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
 {
+       check_object_size(from, n, true);
+
+       return __arch_copy_to_user(to, from, n);
+}
+
+static inline unsigned long __must_check
+copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       check_object_size(from, n, true);
+
        if (access_ok(VERIFY_WRITE, to, n))
-               n = __copy_to_user(to, from, n);
+               n = __arch_copy_to_user(to, from, n);
        return n;
 }
 
index a2e75b84e2ae6b4d3f37d7879bc024832c17d3c9..6dae1956c74d761beb8f1cb5f12dc1a8e912c4b5 100644 (file)
@@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode(void)
        return false;
 }
 
+static inline bool has_vhe(void)
+{
+       return false;
+}
+
 /* The section containing the hypervisor idmap text */
 extern char __hyp_idmap_text_start[];
 extern char __hyp_idmap_text_end[];
diff --git a/arch/arm/include/uapi/asm/types.h b/arch/arm/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..9435a42
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _UAPI_ASM_TYPES_H
+#define _UAPI_ASM_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+/*
+ * The C99 types uintXX_t that are usually defined in 'stdint.h' are not as
+ * unambiguous on ARM as you would expect. For the types below, there is a
+ * difference on ARM between GCC built for bare metal ARM, GCC built for glibc
+ * and the kernel itself, which results in build errors if you try to build with
+ * -ffreestanding and include 'stdint.h' (such as when you include 'arm_neon.h'
+ * in order to use NEON intrinsics)
+ *
+ * As the typedefs for these types in 'stdint.h' are based on builtin defines
+ * supplied by GCC, we can tweak these to align with the kernel's idea of those
+ * types, so 'linux/types.h' and 'stdint.h' can be safely included from the same
+ * source file (provided that -ffreestanding is used).
+ *
+ *                    int32_t         uint32_t               uintptr_t
+ * bare metal GCC     long            unsigned long          unsigned int
+ * glibc GCC          int             unsigned int           unsigned int
+ * kernel             int             unsigned int           unsigned long
+ */
+
+#ifdef __INT32_TYPE__
+#undef __INT32_TYPE__
+#define __INT32_TYPE__         int
+#endif
+
+#ifdef __UINT32_TYPE__
+#undef __UINT32_TYPE__
+#define __UINT32_TYPE__        unsigned int
+#endif
+
+#ifdef __UINTPTR_TYPE__
+#undef __UINTPTR_TYPE__
+#define __UINTPTR_TYPE__       unsigned long
+#endif
+
+#endif /* _UAPI_ASM_TYPES_H */
index 188180b5523de09f55647d2d31547684c450a8c7..be3b3fbd382fbbd4a4ef4baa34b5d3f906ab3562 100644 (file)
@@ -1063,6 +1063,22 @@ static int __init arch_hw_breakpoint_init(void)
                return 0;
        }
 
+       /*
+        * Scorpion CPUs (at least those in APQ8060) seem to set DBGPRSR.SPD
+        * whenever a WFI is issued, even if the core is not powered down, in
+        * violation of the architecture.  When DBGPRSR.SPD is set, accesses to
+        * breakpoint and watchpoint registers are treated as undefined, so
+        * this results in boot time and runtime failures when these are
+        * accessed and we unexpectedly take a trap.
+        *
+        * It's not clear if/how this can be worked around, so we blacklist
+        * Scorpion CPUs to avoid these issues.
+       */
+       if (read_cpuid_part() == ARM_CPU_PART_SCORPION) {
+               pr_info("Scorpion CPU detected. Hardware breakpoints and watchpoints disabled\n");
+               return 0;
+       }
+
        has_ossr = core_has_os_save_restore();
 
        /* Determine how many BRPs/WRPs are available. */
index ce131ed5939d5ff86054afc3a14de7cb51225a79..ae738a6319f6a341c05a3c6a2dee2da30aa02a40 100644 (file)
@@ -600,7 +600,7 @@ static int gpr_set(struct task_struct *target,
                   const void *kbuf, const void __user *ubuf)
 {
        int ret;
-       struct pt_regs newregs;
+       struct pt_regs newregs = *task_pt_regs(target);
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                 &newregs,
index 22313cb5336257cffa870b15e21279a1b4684e99..9af0701f7094be972b0f8c60a0a6c8417ed844eb 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/preempt.h>
 #include <linux/smp.h>
+#include <linux/uaccess.h>
 
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
@@ -40,8 +41,11 @@ static inline void ipi_flush_tlb_mm(void *arg)
 static inline void ipi_flush_tlb_page(void *arg)
 {
        struct tlb_args *ta = (struct tlb_args *)arg;
+       unsigned int __ua_flags = uaccess_save_and_enable();
 
        local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+
+       uaccess_restore(__ua_flags);
 }
 
 static inline void ipi_flush_tlb_kernel_page(void *arg)
@@ -54,8 +58,11 @@ static inline void ipi_flush_tlb_kernel_page(void *arg)
 static inline void ipi_flush_tlb_range(void *arg)
 {
        struct tlb_args *ta = (struct tlb_args *)arg;
+       unsigned int __ua_flags = uaccess_save_and_enable();
 
        local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+
+       uaccess_restore(__ua_flags);
 }
 
 static inline void ipi_flush_tlb_kernel_range(void *arg)
index 11676787ad49042d5049ccd376d153d47ef7bd06..9d7446456e0c4217e0931f3640eb006cb0fb83d7 100644 (file)
@@ -1099,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dummy)
        __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
        __cpu_init_stage2();
 
+       if (is_kernel_in_hyp_mode())
+               kvm_timer_init_vhe();
+
        kvm_arm_init_debug();
 }
 
index 8ecfd15c3a0248db29667fe3dc6ec6429fc9fc7c..df73914e81c8344feccac5df8d5791dcbe92ed60 100644 (file)
@@ -67,7 +67,7 @@ ENTRY(__get_user_4)
 ENDPROC(__get_user_4)
 
 ENTRY(__get_user_8)
-       check_uaccess r0, 8, r1, r2, __get_user_bad
+       check_uaccess r0, 8, r1, r2, __get_user_bad8
 #ifdef CONFIG_THUMB2_KERNEL
 5: TUSER(ldr)  r2, [r0]
 6: TUSER(ldr)  r3, [r0, #4]
index df42c93a93d69e88db6e8e621271a59e36025c5f..f5dce9b4e617df833cd210bac2fe65ac4a93b788 100644 (file)
@@ -31,10 +31,10 @@ static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clockfw_lock);
 
-static void __clk_enable(struct clk *clk)
+void davinci_clk_enable(struct clk *clk)
 {
        if (clk->parent)
-               __clk_enable(clk->parent);
+               davinci_clk_enable(clk->parent);
        if (clk->usecount++ == 0) {
                if (clk->flags & CLK_PSC)
                        davinci_psc_config(clk->domain, clk->gpsc, clk->lpsc,
@@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk)
        }
 }
 
-static void __clk_disable(struct clk *clk)
+void davinci_clk_disable(struct clk *clk)
 {
        if (WARN_ON(clk->usecount == 0))
                return;
@@ -56,7 +56,7 @@ static void __clk_disable(struct clk *clk)
                        clk->clk_disable(clk);
        }
        if (clk->parent)
-               __clk_disable(clk->parent);
+               davinci_clk_disable(clk->parent);
 }
 
 int davinci_clk_reset(struct clk *clk, bool reset)
@@ -103,7 +103,7 @@ int clk_enable(struct clk *clk)
                return -EINVAL;
 
        spin_lock_irqsave(&clockfw_lock, flags);
-       __clk_enable(clk);
+       davinci_clk_enable(clk);
        spin_unlock_irqrestore(&clockfw_lock, flags);
 
        return 0;
@@ -118,7 +118,7 @@ void clk_disable(struct clk *clk)
                return;
 
        spin_lock_irqsave(&clockfw_lock, flags);
-       __clk_disable(clk);
+       davinci_clk_disable(clk);
        spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
index e2a5437a1aee3c017f4f353410e0f0e314a96274..fa2b83752e030a494ae3f02a09db118e463488cd 100644 (file)
@@ -132,6 +132,8 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
 int davinci_set_refclk_rate(unsigned long rate);
 int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
 int davinci_clk_reset(struct clk *clk, bool reset);
+void davinci_clk_enable(struct clk *clk);
+void davinci_clk_disable(struct clk *clk);
 
 extern struct platform_device davinci_wdt_device;
 extern void davinci_watchdog_reset(struct platform_device *);
index e770c97ea45c28bfc77232bb1873f976dcfc271c..1d873d15b545c26a97eefdf15d92d437ff2e1701 100644 (file)
@@ -319,6 +319,16 @@ static struct clk emac_clk = {
        .gpsc           = 1,
 };
 
+/*
+ * In order to avoid adding the emac_clk to the clock lookup table twice (and
+ * screwing up the linked list in the process) create a separate clock for
+ * mdio inheriting the rate from emac_clk.
+ */
+static struct clk mdio_clk = {
+       .name           = "mdio",
+       .parent         = &emac_clk,
+};
+
 static struct clk mcasp_clk = {
        .name           = "mcasp",
        .parent         = &async3_clk,
@@ -367,6 +377,16 @@ static struct clk aemif_clk = {
        .flags          = ALWAYS_ENABLED,
 };
 
+/*
+ * In order to avoid adding the aemif_clk to the clock lookup table twice (and
+ * screwing up the linked list in the process) create a separate clock for
+ * nand inheriting the rate from aemif_clk.
+ */
+static struct clk aemif_nand_clk = {
+       .name           = "nand",
+       .parent         = &aemif_clk,
+};
+
 static struct clk usb11_clk = {
        .name           = "usb11",
        .parent         = &pll0_sysclk4,
@@ -529,7 +549,7 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "arm",          &arm_clk),
        CLK(NULL,               "rmii",         &rmii_clk),
        CLK("davinci_emac.1",   NULL,           &emac_clk),
-       CLK("davinci_mdio.0",   "fck",          &emac_clk),
+       CLK("davinci_mdio.0",   "fck",          &mdio_clk),
        CLK("davinci-mcasp.0",  NULL,           &mcasp_clk),
        CLK("davinci-mcbsp.0",  NULL,           &mcbsp0_clk),
        CLK("davinci-mcbsp.1",  NULL,           &mcbsp1_clk),
@@ -537,7 +557,15 @@ static struct clk_lookup da850_clks[] = {
        CLK("da830-mmc.0",      NULL,           &mmcsd0_clk),
        CLK("da830-mmc.1",      NULL,           &mmcsd1_clk),
        CLK("ti-aemif",         NULL,           &aemif_clk),
-       CLK(NULL,               "aemif",        &aemif_clk),
+       /*
+        * The only user of this clock is davinci_nand and it get's it through
+        * con_id. The nand node itself is created from within the aemif
+        * driver to guarantee that it's probed after the aemif timing
+        * parameters are configured. of_dev_auxdata is not accessible from
+        * the aemif driver and can't be passed to of_platform_populate(). For
+        * that reason we're leaving the dev_id here as NULL.
+        */
+       CLK(NULL,               "aemif",        &aemif_nand_clk),
        CLK("ohci-da8xx",       "usb11",        &usb11_clk),
        CLK("musb-da8xx",       "usb20",        &usb20_clk),
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
index c6feecf7ae242f36ce02ff1c2c43a8c4ad6807d1..9a6af0bd5dc340690bbe794b972b0aeb529faeff 100644 (file)
@@ -22,6 +22,8 @@
 #define DA8XX_USB0_BASE                0x01e00000
 #define DA8XX_USB1_BASE                0x01e25000
 
+static struct clk *usb20_clk;
+
 static struct platform_device da8xx_usb_phy = {
        .name           = "da8xx-usb-phy",
        .id             = -1,
@@ -158,26 +160,13 @@ int __init da8xx_register_usb_refclkin(int rate)
 
 static void usb20_phy_clk_enable(struct clk *clk)
 {
-       struct clk *usb20_clk;
-       int err;
        u32 val;
        u32 timeout = 500000; /* 500 msec */
 
        val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 
-       usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
-       if (IS_ERR(usb20_clk)) {
-               pr_err("could not get usb20 clk: %ld\n", PTR_ERR(usb20_clk));
-               return;
-       }
-
        /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
-       err = clk_prepare_enable(usb20_clk);
-       if (err) {
-               pr_err("failed to enable usb20 clk: %d\n", err);
-               clk_put(usb20_clk);
-               return;
-       }
+       davinci_clk_enable(usb20_clk);
 
        /*
         * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
@@ -197,8 +186,7 @@ static void usb20_phy_clk_enable(struct clk *clk)
 
        pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
 done:
-       clk_disable_unprepare(usb20_clk);
-       clk_put(usb20_clk);
+       davinci_clk_disable(usb20_clk);
 }
 
 static void usb20_phy_clk_disable(struct clk *clk)
@@ -285,11 +273,19 @@ static struct clk_lookup usb20_phy_clk_lookup =
 int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
 {
        struct clk *parent;
-       int ret = 0;
+       int ret;
+
+       usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
+       ret = PTR_ERR_OR_ZERO(usb20_clk);
+       if (ret)
+               return ret;
 
        parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
-       if (IS_ERR(parent))
-               return PTR_ERR(parent);
+       ret = PTR_ERR_OR_ZERO(parent);
+       if (ret) {
+               clk_put(usb20_clk);
+               return ret;
+       }
 
        usb20_phy_clk.parent = parent;
        ret = clk_register(&usb20_phy_clk);
index 98ffe1e62ad5d6debe7c087743d728d5730c26d3..a5d68411a037994cfcf7f3c2b62c0afb5d91617f 100644 (file)
@@ -385,36 +385,6 @@ fail:
        return pen_release != -1 ? ret : 0;
 }
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-
-static void __init exynos_smp_init_cpus(void)
-{
-       void __iomem *scu_base = scu_base_addr();
-       unsigned int i, ncores;
-
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-               ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-       else
-               /*
-                * CPU Nodes are passed thru DT and set_cpu_possible
-                * is set by "arm_dt_init_cpu_maps".
-                */
-               return;
-
-       /* sanity check */
-       if (ncores > nr_cpu_ids) {
-               pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-                       ncores, nr_cpu_ids);
-               ncores = nr_cpu_ids;
-       }
-
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
 static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 {
        int i;
@@ -479,7 +449,6 @@ static void exynos_cpu_die(unsigned int cpu)
 #endif /* CONFIG_HOTPLUG_CPU */
 
 const struct smp_operations exynos_smp_ops __initconst = {
-       .smp_init_cpus          = exynos_smp_init_cpus,
        .smp_prepare_cpus       = exynos_smp_prepare_cpus,
        .smp_secondary_init     = exynos_secondary_init,
        .smp_boot_secondary     = exynos_boot_secondary,
index de5ab8d88549de87ea88fc92c2bf4eda7a022e38..3a8406e45b65dceedf0abdb02f59b4b30bf394a8 100644 (file)
@@ -37,7 +37,6 @@ static const char * const imx1_dt_board_compat[] __initconst = {
 };
 
 DT_MACHINE_START(IMX1_DT, "Freescale i.MX1 (Device Tree Support)")
-       .map_io         = debug_ll_io_init,
        .init_early     = imx1_init_early,
        .init_irq       = imx1_init_irq,
        .dt_compat      = imx1_dt_board_compat,
index 699157759120f13ed4047b05609e53cb419fffe5..c03bf28d8bbc9a1a3f2be4187465c3cb674e25f1 100644 (file)
@@ -60,7 +60,6 @@
 
 #define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu)
 
-static enum cpuhp_state cpuhp_mmdc_state;
 static int ddr_type;
 
 struct fsl_mmdc_devtype_data {
@@ -82,6 +81,7 @@ static const struct of_device_id imx_mmdc_dt_ids[] = {
 
 #ifdef CONFIG_PERF_EVENTS
 
+static enum cpuhp_state cpuhp_mmdc_state;
 static DEFINE_IDA(mmdc_ida);
 
 PMU_EVENT_ATTR_STRING(total-cycles, mmdc_pmu_total_cycles, "event=0x00")
index f6ba589cd312ecb257829d81f7f04c967b60e216..c821c1d5610ef25c56e1c0873452a019a602380d 100644 (file)
@@ -32,7 +32,6 @@
 #include "soc.h"
 
 #define OMAP1_DMA_BASE                 (0xfffed800)
-#define OMAP1_LOGICAL_DMA_CH_COUNT     17
 
 static u32 enable_1510_mode;
 
@@ -348,8 +347,6 @@ static int __init omap1_system_dma_init(void)
                goto exit_iounmap;
        }
 
-       d->lch_count            = OMAP1_LOGICAL_DMA_CH_COUNT;
-
        /* Valid attributes for omap1 plus processors */
        if (cpu_is_omap15xx())
                d->dev_caps = ENABLE_1510_MODE;
@@ -366,13 +363,14 @@ static int __init omap1_system_dma_init(void)
        d->dev_caps             |= CLEAR_CSR_ON_READ;
        d->dev_caps             |= IS_WORD_16;
 
-       if (cpu_is_omap15xx())
-               d->chan_count = 9;
-       else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-               if (!(d->dev_caps & ENABLE_1510_MODE))
-                       d->chan_count = 16;
+       /* available logical channels */
+       if (cpu_is_omap15xx()) {
+               d->lch_count = 9;
+       } else {
+               if (d->dev_caps & ENABLE_1510_MODE)
+                       d->lch_count = 9;
                else
-                       d->chan_count = 9;
+                       d->lch_count = 16;
        }
 
        p = dma_plat_info;
index 469894082fea00c9605ea4dc370d69b18f5b40d3..093458b62c8dadbcc3c7cc1c3b66d84e59af3d8d 100644 (file)
@@ -7,7 +7,7 @@ ccflags-y := -I$(srctree)/$(src)/include \
 
 # Common support
 obj-y := id.o io.o control.o devices.o fb.o timer.o pm.o \
-        common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
+        common.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
         omap_device.o omap-headsmp.o sram.o drm.o
 
 hwmod-common                           = omap_hwmod.o omap_hwmod_reset.o \
index 36d9943205ca4bb7bff163656f7760129c620e3c..dc9e34e670a26f280bdfe7947fa8709ee750465f 100644 (file)
@@ -304,7 +304,7 @@ DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)")
        .init_late      = am43xx_init_late,
        .init_irq       = omap_gic_of_init,
        .init_machine   = omap_generic_init,
-       .init_time      = omap4_local_timer_init,
+       .init_time      = omap3_gptimer_timer_init,
        .dt_compat      = am43_boards_compat,
        .restart        = omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
deleted file mode 100644 (file)
index 7a57714..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * OMAP2+ specific gpio initialization
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Author:
- *     Charulatha V <charu@ti.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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/gpio.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_data/gpio-omap.h>
-
-#include "soc.h"
-#include "omap_hwmod.h"
-#include "omap_device.h"
-#include "omap-pm.h"
-
-#include "powerdomain.h"
-
-static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
-{
-       struct platform_device *pdev;
-       struct omap_gpio_platform_data *pdata;
-       struct omap_gpio_dev_attr *dev_attr;
-       char *name = "omap_gpio";
-       int id;
-       struct powerdomain *pwrdm;
-
-       /*
-        * extract the device id from name field available in the
-        * hwmod database and use the same for constructing ids for
-        * gpio devices.
-        * CAUTION: Make sure the name in the hwmod database does
-        * not change. If changed, make corresponding change here
-        * or make use of static variable mechanism to handle this.
-        */
-       sscanf(oh->name, "gpio%d", &id);
-
-       pdata = kzalloc(sizeof(struct omap_gpio_platform_data), GFP_KERNEL);
-       if (!pdata) {
-               pr_err("gpio%d: Memory allocation failed\n", id);
-               return -ENOMEM;
-       }
-
-       dev_attr = (struct omap_gpio_dev_attr *)oh->dev_attr;
-       pdata->bank_width = dev_attr->bank_width;
-       pdata->dbck_flag = dev_attr->dbck_flag;
-       pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
-       pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
-       if (!pdata->regs) {
-               pr_err("gpio%d: Memory allocation failed\n", id);
-               kfree(pdata);
-               return -ENOMEM;
-       }
-
-       switch (oh->class->rev) {
-       case 0:
-               if (id == 1)
-                       /* non-wakeup GPIO pins for OMAP2 Bank1 */
-                       pdata->non_wakeup_gpios = 0xe203ffc0;
-               else if (id == 2)
-                       /* non-wakeup GPIO pins for OMAP2 Bank2 */
-                       pdata->non_wakeup_gpios = 0x08700040;
-               /* fall through */
-
-       case 1:
-               pdata->regs->revision = OMAP24XX_GPIO_REVISION;
-               pdata->regs->direction = OMAP24XX_GPIO_OE;
-               pdata->regs->datain = OMAP24XX_GPIO_DATAIN;
-               pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT;
-               pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT;
-               pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT;
-               pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1;
-               pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2;
-               pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1;
-               pdata->regs->irqenable2 = OMAP24XX_GPIO_IRQENABLE2;
-               pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1;
-               pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1;
-               pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL;
-               pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN;
-               pdata->regs->ctrl = OMAP24XX_GPIO_CTRL;
-               pdata->regs->wkup_en = OMAP24XX_GPIO_WAKE_EN;
-               pdata->regs->leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0;
-               pdata->regs->leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1;
-               pdata->regs->risingdetect = OMAP24XX_GPIO_RISINGDETECT;
-               pdata->regs->fallingdetect = OMAP24XX_GPIO_FALLINGDETECT;
-               break;
-       case 2:
-               pdata->regs->revision = OMAP4_GPIO_REVISION;
-               pdata->regs->direction = OMAP4_GPIO_OE;
-               pdata->regs->datain = OMAP4_GPIO_DATAIN;
-               pdata->regs->dataout = OMAP4_GPIO_DATAOUT;
-               pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT;
-               pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT;
-               pdata->regs->irqstatus_raw0 = OMAP4_GPIO_IRQSTATUSRAW0;
-               pdata->regs->irqstatus_raw1 = OMAP4_GPIO_IRQSTATUSRAW1;
-               pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0;
-               pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1;
-               pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0;
-               pdata->regs->irqenable2 = OMAP4_GPIO_IRQSTATUSSET1;
-               pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0;
-               pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0;
-               pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME;
-               pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE;
-               pdata->regs->ctrl = OMAP4_GPIO_CTRL;
-               pdata->regs->wkup_en = OMAP4_GPIO_IRQWAKEN0;
-               pdata->regs->leveldetect0 = OMAP4_GPIO_LEVELDETECT0;
-               pdata->regs->leveldetect1 = OMAP4_GPIO_LEVELDETECT1;
-               pdata->regs->risingdetect = OMAP4_GPIO_RISINGDETECT;
-               pdata->regs->fallingdetect = OMAP4_GPIO_FALLINGDETECT;
-               break;
-       default:
-               WARN(1, "Invalid gpio bank_type\n");
-               kfree(pdata->regs);
-               kfree(pdata);
-               return -EINVAL;
-       }
-
-       pwrdm = omap_hwmod_get_pwrdm(oh);
-       pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
-
-       pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata));
-       kfree(pdata);
-
-       if (IS_ERR(pdev)) {
-               WARN(1, "Can't build omap_device for %s:%s.\n",
-                                       name, oh->name);
-               return PTR_ERR(pdev);
-       }
-
-       return 0;
-}
-
-/*
- * gpio_init needs to be done before
- * machine_init functions access gpio APIs.
- * Hence gpio_init is a omap_postcore_initcall.
- */
-static int __init omap2_gpio_init(void)
-{
-       /* If dtb is there, the devices will be created dynamically */
-       if (of_have_populated_dt())
-               return -ENODEV;
-
-       return omap_hwmod_for_each_by_class("gpio", omap2_gpio_dev_init, NULL);
-}
-omap_postcore_initcall(omap2_gpio_init);
index 759e1d45ba25c3977af1d7048bec577062a51b66..e8b988714a09f842c01b5ea8a22d09c31ba20f1d 100644 (file)
@@ -741,14 +741,14 @@ static int _init_main_clk(struct omap_hwmod *oh)
        int ret = 0;
        char name[MOD_CLK_MAX_NAME_LEN];
        struct clk *clk;
+       static const char modck[] = "_mod_ck";
 
-       /* +7 magic comes from '_mod_ck' suffix */
-       if (strlen(oh->name) + 7 > MOD_CLK_MAX_NAME_LEN)
+       if (strlen(oh->name) >= MOD_CLK_MAX_NAME_LEN - strlen(modck))
                pr_warn("%s: warning: cropping name for %s\n", __func__,
                        oh->name);
 
-       strncpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - 7);
-       strcat(name, "_mod_ck");
+       strlcpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - strlen(modck));
+       strlcat(name, modck, MOD_CLK_MAX_NAME_LEN);
 
        clk = clk_get(NULL, name);
        if (!IS_ERR(clk)) {
index cdfbb44ceb0c4f3059bc6568e2e765304f7e374a..f22e9cb39f4ac16af15020a0990e32dd975a9bd3 100644 (file)
@@ -121,10 +121,6 @@ extern struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[];
 extern struct omap_hwmod_irq_info omap2_dispc_irqs[];
 extern struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[];
 extern struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio1_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio2_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio3_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio4_irqs[];
 extern struct omap_hwmod_irq_info omap2_dma_system_irqs[];
 extern struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[];
 extern struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[];
index 477910a48448d653b2de22339d60c61b967aa8e3..70c004794880e0efd567e269eebc0f7484ca5140 100644 (file)
@@ -161,7 +161,7 @@ static struct ti_st_plat_data wilink7_pdata = {
        .nshutdown_gpio = 162,
        .dev_name = "/dev/ttyO1",
        .flow_cntrl = 1,
-       .baud_rate = 300000,
+       .baud_rate = 3000000,
 };
 
 static struct platform_device wl128x_device = {
index 5b2f5138d938ac626a1895b71a9a44cd0d757785..2b138b65129a5d609ff2ae02a55181c10154113b 100644 (file)
@@ -295,10 +295,8 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
                GFP_KERNEL);
 
        if (!prcm_irq_chips || !prcm_irq_setup->saved_mask ||
-           !prcm_irq_setup->priority_mask) {
-               pr_err("PRCM: kzalloc failed\n");
+           !prcm_irq_setup->priority_mask)
                goto err;
-       }
 
        memset(mask, 0, sizeof(mask));
 
index 56128da23c3a1531994e37522a05e625764cc6ee..07dd692c47372f8aa145d00cb5532b75774429c5 100644 (file)
@@ -510,18 +510,19 @@ void __init omap3_secure_sync32k_timer_init(void)
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
+       defined(CONFIG_SOC_AM43XX)
 void __init omap3_gptimer_timer_init(void)
 {
        __omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
                        1, "timer_sys_ck", "ti,timer-alwon", true);
-
-       clocksource_probe();
+       if (of_have_populated_dt())
+               clocksource_probe();
 }
 #endif
 
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) ||         \
-       defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
+       defined(CONFIG_SOC_DRA7XX)
 static void __init omap4_sync32k_timer_init(void)
 {
        __omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
index f6c3f151d0d48c2c62ca056a18fbbe16edc309d9..b59f4f4f256f2bd6785b086c40bbefb0bb68315c 100644 (file)
@@ -345,10 +345,40 @@ static struct s3c24xx_dma_channel s3c2410_dma_channels[DMACH_MAX] = {
        [DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 3), },
 };
 
+static const struct dma_slave_map s3c2410_dma_slave_map[] = {
+       { "s3c2410-sdi", "rx-tx", (void *)DMACH_SDI },
+       { "s3c2410-spi.0", "rx", (void *)DMACH_SPI0_RX },
+       { "s3c2410-spi.0", "tx", (void *)DMACH_SPI0_TX },
+       { "s3c2410-spi.1", "rx", (void *)DMACH_SPI1_RX },
+       { "s3c2410-spi.1", "tx", (void *)DMACH_SPI1_TX },
+       /*
+        * The DMA request source[1] (DMACH_UARTx_SRC2) are
+        * not used in the UART driver.
+        */
+       { "s3c2410-uart.0", "rx", (void *)DMACH_UART0 },
+       { "s3c2410-uart.0", "tx", (void *)DMACH_UART0 },
+       { "s3c2410-uart.1", "rx", (void *)DMACH_UART1 },
+       { "s3c2410-uart.1", "tx", (void *)DMACH_UART1 },
+       { "s3c2410-uart.2", "rx", (void *)DMACH_UART2 },
+       { "s3c2410-uart.2", "tx", (void *)DMACH_UART2 },
+       { "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
+       { "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
+       { "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
+       { "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
+       { "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
+       { "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
+       { "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
+       { "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
+       { "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
+       { "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
+};
+
 static struct s3c24xx_dma_platdata s3c2410_dma_platdata = {
        .num_phy_channels = 4,
        .channels = s3c2410_dma_channels,
        .num_channels = DMACH_MAX,
+       .slave_map = s3c2410_dma_slave_map,
+       .slavecnt = ARRAY_SIZE(s3c2410_dma_slave_map),
 };
 
 struct platform_device s3c2410_device_dma = {
@@ -388,10 +418,36 @@ static struct s3c24xx_dma_channel s3c2412_dma_channels[DMACH_MAX] = {
        [DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, 16 },
 };
 
+static const struct dma_slave_map s3c2412_dma_slave_map[] = {
+       { "s3c2412-sdi", "rx-tx", (void *)DMACH_SDI },
+       { "s3c2412-spi.0", "rx", (void *)DMACH_SPI0_RX },
+       { "s3c2412-spi.0", "tx", (void *)DMACH_SPI0_TX },
+       { "s3c2412-spi.1", "rx", (void *)DMACH_SPI1_RX },
+       { "s3c2412-spi.1", "tx", (void *)DMACH_SPI1_TX },
+       { "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
+       { "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
+       { "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
+       { "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
+       { "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
+       { "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
+       { "s3c2412-iis", "rx", (void *)DMACH_I2S_IN },
+       { "s3c2412-iis", "tx", (void *)DMACH_I2S_OUT },
+       { "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
+       { "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
+       { "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
+       { "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
+       { "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
+       { "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
+       { "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
+       { "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
+};
+
 static struct s3c24xx_dma_platdata s3c2412_dma_platdata = {
        .num_phy_channels = 4,
        .channels = s3c2412_dma_channels,
        .num_channels = DMACH_MAX,
+       .slave_map = s3c2412_dma_slave_map,
+       .slavecnt = ARRAY_SIZE(s3c2412_dma_slave_map),
 };
 
 struct platform_device s3c2412_device_dma = {
@@ -534,10 +590,30 @@ static struct s3c24xx_dma_channel s3c2443_dma_channels[DMACH_MAX] = {
        [DMACH_MIC_IN] = { S3C24XX_DMA_APB, true, 29 },
 };
 
+static const struct dma_slave_map s3c2443_dma_slave_map[] = {
+       { "s3c2440-sdi", "rx-tx", (void *)DMACH_SDI },
+       { "s3c2443-spi.0", "rx", (void *)DMACH_SPI0_RX },
+       { "s3c2443-spi.0", "tx", (void *)DMACH_SPI0_TX },
+       { "s3c2443-spi.1", "rx", (void *)DMACH_SPI1_RX },
+       { "s3c2443-spi.1", "tx", (void *)DMACH_SPI1_TX },
+       { "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
+       { "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
+       { "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
+       { "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
+       { "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
+       { "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
+       { "s3c2440-uart.3", "rx", (void *)DMACH_UART3 },
+       { "s3c2440-uart.3", "tx", (void *)DMACH_UART3 },
+       { "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
+       { "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
+};
+
 static struct s3c24xx_dma_platdata s3c2443_dma_platdata = {
        .num_phy_channels = 6,
        .channels = s3c2443_dma_channels,
        .num_channels = DMACH_MAX,
+       .slave_map = s3c2443_dma_slave_map,
+       .slavecnt = ARRAY_SIZE(s3c2443_dma_slave_map),
 };
 
 struct platform_device s3c2443_device_dma = {
index 8538910db202ab6a13e0e3588f27b2a3157c4bc2..a970e7fcba9e02fe6e2651cd5cfca76321d26314 100644 (file)
@@ -134,8 +134,8 @@ bool prcmu_pending_irq(void)
  */
 bool prcmu_is_cpu_in_wfi(int cpu)
 {
-       return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
-                    PRCM_ARM_WFI_STANDBY_WFI0;
+       return readl(PRCM_ARM_WFI_STANDBY) &
+               (cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : PRCM_ARM_WFI_STANDBY_WFI0);
 }
 
 /*
index 3a2e678b8d30cabfb058fd82bb1d3336e3dab02d..0122ad1a60270cda8c53faf69296b8a93a902851 100644 (file)
@@ -610,9 +610,9 @@ static int __init early_abort_handler(unsigned long addr, unsigned int fsr,
 
 void __init early_abt_enable(void)
 {
-       fsr_info[22].fn = early_abort_handler;
+       fsr_info[FSR_FS_AEA].fn = early_abort_handler;
        local_abt_enable();
-       fsr_info[22].fn = do_bad;
+       fsr_info[FSR_FS_AEA].fn = do_bad;
 }
 
 #ifndef CONFIG_ARM_LPAE
index 67532f24227105c02f8d5a5be13ee46879aac237..afc1f84e763b248b2193715e757d432cc055eac8 100644 (file)
 #define FSR_FS5_0              (0x3f)
 
 #ifdef CONFIG_ARM_LPAE
+#define FSR_FS_AEA             17
+
 static inline int fsr_fs(unsigned int fsr)
 {
        return fsr & FSR_FS5_0;
 }
 #else
+#define FSR_FS_AEA             22
+
 static inline int fsr_fs(unsigned int fsr)
 {
        return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
index fc033c0d2a0f21b443ed0e28ad35d87598870e55..0cbe24b49710fd4057aec2da23ccbf3830ca4b92 100644 (file)
        #address-cells = <2>;
        #size-cells = <2>;
 
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /* 16 MiB reserved for Hardware ROM Firmware */
+               hwrom_reserved: hwrom@0 {
+                       reg = <0x0 0x0 0x0 0x1000000>;
+                       no-map;
+               };
+
+               /* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+               secmon_reserved: secmon@10000000 {
+                       reg = <0x0 0x10000000 0x0 0x200000>;
+                       no-map;
+               };
+       };
+
        cpus {
                #address-cells = <0x2>;
                #size-cells = <0x0>;
                                status = "disabled";
                        };
                };
+
+               vpu: vpu@d0100000 {
+                       compatible = "amlogic,meson-gx-vpu";
+                       reg = <0x0 0xd0100000 0x0 0x100000>,
+                             <0x0 0xc883c000 0x0 0x1000>,
+                             <0x0 0xc8838000 0x0 0x1000>;
+                       reg-names = "vpu", "hhi", "dmc";
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       /* CVBS VDAC output port */
+                       cvbs_vdac_port: port@0 {
+                               reg = <0>;
+                       };
+               };
        };
 };
index 969682092e0fe040fb1b6de918de99d095fd2c91..4cbd626a9e887b01285c6052fb3590d46bcae176 100644 (file)
                clocks = <&wifi32k>;
                clock-names = "ext_clock";
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
 };
 
 &uart_AO {
        clocks = <&clkc CLKID_FCLK_DIV4>;
        clock-names = "clkin0";
 };
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
index 238fbeacd330ab7a8bf7a2a6fdf7f1a6e0365499..c59403adb387dbcd33d375561ee3eaa07ebdfa3f 100644 (file)
        };
 };
 
+&scpi_clocks {
+       status = "disabled";
+};
+
 &uart_AO {
        status = "okay";
        pinctrl-0 = <&uart_ao_a_pins>;
        status = "okay";
        pinctrl-0 = <&eth_rgmii_pins>;
        pinctrl-names = "default";
+       phy-handle = <&eth_phy0>;
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               eth_phy0: ethernet-phy@0 {
+                       reg = <0>;
+                       eee-broken-1000t;
+               };
+       };
 };
 
 &ir {
index 203be28978d5ede48d7050356f14a2ad19423a7e..4a96e0f6f9265b858287c039714e652062134c9e 100644 (file)
                clocks = <&wifi32k>;
                clock-names = "ext_clock";
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
 };
 
 /* This UART is brought out to the DB9 connector */
        clocks = <&clkc CLKID_FCLK_DIV4>;
        clock-names = "clkin0";
 };
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
index 51edd5b5c4604518bf8e329c11d123c2aa706af6..b35307321b63981cc7c8dee4042d4c0ba99b7ee9 100644 (file)
@@ -55,7 +55,7 @@
                mboxes = <&mailbox 1 &mailbox 2>;
                shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
 
-               clocks {
+               scpi_clocks: clocks {
                        compatible = "arm,scpi-clocks";
 
                        scpi_dvfs: scpi_clocks@0 {
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
+
+&vpu {
+       compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
+};
index e99101ae966438414c055f54c635c8b0878a528e..cea4a3eded9b805983e0af414cfd6d901ad5a703 100644 (file)
                clocks = <&wifi32k>;
                clock-names = "ext_clock";
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
 };
 
 &uart_AO {
        clocks = <&clkc CLKID_FCLK_DIV4>;
        clock-names = "clkin0";
 };
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
index 9f89b99c4806776d1a009c9e02f02e3584e8c294..69216246275dfa05e852e513337eea1cb8d53e55 100644 (file)
@@ -43,7 +43,7 @@
 
 #include "meson-gx.dtsi"
 #include <dt-bindings/clock/gxbb-clkc.h>
-#include <dt-bindings/gpio/meson-gxbb-gpio.h>
+#include <dt-bindings/gpio/meson-gxl-gpio.h>
 
 / {
        compatible = "amlogic,meson-gxl";
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
+
+&vpu {
+       compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
+};
index f859d75db8bd936845663084ffbfd7309148a9f4..5a337d339df1d58b984ab575ba88b07a03a067c2 100644 (file)
                compatible = "mmc-pwrseq-emmc";
                reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
 };
 
 /* This UART is brought out to the DB9 connector */
                max-speed = <1000>;
        };
 };
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
index c1974bbbddead8d3b955e105ec018701fca3ffd7..eb2f0c3e5e538e4bebf211512bccd4a8eaab02b5 100644 (file)
                };
        };
 };
+
+&vpu {
+       compatible = "amlogic,meson-gxm-vpu", "amlogic,meson-gx-vpu";
+};
index a852e28a40e17761b5b393b21d9798eb9a80cd8b..a83ed2c6bbf79afd64c24577ca2530e7da6f0b87 100644 (file)
@@ -81,7 +81,7 @@
                #address-cells = <0>;
                interrupt-controller;
                reg = <0x0 0x2c001000 0 0x1000>,
-                     <0x0 0x2c002000 0 0x1000>,
+                     <0x0 0x2c002000 0 0x2000>,
                      <0x0 0x2c004000 0 0x2000>,
                      <0x0 0x2c006000 0 0x2000>;
                interrupts = <1 9 0xf04>;
index 64226d5ae4715172a12c8509022fb6f13814d318..135890cd8a859708c9adf6d3e184bd7ec093a3e0 100644 (file)
                };
 
                amba {
-                       compatible = "arm,amba-bus";
+                       compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
index 9d1d7ad9b075a314d5777260622d66487c82cf45..29ed6b61c737a7827eb8caae01ef335fdbd222b1 100644 (file)
                        reg = <0x0 0x86000000 0x0 0x200000>;
                        no-map;
                };
+
+               memory@85800000 {
+                       reg = <0x0 0x85800000 0x0 0x800000>;
+                       no-map;
+               };
+
+               memory@86200000 {
+                       reg = <0x0 0x86200000 0x0 0x2600000>;
+                       no-map;
+               };
        };
 
        cpus {
index 6ffb0517421a92f40d43ffa37682bfd825efca25..dbea2c3d8f0c229f05573f94b9318837a8c11300 100644 (file)
                power-source = <3300>;
        };
 
-       sdhi0_pins_uhs: sd0 {
+       sdhi0_pins_uhs: sd0_uhs {
                groups = "sdhi0_data4", "sdhi0_ctrl";
                function = "sdhi0";
                power-source = <1800>;
index 358089687a69b5946851ef7c5ac5c0a776d9d161..ef1b9e573af0f5bd2ed6792ba5c9450a64ecaa45 100644 (file)
@@ -27,7 +27,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x40000000>;
        };
index 68a908334c7b12846e74c16d5c7168d9276747dd..54dc28351c8cb85a0abbd4bbad554d56dbcbac79 100644 (file)
@@ -72,7 +72,7 @@
                             <1 10 0xf08>;
        };
 
-       amba_apu {
+       amba_apu: amba_apu@0 {
                compatible = "simple-bus";
                #address-cells = <2>;
                #size-cells = <1>;
                };
 
                i2c0: i2c@ff020000 {
-                       compatible = "cdns,i2c-r1p10";
+                       compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
                        status = "disabled";
                        interrupt-parent = <&gic>;
                        interrupts = <0 17 4>;
                };
 
                i2c1: i2c@ff030000 {
-                       compatible = "cdns,i2c-r1p10";
+                       compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
                        status = "disabled";
                        interrupt-parent = <&gic>;
                        interrupts = <0 18 4>;
index 869dded0f09f810f8b05005eed0e3d1d86287b93..33b744d547392d6464d34d5ca91d1296454ad784 100644 (file)
@@ -331,6 +331,7 @@ CONFIG_DRM_VC4=m
 CONFIG_DRM_PANEL_SIMPLE=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_HISI_KIRIN=m
+CONFIG_DRM_MESON=m
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
 CONFIG_BACKLIGHT_GENERIC=m
index c53dbeae79f2f5fce8353b169e96ff6c79294aa5..838dad5c209fae0f3a660e79d1f5fef8eb1f0c68 100644 (file)
@@ -193,15 +193,16 @@ AES_ENTRY(aes_cbc_encrypt)
        cbz             w6, .Lcbcencloop
 
        ld1             {v0.16b}, [x5]                  /* get iv */
-       enc_prepare     w3, x2, x5
+       enc_prepare     w3, x2, x6
 
 .Lcbcencloop:
        ld1             {v1.16b}, [x1], #16             /* get next pt block */
        eor             v0.16b, v0.16b, v1.16b          /* ..and xor with iv */
-       encrypt_block   v0, w3, x2, x5, w6
+       encrypt_block   v0, w3, x2, x6, w7
        st1             {v0.16b}, [x0], #16
        subs            w4, w4, #1
        bne             .Lcbcencloop
+       st1             {v0.16b}, [x5]                  /* return iv */
        ret
 AES_ENDPROC(aes_cbc_encrypt)
 
@@ -211,7 +212,7 @@ AES_ENTRY(aes_cbc_decrypt)
        cbz             w6, .LcbcdecloopNx
 
        ld1             {v7.16b}, [x5]                  /* get iv */
-       dec_prepare     w3, x2, x5
+       dec_prepare     w3, x2, x6
 
 .LcbcdecloopNx:
 #if INTERLEAVE >= 2
@@ -248,7 +249,7 @@ AES_ENTRY(aes_cbc_decrypt)
 .Lcbcdecloop:
        ld1             {v1.16b}, [x1], #16             /* get next ct block */
        mov             v0.16b, v1.16b                  /* ...and copy to v0 */
-       decrypt_block   v0, w3, x2, x5, w6
+       decrypt_block   v0, w3, x2, x6, w7
        eor             v0.16b, v0.16b, v7.16b          /* xor with iv => pt */
        mov             v7.16b, v1.16b                  /* ct is next iv */
        st1             {v0.16b}, [x0], #16
@@ -256,6 +257,7 @@ AES_ENTRY(aes_cbc_decrypt)
        bne             .Lcbcdecloop
 .Lcbcdecout:
        FRAME_POP
+       st1             {v7.16b}, [x5]                  /* return iv */
        ret
 AES_ENDPROC(aes_cbc_decrypt)
 
@@ -267,24 +269,15 @@ AES_ENDPROC(aes_cbc_decrypt)
 
 AES_ENTRY(aes_ctr_encrypt)
        FRAME_PUSH
-       cbnz            w6, .Lctrfirst          /* 1st time around? */
-       umov            x5, v4.d[1]             /* keep swabbed ctr in reg */
-       rev             x5, x5
-#if INTERLEAVE >= 2
-       cmn             w5, w4                  /* 32 bit overflow? */
-       bcs             .Lctrinc
-       add             x5, x5, #1              /* increment BE ctr */
-       b               .LctrincNx
-#else
-       b               .Lctrinc
-#endif
-.Lctrfirst:
+       cbz             w6, .Lctrnotfirst       /* 1st time around? */
        enc_prepare     w3, x2, x6
        ld1             {v4.16b}, [x5]
-       umov            x5, v4.d[1]             /* keep swabbed ctr in reg */
-       rev             x5, x5
+
+.Lctrnotfirst:
+       umov            x8, v4.d[1]             /* keep swabbed ctr in reg */
+       rev             x8, x8
 #if INTERLEAVE >= 2
-       cmn             w5, w4                  /* 32 bit overflow? */
+       cmn             w8, w4                  /* 32 bit overflow? */
        bcs             .Lctrloop
 .LctrloopNx:
        subs            w4, w4, #INTERLEAVE
@@ -292,11 +285,11 @@ AES_ENTRY(aes_ctr_encrypt)
 #if INTERLEAVE == 2
        mov             v0.8b, v4.8b
        mov             v1.8b, v4.8b
-       rev             x7, x5
-       add             x5, x5, #1
+       rev             x7, x8
+       add             x8, x8, #1
        ins             v0.d[1], x7
-       rev             x7, x5
-       add             x5, x5, #1
+       rev             x7, x8
+       add             x8, x8, #1
        ins             v1.d[1], x7
        ld1             {v2.16b-v3.16b}, [x1], #32      /* get 2 input blocks */
        do_encrypt_block2x
@@ -305,7 +298,7 @@ AES_ENTRY(aes_ctr_encrypt)
        st1             {v0.16b-v1.16b}, [x0], #32
 #else
        ldr             q8, =0x30000000200000001        /* addends 1,2,3[,0] */
-       dup             v7.4s, w5
+       dup             v7.4s, w8
        mov             v0.16b, v4.16b
        add             v7.4s, v7.4s, v8.4s
        mov             v1.16b, v4.16b
@@ -323,18 +316,12 @@ AES_ENTRY(aes_ctr_encrypt)
        eor             v2.16b, v7.16b, v2.16b
        eor             v3.16b, v5.16b, v3.16b
        st1             {v0.16b-v3.16b}, [x0], #64
-       add             x5, x5, #INTERLEAVE
+       add             x8, x8, #INTERLEAVE
 #endif
-       cbz             w4, .LctroutNx
-.LctrincNx:
-       rev             x7, x5
+       rev             x7, x8
        ins             v4.d[1], x7
+       cbz             w4, .Lctrout
        b               .LctrloopNx
-.LctroutNx:
-       sub             x5, x5, #1
-       rev             x7, x5
-       ins             v4.d[1], x7
-       b               .Lctrout
 .Lctr1x:
        adds            w4, w4, #INTERLEAVE
        beq             .Lctrout
@@ -342,30 +329,39 @@ AES_ENTRY(aes_ctr_encrypt)
 .Lctrloop:
        mov             v0.16b, v4.16b
        encrypt_block   v0, w3, x2, x6, w7
+
+       adds            x8, x8, #1              /* increment BE ctr */
+       rev             x7, x8
+       ins             v4.d[1], x7
+       bcs             .Lctrcarry              /* overflow? */
+
+.Lctrcarrydone:
        subs            w4, w4, #1
        bmi             .Lctrhalfblock          /* blocks < 0 means 1/2 block */
        ld1             {v3.16b}, [x1], #16
        eor             v3.16b, v0.16b, v3.16b
        st1             {v3.16b}, [x0], #16
-       beq             .Lctrout
-.Lctrinc:
-       adds            x5, x5, #1              /* increment BE ctr */
-       rev             x7, x5
-       ins             v4.d[1], x7
-       bcc             .Lctrloop               /* no overflow? */
-       umov            x7, v4.d[0]             /* load upper word of ctr  */
-       rev             x7, x7                  /* ... to handle the carry */
-       add             x7, x7, #1
-       rev             x7, x7
-       ins             v4.d[0], x7
-       b               .Lctrloop
+       bne             .Lctrloop
+
+.Lctrout:
+       st1             {v4.16b}, [x5]          /* return next CTR value */
+       FRAME_POP
+       ret
+
 .Lctrhalfblock:
        ld1             {v3.8b}, [x1]
        eor             v3.8b, v0.8b, v3.8b
        st1             {v3.8b}, [x0]
-.Lctrout:
        FRAME_POP
        ret
+
+.Lctrcarry:
+       umov            x7, v4.d[0]             /* load upper word of ctr  */
+       rev             x7, x7                  /* ... to handle the carry */
+       add             x7, x7, #1
+       rev             x7, x7
+       ins             v4.d[0], x7
+       b               .Lctrcarrydone
 AES_ENDPROC(aes_ctr_encrypt)
        .ltorg
 
index 446f6c46d4b17b352ef695665409c6863d470706..3a4301163e04a26d979bf506f8c4a537a2dd9715 100644 (file)
@@ -164,22 +164,25 @@ lr        .req    x30             // link register
 
 /*
  * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
- * <symbol> is within the range +/- 4 GB of the PC.
+ * <symbol> is within the range +/- 4 GB of the PC when running
+ * in core kernel context. In module context, a movz/movk sequence
+ * is used, since modules may be loaded far away from the kernel
+ * when KASLR is in effect.
  */
        /*
         * @dst: destination register (64 bit wide)
         * @sym: name of the symbol
-        * @tmp: optional scratch register to be used if <dst> == sp, which
-        *       is not allowed in an adrp instruction
         */
-       .macro  adr_l, dst, sym, tmp=
-       .ifb    \tmp
+       .macro  adr_l, dst, sym
+#ifndef MODULE
        adrp    \dst, \sym
        add     \dst, \dst, :lo12:\sym
-       .else
-       adrp    \tmp, \sym
-       add     \dst, \tmp, :lo12:\sym
-       .endif
+#else
+       movz    \dst, #:abs_g3:\sym
+       movk    \dst, #:abs_g2_nc:\sym
+       movk    \dst, #:abs_g1_nc:\sym
+       movk    \dst, #:abs_g0_nc:\sym
+#endif
        .endm
 
        /*
@@ -190,6 +193,7 @@ lr  .req    x30             // link register
         *       the address
         */
        .macro  ldr_l, dst, sym, tmp=
+#ifndef MODULE
        .ifb    \tmp
        adrp    \dst, \sym
        ldr     \dst, [\dst, :lo12:\sym]
@@ -197,6 +201,15 @@ lr .req    x30             // link register
        adrp    \tmp, \sym
        ldr     \dst, [\tmp, :lo12:\sym]
        .endif
+#else
+       .ifb    \tmp
+       adr_l   \dst, \sym
+       ldr     \dst, [\dst]
+       .else
+       adr_l   \tmp, \sym
+       ldr     \dst, [\tmp]
+       .endif
+#endif
        .endm
 
        /*
@@ -206,8 +219,13 @@ lr .req    x30             // link register
         *       while <src> needs to be preserved.
         */
        .macro  str_l, src, sym, tmp
+#ifndef MODULE
        adrp    \tmp, \sym
        str     \src, [\tmp, :lo12:\sym]
+#else
+       adr_l   \tmp, \sym
+       str     \src, [\tmp]
+#endif
        .endm
 
        /*
index f2bcbe2d98895ea35b95b8a1e518d808738284b4..86c404171305abd290a6a85d7a5edd69c55ecd02 100644 (file)
@@ -9,9 +9,17 @@
 
 struct task_struct;
 
+/*
+ * We don't use read_sysreg() as we want the compiler to cache the value where
+ * possible.
+ */
 static __always_inline struct task_struct *get_current(void)
 {
-       return (struct task_struct *)read_sysreg(sp_el0);
+       unsigned long sp_el0;
+
+       asm ("mrs %0, sp_el0" : "=r" (sp_el0));
+
+       return (struct task_struct *)sp_el0;
 }
 
 #define current get_current()
index bfe632808d7724c0a51562efb60501e67f6bf157..90c39a6623797dd2c5309b8d70e7975cb938524c 100644 (file)
@@ -222,7 +222,7 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define _virt_addr_valid(kaddr)        pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 #else
 #define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
-#define __page_to_voff(page)   (((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
+#define __page_to_voff(kaddr)  (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
 
 #define page_to_virt(page)     ((void *)((__page_to_voff(page)) | PAGE_OFFSET))
 #define virt_to_page(vaddr)    ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
index fea10736b11fbd1204602c3b695da34ea255bf78..439f6b5d31f67576e57e67cdf1e8284bf57c08a7 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/ptrace.h>
 #include <asm/sections.h>
 #include <asm/sysreg.h>
+#include <asm/cpufeature.h>
 
 /*
  * __boot_cpu_mode records what mode CPUs were booted in.
@@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode(void)
        return read_sysreg(CurrentEL) == CurrentEL_EL2;
 }
 
+static inline bool has_vhe(void)
+{
+       if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
+               return true;
+
+       return false;
+}
+
 #ifdef CONFIG_ARM64_VHE
 extern void verify_cpu_run_el(void);
 #else
index b5c3933ed44163b2fb489a00553195afc1ff6806..d1ff83dfe5deae580cdb0ebf93f25b32a63f5a74 100644 (file)
@@ -77,6 +77,7 @@ struct user_fpsimd_state {
        __uint128_t     vregs[32];
        __u32           fpsr;
        __u32           fpcr;
+       __u32           __reserved[2];
 };
 
 struct user_hwdebug_state {
index 923841ffe4a981669be9bea76d09540244550a1f..43512d4d7df219b4b7093927fc1d9107004b6775 100644 (file)
@@ -683,7 +683,7 @@ el0_inv:
        mov     x0, sp
        mov     x1, #BAD_SYNC
        mov     x2, x25
-       bl      bad_mode
+       bl      bad_el0_sync
        b       ret_to_user
 ENDPROC(el0_sync)
 
index fc35e06ccaaca863ad680ff09166c3f2ba034c54..a22161ccf4470afa644850cd47c18b561da0d0e1 100644 (file)
@@ -551,6 +551,8 @@ static int hw_break_set(struct task_struct *target,
        /* (address, ctrl) registers */
        limit = regset->n * regset->size;
        while (count && offset < limit) {
+               if (count < PTRACE_HBP_ADDR_SZ)
+                       return -EINVAL;
                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
                                         offset, offset + PTRACE_HBP_ADDR_SZ);
                if (ret)
@@ -560,6 +562,8 @@ static int hw_break_set(struct task_struct *target,
                        return ret;
                offset += PTRACE_HBP_ADDR_SZ;
 
+               if (!count)
+                       break;
                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
                                         offset, offset + PTRACE_HBP_CTRL_SZ);
                if (ret)
@@ -596,7 +600,7 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
                   const void *kbuf, const void __user *ubuf)
 {
        int ret;
-       struct user_pt_regs newregs;
+       struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
        if (ret)
@@ -626,7 +630,8 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
                   const void *kbuf, const void __user *ubuf)
 {
        int ret;
-       struct user_fpsimd_state newstate;
+       struct user_fpsimd_state newstate =
+               target->thread.fpsimd_state.user_fpsimd;
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
        if (ret)
@@ -650,7 +655,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,
                   const void *kbuf, const void __user *ubuf)
 {
        int ret;
-       unsigned long tls;
+       unsigned long tls = target->thread.tp_value;
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
        if (ret)
@@ -676,7 +681,8 @@ static int system_call_set(struct task_struct *target,
                           unsigned int pos, unsigned int count,
                           const void *kbuf, const void __user *ubuf)
 {
-       int syscallno, ret;
+       int syscallno = task_pt_regs(target)->syscallno;
+       int ret;
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
        if (ret)
@@ -948,7 +954,7 @@ static int compat_tls_set(struct task_struct *target,
                          const void __user *ubuf)
 {
        int ret;
-       compat_ulong_t tls;
+       compat_ulong_t tls = target->thread.tp_value;
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
        if (ret)
index 23e9e13bd2aa797840fcd79e2d61e747ebbe42f6..655e65f38f315758b617d6aaa89f8feed63b496a 100644 (file)
@@ -11,6 +11,7 @@
  * for more details.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/init.h>
@@ -209,7 +210,12 @@ static struct notifier_block init_cpu_capacity_notifier = {
 
 static int __init register_cpufreq_notifier(void)
 {
-       if (cap_parsing_failed)
+       /*
+        * on ACPI-based systems we need to use the default cpu capacity
+        * until we have the necessary code to parse the cpu capacity, so
+        * skip registering cpufreq notifier.
+        */
+       if (!acpi_disabled || cap_parsing_failed)
                return -EINVAL;
 
        if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) {
index 5b830be79c0120a331e32bdf417b45f4c0bb8911..659b2e6b6cf767ff94d2512ad0897aa236469139 100644 (file)
@@ -604,17 +604,34 @@ const char *esr_get_class_string(u32 esr)
 }
 
 /*
- * bad_mode handles the impossible case in the exception vector.
+ * bad_mode handles the impossible case in the exception vector. This is always
+ * fatal.
  */
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 {
-       siginfo_t info;
-       void __user *pc = (void __user *)instruction_pointer(regs);
        console_verbose();
 
        pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
                handler[reason], smp_processor_id(), esr,
                esr_get_class_string(esr));
+
+       die("Oops - bad mode", regs, 0);
+       local_irq_disable();
+       panic("bad mode");
+}
+
+/*
+ * bad_el0_sync handles unexpected, but potentially recoverable synchronous
+ * exceptions taken from EL0. Unlike bad_mode, this returns.
+ */
+asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
+{
+       siginfo_t info;
+       void __user *pc = (void __user *)instruction_pointer(regs);
+       console_verbose();
+
+       pr_crit("Bad EL0 synchronous exception detected on CPU%d, code 0x%08x -- %s\n",
+               smp_processor_id(), esr, esr_get_class_string(esr));
        __show_regs(regs);
 
        info.si_signo = SIGILL;
@@ -622,7 +639,10 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
        info.si_code  = ILL_ILLOPC;
        info.si_addr  = pc;
 
-       arm64_notify_die("Oops - bad mode", regs, &info, 0);
+       current->thread.fault_address = 0;
+       current->thread.fault_code = 0;
+
+       force_sig_info(info.si_signo, &info, current);
 }
 
 void __pte_error(const char *file, int line, unsigned long val)
index 290a84f3351f706bd026e00364c2d433a4852aed..e04082700bb16c3598333de72b3c64659be63e5e 100644 (file)
@@ -524,7 +524,8 @@ EXPORT_SYMBOL(dummy_dma_ops);
 
 static int __init arm64_dma_init(void)
 {
-       if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+       if (swiotlb_force == SWIOTLB_FORCE ||
+           max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
                swiotlb = 1;
 
        return atomic_pool_init();
index a78a5c401806c80ee63818c8d353f3ca44bf58d3..156169c6981ba09ef815308ae847d84ccc02e4f4 100644 (file)
@@ -88,21 +88,21 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
                        break;
 
                pud = pud_offset(pgd, addr);
-               printk(", *pud=%016llx", pud_val(*pud));
+               pr_cont(", *pud=%016llx", pud_val(*pud));
                if (pud_none(*pud) || pud_bad(*pud))
                        break;
 
                pmd = pmd_offset(pud, addr);
-               printk(", *pmd=%016llx", pmd_val(*pmd));
+               pr_cont(", *pmd=%016llx", pmd_val(*pmd));
                if (pmd_none(*pmd) || pmd_bad(*pmd))
                        break;
 
                pte = pte_offset_map(pmd, addr);
-               printk(", *pte=%016llx", pte_val(*pte));
+               pr_cont(", *pte=%016llx", pte_val(*pte));
                pte_unmap(pte);
        } while(0);
 
-       printk("\n");
+       pr_cont("\n");
 }
 
 #ifdef CONFIG_ARM64_HW_AFDBM
index 964b7549af5cc7f827c57fe17709e7575a471c56..e25584d723960e73fb8eec8d1a5f48fa57197582 100644 (file)
@@ -239,7 +239,7 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma,
                ncontig = find_num_contig(vma->vm_mm, addr, cpte,
                                          *cpte, &pgsize);
                for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
-                       changed = ptep_set_access_flags(vma, addr, cpte,
+                       changed |= ptep_set_access_flags(vma, addr, cpte,
                                                        pfn_pte(pfn,
                                                                hugeprot),
                                                        dirty);
index 212c4d1e2f26df7f291270fb461abac912ce7161..380ebe70509347f8c9329433a625527b65442aa6 100644 (file)
@@ -401,8 +401,11 @@ static void __init free_unused_memmap(void)
  */
 void __init mem_init(void)
 {
-       if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+       if (swiotlb_force == SWIOTLB_FORCE ||
+           max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
                swiotlb_init(1);
+       else
+               swiotlb_force = SWIOTLB_NO_FORCE;
 
        set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
 
index 1c2a5e264fc71cfd52f2acb0b24ddb1aff792be7..e93c9494503ac8fc3cfaa8167ea3523abb3e2925 100644 (file)
@@ -139,7 +139,7 @@ static inline void atomic64_dec(atomic64_t *v)
 #define atomic64_sub_and_test(i,v)     (atomic64_sub_return((i), (v)) == 0)
 #define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
 #define atomic64_inc_and_test(v)       (atomic64_inc_return((v)) == 0)
-
+#define atomic64_inc_not_zero(v)       atomic64_add_unless((v), 1, 0)
 
 #define atomic_cmpxchg(v, old, new)    (cmpxchg(&(v)->counter, old, new))
 #define atomic_xchg(v, new)            (xchg(&(v)->counter, new))
@@ -161,6 +161,39 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
        return c;
 }
 
+static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
+{
+       long long c, old;
+
+       c = atomic64_read(v);
+       for (;;) {
+               if (unlikely(c == u))
+                       break;
+               old = atomic64_cmpxchg(v, c, c + i);
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+       return c != u;
+}
+
+static inline long long atomic64_dec_if_positive(atomic64_t *v)
+{
+       long long c, old, dec;
+
+       c = atomic64_read(v);
+       for (;;) {
+               dec = c - 1;
+               if (unlikely(dec < 0))
+                       break;
+               old = atomic64_cmpxchg((v), c, dec);
+               if (likely(old == c))
+                       break;
+               c = old;
+       }
+               return dec;
+}
+
 #define ATOMIC_OP(op)                                                  \
 static inline int atomic_fetch_##op(int i, atomic_t *v)                        \
 {                                                                      \
index 6a02b3a3fa6513a4f517c31c88aa435ddc766f3a..e92fb190e2d628e878b209a14e8c8be551510654 100644 (file)
@@ -521,6 +521,9 @@ void *kvm_mips_build_exit(void *addr)
        uasm_i_and(&p, V0, V0, AT);
        uasm_i_lui(&p, AT, ST0_CU0 >> 16);
        uasm_i_or(&p, V0, V0, AT);
+#ifdef CONFIG_64BIT
+       uasm_i_ori(&p, V0, V0, ST0_SX | ST0_UX);
+#endif
        uasm_i_mtc0(&p, V0, C0_STATUS);
        uasm_i_ehb(&p);
 
@@ -643,7 +646,7 @@ static void *kvm_mips_build_ret_to_guest(void *addr)
 
        /* Setup status register for running guest in UM */
        uasm_i_ori(&p, V1, V1, ST0_EXL | KSU_USER | ST0_IE);
-       UASM_i_LA(&p, AT, ~(ST0_CU0 | ST0_MX));
+       UASM_i_LA(&p, AT, ~(ST0_CU0 | ST0_MX | ST0_SX | ST0_UX));
        uasm_i_and(&p, V1, V1, AT);
        uasm_i_mtc0(&p, V1, C0_STATUS);
        uasm_i_ehb(&p);
index 06a60b19acfb53c2788ba6b9c79de983bb6fe43e..29ec9ab3fd5570737caa7f5c63768177a5caffa7 100644 (file)
@@ -360,8 +360,8 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
        dump_handler("kvm_exit", gebase + 0x2000, vcpu->arch.vcpu_run);
 
        /* Invalidate the icache for these ranges */
-       local_flush_icache_range((unsigned long)gebase,
-                               (unsigned long)gebase + ALIGN(size, PAGE_SIZE));
+       flush_icache_range((unsigned long)gebase,
+                          (unsigned long)gebase + ALIGN(size, PAGE_SIZE));
 
        /*
         * Allocate comm page for guest kernel, a TLB will be reserved for
index 393d311735c8b573bd5702eac1dcaaac1103600e..67e333aa7629c406745564cb24acc5903733ec41 100644 (file)
@@ -16,7 +16,7 @@
 struct task_struct;
 struct thread_struct;
 
-#if !defined(CONFIG_LAZY_SAVE_FPU)
+#if defined(CONFIG_FPU) && !defined(CONFIG_LAZY_SAVE_FPU)
 struct fpu_state_struct;
 extern asmlinkage void fpu_save(struct fpu_state_struct *);
 #define switch_fpu(prev, next)                                         \
index 3f9406d9b9d675c833cdfd6f661b24e359bd3453..da87943328a510d468d089fdf648edfa5933445b 100644 (file)
@@ -6,7 +6,7 @@
 #endif
 
 #include <linux/compiler.h>
-#include <asm/types.h>         /* for BITS_PER_LONG/SHIFT_PER_LONG */
+#include <asm/types.h>
 #include <asm/byteorder.h>
 #include <asm/barrier.h>
 #include <linux/atomic.h>
  * to include/asm-i386/bitops.h or kerneldoc
  */
 
+#if __BITS_PER_LONG == 64
+#define SHIFT_PER_LONG 6
+#else
+#define SHIFT_PER_LONG 5
+#endif
+
 #define CHOP_SHIFTCOUNT(x) (((unsigned long) (x)) & (BITS_PER_LONG - 1))
 
 
index e0a23c7bdd432adc59f4f4ebefcc4d51f91b05f1..07fa7e50bdc069dd989cd52dd283517250a3b1e4 100644 (file)
@@ -3,10 +3,8 @@
 
 #if defined(__LP64__)
 #define __BITS_PER_LONG 64
-#define SHIFT_PER_LONG 6
 #else
 #define __BITS_PER_LONG 32
-#define SHIFT_PER_LONG 5
 #endif
 
 #include <asm-generic/bitsperlong.h>
index e78403b129ef927361032c8c92c5e3c82e830941..928e1bbac98fef4fa098163d12a98670000065d2 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _PARISC_SWAB_H
 #define _PARISC_SWAB_H
 
+#include <asm/bitsperlong.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 
@@ -38,7 +39,7 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
 }
 #define __arch_swab32 __arch_swab32
 
-#if BITS_PER_LONG > 32
+#if __BITS_PER_LONG > 32
 /*
 ** From "PA-RISC 2.0 Architecture", HP Professional Books.
 ** See Appendix I page 8 , "Endian Byte Swapping".
@@ -61,6 +62,6 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
        return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* BITS_PER_LONG > 32 */
+#endif /* __BITS_PER_LONG > 32 */
 
 #endif /* _PARISC_SWAB_H */
index a8ee573fe610bd5e2d8191b4dffb05e134a6d3c2..281f4f1fcd1f68ab2fbc613afa3f2597bd090550 100644 (file)
@@ -164,7 +164,6 @@ config PPC
        select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE
        select HAVE_ARCH_HARDENED_USERCOPY
        select HAVE_KERNEL_GZIP
-       select HAVE_CC_STACKPROTECTOR
 
 config GENERIC_CSUM
        def_bool CPU_LITTLE_ENDIAN
@@ -484,6 +483,7 @@ config RELOCATABLE
        bool "Build a relocatable kernel"
        depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
        select NONSTATIC_KERNEL
+       select MODULE_REL_CRCS if MODVERSIONS
        help
          This builds a kernel image that is capable of running at the
          location the kernel is loaded at. For ppc32, there is no any
index 1c64bc6330bc0b9f70b71038e678fd110e6e1456..0c4e470571ca0faa74d3e9fa38fa57a384cab4bf 100644 (file)
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hash__hugepd_ok(hugepd_t hpd)
 {
+       unsigned long hpdval = hpd_val(hpd);
        /*
         * if it is not a pte and have hugepd shift mask
         * set, then it is a hugepd directory pointer
         */
-       if (!(hpd.pd & _PAGE_PTE) &&
-           ((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
+       if (!(hpdval & _PAGE_PTE) &&
+           ((hpdval & HUGEPD_SHIFT_MASK) != 0))
                return true;
        return false;
 }
index f61cad3de4e69ec093674355332f7d3ee093cf2b..4c935f7504f783532d3521d04142dfdb5831f943 100644 (file)
@@ -201,6 +201,10 @@ extern int __meminit hash__vmemmap_create_mapping(unsigned long start,
                                              unsigned long phys);
 extern void hash__vmemmap_remove_mapping(unsigned long start,
                                     unsigned long page_size);
+
+int hash__create_section_mapping(unsigned long start, unsigned long end);
+int hash__remove_section_mapping(unsigned long start, unsigned long end);
+
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_HASH_H */
index b312b152461b0539a22c5939ba7728a38f5d8d32..6e834caa37206a476792823463e81ac4c9617f9c 100644 (file)
@@ -23,7 +23,9 @@ static __always_inline bool cpu_has_feature(unsigned long feature)
 {
        int i;
 
+#ifndef __clang__ /* clang can't cope with this */
        BUILD_BUG_ON(!__builtin_constant_p(feature));
+#endif
 
 #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
        if (!static_key_initialized) {
index ede215167d1ad4f37f4d732c0eeaeee5cbd58bd4..7f4025a6c69ea5b71b340989b35197d8f9d17b91 100644 (file)
@@ -21,12 +21,12 @@ static inline pte_t *hugepd_page(hugepd_t hpd)
         * We have only four bits to encode, MMU page size
         */
        BUILD_BUG_ON((MMU_PAGE_COUNT - 1) > 0xf);
-       return __va(hpd.pd & HUGEPD_ADDR_MASK);
+       return __va(hpd_val(hpd) & HUGEPD_ADDR_MASK);
 }
 
 static inline unsigned int hugepd_mmu_psize(hugepd_t hpd)
 {
-       return (hpd.pd & HUGEPD_SHIFT_MASK) >> 2;
+       return (hpd_val(hpd) & HUGEPD_SHIFT_MASK) >> 2;
 }
 
 static inline unsigned int hugepd_shift(hugepd_t hpd)
@@ -52,18 +52,20 @@ static inline pte_t *hugepd_page(hugepd_t hpd)
 {
        BUG_ON(!hugepd_ok(hpd));
 #ifdef CONFIG_PPC_8xx
-       return (pte_t *)__va(hpd.pd & ~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
+       return (pte_t *)__va(hpd_val(hpd) &
+                            ~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
 #else
-       return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+       return (pte_t *)((hpd_val(hpd) &
+                         ~HUGEPD_SHIFT_MASK) | PD_HUGE);
 #endif
 }
 
 static inline unsigned int hugepd_shift(hugepd_t hpd)
 {
 #ifdef CONFIG_PPC_8xx
-       return ((hpd.pd & _PMD_PAGE_MASK) >> 1) + 17;
+       return ((hpd_val(hpd) & _PMD_PAGE_MASK) >> 1) + 17;
 #else
-       return hpd.pd & HUGEPD_SHIFT_MASK;
+       return hpd_val(hpd) & HUGEPD_SHIFT_MASK;
 #endif
 }
 
index a34c764ca8dd83435faf75307e30e5149e55de4b..233a7e8cc8e32d6cf0ac904b3f02b2f340e3883b 100644 (file)
@@ -160,7 +160,9 @@ static __always_inline bool mmu_has_feature(unsigned long feature)
 {
        int i;
 
+#ifndef __clang__ /* clang can't cope with this */
        BUILD_BUG_ON(!__builtin_constant_p(feature));
+#endif
 
 #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
        if (!static_key_initialized) {
index cc12c61ef315fc6ca5d43233bd54889cd19a01a0..53885512b8d31b12acec28dc3ba6688e57fb9615 100644 (file)
@@ -90,9 +90,5 @@ static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sec
 }
 #endif
 
-#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
-#define ARCH_RELOCATES_KCRCTAB
-#define reloc_start PHYSICAL_START
-#endif
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MODULE_H */
index 172849727054e179ea1bd58e24e2d85118ed8f91..0cd8a3852763292eabe905b33960f888e875c978 100644 (file)
@@ -227,9 +227,10 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 static inline int hugepd_ok(hugepd_t hpd)
 {
 #ifdef CONFIG_PPC_8xx
-       return ((hpd.pd & 0x4) != 0);
+       return ((hpd_val(hpd) & 0x4) != 0);
 #else
-       return (hpd.pd > 0);
+       /* We clear the top bit to indicate hugepd */
+       return ((hpd_val(hpd) & PD_HUGE) ==  0);
 #endif
 }
 
index 56398e7e61004d7766f8e77627df54e73f7e75bf..47120bf2670c49f224744445c5dc154f0de60b31 100644 (file)
@@ -294,15 +294,12 @@ extern long long virt_phys_offset;
 #include <asm/pgtable-types.h>
 #endif
 
-typedef struct { signed long pd; } hugepd_t;
 
 #ifndef CONFIG_HUGETLB_PAGE
 #define is_hugepd(pdep)                (0)
 #define pgd_huge(pgd)          (0)
 #endif /* CONFIG_HUGETLB_PAGE */
 
-#define __hugepd(x) ((hugepd_t) { (x) })
-
 struct page;
 extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr,
index e157489ee7a1220156868099903d45509bedd7e6..ae0a23091a9b347d3e31ed96330772bc9caa3020 100644 (file)
@@ -65,6 +65,7 @@ struct power_pmu {
 #define PPMU_HAS_SSLOT         0x00000020 /* Has sampled slot in MMCRA */
 #define PPMU_HAS_SIER          0x00000040 /* Has SIER */
 #define PPMU_ARCH_207S         0x00000080 /* PMC is architecture v2.07S */
+#define PPMU_NO_SIAR           0x00000100 /* Do not use SIAR */
 
 /*
  * Values for flags to get_alternatives()
index 49c0a5a80efa2948764e247d3cbd76fc6fdf06a0..9c0f5db5cf461a92e72185701b4cbc1df168dfcc 100644 (file)
@@ -104,4 +104,12 @@ static inline bool pmd_xchg(pmd_t *pmdp, pmd_t old, pmd_t new)
        return pmd_raw(old) == prev;
 }
 
+typedef struct { __be64 pdbe; } hugepd_t;
+#define __hugepd(x) ((hugepd_t) { cpu_to_be64(x) })
+
+static inline unsigned long hpd_val(hugepd_t x)
+{
+       return be64_to_cpu(x.pdbe);
+}
+
 #endif /* _ASM_POWERPC_PGTABLE_BE_TYPES_H */
index e7f4f3e0fcde94ba237fa2a269c32d40458cc8f2..8bd3b13fe2fb2e8bd1c5762c4e080c9cd921edaa 100644 (file)
@@ -66,4 +66,11 @@ static inline bool pte_xchg(pte_t *ptep, pte_t old, pte_t new)
 }
 #endif
 
+typedef struct { unsigned long pd; } hugepd_t;
+#define __hugepd(x) ((hugepd_t) { (x) })
+static inline unsigned long hpd_val(hugepd_t x)
+{
+       return x.pd;
+}
+
 #endif /* _ASM_POWERPC_PGTABLE_TYPES_H */
index c56ea8c84abb1771ff65f66ba91ffff02bff5fae..c4ced1d01d579fe0b7aeb13a71b21eb2ffb7072c 100644 (file)
 #define PPC_INST_MCRXR                 0x7c000400
 #define PPC_INST_MCRXR_MASK            0xfc0007fe
 #define PPC_INST_MFSPR_PVR             0x7c1f42a6
-#define PPC_INST_MFSPR_PVR_MASK                0xfc1fffff
+#define PPC_INST_MFSPR_PVR_MASK                0xfc1ffffe
 #define PPC_INST_MFTMR                 0x7c0002dc
 #define PPC_INST_MSGSND                        0x7c00019c
 #define PPC_INST_MSGCLR                        0x7c0001dc
 #define PPC_INST_RFDI                  0x4c00004e
 #define PPC_INST_RFMCI                 0x4c00004c
 #define PPC_INST_MFSPR_DSCR            0x7c1102a6
-#define PPC_INST_MFSPR_DSCR_MASK       0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_MASK       0xfc1ffffe
 #define PPC_INST_MTSPR_DSCR            0x7c1103a6
-#define PPC_INST_MTSPR_DSCR_MASK       0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_MASK       0xfc1ffffe
 #define PPC_INST_MFSPR_DSCR_USER       0x7c0302a6
-#define PPC_INST_MFSPR_DSCR_USER_MASK  0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_USER_MASK  0xfc1ffffe
 #define PPC_INST_MTSPR_DSCR_USER       0x7c0303a6
-#define PPC_INST_MTSPR_DSCR_USER_MASK  0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_USER_MASK  0xfc1ffffe
 #define PPC_INST_MFVSRD                        0x7c000066
 #define PPC_INST_MTVSRD                        0x7c000166
 #define PPC_INST_SLBFEE                        0x7c0007a7
index 0d4531aa2052d77fb8036b05f3550c33cfdde49e..dff79798903da7edc9dbc6e440fa97bbe9afe53f 100644 (file)
 #define   SRR1_ISI_N_OR_G      0x10000000 /* ISI: Access is no-exec or G */
 #define   SRR1_ISI_PROT                0x08000000 /* ISI: Other protection fault */
 #define   SRR1_WAKEMASK                0x00380000 /* reason for wakeup */
-#define   SRR1_WAKEMASK_P8     0x003c0000 /* reason for wakeup on POWER8 */
+#define   SRR1_WAKEMASK_P8     0x003c0000 /* reason for wakeup on POWER8 and 9 */
 #define   SRR1_WAKESYSERR      0x00300000 /* System error */
 #define   SRR1_WAKEEE          0x00200000 /* External interrupt */
+#define   SRR1_WAKEHVI         0x00240000 /* Hypervisor Virtualization Interrupt (P9) */
 #define   SRR1_WAKEMT          0x00280000 /* mtctrl */
 #define          SRR1_WAKEHMI          0x00280000 /* Hypervisor maintenance */
 #define   SRR1_WAKEDEC         0x00180000 /* Decrementer interrupt */
diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
deleted file mode 100644 (file)
index 6720190..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * GCC stack protector support.
- *
- * Stack protector works by putting predefined pattern at the start of
- * the stack frame and verifying that it hasn't been overwritten when
- * returning from the function.  The pattern is called stack canary
- * and gcc expects it to be defined by a global variable called
- * "__stack_chk_guard" on PPC.  This unfortunately means that on SMP
- * we cannot have a different canary value per task.
- */
-
-#ifndef _ASM_STACKPROTECTOR_H
-#define _ASM_STACKPROTECTOR_H
-
-#include <linux/random.h>
-#include <linux/version.h>
-#include <asm/reg.h>
-
-extern unsigned long __stack_chk_guard;
-
-/*
- * Initialize the stackprotector canary value.
- *
- * NOTE: this must only be called from functions that never return,
- * and it must always be inlined.
- */
-static __always_inline void boot_init_stack_canary(void)
-{
-       unsigned long canary;
-
-       /* Try to get a semi random initial value. */
-       get_random_bytes(&canary, sizeof(canary));
-       canary ^= mftb();
-       canary ^= LINUX_VERSION_CODE;
-
-       current->stack_canary = canary;
-       __stack_chk_guard = current->stack_canary;
-}
-
-#endif /* _ASM_STACKPROTECTOR_H */
index f0b238516e9b44b5afabc52a8460daaa6e81ca97..e0b9e576905aa2e1c24060db56de70f8b02ea920 100644 (file)
@@ -44,6 +44,7 @@ static inline int icp_hv_init(void) { return -ENODEV; }
 
 #ifdef CONFIG_PPC_POWERNV
 extern int icp_opal_init(void);
+extern void icp_opal_flush_interrupt(void);
 #else
 static inline int icp_opal_init(void) { return -ENODEV; }
 #endif
index 23f8082d7bfad95f4c9fbb8201e3e58c3104928f..f4c2b52e58b36eb44bcb6be2a2428bc0458f7660 100644 (file)
@@ -19,10 +19,6 @@ CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 
-# -fstack-protector triggers protection checks in this code,
-# but it is being used too early to link to meaningful stack_chk logic.
-CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
-
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
 CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
index 0601e6a7297c64ea4b2129011d32ae42a662ac07..195a9fc8f81c8fc41fca8b05239948d4f28d54af 100644 (file)
@@ -91,9 +91,6 @@ int main(void)
        DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp));
 #endif
 
-#ifdef CONFIG_CC_STACKPROTECTOR
-       DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
-#endif
        DEFINE(KSP, offsetof(struct thread_struct, ksp));
        DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
 #ifdef CONFIG_BOOKE
index 8180bfd7ab931c5b6d16a1c1b7cb73689206571b..9de7f79e702b1d755bdc855a2da82876959eeade 100644 (file)
@@ -298,9 +298,17 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
         *
         * For pHyp, we have to enable IO for log retrieval. Otherwise,
         * 0xFF's is always returned from PCI config space.
+        *
+        * When the @severity is EEH_LOG_PERM, the PE is going to be
+        * removed. Prior to that, the drivers for devices included in
+        * the PE will be closed. The drivers rely on working IO path
+        * to bring the devices to quiet state. Otherwise, PCI traffic
+        * from those devices after they are removed is like to cause
+        * another unexpected EEH error.
         */
        if (!(pe->type & EEH_PE_PHB)) {
-               if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
+               if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) ||
+                   severity == EEH_LOG_PERM)
                        eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 
                /*
index d88573bdd0907c6682cf03395bc296155cea9124..b94887165a101557c97fd6a53139ae7df67dbbd9 100644 (file)
@@ -545,7 +545,7 @@ static void *eeh_pe_detach_dev(void *data, void *userdata)
 static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
 {
        struct eeh_pe *pe = (struct eeh_pe *)data;
-       bool *clear_sw_state = flag;
+       bool clear_sw_state = *(bool *)flag;
        int i, rc = 1;
 
        for (i = 0; rc && i < 3; i++)
index 5742dbdbee4677924ebf0019b891e43879410131..3841d749a430069f4d4f2705c4199c08609b3757 100644 (file)
@@ -674,11 +674,7 @@ BEGIN_FTR_SECTION
        mtspr   SPRN_SPEFSCR,r0         /* restore SPEFSCR reg */
 END_FTR_SECTION_IFSET(CPU_FTR_SPE)
 #endif /* CONFIG_SPE */
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
-       lwz     r0,TSK_STACK_CANARY(r2)
-       lis     r4,__stack_chk_guard@ha
-       stw     r0,__stack_chk_guard@l(r4)
-#endif
+
        lwz     r0,_CCR(r1)
        mtcrf   0xFF,r0
        /* r3-r12 are destroyed -- Cort */
index bb1807184bad5da5f9b65ce69087184e67534c03..0b0f89685b679745895251b011d0db522d4558e1 100644 (file)
@@ -286,14 +286,6 @@ static void dedotify_versions(struct modversion_info *vers,
        for (end = (void *)vers + size; vers < end; vers++)
                if (vers->name[0] == '.') {
                        memmove(vers->name, vers->name+1, strlen(vers->name));
-#ifdef ARCH_RELOCATES_KCRCTAB
-                       /* The TOC symbol has no CRC computed. To avoid CRC
-                        * check failing, we must force it to the expected
-                        * value (see CRC check in module.c).
-                        */
-                       if (!strcmp(vers->name, "TOC."))
-                               vers->crc = -(unsigned long)reloc_start;
-#endif
                }
 }
 
index 04885cec24df1413f90121115cf6569e4aa444e6..5dd056df0baaec576431adb4cbe8ab370d8f44c1 100644 (file)
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
-#ifdef CONFIG_CC_STACKPROTECTOR
-#include <linux/stackprotector.h>
-unsigned long __stack_chk_guard __read_mostly;
-EXPORT_SYMBOL(__stack_chk_guard);
-#endif
-
 /* Transactional Memory debug */
 #ifdef TM_DEBUG_SW
 #define TM_DEBUG(x...) printk(KERN_INFO x)
index ec47a939cbdd6dd81c6c05ed6707f28e12d9f0ea..ac83eb04a8b871293c53e7bd6ff4d439b89704a9 100644 (file)
@@ -2834,6 +2834,9 @@ static void __init prom_find_boot_cpu(void)
 
        cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
 
+       if (!PHANDLE_VALID(cpu_pkg))
+               return;
+
        prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
        prom.cpu = be32_to_cpu(rval);
 
index e4744ff38a1782de7aa60305fc3f72dc9c109cba..925a4ef9055932174b4dc5a8f0424b330149132b 100644 (file)
@@ -463,6 +463,10 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 
        flush_fp_to_thread(target);
 
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.TS_FPR(i);
+       buf[32] = target->thread.fp_state.fpscr;
+
        /* copy to local buffer then write that out */
        i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
        if (i)
@@ -672,6 +676,9 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
        flush_altivec_to_thread(target);
        flush_vsx_to_thread(target);
 
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
+
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                 buf, 0, 32 * sizeof(double));
        if (!ret)
@@ -1019,6 +1026,10 @@ static int tm_cfpr_set(struct task_struct *target,
        flush_fp_to_thread(target);
        flush_altivec_to_thread(target);
 
+       for (i = 0; i < 32; i++)
+               buf[i] = target->thread.TS_CKFPR(i);
+       buf[32] = target->thread.ckfp_state.fpscr;
+
        /* copy to local buffer then write that out */
        i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
        if (i)
@@ -1283,6 +1294,9 @@ static int tm_cvsx_set(struct task_struct *target,
        flush_altivec_to_thread(target);
        flush_vsx_to_thread(target);
 
+       for (i = 0; i < 32 ; i++)
+               buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
+
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                 buf, 0, 32 * sizeof(double));
        if (!ret)
index 6fd30ac7d14a0d2761e82d479fe01724bd53a38d..62a50d6d1053c9f1e3854ecb9de877e0f02cbb3b 100644 (file)
@@ -253,8 +253,11 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
        if (unlikely(debugger_fault_handler(regs)))
                goto bail;
 
-       /* On a kernel SLB miss we can only check for a valid exception entry */
-       if (!user_mode(regs) && (address >= TASK_SIZE)) {
+       /*
+        * The kernel should never take an execute fault nor should it
+        * take a page fault to a kernel address.
+        */
+       if (!user_mode(regs) && (is_exec || (address >= TASK_SIZE))) {
                rc = SIGSEGV;
                goto bail;
        }
@@ -390,20 +393,6 @@ good_area:
 #endif /* CONFIG_8xx */
 
        if (is_exec) {
-               /*
-                * An execution fault + no execute ?
-                *
-                * On CPUs that don't have CPU_FTR_COHERENT_ICACHE we
-                * deliberately create NX mappings, and use the fault to do the
-                * cache flush. This is usually handled in hash_page_do_lazy_icache()
-                * but we could end up here if that races with a concurrent PTE
-                * update. In that case we need to fall through here to the VMA
-                * check below.
-                */
-               if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
-                       (regs->msr & SRR1_ISI_N_OR_G))
-                       goto bad_area;
-
                /*
                 * Allow execution from readable areas if the MMU does not
                 * provide separate controls over reading and executing.
index 80334937e14fdf8519236a9930e73707ef373d86..67e19a0821be25c8e5f458857e9fda31ca42adb6 100644 (file)
@@ -747,7 +747,7 @@ static unsigned long __init htab_get_table_size(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int create_section_mapping(unsigned long start, unsigned long end)
+int hash__create_section_mapping(unsigned long start, unsigned long end)
 {
        int rc = htab_bolt_mapping(start, end, __pa(start),
                                   pgprot_val(PAGE_KERNEL), mmu_linear_psize,
@@ -761,7 +761,7 @@ int create_section_mapping(unsigned long start, unsigned long end)
        return rc;
 }
 
-int remove_section_mapping(unsigned long start, unsigned long end)
+int hash__remove_section_mapping(unsigned long start, unsigned long end)
 {
        int rc = htab_remove_mapping(start, end, mmu_linear_psize,
                                     mmu_kernel_ssize);
index d5026f3800b6129bc4c05ef303b4c37d80065cc0..37b5f91e381b77d545b5c336e60aecb0194dcd7d 100644 (file)
@@ -125,11 +125,14 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
 int hugepd_ok(hugepd_t hpd)
 {
        bool is_hugepd;
+       unsigned long hpdval;
+
+       hpdval = hpd_val(hpd);
 
        /*
         * We should not find this format in page directory, warn otherwise.
         */
-       is_hugepd = (((hpd.pd & 0x3) == 0x0) && ((hpd.pd & HUGEPD_SHIFT_MASK) != 0));
+       is_hugepd = (((hpdval & 0x3) == 0x0) && ((hpdval & HUGEPD_SHIFT_MASK) != 0));
        WARN(is_hugepd, "Found wrong page directory format\n");
        return 0;
 }
index 289df38fb7e08bcde6228276fb9d8415042bdd30..8c3389cbcd12216ef7b71884163322255f76ea68 100644 (file)
@@ -53,7 +53,7 @@ static u64 gpage_freearray[MAX_NUMBER_GPAGES];
 static unsigned nr_gpages;
 #endif
 
-#define hugepd_none(hpd)       ((hpd).pd == 0)
+#define hugepd_none(hpd)       (hpd_val(hpd) == 0)
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
@@ -103,24 +103,24 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        for (i = 0; i < num_hugepd; i++, hpdp++) {
                if (unlikely(!hugepd_none(*hpdp)))
                        break;
-               else
+               else {
 #ifdef CONFIG_PPC_BOOK3S_64
-                       hpdp->pd = __pa(new) |
-                                  (shift_to_mmu_psize(pshift) << 2);
+                       *hpdp = __hugepd(__pa(new) |
+                                        (shift_to_mmu_psize(pshift) << 2));
 #elif defined(CONFIG_PPC_8xx)
-                       hpdp->pd = __pa(new) |
-                                  (pshift == PAGE_SHIFT_8M ? _PMD_PAGE_8M :
-                                                             _PMD_PAGE_512K) |
-                                  _PMD_PRESENT;
+                       *hpdp = __hugepd(__pa(new) |
+                                        (pshift == PAGE_SHIFT_8M ? _PMD_PAGE_8M :
+                                         _PMD_PAGE_512K) | _PMD_PRESENT);
 #else
                        /* We use the old format for PPC_FSL_BOOK3E */
-                       hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+                       *hpdp = __hugepd(((unsigned long)new & ~PD_HUGE) | pshift);
 #endif
+               }
        }
        /* If we bailed from the for loop early, an error occurred, clean up */
        if (i < num_hugepd) {
                for (i = i - 1 ; i >= 0; i--, hpdp--)
-                       hpdp->pd = 0;
+                       *hpdp = __hugepd(0);
                kmem_cache_free(cachep, new);
        }
        spin_unlock(&mm->page_table_lock);
@@ -454,7 +454,7 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
                return;
 
        for (i = 0; i < num_hugepd; i++, hpdp++)
-               hpdp->pd = 0;
+               *hpdp = __hugepd(0);
 
        if (shift >= pdshift)
                hugepd_free(tlb, hugepte);
@@ -810,12 +810,8 @@ static int __init hugetlbpage_init(void)
                 * if we have pdshift and shift value same, we don't
                 * use pgt cache for hugepd.
                 */
-               if (pdshift > shift) {
+               if (pdshift > shift)
                        pgtable_cache_add(pdshift - shift, NULL);
-                       if (!PGT_CACHE(pdshift - shift))
-                               panic("hugetlbpage_init(): could not create "
-                                     "pgtable cache for %d bit pagesize\n", shift);
-               }
 #if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
                else if (!hugepte_cache) {
                        /*
@@ -852,9 +848,6 @@ static int __init hugetlbpage_init(void)
        else if (mmu_psize_defs[MMU_PAGE_2M].shift)
                HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_2M].shift;
 #endif
-       else
-               panic("%s: Unable to set default huge page size\n", __func__);
-
        return 0;
 }
 
index a175cd82ae8c5f2807508e5a2ee2daf34e7fc05a..f2108c40e697dfa5128dc7b8f742e8a2db8063fd 100644 (file)
@@ -78,8 +78,12 @@ void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
        align = max_t(unsigned long, align, minalign);
        name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
        new = kmem_cache_create(name, table_size, align, 0, ctor);
+       if (!new)
+               panic("Could not allocate pgtable cache for order %d", shift);
+
        kfree(name);
        pgtable_cache[shift - 1] = new;
+
        pr_debug("Allocated pgtable cache for order %d\n", shift);
 }
 
@@ -88,7 +92,7 @@ void pgtable_cache_init(void)
 {
        pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor);
 
-       if (PMD_INDEX_SIZE && !PGT_CACHE(PMD_INDEX_SIZE))
+       if (PMD_CACHE_INDEX && !PGT_CACHE(PMD_CACHE_INDEX))
                pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor);
        /*
         * In all current configs, when the PUD index exists it's the
@@ -97,11 +101,4 @@ void pgtable_cache_init(void)
         */
        if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
                pgtable_cache_add(PUD_INDEX_SIZE, pud_ctor);
-
-       if (!PGT_CACHE(PGD_INDEX_SIZE))
-               panic("Couldn't allocate pgd cache");
-       if (PMD_INDEX_SIZE && !PGT_CACHE(PMD_INDEX_SIZE))
-               panic("Couldn't allocate pmd pgtable caches");
-       if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
-               panic("Couldn't allocate pud pgtable caches");
 }
index 93abf8a9813d5c2d47a1aa150cafa4076111b0db..8e1588021d1c90d37073d91962d8822777a152fe 100644 (file)
@@ -347,7 +347,8 @@ early_param("disable_radix", parse_disable_radix);
 void __init mmu_early_init_devtree(void)
 {
        /* Disable radix mode based on kernel command line. */
-       if (disable_radix)
+       /* We don't yet have the machinery to do radix as a guest. */
+       if (disable_radix || !(mfmsr() & MSR_HV))
                cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
 
        if (early_radix_enabled())
index ebf9782bacf97dffb1a88a71416b7235c840638e..653ff6c74ebe3d112ed13a70006032d3e7a5dd23 100644 (file)
@@ -126,3 +126,21 @@ void mmu_cleanup_all(void)
        else if (mmu_hash_ops.hpte_clear_all)
                mmu_hash_ops.hpte_clear_all();
 }
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int create_section_mapping(unsigned long start, unsigned long end)
+{
+       if (radix_enabled())
+               return -ENODEV;
+
+       return hash__create_section_mapping(start, end);
+}
+
+int remove_section_mapping(unsigned long start, unsigned long end)
+{
+       if (radix_enabled())
+               return -ENODEV;
+
+       return hash__remove_section_mapping(start, end);
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
index cfa53ccc8bafc908e80532a4a64e44ad358dffc7..34f1a0dbc898ee4a28a6adcd41c0ce5d3fe61198 100644 (file)
@@ -65,7 +65,7 @@ int radix__map_kernel_page(unsigned long ea, unsigned long pa,
                if (!pmdp)
                        return -ENOMEM;
                if (map_page_size == PMD_SIZE) {
-                       ptep = (pte_t *)pudp;
+                       ptep = pmdp_ptep(pmdp);
                        goto set_the_pte;
                }
                ptep = pte_alloc_kernel(pmdp, ea);
@@ -90,7 +90,7 @@ int radix__map_kernel_page(unsigned long ea, unsigned long pa,
                }
                pmdp = pmd_offset(pudp, ea);
                if (map_page_size == PMD_SIZE) {
-                       ptep = (pte_t *)pudp;
+                       ptep = pmdp_ptep(pmdp);
                        goto set_the_pte;
                }
                if (!pmd_present(*pmdp)) {
index 61b79119065ff3030162df12446a67c712cd6649..952713d6cf04d0e826a685f181561d587df41257 100644 (file)
@@ -50,9 +50,7 @@ static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
        for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
                __tlbiel_pid(pid, set, ric);
        }
-       if (cpu_has_feature(CPU_FTR_POWER9_DD1))
-               asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
-       return;
+       asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
 }
 
 static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
@@ -85,8 +83,6 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid,
        asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
                     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
        asm volatile("ptesync": : :"memory");
-       if (cpu_has_feature(CPU_FTR_POWER9_DD1))
-               asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
 }
 
 static inline void _tlbie_va(unsigned long va, unsigned long pid,
index fd3e4034c04d2207a30cc82d6c65dffc6094c603..270eb9b74e2e13eff5f37b441f76a37a019ff73e 100644 (file)
@@ -295,6 +295,8 @@ static inline void perf_read_regs(struct pt_regs *regs)
         */
        if (TRAP(regs) != 0xf00)
                use_siar = 0;
+       else if ((ppmu->flags & PPMU_NO_SIAR))
+               use_siar = 0;
        else if (marked)
                use_siar = 1;
        else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
index 6447dc1c3d896cea18615d3b5bacc4bb6285fbb1..929b56d47ad9bf6bc79f7ae9dd0ab27b2142427d 100644 (file)
@@ -16,7 +16,7 @@ EVENT(PM_CYC,                                 0x0001e)
 EVENT(PM_ICT_NOSLOT_CYC,                       0x100f8)
 EVENT(PM_CMPLU_STALL,                          0x1e054)
 EVENT(PM_INST_CMPL,                            0x00002)
-EVENT(PM_BRU_CMPL,                             0x40060)
+EVENT(PM_BRU_CMPL,                             0x10012)
 EVENT(PM_BR_MPRED_CMPL,                                0x400f6)
 
 /* All L1 D cache load references counted at finish, gated by reject */
index 346010e8d463d36d2c411839ecb550d9534f61b1..7332634e18c95212f1448c578f2726b8ebf3aee0 100644 (file)
@@ -384,7 +384,7 @@ static struct power_pmu power9_isa207_pmu = {
        .bhrb_filter_map        = power9_bhrb_filter_map,
        .get_constraint         = isa207_get_constraint,
        .disable_pmc            = isa207_disable_pmc,
-       .flags                  = PPMU_HAS_SIER | PPMU_ARCH_207S,
+       .flags                  = PPMU_NO_SIAR | PPMU_ARCH_207S,
        .n_generic              = ARRAY_SIZE(power9_generic_events),
        .generic_events         = power9_generic_events,
        .cache_events           = &power9_cache_events,
index c789258ae1e1ce656be3e4c1bd1a9b28523f307e..eec0e8d0454d11859e83aeef105a07010b1b9aac 100644 (file)
@@ -155,8 +155,10 @@ static void pnv_smp_cpu_kill_self(void)
                wmask = SRR1_WAKEMASK_P8;
 
        idle_states = pnv_get_supported_cpuidle_states();
+
        /* We don't want to take decrementer interrupts while we are offline,
-        * so clear LPCR:PECE1. We keep PECE2 enabled.
+        * so clear LPCR:PECE1. We keep PECE2 (and LPCR_PECE_HVEE on P9)
+        * enabled as to let IPIs in.
         */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
 
@@ -206,8 +208,12 @@ static void pnv_smp_cpu_kill_self(void)
                 * contains 0.
                 */
                if (((srr1 & wmask) == SRR1_WAKEEE) ||
+                   ((srr1 & wmask) == SRR1_WAKEHVI) ||
                    (local_paca->irq_happened & PACA_IRQ_EE)) {
-                       icp_native_flush_interrupt();
+                       if (cpu_has_feature(CPU_FTR_ARCH_300))
+                               icp_opal_flush_interrupt();
+                       else
+                               icp_native_flush_interrupt();
                } else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
                        unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
                        asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
@@ -221,6 +227,8 @@ static void pnv_smp_cpu_kill_self(void)
                if (srr1 && !generic_check_cpu_restart(cpu))
                        DBG("CPU%d Unexpected exit while offline !\n", cpu);
        }
+
+       /* Re-enable decrementer interrupts */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
        DBG("CPU%d coming online...\n", cpu);
 }
index d38e86fd5720f181ac10cc869b35e8b093ca5803..f9670eabfcfa70ca338aa0c5f2e10217803c7162 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/xics.h>
 #include <asm/io.h>
 #include <asm/opal.h>
+#include <asm/kvm_ppc.h>
 
 static void icp_opal_teardown_cpu(void)
 {
@@ -39,7 +40,26 @@ static void icp_opal_flush_ipi(void)
         * Should we be flagging idle loop instead?
         * Or creating some task to be scheduled?
         */
-       opal_int_eoi((0x00 << 24) | XICS_IPI);
+       if (opal_int_eoi((0x00 << 24) | XICS_IPI) > 0)
+               force_external_irq_replay();
+}
+
+static unsigned int icp_opal_get_xirr(void)
+{
+       unsigned int kvm_xirr;
+       __be32 hw_xirr;
+       int64_t rc;
+
+       /* Handle an interrupt latched by KVM first */
+       kvm_xirr = kvmppc_get_xics_latch();
+       if (kvm_xirr)
+               return kvm_xirr;
+
+       /* Then ask OPAL */
+       rc = opal_int_get_xirr(&hw_xirr, false);
+       if (rc < 0)
+               return 0;
+       return be32_to_cpu(hw_xirr);
 }
 
 static unsigned int icp_opal_get_irq(void)
@@ -47,12 +67,8 @@ static unsigned int icp_opal_get_irq(void)
        unsigned int xirr;
        unsigned int vec;
        unsigned int irq;
-       int64_t rc;
 
-       rc = opal_int_get_xirr(&xirr, false);
-       if (rc < 0)
-               return 0;
-       xirr = be32_to_cpu(xirr);
+       xirr = icp_opal_get_xirr();
        vec = xirr & 0x00ffffff;
        if (vec == XICS_IRQ_SPURIOUS)
                return 0;
@@ -67,7 +83,8 @@ static unsigned int icp_opal_get_irq(void)
        xics_mask_unknown_vec(vec);
 
        /* We might learn about it later, so EOI it */
-       opal_int_eoi(xirr);
+       if (opal_int_eoi(xirr) > 0)
+               force_external_irq_replay();
 
        return 0;
 }
@@ -103,18 +120,49 @@ static void icp_opal_cause_ipi(int cpu, unsigned long data)
 {
        int hw_cpu = get_hard_smp_processor_id(cpu);
 
+       kvmppc_set_host_ipi(cpu, 1);
        opal_int_set_mfrr(hw_cpu, IPI_PRIORITY);
 }
 
 static irqreturn_t icp_opal_ipi_action(int irq, void *dev_id)
 {
-       int hw_cpu = hard_smp_processor_id();
+       int cpu = smp_processor_id();
 
-       opal_int_set_mfrr(hw_cpu, 0xff);
+       kvmppc_set_host_ipi(cpu, 0);
+       opal_int_set_mfrr(get_hard_smp_processor_id(cpu), 0xff);
 
        return smp_ipi_demux();
 }
 
+/*
+ * Called when an interrupt is received on an off-line CPU to
+ * clear the interrupt, so that the CPU can go back to nap mode.
+ */
+void icp_opal_flush_interrupt(void)
+{
+       unsigned int xirr;
+       unsigned int vec;
+
+       do {
+               xirr = icp_opal_get_xirr();
+               vec = xirr & 0x00ffffff;
+               if (vec == XICS_IRQ_SPURIOUS)
+                       break;
+               if (vec == XICS_IPI) {
+                       /* Clear pending IPI */
+                       int cpu = smp_processor_id();
+                       kvmppc_set_host_ipi(cpu, 0);
+                       opal_int_set_mfrr(get_hard_smp_processor_id(cpu), 0xff);
+               } else {
+                       pr_err("XICS: hw interrupt 0x%x to offline cpu, "
+                              "disabling\n", vec);
+                       xics_mask_unknown_vec(vec);
+               }
+
+               /* EOI the interrupt */
+       } while (opal_int_eoi(xirr) > 0);
+}
+
 #endif /* CONFIG_SMP */
 
 static const struct icp_ops icp_opal_ops = {
index e659daffe368836baf4db7908cdb4cb83575f0d1..e00975361fec00fb89ad916f1b8a15539a449a6c 100644 (file)
@@ -69,7 +69,7 @@ CONFIG_CMA=y
 CONFIG_CMA_DEBUG=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_MEM_SOFT_DIRTY=y
-CONFIG_ZPOOL=m
+CONFIG_ZSWAP=y
 CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
 CONFIG_ZSMALLOC_STAT=y
@@ -141,8 +141,6 @@ CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -159,13 +157,12 @@ CONFIG_NF_TABLES=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
-CONFIG_NFT_RBTREE=m
-CONFIG_NFT_HASH=m
 CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -219,7 +216,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -258,7 +254,6 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
 CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -436,7 +431,6 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
@@ -480,6 +474,7 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
 CONFIG_JBD2_DEBUG=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
@@ -592,14 +587,12 @@ CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
-CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
 CONFIG_NOTIFIER_ERROR_INJECTION=m
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
 CONFIG_PM_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
 CONFIG_FAILSLAB=y
@@ -618,6 +611,7 @@ CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
 CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
@@ -630,6 +624,7 @@ CONFIG_TEST_STRING_HELPERS=y
 CONFIG_TEST_KSTRTOX=y
 CONFIG_DMA_API_DEBUG=y
 CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -640,16 +635,18 @@ CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
 CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_IMA=y
 CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_RSA=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
-# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -673,11 +670,13 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
index 95ceac50bc6512313cf2d7cda8090c88596ae865..f05d2d6e10872a417cfb67a9624d7d74f56e5cc6 100644 (file)
@@ -12,6 +12,7 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
+# CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
@@ -54,8 +55,9 @@ CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
+CONFIG_LIVEPATCH=y
 CONFIG_TUNE_ZEC12=y
-CONFIG_NR_CPUS=256
+CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
@@ -65,6 +67,7 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_CMA=y
+CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
 CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
@@ -136,8 +139,6 @@ CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -154,13 +155,12 @@ CONFIG_NF_TABLES=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
-CONFIG_NFT_RBTREE=m
-CONFIG_NFT_HASH=m
 CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -214,7 +214,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -253,7 +252,6 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
 CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -430,7 +428,6 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
@@ -460,6 +457,7 @@ CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
@@ -473,6 +471,7 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
 CONFIG_JBD2_DEBUG=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
@@ -495,6 +494,7 @@ CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
+CONFIG_OVERLAY_FS_REDIRECT_DIR=y
 CONFIG_FSCACHE=m
 CONFIG_CACHEFILES=m
 CONFIG_ISO9660_FS=y
@@ -551,25 +551,27 @@ CONFIG_FRAME_WARN=1024
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_TIMER_STATS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
-CONFIG_NOTIFIER_ERROR_INJECTION=m
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
-CONFIG_PM_NOTIFIER_ERROR_INJECT=m
 CONFIG_LATENCYTOP=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-# CONFIG_KPROBE_EVENT is not set
+CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
-CONFIG_RBTREE_TEST=m
-CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
@@ -577,18 +579,25 @@ CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
 CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
 CONFIG_IMA=y
+CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCRYPT=m
 CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -598,6 +607,7 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -612,10 +622,13 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
@@ -624,9 +637,6 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
-CONFIG_ASYMMETRIC_KEY_TYPE=y
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
 CONFIG_CORDIC=m
index bc7b176f57950d1f4f9d17cfe8721229fe4e34c2..2cf87343b59030f76267e47dc88672e536bf6e9b 100644 (file)
@@ -65,6 +65,7 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_CMA=y
+CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
 CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
@@ -136,8 +137,6 @@ CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -154,13 +153,12 @@ CONFIG_NF_TABLES=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
-CONFIG_NFT_RBTREE=m
-CONFIG_NFT_HASH=m
 CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -214,7 +212,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -253,7 +250,6 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
 CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -430,7 +426,6 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
@@ -474,6 +469,7 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
 CONFIG_JBD2_DEBUG=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
@@ -496,6 +492,7 @@ CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
+CONFIG_OVERLAY_FS_REDIRECT_DIR=y
 CONFIG_FSCACHE=m
 CONFIG_CACHEFILES=m
 CONFIG_ISO9660_FS=y
@@ -563,12 +560,16 @@ CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
 CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
@@ -576,18 +577,25 @@ CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
 CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
 CONFIG_IMA=y
+CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCRYPT=m
 CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -597,6 +605,7 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -611,10 +620,13 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
@@ -623,9 +635,6 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
-CONFIG_ASYMMETRIC_KEY_TYPE=y
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
 CONFIG_CORDIC=m
index 2d40ef0a6295d9a93c3527d6592eba2780736a2e..d00e368fb5e6ef949b6fb070321fa3a6dc9c8501 100644 (file)
@@ -38,7 +38,6 @@ CONFIG_JUMP_LABEL=y
 CONFIG_STATIC_KEYS_SELFTEST=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
@@ -130,8 +129,11 @@ CONFIG_DUMMY=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
 CONFIG_VIRTIO_NET=y
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
+CONFIG_DEVKMEM=y
 CONFIG_RAW_DRIVER=m
 CONFIG_VIRTIO_BALLOON=y
 CONFIG_EXT4_FS=y
@@ -183,7 +185,6 @@ CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_S390_PTDUMP=y
 CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_AUTHENC=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
index d7697ab802f6c94813a27394baa255fa26a93ddc..8e136b88cdf4f13460b960f8db9d02e1ae88324f 100644 (file)
@@ -15,7 +15,9 @@
        BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
        asm volatile(                                                   \
                "       lctlg   %1,%2,%0\n"                             \
-               : : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\
+               :                                                       \
+               : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high)    \
+               : "memory");                                            \
 }
 
 #define __ctl_store(array, low, high) {                                        \
index 7447ba509c30eb0b409598d062ea408603f313af..12020b55887bfd258e6545e687ec4a9de4fdb214 100644 (file)
@@ -963,6 +963,11 @@ static int s390_fpregs_set(struct task_struct *target,
        if (target == current)
                save_fpu_regs();
 
+       if (MACHINE_HAS_VX)
+               convert_vx_to_fp(fprs, target->thread.fpu.vxrs);
+       else
+               memcpy(&fprs, target->thread.fpu.fprs, sizeof(fprs));
+
        /* If setting FPC, must validate it first. */
        if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
                u32 ufpc[2] = { target->thread.fpu.fpc, 0 };
@@ -1067,6 +1072,9 @@ static int s390_vxrs_low_set(struct task_struct *target,
        if (target == current)
                save_fpu_regs();
 
+       for (i = 0; i < __NUM_VXRS_LOW; i++)
+               vxrs[i] = *((__u64 *)(target->thread.fpu.vxrs + i) + 1);
+
        rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
        if (rc == 0)
                for (i = 0; i < __NUM_VXRS_LOW; i++)
index bec71e902be3f8030697084540130227ecb55088..6484a250021e2717c448eb8f4f0b987169c264f1 100644 (file)
@@ -916,7 +916,7 @@ static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr)
        memcpy(&mach->fac_mask, kvm->arch.model.fac_mask,
               S390_ARCH_FAC_LIST_SIZE_BYTE);
        memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list,
-              S390_ARCH_FAC_LIST_SIZE_BYTE);
+              sizeof(S390_lowcore.stfle_fac_list));
        if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach)))
                ret = -EFAULT;
        kfree(mach);
@@ -1437,7 +1437,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
        /* Populate the facility mask initially. */
        memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list,
-              S390_ARCH_FAC_LIST_SIZE_BYTE);
+              sizeof(S390_lowcore.stfle_fac_list));
        for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) {
                if (i < kvm_s390_fac_list_mask_size())
                        kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i];
index 7a1897c51c5495f3f2b13d86ba8f6344e2234788..d56ef26d46816b834068609ceb940ce01901d731 100644 (file)
@@ -202,7 +202,7 @@ static inline pgste_t ptep_xchg_start(struct mm_struct *mm,
        return pgste;
 }
 
-static inline void ptep_xchg_commit(struct mm_struct *mm,
+static inline pte_t ptep_xchg_commit(struct mm_struct *mm,
                                    unsigned long addr, pte_t *ptep,
                                    pgste_t pgste, pte_t old, pte_t new)
 {
@@ -220,6 +220,7 @@ static inline void ptep_xchg_commit(struct mm_struct *mm,
        } else {
                *ptep = new;
        }
+       return old;
 }
 
 pte_t ptep_xchg_direct(struct mm_struct *mm, unsigned long addr,
@@ -231,7 +232,7 @@ pte_t ptep_xchg_direct(struct mm_struct *mm, unsigned long addr,
        preempt_disable();
        pgste = ptep_xchg_start(mm, addr, ptep);
        old = ptep_flush_direct(mm, addr, ptep);
-       ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
+       old = ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
        preempt_enable();
        return old;
 }
@@ -246,7 +247,7 @@ pte_t ptep_xchg_lazy(struct mm_struct *mm, unsigned long addr,
        preempt_disable();
        pgste = ptep_xchg_start(mm, addr, ptep);
        old = ptep_flush_lazy(mm, addr, ptep);
-       ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
+       old = ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
        preempt_enable();
        return old;
 }
index b84be675e507857e27766b6339e438270aea0ebe..d0317993e9476fd1178a693638d9ede23860171b 100644 (file)
@@ -35,15 +35,15 @@ void __tsb_context_switch(unsigned long pgd_pa,
 static inline void tsb_context_switch(struct mm_struct *mm)
 {
        __tsb_context_switch(__pa(mm->pgd),
-                            &mm->context.tsb_block[0],
+                            &mm->context.tsb_block[MM_TSB_BASE],
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-                            (mm->context.tsb_block[1].tsb ?
-                             &mm->context.tsb_block[1] :
+                            (mm->context.tsb_block[MM_TSB_HUGE].tsb ?
+                             &mm->context.tsb_block[MM_TSB_HUGE] :
                              NULL)
 #else
                             NULL
 #endif
-                            , __pa(&mm->context.tsb_descr[0]));
+                            , __pa(&mm->context.tsb_descr[MM_TSB_BASE]));
 }
 
 void tsb_grow(struct mm_struct *mm,
index 3bebf395252cc63ee3b39996f8a0d0431e7faf37..4d0248aa0928695597161d93f325a49311b43e2c 100644 (file)
@@ -1021,7 +1021,7 @@ static void __init alloc_one_queue(unsigned long *pa_ptr, unsigned long qmask)
        unsigned long order = get_order(size);
        unsigned long p;
 
-       p = __get_free_pages(GFP_KERNEL, order);
+       p = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
        if (!p) {
                prom_printf("SUN4V: Error, cannot allocate queue.\n");
                prom_halt();
index c59af546f522999342361a5babcb64a1dfab3ccd..3caed40235898698751ff0cf3d6ca7d98dc83da6 100644 (file)
@@ -43,8 +43,8 @@ static const char poweroff_msg[32] __attribute__((aligned(32))) =
        "Linux powering off";
 static const char rebooting_msg[32] __attribute__((aligned(32))) =
        "Linux rebooting";
-static const char panicing_msg[32] __attribute__((aligned(32))) =
-       "Linux panicing";
+static const char panicking_msg[32] __attribute__((aligned(32))) =
+       "Linux panicking";
 
 static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused)
 {
@@ -76,7 +76,7 @@ static struct notifier_block sstate_reboot_notifier = {
 
 static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
 {
-       do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
+       do_set_sstate(HV_SOFT_STATE_TRANSITION, panicking_msg);
 
        return NOTIFY_DONE;
 }
index 4bc10e44d1ca32a0acdf69b8492e128e7ef0e600..dfc97a47c9a08a330f31040fe120030ebe8cc098 100644 (file)
@@ -2051,6 +2051,73 @@ void sun4v_resum_overflow(struct pt_regs *regs)
        atomic_inc(&sun4v_resum_oflow_cnt);
 }
 
+/* Given a set of registers, get the virtual addressi that was being accessed
+ * by the faulting instructions at tpc.
+ */
+static unsigned long sun4v_get_vaddr(struct pt_regs *regs)
+{
+       unsigned int insn;
+
+       if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
+               return compute_effective_address(regs, insn,
+                                                (insn >> 25) & 0x1f);
+       }
+       return 0;
+}
+
+/* Attempt to handle non-resumable errors generated from userspace.
+ * Returns true if the signal was handled, false otherwise.
+ */
+bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
+                                 struct sun4v_error_entry *ent) {
+
+       unsigned int attrs = ent->err_attrs;
+
+       if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
+               unsigned long addr = ent->err_raddr;
+               siginfo_t info;
+
+               if (addr == ~(u64)0) {
+                       /* This seems highly unlikely to ever occur */
+                       pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory error detected in unknown location!\n");
+               } else {
+                       unsigned long page_cnt = DIV_ROUND_UP(ent->err_size,
+                                                             PAGE_SIZE);
+
+                       /* Break the unfortunate news. */
+                       pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory failed at %016lX\n",
+                                addr);
+                       pr_emerg("SUN4V NON-RECOVERABLE ERROR:   Claiming %lu ages.\n",
+                                page_cnt);
+
+                       while (page_cnt-- > 0) {
+                               if (pfn_valid(addr >> PAGE_SHIFT))
+                                       get_page(pfn_to_page(addr >> PAGE_SHIFT));
+                               addr += PAGE_SIZE;
+                       }
+               }
+               info.si_signo = SIGKILL;
+               info.si_errno = 0;
+               info.si_trapno = 0;
+               force_sig_info(info.si_signo, &info, current);
+
+               return true;
+       }
+       if (attrs & SUN4V_ERR_ATTRS_PIO) {
+               siginfo_t info;
+
+               info.si_signo = SIGBUS;
+               info.si_code = BUS_ADRERR;
+               info.si_addr = (void __user *)sun4v_get_vaddr(regs);
+               force_sig_info(info.si_signo, &info, current);
+
+               return true;
+       }
+
+       /* Default to doing nothing */
+       return false;
+}
+
 /* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
  * Log the event, clear the first word of the entry, and die.
  */
@@ -2075,6 +2142,12 @@ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
 
        put_cpu();
 
+       if (!(regs->tstate & TSTATE_PRIV) &&
+           sun4v_nonresum_error_user_handled(regs, &local_copy)) {
+               /* DON'T PANIC: This userspace error was handled. */
+               return;
+       }
+
 #ifdef CONFIG_PCI
        /* Check for the special PCI poke sequence. */
        if (pci_poke_in_progress && pci_poke_cpu == cpu) {
index d89b7011667cb4f1a6f3ad55238d2c815e229c41..e279572824b15e07616b98215fb51c1fa65f4c9f 100644 (file)
@@ -111,7 +111,7 @@ static int tile_gpr_set(struct task_struct *target,
                          const void *kbuf, const void __user *ubuf)
 {
        int ret;
-       struct pt_regs regs;
+       struct pt_regs regs = *task_pt_regs(target);
 
        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0,
                                 sizeof(regs));
index cc3bd583dce1abc5fafe6b92417b8a713cd4cdfd..9e240fcba784b085bd55e77dc79c08d21d1a23e2 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include "ctype.h"
+#include "string.h"
 
 int memcmp(const void *s1, const void *s2, size_t len)
 {
index 725e820602b1781308b863a10c105dd3d2734d31..113588ddb43f8d7e7be66283118a2f33c46fb7e1 100644 (file)
@@ -18,4 +18,13 @@ int memcmp(const void *s1, const void *s2, size_t len);
 #define memset(d,c,l) __builtin_memset(d,c,l)
 #define memcmp __builtin_memcmp
 
+extern int strcmp(const char *str1, const char *str2);
+extern int strncmp(const char *cs, const char *ct, size_t count);
+extern size_t strlen(const char *s);
+extern char *strstr(const char *s1, const char *s2);
+extern size_t strnlen(const char *s, size_t maxlen);
+extern unsigned int atou(const char *s);
+extern unsigned long long simple_strtoull(const char *cp, char **endp,
+                                         unsigned int base);
+
 #endif /* BOOT_STRING_H */
index 31c34ee131f34505872a018b75a8489f1ac9c854..7ff1b0c86a8e5a630844c3ade200b592cbad413d 100644 (file)
@@ -1020,7 +1020,8 @@ struct {
        const char *basename;
        struct simd_skcipher_alg *simd;
 } aesni_simd_skciphers2[] = {
-#if IS_ENABLED(CONFIG_CRYPTO_PCBC)
+#if (defined(MODULE) && IS_ENABLED(CONFIG_CRYPTO_PCBC)) || \
+    IS_BUILTIN(CONFIG_CRYPTO_PCBC)
        {
                .algname        = "pcbc(aes)",
                .drvname        = "pcbc-aes-aesni",
@@ -1084,9 +1085,9 @@ static void aesni_free_simds(void)
                    aesni_simd_skciphers[i]; i++)
                simd_skcipher_free(aesni_simd_skciphers[i]);
 
-       for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers2) &&
-                   aesni_simd_skciphers2[i].simd; i++)
-               simd_skcipher_free(aesni_simd_skciphers2[i].simd);
+       for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers2); i++)
+               if (aesni_simd_skciphers2[i].simd)
+                       simd_skcipher_free(aesni_simd_skciphers2[i].simd);
 }
 
 static int __init aesni_init(void)
@@ -1167,7 +1168,7 @@ static int __init aesni_init(void)
                simd = simd_skcipher_create_compat(algname, drvname, basename);
                err = PTR_ERR(simd);
                if (IS_ERR(simd))
-                       goto unregister_simds;
+                       continue;
 
                aesni_simd_skciphers2[i].simd = simd;
        }
index 701d29f8e4d300ac01553e5d8317a5e40dbdcc6d..57f7ec35216ef5e2a78efa0d303f8f343b010d68 100644 (file)
@@ -254,23 +254,6 @@ ENTRY(__switch_to_asm)
        jmp     __switch_to
 END(__switch_to_asm)
 
-/*
- * The unwinder expects the last frame on the stack to always be at the same
- * offset from the end of the page, which allows it to validate the stack.
- * Calling schedule_tail() directly would break that convention because its an
- * asmlinkage function so its argument has to be pushed on the stack.  This
- * wrapper creates a proper "end of stack" frame header before the call.
- */
-ENTRY(schedule_tail_wrapper)
-       FRAME_BEGIN
-
-       pushl   %eax
-       call    schedule_tail
-       popl    %eax
-
-       FRAME_END
-       ret
-ENDPROC(schedule_tail_wrapper)
 /*
  * A newly forked process directly context switches into this address.
  *
@@ -279,15 +262,24 @@ ENDPROC(schedule_tail_wrapper)
  * edi: kernel thread arg
  */
 ENTRY(ret_from_fork)
-       call    schedule_tail_wrapper
+       FRAME_BEGIN             /* help unwinder find end of stack */
+
+       /*
+        * schedule_tail() is asmlinkage so we have to put its 'prev' argument
+        * on the stack.
+        */
+       pushl   %eax
+       call    schedule_tail
+       popl    %eax
 
        testl   %ebx, %ebx
        jnz     1f              /* kernel threads are uncommon */
 
 2:
        /* When we fork, we trace the syscall return in the child, too. */
-       movl    %esp, %eax
+       leal    FRAME_OFFSET(%esp), %eax
        call    syscall_return_slowpath
+       FRAME_END
        jmp     restore_all
 
        /* kernel thread */
index 5b219707c2f236cfcf1a856cf9a5023dd93775c3..044d18ebc43ce96a512abd1e5f36eb8dfaee0636 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/smap.h>
 #include <asm/pgtable_types.h>
 #include <asm/export.h>
+#include <asm/frame.h>
 #include <linux/err.h>
 
 .code64
@@ -408,17 +409,19 @@ END(__switch_to_asm)
  * r12: kernel thread arg
  */
 ENTRY(ret_from_fork)
+       FRAME_BEGIN                     /* help unwinder find end of stack */
        movq    %rax, %rdi
-       call    schedule_tail                   /* rdi: 'prev' task parameter */
+       call    schedule_tail           /* rdi: 'prev' task parameter */
 
-       testq   %rbx, %rbx                      /* from kernel_thread? */
-       jnz     1f                              /* kernel threads are uncommon */
+       testq   %rbx, %rbx              /* from kernel_thread? */
+       jnz     1f                      /* kernel threads are uncommon */
 
 2:
-       movq    %rsp, %rdi
+       leaq    FRAME_OFFSET(%rsp),%rdi /* pt_regs pointer */
        call    syscall_return_slowpath /* returns with IRQs disabled */
        TRACE_IRQS_ON                   /* user mode is traced as IRQS on */
        SWAPGS
+       FRAME_END
        jmp     restore_regs_and_iret
 
 1:
index 05612a2529c8bba1e9aa9131a4cabaebe96d5736..496e60391fac68e231ebac4fae9ff74ae867ffc0 100644 (file)
@@ -1010,7 +1010,7 @@ static __init int amd_ibs_init(void)
         * all online cpus.
         */
        cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
-                         "perf/x86/amd/ibs:STARTING",
+                         "perf/x86/amd/ibs:starting",
                          x86_pmu_amd_ibs_starting_cpu,
                          x86_pmu_amd_ibs_dying_cpu);
 
index 019c5887b698af2a5fbf322c7cc5d6d3f8ab7e57..1635c0c8df23a697a93a8a7bd0dbbfd534c3caef 100644 (file)
@@ -505,6 +505,10 @@ int x86_pmu_hw_config(struct perf_event *event)
 
                if (event->attr.precise_ip > precise)
                        return -EOPNOTSUPP;
+
+               /* There's no sense in having PEBS for non sampling events: */
+               if (!is_sampling_event(event))
+                       return -EINVAL;
        }
        /*
         * check that PEBS LBR correction does not conflict with
index 86138267b68a77753737ffd4c4be2ece6a24cc84..eb1484c86bb4b4611450c49df01aab1a18d8fa5f 100644 (file)
@@ -3176,13 +3176,16 @@ static void intel_pmu_cpu_starting(int cpu)
 
        if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
                for_each_cpu(i, topology_sibling_cpumask(cpu)) {
+                       struct cpu_hw_events *sibling;
                        struct intel_excl_cntrs *c;
 
-                       c = per_cpu(cpu_hw_events, i).excl_cntrs;
+                       sibling = &per_cpu(cpu_hw_events, i);
+                       c = sibling->excl_cntrs;
                        if (c && c->core_id == core_id) {
                                cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
                                cpuc->excl_cntrs = c;
-                               cpuc->excl_thread_id = 1;
+                               if (!sibling->excl_thread_id)
+                                       cpuc->excl_thread_id = 1;
                                break;
                        }
                }
@@ -3987,7 +3990,7 @@ __init int intel_pmu_init(void)
                     x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
                x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
        }
-       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+       x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) - 1;
 
        if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
                WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
index fec8a461bdef6da49c0e7f46c655f235e7fc1275..1076c9a77292d77e5dbb34adbd5ce526121daa73 100644 (file)
@@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
        .stop           = cstate_pmu_event_stop,
        .read           = cstate_pmu_event_update,
        .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+       .module         = THIS_MODULE,
 };
 
 static struct pmu cstate_pkg_pmu = {
@@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
        .stop           = cstate_pmu_event_stop,
        .read           = cstate_pmu_event_update,
        .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+       .module         = THIS_MODULE,
 };
 
 static const struct cstate_model nhm_cstates __initconst = {
index be202390bbd37b00106864123a647786497ce2cd..9dfeeeca0ea8f11a3beb4c23eeb1d115e77189db 100644 (file)
@@ -1389,9 +1389,13 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
                        continue;
 
                /* log dropped samples number */
-               if (error[bit])
+               if (error[bit]) {
                        perf_log_lost_samples(event, error[bit]);
 
+                       if (perf_event_account_interrupt(event))
+                               x86_pmu_stop(event, 0);
+               }
+
                if (counts[bit]) {
                        __intel_pmu_pebs_event(event, iregs, base,
                                               top, bit, counts[bit]);
index bd34124449b08a4be95f114b3295c22e4d57cd34..22ef4f72cf320adf510545ce08fd342bc89839d2 100644 (file)
@@ -161,7 +161,13 @@ static u64 rapl_timer_ms;
 
 static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
 {
-       return rapl_pmus->pmus[topology_logical_package_id(cpu)];
+       unsigned int pkgid = topology_logical_package_id(cpu);
+
+       /*
+        * The unsigned check also catches the '-1' return value for non
+        * existent mappings in the topology map.
+        */
+       return pkgid < rapl_pmus->maxpkg ? rapl_pmus->pmus[pkgid] : NULL;
 }
 
 static inline u64 rapl_read_counter(struct perf_event *event)
@@ -402,6 +408,8 @@ static int rapl_pmu_event_init(struct perf_event *event)
 
        /* must be done before validate_group */
        pmu = cpu_to_rapl_pmu(event->cpu);
+       if (!pmu)
+               return -EINVAL;
        event->cpu = pmu->cpu;
        event->pmu_private = pmu;
        event->hw.event_base = msr;
@@ -585,6 +593,20 @@ static int rapl_cpu_online(unsigned int cpu)
        struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
        int target;
 
+       if (!pmu) {
+               pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
+               if (!pmu)
+                       return -ENOMEM;
+
+               raw_spin_lock_init(&pmu->lock);
+               INIT_LIST_HEAD(&pmu->active_list);
+               pmu->pmu = &rapl_pmus->pmu;
+               pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
+               rapl_hrtimer_init(pmu);
+
+               rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
+       }
+
        /*
         * Check if there is an online cpu in the package which collects rapl
         * events already.
@@ -598,27 +620,6 @@ static int rapl_cpu_online(unsigned int cpu)
        return 0;
 }
 
-static int rapl_cpu_prepare(unsigned int cpu)
-{
-       struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
-
-       if (pmu)
-               return 0;
-
-       pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
-       if (!pmu)
-               return -ENOMEM;
-
-       raw_spin_lock_init(&pmu->lock);
-       INIT_LIST_HEAD(&pmu->active_list);
-       pmu->pmu = &rapl_pmus->pmu;
-       pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
-       pmu->cpu = -1;
-       rapl_hrtimer_init(pmu);
-       rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
-       return 0;
-}
-
 static int rapl_check_hw_unit(bool apply_quirk)
 {
        u64 msr_rapl_power_unit_bits;
@@ -697,6 +698,7 @@ static int __init init_rapl_pmus(void)
        rapl_pmus->pmu.start            = rapl_pmu_event_start;
        rapl_pmus->pmu.stop             = rapl_pmu_event_stop;
        rapl_pmus->pmu.read             = rapl_pmu_event_read;
+       rapl_pmus->pmu.module           = THIS_MODULE;
        return 0;
 }
 
@@ -802,29 +804,21 @@ static int __init rapl_pmu_init(void)
        /*
         * Install callbacks. Core will call them for each online cpu.
         */
-
-       ret = cpuhp_setup_state(CPUHP_PERF_X86_RAPL_PREP, "perf/x86/rapl:prepare",
-                               rapl_cpu_prepare, NULL);
-       if (ret)
-               goto out;
-
        ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_RAPL_ONLINE,
                                "perf/x86/rapl:online",
                                rapl_cpu_online, rapl_cpu_offline);
        if (ret)
-               goto out1;
+               goto out;
 
        ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1);
        if (ret)
-               goto out2;
+               goto out1;
 
        rapl_advertise();
        return 0;
 
-out2:
-       cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
 out1:
-       cpuhp_remove_state(CPUHP_PERF_X86_RAPL_PREP);
+       cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
 out:
        pr_warn("Initialization failed (%d), disabled\n", ret);
        cleanup_rapl_pmus();
@@ -835,7 +829,6 @@ module_init(rapl_pmu_init);
 static void __exit intel_rapl_exit(void)
 {
        cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE);
-       cpuhp_remove_state_nocalls(CPUHP_PERF_X86_RAPL_PREP);
        perf_pmu_unregister(&rapl_pmus->pmu);
        cleanup_rapl_pmus();
 }
index 97c246f84dea1e79d0f4517376763dcb88a18aea..1ab45976474d52597700b291e24b0b0a235dff03 100644 (file)
@@ -100,7 +100,13 @@ ssize_t uncore_event_show(struct kobject *kobj,
 
 struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
 {
-       return pmu->boxes[topology_logical_package_id(cpu)];
+       unsigned int pkgid = topology_logical_package_id(cpu);
+
+       /*
+        * The unsigned check also catches the '-1' return value for non
+        * existent mappings in the topology map.
+        */
+       return pkgid < max_packages ? pmu->boxes[pkgid] : NULL;
 }
 
 u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
@@ -733,6 +739,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
                        .start          = uncore_pmu_event_start,
                        .stop           = uncore_pmu_event_stop,
                        .read           = uncore_pmu_event_read,
+                       .module         = THIS_MODULE,
                };
        } else {
                pmu->pmu = *pmu->type->pmu;
@@ -763,30 +770,6 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)
        pmu->registered = false;
 }
 
-static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
-{
-       struct intel_uncore_pmu *pmu = type->pmus;
-       struct intel_uncore_box *box;
-       int i, pkg;
-
-       if (pmu) {
-               pkg = topology_physical_package_id(cpu);
-               for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       box = pmu->boxes[pkg];
-                       if (box)
-                               uncore_box_exit(box);
-               }
-       }
-}
-
-static void uncore_exit_boxes(void *dummy)
-{
-       struct intel_uncore_type **types;
-
-       for (types = uncore_msr_uncores; *types; types++)
-               __uncore_exit_boxes(*types++, smp_processor_id());
-}
-
 static void uncore_free_boxes(struct intel_uncore_pmu *pmu)
 {
        int pkg;
@@ -1057,86 +1040,6 @@ static void uncore_pci_exit(void)
        }
 }
 
-static int uncore_cpu_dying(unsigned int cpu)
-{
-       struct intel_uncore_type *type, **types = uncore_msr_uncores;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       int i, pkg;
-
-       pkg = topology_logical_package_id(cpu);
-       for (; *types; types++) {
-               type = *types;
-               pmu = type->pmus;
-               for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       box = pmu->boxes[pkg];
-                       if (box && atomic_dec_return(&box->refcnt) == 0)
-                               uncore_box_exit(box);
-               }
-       }
-       return 0;
-}
-
-static int first_init;
-
-static int uncore_cpu_starting(unsigned int cpu)
-{
-       struct intel_uncore_type *type, **types = uncore_msr_uncores;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       int i, pkg, ncpus = 1;
-
-       if (first_init) {
-               /*
-                * On init we get the number of online cpus in the package
-                * and set refcount for all of them.
-                */
-               ncpus = cpumask_weight(topology_core_cpumask(cpu));
-       }
-
-       pkg = topology_logical_package_id(cpu);
-       for (; *types; types++) {
-               type = *types;
-               pmu = type->pmus;
-               for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       box = pmu->boxes[pkg];
-                       if (!box)
-                               continue;
-                       /* The first cpu on a package activates the box */
-                       if (atomic_add_return(ncpus, &box->refcnt) == ncpus)
-                               uncore_box_init(box);
-               }
-       }
-
-       return 0;
-}
-
-static int uncore_cpu_prepare(unsigned int cpu)
-{
-       struct intel_uncore_type *type, **types = uncore_msr_uncores;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       int i, pkg;
-
-       pkg = topology_logical_package_id(cpu);
-       for (; *types; types++) {
-               type = *types;
-               pmu = type->pmus;
-               for (i = 0; i < type->num_boxes; i++, pmu++) {
-                       if (pmu->boxes[pkg])
-                               continue;
-                       /* First cpu of a package allocates the box */
-                       box = uncore_alloc_box(type, cpu_to_node(cpu));
-                       if (!box)
-                               return -ENOMEM;
-                       box->pmu = pmu;
-                       box->pkgid = pkg;
-                       pmu->boxes[pkg] = box;
-               }
-       }
-       return 0;
-}
-
 static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu,
                                   int new_cpu)
 {
@@ -1176,12 +1079,14 @@ static void uncore_change_context(struct intel_uncore_type **uncores,
 
 static int uncore_event_cpu_offline(unsigned int cpu)
 {
-       int target;
+       struct intel_uncore_type *type, **types = uncore_msr_uncores;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, pkg, target;
 
        /* Check if exiting cpu is used for collecting uncore events */
        if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
-               return 0;
-
+               goto unref;
        /* Find a new cpu to collect uncore events */
        target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
 
@@ -1193,12 +1098,82 @@ static int uncore_event_cpu_offline(unsigned int cpu)
 
        uncore_change_context(uncore_msr_uncores, cpu, target);
        uncore_change_context(uncore_pci_uncores, cpu, target);
+
+unref:
+       /* Clear the references */
+       pkg = topology_logical_package_id(cpu);
+       for (; *types; types++) {
+               type = *types;
+               pmu = type->pmus;
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       box = pmu->boxes[pkg];
+                       if (box && atomic_dec_return(&box->refcnt) == 0)
+                               uncore_box_exit(box);
+               }
+       }
        return 0;
 }
 
+static int allocate_boxes(struct intel_uncore_type **types,
+                        unsigned int pkg, unsigned int cpu)
+{
+       struct intel_uncore_box *box, *tmp;
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       LIST_HEAD(allocated);
+       int i;
+
+       /* Try to allocate all required boxes */
+       for (; *types; types++) {
+               type = *types;
+               pmu = type->pmus;
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       if (pmu->boxes[pkg])
+                               continue;
+                       box = uncore_alloc_box(type, cpu_to_node(cpu));
+                       if (!box)
+                               goto cleanup;
+                       box->pmu = pmu;
+                       box->pkgid = pkg;
+                       list_add(&box->active_list, &allocated);
+               }
+       }
+       /* Install them in the pmus */
+       list_for_each_entry_safe(box, tmp, &allocated, active_list) {
+               list_del_init(&box->active_list);
+               box->pmu->boxes[pkg] = box;
+       }
+       return 0;
+
+cleanup:
+       list_for_each_entry_safe(box, tmp, &allocated, active_list) {
+               list_del_init(&box->active_list);
+               kfree(box);
+       }
+       return -ENOMEM;
+}
+
 static int uncore_event_cpu_online(unsigned int cpu)
 {
-       int target;
+       struct intel_uncore_type *type, **types = uncore_msr_uncores;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, ret, pkg, target;
+
+       pkg = topology_logical_package_id(cpu);
+       ret = allocate_boxes(types, pkg, cpu);
+       if (ret)
+               return ret;
+
+       for (; *types; types++) {
+               type = *types;
+               pmu = type->pmus;
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       box = pmu->boxes[pkg];
+                       if (!box && atomic_inc_return(&box->refcnt) == 1)
+                               uncore_box_init(box);
+               }
+       }
 
        /*
         * Check if there is an online cpu in the package
@@ -1388,38 +1363,16 @@ static int __init intel_uncore_init(void)
        if (cret && pret)
                return -ENODEV;
 
-       /*
-        * Install callbacks. Core will call them for each online cpu.
-        *
-        * The first online cpu of each package allocates and takes
-        * the refcounts for all other online cpus in that package.
-        * If msrs are not enabled no allocation is required and
-        * uncore_cpu_prepare() is not called for each online cpu.
-        */
-       if (!cret) {
-              ret = cpuhp_setup_state(CPUHP_PERF_X86_UNCORE_PREP,
-                                      "perf/x86/intel/uncore:prepare",
-                                      uncore_cpu_prepare, NULL);
-               if (ret)
-                       goto err;
-       } else {
-               cpuhp_setup_state_nocalls(CPUHP_PERF_X86_UNCORE_PREP,
-                                         "perf/x86/intel/uncore:prepare",
-                                         uncore_cpu_prepare, NULL);
-       }
-       first_init = 1;
-       cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_STARTING,
-                         "perf/x86/uncore:starting",
-                         uncore_cpu_starting, uncore_cpu_dying);
-       first_init = 0;
-       cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE,
-                         "perf/x86/uncore:online",
-                         uncore_event_cpu_online, uncore_event_cpu_offline);
+       /* Install hotplug callbacks to setup the targets for each package */
+       ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE,
+                               "perf/x86/intel/uncore:online",
+                               uncore_event_cpu_online,
+                               uncore_event_cpu_offline);
+       if (ret)
+               goto err;
        return 0;
 
 err:
-       /* Undo box->init_box() */
-       on_each_cpu_mask(&uncore_cpu_mask, uncore_exit_boxes, NULL, 1);
        uncore_types_exit(uncore_msr_uncores);
        uncore_pci_exit();
        return ret;
@@ -1428,9 +1381,7 @@ module_init(intel_uncore_init);
 
 static void __exit intel_uncore_exit(void)
 {
-       cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
-       cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_UNCORE_STARTING);
-       cpuhp_remove_state_nocalls(CPUHP_PERF_X86_UNCORE_PREP);
+       cpuhp_remove_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
        uncore_types_exit(uncore_msr_uncores);
        uncore_pci_exit();
 }
index e6832be714bc6e76965e1faa7cedcc3ad309c8fa..dae2fedc16015e691ad6ae85ce4bc4122011eefc 100644 (file)
@@ -2686,7 +2686,7 @@ static struct intel_uncore_type *hswep_msr_uncores[] = {
 
 void hswep_uncore_cpu_init(void)
 {
-       int pkg = topology_phys_to_logical_pkg(0);
+       int pkg = boot_cpu_data.logical_proc_id;
 
        if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
                hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
index 34a46dc076d3610212e6f5c9f0abfb2ab9bc3629..8167fdb67ae846a0da668006159abfc56f3d99fc 100644 (file)
@@ -57,7 +57,7 @@
 #define INTEL_FAM6_ATOM_SILVERMONT2    0x4D /* Avaton/Rangely */
 #define INTEL_FAM6_ATOM_AIRMONT                0x4C /* CherryTrail / Braswell */
 #define INTEL_FAM6_ATOM_MERRIFIELD     0x4A /* Tangier */
-#define INTEL_FAM6_ATOM_MOOREFIELD     0x5A /* Annidale */
+#define INTEL_FAM6_ATOM_MOOREFIELD     0x5A /* Anniedale */
 #define INTEL_FAM6_ATOM_GOLDMONT       0x5C
 #define INTEL_FAM6_ATOM_DENVERTON      0x5F /* Goldmont Microserver */
 
index 38711df3bcb56b6939f2f84af16b920f0409049b..2266f864b7477a3ff88fee26f07df62eb5073ab4 100644 (file)
@@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);
 extern void load_ucode_ap(void);
 void reload_early_microcode(void);
 extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
+extern bool initrd_gone;
 #else
 static inline int __init microcode_init(void)                  { return 0; };
 static inline void __init load_ucode_bsp(void)                 { }
index 195becc6f78074f23f25dc7d5d14da4bd90aac76..e793fc9a9b20c36d2e0d0e8e2a359fd1c70f2d8e 100644 (file)
@@ -52,6 +52,21 @@ struct extended_sigtable {
 
 #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 
+static inline u32 intel_get_microcode_revision(void)
+{
+       u32 rev, dummy;
+
+       native_wrmsrl(MSR_IA32_UCODE_REV, 0);
+
+       /* As documented in the SDM: Do a CPUID 1 here */
+       native_cpuid_eax(1);
+
+       /* get the current revision from MSR 0x8B */
+       native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);
+
+       return rev;
+}
+
 #ifdef CONFIG_MICROCODE_INTEL
 extern void __init load_ucode_intel_bsp(void);
 extern void load_ucode_intel_ap(void);
index eaf100508c36203ad888c0b4484ba264e20bd0ad..e6cfe7ba2d65968611d049a136fc1b09506065e1 100644 (file)
@@ -104,6 +104,7 @@ struct cpuinfo_x86 {
        __u8                    x86_phys_bits;
        /* CPUID returned core id bits: */
        __u8                    x86_coreid_bits;
+       __u8                    cu_id;
        /* Max extended CPUID function supported: */
        __u32                   extended_cpuid_level;
        /* Maximum supported CPUID level, -1=no CPUID: */
@@ -219,6 +220,24 @@ static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
            : "memory");
 }
 
+#define native_cpuid_reg(reg)                                  \
+static inline unsigned int native_cpuid_##reg(unsigned int op) \
+{                                                              \
+       unsigned int eax = op, ebx, ecx = 0, edx;               \
+                                                               \
+       native_cpuid(&eax, &ebx, &ecx, &edx);                   \
+                                                               \
+       return reg;                                             \
+}
+
+/*
+ * Native CPUID functions returning a single datum.
+ */
+native_cpuid_reg(eax)
+native_cpuid_reg(ebx)
+native_cpuid_reg(ecx)
+native_cpuid_reg(edx)
+
 static inline void load_cr3(pgd_t *pgdir)
 {
        write_cr3(__pa(pgdir));
index a3269c897ec578508fd41c6f7ab9b3622934e623..2e41c50ddf47f414c8f2e4b0a99965ceafffb4bf 100644 (file)
@@ -58,7 +58,7 @@ get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
        if (task == current)
                return __builtin_frame_address(0);
 
-       return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
+       return &((struct inactive_task_frame *)task->thread.sp)->bp;
 }
 #else
 static inline unsigned long *
index 5cb436acd46315b75ba40aacc780373ea2cc4f7c..fcc5cd387fd17a59e5f28ba5fc8fb65fc57ae5af 100644 (file)
@@ -36,7 +36,10 @@ static inline void prepare_switch_to(struct task_struct *prev,
 
 asmlinkage void ret_from_fork(void);
 
-/* data that is pointed to by thread.sp */
+/*
+ * This is the structure pointed to by thread.sp for an inactive task.  The
+ * order of the fields must match the code in __switch_to_asm().
+ */
 struct inactive_task_frame {
 #ifdef CONFIG_X86_64
        unsigned long r15;
@@ -48,6 +51,11 @@ struct inactive_task_frame {
        unsigned long di;
 #endif
        unsigned long bx;
+
+       /*
+        * These two fields must be together.  They form a stack frame header,
+        * needed by get_frame_pointer().
+        */
        unsigned long bp;
        unsigned long ret_addr;
 };
index 945e512a112a321771797869b39c496d7f5c2b8f..bd6b8c270c24af4a2869034758e1f3e5e04c01a8 100644 (file)
@@ -2115,6 +2115,7 @@ static inline void __init check_timer(void)
                        if (idx != -1 && irq_trigger(idx))
                                unmask_ioapic_irq(irq_get_chip_data(0));
                }
+               irq_domain_deactivate_irq(irq_data);
                irq_domain_activate_irq(irq_data);
                if (timer_irq_works()) {
                        if (disable_timer_pin_1 > 0)
@@ -2136,6 +2137,7 @@ static inline void __init check_timer(void)
                 * legacy devices should be connected to IO APIC #0
                 */
                replace_pin_at_irq_node(data, node, apic1, pin1, apic2, pin2);
+               irq_domain_deactivate_irq(irq_data);
                irq_domain_activate_irq(irq_data);
                legacy_pic->unmask(0);
                if (timer_irq_works()) {
index 71cae73a507617a2559aa0815a9e178a22f33385..2b4cf04239b6c011a9d9a5ef84bdca5ef073a69e 100644 (file)
@@ -312,12 +312,19 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
                u32 eax, ebx, ecx, edx;
 
                cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
-               node_id = ecx & 7;
 
-               /* get compute unit information */
-               smp_num_siblings = ((ebx >> 8) & 3) + 1;
-               c->x86_max_cores /= smp_num_siblings;
-               c->cpu_core_id = ebx & 0xff;
+               node_id  = ecx & 0xff;
+               smp_num_siblings = ((ebx >> 8) & 0xff) + 1;
+
+               if (c->x86 == 0x15)
+                       c->cu_id = ebx & 0xff;
+
+               if (c->x86 >= 0x17) {
+                       c->cpu_core_id = ebx & 0xff;
+
+                       if (smp_num_siblings > 1)
+                               c->x86_max_cores /= smp_num_siblings;
+               }
 
                /*
                 * We may have multiple LLCs if L3 caches exist, so check if we
index dc1697ca5191ce87cd9f27a78236ede3897243ab..ede03e849a8bd62808d33e1002c95a20568d5f8c 100644 (file)
@@ -1015,6 +1015,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
        c->x86_model_id[0] = '\0';  /* Unset */
        c->x86_max_cores = 1;
        c->x86_coreid_bits = 0;
+       c->cu_id = 0xff;
 #ifdef CONFIG_X86_64
        c->x86_clflush_size = 64;
        c->x86_phys_bits = 36;
@@ -1221,7 +1222,7 @@ static __init int setup_disablecpuid(char *arg)
 {
        int bit;
 
-       if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+       if (get_option(&arg, &bit) && bit >= 0 && bit < NCAPINTS * 32)
                setup_clear_cpu_cap(bit);
        else
                return 0;
index fcd484d2bb034a4533d3c4355d3ace82c92060dd..203f860d2ab3339c11ddc34d976f56ffa6ef069c 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/bugs.h>
 #include <asm/cpu.h>
 #include <asm/intel-family.h>
+#include <asm/microcode_intel.h>
 
 #ifdef CONFIG_X86_64
 #include <linux/topology.h>
@@ -78,14 +79,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)
                (c->x86 == 0x6 && c->x86_model >= 0x0e))
                set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
 
-       if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
-               unsigned lower_word;
-
-               wrmsr(MSR_IA32_UCODE_REV, 0, 0);
-               /* Required by the SDM */
-               sync_core();
-               rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
-       }
+       if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
+               c->microcode = intel_get_microcode_revision();
 
        /*
         * Atom erratum AAE44/AAF40/AAG38/AAH41:
index 00ef43233e034b0cde9b2adc88b8003ddc42d00b..537c6647d84ca3e7cca771feb6c98bda94ef8c70 100644 (file)
@@ -1373,20 +1373,15 @@ static unsigned long mce_adjust_timer_default(unsigned long interval)
 
 static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default;
 
-static void __restart_timer(struct timer_list *t, unsigned long interval)
+static void __start_timer(struct timer_list *t, unsigned long interval)
 {
        unsigned long when = jiffies + interval;
        unsigned long flags;
 
        local_irq_save(flags);
 
-       if (timer_pending(t)) {
-               if (time_before(when, t->expires))
-                       mod_timer(t, when);
-       } else {
-               t->expires = round_jiffies(when);
-               add_timer_on(t, smp_processor_id());
-       }
+       if (!timer_pending(t) || time_before(when, t->expires))
+               mod_timer(t, round_jiffies(when));
 
        local_irq_restore(flags);
 }
@@ -1421,7 +1416,7 @@ static void mce_timer_fn(unsigned long data)
 
 done:
        __this_cpu_write(mce_next_interval, iv);
-       __restart_timer(t, iv);
+       __start_timer(t, iv);
 }
 
 /*
@@ -1432,7 +1427,7 @@ void mce_timer_kick(unsigned long interval)
        struct timer_list *t = this_cpu_ptr(&mce_timer);
        unsigned long iv = __this_cpu_read(mce_next_interval);
 
-       __restart_timer(t, interval);
+       __start_timer(t, interval);
 
        if (interval < iv)
                __this_cpu_write(mce_next_interval, interval);
@@ -1779,17 +1774,15 @@ static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c)
        }
 }
 
-static void mce_start_timer(unsigned int cpu, struct timer_list *t)
+static void mce_start_timer(struct timer_list *t)
 {
        unsigned long iv = check_interval * HZ;
 
        if (mca_cfg.ignore_ce || !iv)
                return;
 
-       per_cpu(mce_next_interval, cpu) = iv;
-
-       t->expires = round_jiffies(jiffies + iv);
-       add_timer_on(t, cpu);
+       this_cpu_write(mce_next_interval, iv);
+       __start_timer(t, iv);
 }
 
 static void __mcheck_cpu_setup_timer(void)
@@ -1806,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void)
        unsigned int cpu = smp_processor_id();
 
        setup_pinned_timer(t, mce_timer_fn, cpu);
-       mce_start_timer(cpu, t);
+       mce_start_timer(t);
 }
 
 /* Handle unconfigured int18 (should never happen) */
@@ -2566,7 +2559,7 @@ static int mce_cpu_dead(unsigned int cpu)
 
 static int mce_cpu_online(unsigned int cpu)
 {
-       struct timer_list *t = &per_cpu(mce_timer, cpu);
+       struct timer_list *t = this_cpu_ptr(&mce_timer);
        int ret;
 
        mce_device_create(cpu);
@@ -2577,13 +2570,13 @@ static int mce_cpu_online(unsigned int cpu)
                return ret;
        }
        mce_reenable_cpu();
-       mce_start_timer(cpu, t);
+       mce_start_timer(t);
        return 0;
 }
 
 static int mce_cpu_pre_down(unsigned int cpu)
 {
-       struct timer_list *t = &per_cpu(mce_timer, cpu);
+       struct timer_list *t = this_cpu_ptr(&mce_timer);
 
        mce_disable_cpu();
        del_timer_sync(t);
index 6a31e2691f3aa0ac68620459c371ca42912c4475..079e81733a58950486a7012b70e06f45e71af688 100644 (file)
@@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family)
 reget:
                if (!get_builtin_microcode(&cp, family)) {
 #ifdef CONFIG_BLK_DEV_INITRD
-                       cp = find_cpio_data(ucode_path, (void *)initrd_start,
-                                           initrd_end - initrd_start, NULL);
+                       if (!initrd_gone)
+                               cp = find_cpio_data(ucode_path, (void *)initrd_start,
+                                                   initrd_end - initrd_start, NULL);
 #endif
                        if (!(cp.data && cp.size)) {
                                /*
index 2af69d27da629a5c802498e692300f9980862a2a..73102d932760b871896a956a88ff178362cc5a94 100644 (file)
@@ -46,6 +46,8 @@
 static struct microcode_ops    *microcode_ops;
 static bool dis_ucode_ldr = true;
 
+bool initrd_gone;
+
 LIST_HEAD(microcode_cache);
 
 /*
@@ -190,21 +192,24 @@ void load_ucode_ap(void)
 static int __init save_microcode_in_initrd(void)
 {
        struct cpuinfo_x86 *c = &boot_cpu_data;
+       int ret = -EINVAL;
 
        switch (c->x86_vendor) {
        case X86_VENDOR_INTEL:
                if (c->x86 >= 6)
-                       return save_microcode_in_initrd_intel();
+                       ret = save_microcode_in_initrd_intel();
                break;
        case X86_VENDOR_AMD:
                if (c->x86 >= 0x10)
-                       return save_microcode_in_initrd_amd(c->x86);
+                       ret = save_microcode_in_initrd_amd(c->x86);
                break;
        default:
                break;
        }
 
-       return -EINVAL;
+       initrd_gone = true;
+
+       return ret;
 }
 
 struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
@@ -247,9 +252,16 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
         * has the virtual address of the beginning of the initrd. It also
         * possibly relocates the ramdisk. In either case, initrd_start contains
         * the updated address so use that instead.
+        *
+        * initrd_gone is for the hotplug case where we've thrown out initrd
+        * already.
         */
-       if (!use_pa && initrd_start)
-               start = initrd_start;
+       if (!use_pa) {
+               if (initrd_gone)
+                       return (struct cpio_data){ NULL, 0, "" };
+               if (initrd_start)
+                       start = initrd_start;
+       }
 
        return find_cpio_data(path, (void *)start, size, NULL);
 #else /* !CONFIG_BLK_DEV_INITRD */
index b624b54912e11e4e58992b9e1ca2d7cab20ce9e4..8325d8a09ab0768dd08156b8e4c5b755b78c10f9 100644 (file)
@@ -41,7 +41,7 @@
 
 static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
 
-/* Current microcode patch used in early patching */
+/* Current microcode patch used in early patching on the APs. */
 struct microcode_intel *intel_ucode_patch;
 
 static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
@@ -150,7 +150,7 @@ static struct ucode_patch *__alloc_microcode_buf(void *data, unsigned int size)
 {
        struct ucode_patch *p;
 
-       p = kzalloc(size, GFP_KERNEL);
+       p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);
        if (!p)
                return ERR_PTR(-ENOMEM);
 
@@ -368,26 +368,6 @@ next:
        return patch;
 }
 
-static void cpuid_1(void)
-{
-       /*
-        * According to the Intel SDM, Volume 3, 9.11.7:
-        *
-        *   CPUID returns a value in a model specific register in
-        *   addition to its usual register return values. The
-        *   semantics of CPUID cause it to deposit an update ID value
-        *   in the 64-bit model-specific register at address 08BH
-        *   (IA32_BIOS_SIGN_ID). If no update is present in the
-        *   processor, the value in the MSR remains unmodified.
-        *
-        * Use native_cpuid -- this code runs very early and we don't
-        * want to mess with paravirt.
-        */
-       unsigned int eax = 1, ebx, ecx = 0, edx;
-
-       native_cpuid(&eax, &ebx, &ecx, &edx);
-}
-
 static int collect_cpu_info_early(struct ucode_cpu_info *uci)
 {
        unsigned int val[2];
@@ -410,15 +390,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
                native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
                csig.pf = 1 << ((val[1] >> 18) & 7);
        }
-       native_wrmsrl(MSR_IA32_UCODE_REV, 0);
-
-       /* As documented in the SDM: Do a CPUID 1 here */
-       cpuid_1();
-
-       /* get the current revision from MSR 0x8B */
-       native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-       csig.rev = val[1];
+       csig.rev = intel_get_microcode_revision();
 
        uci->cpu_sig = csig;
        uci->valid = 1;
@@ -602,7 +575,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)
 static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
 {
        struct microcode_intel *mc;
-       unsigned int val[2];
+       u32 rev;
 
        mc = uci->mc;
        if (!mc)
@@ -610,21 +583,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
 
        /* write microcode via MSR 0x79 */
        native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
-       native_wrmsrl(MSR_IA32_UCODE_REV, 0);
-
-       /* As documented in the SDM: Do a CPUID 1 here */
-       cpuid_1();
 
-       /* get the current revision from MSR 0x8B */
-       native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-       if (val[1] != mc->hdr.rev)
+       rev = intel_get_microcode_revision();
+       if (rev != mc->hdr.rev)
                return -1;
 
 #ifdef CONFIG_X86_64
        /* Flush global tlb. This is precaution. */
        flush_tlb_early();
 #endif
-       uci->cpu_sig.rev = val[1];
+       uci->cpu_sig.rev = rev;
 
        if (early)
                print_ucode(uci);
@@ -639,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void)
        struct ucode_cpu_info uci;
        struct cpio_data cp;
 
-       /*
-        * AP loading didn't find any microcode patch, no need to save anything.
-        */
-       if (!intel_ucode_patch || IS_ERR(intel_ucode_patch))
-               return 0;
-
        if (!load_builtin_intel_microcode(&cp))
                cp = find_microcode_in_initrd(ucode_path, false);
 
@@ -660,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void)
        return 0;
 }
 
-
 /*
  * @res_patch, output: a pointer to the patch we found.
  */
@@ -804,8 +765,8 @@ static int apply_microcode_intel(int cpu)
        struct microcode_intel *mc;
        struct ucode_cpu_info *uci;
        struct cpuinfo_x86 *c;
-       unsigned int val[2];
        static int prev_rev;
+       u32 rev;
 
        /* We should bind the task to the CPU */
        if (WARN_ON(raw_smp_processor_id() != cpu))
@@ -822,33 +783,28 @@ static int apply_microcode_intel(int cpu)
 
        /* write microcode via MSR 0x79 */
        wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
-       wrmsrl(MSR_IA32_UCODE_REV, 0);
-
-       /* As documented in the SDM: Do a CPUID 1 here */
-       cpuid_1();
 
-       /* get the current revision from MSR 0x8B */
-       rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+       rev = intel_get_microcode_revision();
 
-       if (val[1] != mc->hdr.rev) {
+       if (rev != mc->hdr.rev) {
                pr_err("CPU%d update to revision 0x%x failed\n",
                       cpu, mc->hdr.rev);
                return -1;
        }
 
-       if (val[1] != prev_rev) {
+       if (rev != prev_rev) {
                pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
-                       val[1],
+                       rev,
                        mc->hdr.date & 0xffff,
                        mc->hdr.date >> 24,
                        (mc->hdr.date >> 16) & 0xff);
-               prev_rev = val[1];
+               prev_rev = rev;
        }
 
        c = &cpu_data(cpu);
 
-       uci->cpu_sig.rev = val[1];
-       c->microcode = val[1];
+       uci->cpu_sig.rev = rev;
+       c->microcode = rev;
 
        return 0;
 }
@@ -860,7 +816,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
        u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
        int new_rev = uci->cpu_sig.rev;
        unsigned int leftover = size;
-       unsigned int curr_mc_size = 0;
+       unsigned int curr_mc_size = 0, new_mc_size = 0;
        unsigned int csig, cpf;
 
        while (leftover) {
@@ -901,6 +857,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
                        vfree(new_mc);
                        new_rev = mc_header.rev;
                        new_mc  = mc;
+                       new_mc_size = mc_size;
                        mc = NULL;      /* trigger new vmalloc */
                }
 
@@ -926,7 +883,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
         * permanent memory. So it will be loaded early when a CPU is hot added
         * or resumes.
         */
-       save_mc_for_early(new_mc, curr_mc_size);
+       save_mc_for_early(new_mc, new_mc_size);
 
        pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
                 cpu, new_rev, uci->cpu_sig.rev);
index e4e97a5355ce852ac49937fd180f62b614c1286c..de7234401275b56760f27573eea5669e2bda4f68 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/fpu/regset.h>
 #include <asm/fpu/signal.h>
 #include <asm/fpu/types.h>
+#include <asm/fpu/xstate.h>
 #include <asm/traps.h>
 
 #include <linux/hardirq.h>
@@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state)
         * it will #GP. Make sure it is replaced after the memset().
         */
        if (static_cpu_has(X86_FEATURE_XSAVES))
-               state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT;
+               state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
+                                              xfeatures_mask;
 
        if (static_cpu_has(X86_FEATURE_FXSR))
                fpstate_init_fxstate(&state->fxsave);
index 85e87b46c318026ed28d87056c516aec3e5fb9ed..dc6ba5bda9fc83630c773a80c4adea6871db0a59 100644 (file)
@@ -352,6 +352,7 @@ static int hpet_resume(struct clock_event_device *evt, int timer)
        } else {
                struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
 
+               irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq));
                irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
                disable_irq(hdev->irq);
                irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
index b47edb8f52566e223f89800b5b0465349331985a..410efb2c7b80028ba63367e5ed6d5e27518b0f24 100644 (file)
@@ -68,12 +68,10 @@ static struct dma_map_ops swiotlb_dma_ops = {
  */
 int __init pci_swiotlb_detect_override(void)
 {
-       int use_swiotlb = swiotlb | swiotlb_force;
-
-       if (swiotlb_force)
+       if (swiotlb_force == SWIOTLB_FORCE)
                swiotlb = 1;
 
-       return use_swiotlb;
+       return swiotlb;
 }
 IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
                  pci_xen_swiotlb_detect,
index 4cfba947d77429fd13d393819b1682879ed9aa06..eb69b14dbfc87d9ef1679904c3b3b61f701ef99d 100644 (file)
@@ -575,7 +575,9 @@ static void __init reserve_crashkernel(void)
        /* 0 means: find the address automatically */
        if (crash_base <= 0) {
                /*
-                *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
+                * Set CRASH_ADDR_LOW_MAX upper bound for crash memory,
+                * as old kexec-tools loads bzImage below that, unless
+                * "crashkernel=size[KMG],high" is specified.
                 */
                crash_base = memblock_find_in_range(CRASH_ALIGN,
                                                    high ? CRASH_ADDR_HIGH_MAX
index 46732dc3b73cd67e874dfe99b0eeb807f816e06a..99b920d0e5163d3162fe8607a28c5e83d0ca7e55 100644 (file)
@@ -433,9 +433,15 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
                int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
 
                if (c->phys_proc_id == o->phys_proc_id &&
-                   per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2) &&
-                   c->cpu_core_id == o->cpu_core_id)
-                       return topology_sane(c, o, "smt");
+                   per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) {
+                       if (c->cpu_core_id == o->cpu_core_id)
+                               return topology_sane(c, o, "smt");
+
+                       if ((c->cu_id != 0xff) &&
+                           (o->cu_id != 0xff) &&
+                           (c->cu_id == o->cu_id))
+                               return topology_sane(c, o, "smt");
+               }
 
        } else if (c->phys_proc_id == o->phys_proc_id &&
                   c->cpu_core_id == o->cpu_core_id) {
index be3a49ee035650f1f1eac68c07ad0e8898c40585..37e7cf544e51580e8633651bed25858cbcb840bf 100644 (file)
@@ -694,6 +694,7 @@ unsigned long native_calibrate_tsc(void)
                        crystal_khz = 24000;    /* 24.0 MHz */
                        break;
                case INTEL_FAM6_SKYLAKE_X:
+               case INTEL_FAM6_ATOM_DENVERTON:
                        crystal_khz = 25000;    /* 25.0 MHz */
                        break;
                case INTEL_FAM6_ATOM_GOLDMONT:
@@ -1355,6 +1356,9 @@ void __init tsc_init(void)
                (unsigned long)cpu_khz / 1000,
                (unsigned long)cpu_khz % 1000);
 
+       /* Sanitize TSC ADJUST before cyc2ns gets initialized */
+       tsc_store_and_check_tsc_adjust(true);
+
        /*
         * Secondary CPUs do not run through tsc_init(), so set up
         * all the scale factors for all CPUs, assuming the same
@@ -1385,8 +1389,6 @@ void __init tsc_init(void)
 
        if (unsynchronized_tsc())
                mark_tsc_unstable("TSCs unsynchronized");
-       else
-               tsc_store_and_check_tsc_adjust(true);
 
        check_system_tsc_reliable();
 
index d0db011051a54212742680d3f25c2c52fb5c8ea6..728f7537847583108075d91ad4aa75edfd86f077 100644 (file)
@@ -286,13 +286,6 @@ void check_tsc_sync_source(int cpu)
        if (unsynchronized_tsc())
                return;
 
-       if (tsc_clocksource_reliable) {
-               if (cpu == (nr_cpu_ids-1) || system_state != SYSTEM_BOOTING)
-                       pr_info(
-                       "Skipped synchronization checks as TSC is reliable.\n");
-               return;
-       }
-
        /*
         * Set the maximum number of test runs to
         *  1 if the CPU does not provide the TSC_ADJUST MSR
@@ -380,14 +373,19 @@ void check_tsc_sync_target(void)
        int cpus = 2;
 
        /* Also aborts if there is no TSC. */
-       if (unsynchronized_tsc() || tsc_clocksource_reliable)
+       if (unsynchronized_tsc())
                return;
 
        /*
         * Store, verify and sanitize the TSC adjust register. If
         * successful skip the test.
+        *
+        * The test is also skipped when the TSC is marked reliable. This
+        * is true for SoCs which have no fallback clocksource. On these
+        * SoCs the TSC is frequency synchronized, but still the TSC ADJUST
+        * register might have been wreckaged by the BIOS..
         */
-       if (tsc_store_and_check_tsc_adjust(false)) {
+       if (tsc_store_and_check_tsc_adjust(false) || tsc_clocksource_reliable) {
                atomic_inc(&skip_test);
                return;
        }
index 4443e499f2790923e6510bc57a88d5a9e0578051..23d15565d02ad780529091e5004557081bb62844 100644 (file)
@@ -6,6 +6,21 @@
 
 #define FRAME_HEADER_SIZE (sizeof(long) * 2)
 
+/*
+ * This disables KASAN checking when reading a value from another task's stack,
+ * since the other task could be running on another CPU and could have poisoned
+ * the stack in the meantime.
+ */
+#define READ_ONCE_TASK_STACK(task, x)                  \
+({                                                     \
+       unsigned long val;                              \
+       if (task == current)                            \
+               val = READ_ONCE(x);                     \
+       else                                            \
+               val = READ_ONCE_NOCHECK(x);             \
+       val;                                            \
+})
+
 static void unwind_dump(struct unwind_state *state, unsigned long *sp)
 {
        static bool dumped_before = false;
@@ -48,7 +63,8 @@ unsigned long unwind_get_return_address(struct unwind_state *state)
        if (state->regs && user_mode(state->regs))
                return 0;
 
-       addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, *addr_p,
+       addr = READ_ONCE_TASK_STACK(state->task, *addr_p);
+       addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr,
                                     addr_p);
 
        return __kernel_text_address(addr) ? addr : 0;
@@ -162,7 +178,7 @@ bool unwind_next_frame(struct unwind_state *state)
        if (state->regs)
                next_bp = (unsigned long *)state->regs->bp;
        else
-               next_bp = (unsigned long *)*state->bp;
+               next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp);
 
        /* is the next frame pointer an encoded pointer to pt_regs? */
        regs = decode_frame_pointer(next_bp);
@@ -207,6 +223,16 @@ bool unwind_next_frame(struct unwind_state *state)
        return true;
 
 bad_address:
+       /*
+        * When unwinding a non-current task, the task might actually be
+        * running on another CPU, in which case it could be modifying its
+        * stack while we're reading it.  This is generally not a problem and
+        * can be ignored as long as the caller understands that unwinding
+        * another task will not always succeed.
+        */
+       if (state->task != current)
+               goto the_end;
+
        if (state->regs) {
                printk_deferred_once(KERN_WARNING
                        "WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
index ec5d7545e6dcbe2d1724e48b5e595b01071a3adc..0442d98367aec50f3810a332c81be5eac0a29a95 100644 (file)
@@ -160,11 +160,12 @@ void save_v86_state(struct kernel_vm86_regs *regs, int retval)
 
 static void mark_screen_rdonly(struct mm_struct *mm)
 {
+       struct vm_area_struct *vma;
+       spinlock_t *ptl;
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
-       spinlock_t *ptl;
        int i;
 
        down_write(&mm->mmap_sem);
@@ -177,7 +178,7 @@ static void mark_screen_rdonly(struct mm_struct *mm)
        pmd = pmd_offset(pud, 0xA0000);
 
        if (pmd_trans_huge(*pmd)) {
-               struct vm_area_struct *vma = find_vma(mm, 0xA0000);
+               vma = find_vma(mm, 0xA0000);
                split_huge_pmd(vma, pmd, 0xA0000);
        }
        if (pmd_none_or_clear_bad(pmd))
index 56628a44668b7ec43cee087af817ebb1725cf7cd..cedbba0f3402d2343ce069fe3ed6a07f44f68907 100644 (file)
@@ -818,6 +818,20 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
        return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 }
 
+static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
+                              struct segmented_address addr,
+                              void *data,
+                              unsigned int size)
+{
+       int rc;
+       ulong linear;
+
+       rc = linearize(ctxt, addr, size, true, &linear);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
+       return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
+}
+
 /*
  * Prefetch the remaining bytes of the instruction without crossing page
  * boundary if they are not in fetch_cache yet.
@@ -1571,7 +1585,6 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                                    &ctxt->exception);
 }
 
-/* Does not support long mode */
 static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                                     u16 selector, int seg, u8 cpl,
                                     enum x86_transfer_type transfer,
@@ -1608,20 +1621,34 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 
        rpl = selector & 3;
 
-       /* NULL selector is not valid for TR, CS and SS (except for long mode) */
-       if ((seg == VCPU_SREG_CS
-            || (seg == VCPU_SREG_SS
-                && (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
-            || seg == VCPU_SREG_TR)
-           && null_selector)
-               goto exception;
-
        /* TR should be in GDT only */
        if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
                goto exception;
 
-       if (null_selector) /* for NULL selector skip all following checks */
+       /* NULL selector is not valid for TR, CS and (except for long mode) SS */
+       if (null_selector) {
+               if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
+                       goto exception;
+
+               if (seg == VCPU_SREG_SS) {
+                       if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
+                               goto exception;
+
+                       /*
+                        * ctxt->ops->set_segment expects the CPL to be in
+                        * SS.DPL, so fake an expand-up 32-bit data segment.
+                        */
+                       seg_desc.type = 3;
+                       seg_desc.p = 1;
+                       seg_desc.s = 1;
+                       seg_desc.dpl = cpl;
+                       seg_desc.d = 1;
+                       seg_desc.g = 1;
+               }
+
+               /* Skip all following checks */
                goto load;
+       }
 
        ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
        if (ret != X86EMUL_CONTINUE)
@@ -1737,6 +1764,21 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
                                   u16 selector, int seg)
 {
        u8 cpl = ctxt->ops->cpl(ctxt);
+
+       /*
+        * None of MOV, POP and LSS can load a NULL selector in CPL=3, but
+        * they can load it at CPL<3 (Intel's manual says only LSS can,
+        * but it's wrong).
+        *
+        * However, the Intel manual says that putting IST=1/DPL=3 in
+        * an interrupt gate will result in SS=3 (the AMD manual instead
+        * says it doesn't), so allow SS=3 in __load_segment_descriptor
+        * and only forbid it here.
+        */
+       if (seg == VCPU_SREG_SS && selector == 3 &&
+           ctxt->mode == X86EMUL_MODE_PROT64)
+               return emulate_exception(ctxt, GP_VECTOR, 0, true);
+
        return __load_segment_descriptor(ctxt, selector, seg, cpl,
                                         X86_TRANSFER_NONE, NULL);
 }
@@ -3685,8 +3727,8 @@ static int emulate_store_desc_ptr(struct x86_emulate_ctxt *ctxt,
        }
        /* Disable writeback. */
        ctxt->dst.type = OP_NONE;
-       return segmented_write(ctxt, ctxt->dst.addr.mem,
-                              &desc_ptr, 2 + ctxt->op_bytes);
+       return segmented_write_std(ctxt, ctxt->dst.addr.mem,
+                                  &desc_ptr, 2 + ctxt->op_bytes);
 }
 
 static int em_sgdt(struct x86_emulate_ctxt *ctxt)
@@ -3932,7 +3974,7 @@ static int em_fxsave(struct x86_emulate_ctxt *ctxt)
        else
                size = offsetof(struct fxregs_state, xmm_space[0]);
 
-       return segmented_write(ctxt, ctxt->memop.addr.mem, &fx_state, size);
+       return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
 }
 
 static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
@@ -3974,7 +4016,7 @@ static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
-       rc = segmented_read(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
+       rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
index 5fe290c1b7d892729e7cfd637433b8171423f407..2f6ef5121a4ca36ac73639e5ffc6aa86624067d2 100644 (file)
@@ -2426,3 +2426,9 @@ void kvm_lapic_init(void)
        jump_label_rate_limit(&apic_hw_disabled, HZ);
        jump_label_rate_limit(&apic_sw_disabled, HZ);
 }
+
+void kvm_lapic_exit(void)
+{
+       static_key_deferred_flush(&apic_hw_disabled);
+       static_key_deferred_flush(&apic_sw_disabled);
+}
index e0c80233b3e17a1793cbafd422688091034b15c5..ff8039d616723fd79c493c0a1369658e440224b2 100644 (file)
@@ -110,6 +110,7 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
 
 int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
 void kvm_lapic_init(void);
+void kvm_lapic_exit(void);
 
 #define VEC_POS(v) ((v) & (32 - 1))
 #define REG_POS(v) (((v) >> 5) << 4)
index 24db5fb6f575af27d3b61a67b15ce9996158ed8b..a236decb81e4ffca42525d8a9cd3d5d8c98916a9 100644 (file)
@@ -132,12 +132,6 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
 
 #define VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE 5
 
-#define VMX_VPID_EXTENT_SUPPORTED_MASK         \
-       (VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT |  \
-       VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |    \
-       VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT |    \
-       VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT)
-
 /*
  * Hyper-V requires all of these, so mark them as supported even though
  * they are just treated the same as all-context.
@@ -10473,12 +10467,12 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
            !nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4)) {
                nested_vmx_entry_failure(vcpu, vmcs12,
                        EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
-               goto out;
+               return 1;
        }
        if (vmcs12->vmcs_link_pointer != -1ull) {
                nested_vmx_entry_failure(vcpu, vmcs12,
                        EXIT_REASON_INVALID_STATE, ENTRY_FAIL_VMCS_LINK_PTR);
-               goto out;
+               return 1;
        }
 
        /*
@@ -10498,7 +10492,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
                     ia32e != !!(vmcs12->guest_ia32_efer & EFER_LME))) {
                        nested_vmx_entry_failure(vcpu, vmcs12,
                                EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
-                       goto out;
+                       return 1;
                }
        }
 
@@ -10516,7 +10510,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
                    ia32e != !!(vmcs12->host_ia32_efer & EFER_LME)) {
                        nested_vmx_entry_failure(vcpu, vmcs12,
                                EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
-                       goto out;
+                       return 1;
                }
        }
 
index 51ccfe08e32ff0570517fda01277dc0085721e94..e52c9088660fac47d6da377b39412378ff0157b0 100644 (file)
@@ -3070,6 +3070,8 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
        memset(&events->reserved, 0, sizeof(events->reserved));
 }
 
+static void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags);
+
 static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                                              struct kvm_vcpu_events *events)
 {
@@ -3106,10 +3108,13 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                vcpu->arch.apic->sipi_vector = events->sipi_vector;
 
        if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
+               u32 hflags = vcpu->arch.hflags;
                if (events->smi.smm)
-                       vcpu->arch.hflags |= HF_SMM_MASK;
+                       hflags |= HF_SMM_MASK;
                else
-                       vcpu->arch.hflags &= ~HF_SMM_MASK;
+                       hflags &= ~HF_SMM_MASK;
+               kvm_set_hflags(vcpu, hflags);
+
                vcpu->arch.smi_pending = events->smi.pending;
                if (events->smi.smm_inside_nmi)
                        vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
@@ -3177,6 +3182,7 @@ static void fill_xsave(u8 *dest, struct kvm_vcpu *vcpu)
        memcpy(dest, xsave, XSAVE_HDR_OFFSET);
 
        /* Set XSTATE_BV */
+       xstate_bv &= vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FPSSE;
        *(u64 *)(dest + XSAVE_HDR_OFFSET) = xstate_bv;
 
        /*
@@ -3337,6 +3343,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 
        switch (cap->cap) {
        case KVM_CAP_HYPERV_SYNIC:
+               if (!irqchip_in_kernel(vcpu->kvm))
+                       return -EINVAL;
                return kvm_hv_activate_synic(vcpu);
        default:
                return -EINVAL;
@@ -6040,6 +6048,7 @@ out:
 
 void kvm_arch_exit(void)
 {
+       kvm_lapic_exit();
        perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
 
        if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
@@ -6163,7 +6172,8 @@ static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt)
 
        kvm_x86_ops->patch_hypercall(vcpu, instruction);
 
-       return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
+       return emulator_write_emulated(ctxt, rip, instruction, 3,
+               &ctxt->exception);
 }
 
 static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
index ea9c49adaa1fce1f6cbf3962800e0b24bdf72c91..8aa6bea1cd6cc467cd5d39dbcde7d625c009495c 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/debugfs.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 
 #include <asm/pgtable.h>
@@ -406,6 +407,7 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
                } else
                        note_page(m, &st, __pgprot(0), 1);
 
+               cond_resched();
                start++;
        }
 
index 324e5713d386f0ed235b0394f71c0290df870fae..af59f808742f94df84ab0aaed1ac2db3ea27e016 100644 (file)
@@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs)
         * We were not able to extract an address from the instruction,
         * probably because there was something invalid in it.
         */
-       if (info->si_addr == (void *)-1) {
+       if (info->si_addr == (void __user *)-1) {
                err = -EINVAL;
                goto err_out;
        }
index e76d1af60f7ad76a12fa4f01cf61b3c508ae0453..bb660e53cbd6ba51eace412622fdd7342939ddc1 100644 (file)
@@ -1172,6 +1172,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                set_memory_ro((unsigned long)header, header->pages);
                prog->bpf_func = (void *)image;
                prog->jited = 1;
+       } else {
+               prog = orig_prog;
        }
 
 out_addrs:
index 3cd69832d7f4c6f3743bbb3a190c39672c89461d..3961103e91760a14d24eec1ad3caffa5ad1f2adb 100644 (file)
@@ -114,6 +114,16 @@ static const struct dmi_system_id pci_crs_quirks[] __initconst = {
                        DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
                },
        },
+       /* https://bugzilla.kernel.org/show_bug.cgi?id=42606 */
+       {
+               .callback = set_nouse_crs,
+               .ident = "Supermicro X8DTH",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X8DTH-i/6/iF/6F"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "2.0a"),
+               },
+       },
 
        /* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
        {
index 936a488d6cf6df3c2aadbbdbc036b8eb06701cb0..274dfc48184977db435a9c5c78607cd8a182067c 100644 (file)
@@ -210,6 +210,70 @@ int __init efi_memblock_x86_reserve_range(void)
        return 0;
 }
 
+#define OVERFLOW_ADDR_SHIFT    (64 - EFI_PAGE_SHIFT)
+#define OVERFLOW_ADDR_MASK     (U64_MAX << OVERFLOW_ADDR_SHIFT)
+#define U64_HIGH_BIT           (~(U64_MAX >> 1))
+
+static bool __init efi_memmap_entry_valid(const efi_memory_desc_t *md, int i)
+{
+       u64 end = (md->num_pages << EFI_PAGE_SHIFT) + md->phys_addr - 1;
+       u64 end_hi = 0;
+       char buf[64];
+
+       if (md->num_pages == 0) {
+               end = 0;
+       } else if (md->num_pages > EFI_PAGES_MAX ||
+                  EFI_PAGES_MAX - md->num_pages <
+                  (md->phys_addr >> EFI_PAGE_SHIFT)) {
+               end_hi = (md->num_pages & OVERFLOW_ADDR_MASK)
+                       >> OVERFLOW_ADDR_SHIFT;
+
+               if ((md->phys_addr & U64_HIGH_BIT) && !(end & U64_HIGH_BIT))
+                       end_hi += 1;
+       } else {
+               return true;
+       }
+
+       pr_warn_once(FW_BUG "Invalid EFI memory map entries:\n");
+
+       if (end_hi) {
+               pr_warn("mem%02u: %s range=[0x%016llx-0x%llx%016llx] (invalid)\n",
+                       i, efi_md_typeattr_format(buf, sizeof(buf), md),
+                       md->phys_addr, end_hi, end);
+       } else {
+               pr_warn("mem%02u: %s range=[0x%016llx-0x%016llx] (invalid)\n",
+                       i, efi_md_typeattr_format(buf, sizeof(buf), md),
+                       md->phys_addr, end);
+       }
+       return false;
+}
+
+static void __init efi_clean_memmap(void)
+{
+       efi_memory_desc_t *out = efi.memmap.map;
+       const efi_memory_desc_t *in = out;
+       const efi_memory_desc_t *end = efi.memmap.map_end;
+       int i, n_removal;
+
+       for (i = n_removal = 0; in < end; i++) {
+               if (efi_memmap_entry_valid(in, i)) {
+                       if (out != in)
+                               memcpy(out, in, efi.memmap.desc_size);
+                       out = (void *)out + efi.memmap.desc_size;
+               } else {
+                       n_removal++;
+               }
+               in = (void *)in + efi.memmap.desc_size;
+       }
+
+       if (n_removal > 0) {
+               u64 size = efi.memmap.nr_map - n_removal;
+
+               pr_warn("Removing %d invalid memory map entries.\n", n_removal);
+               efi_memmap_install(efi.memmap.phys_map, size);
+       }
+}
+
 void __init efi_print_memmap(void)
 {
        efi_memory_desc_t *md;
@@ -472,6 +536,8 @@ void __init efi_init(void)
                }
        }
 
+       efi_clean_memmap();
+
        if (efi_enabled(EFI_DBG))
                efi_print_memmap();
 }
index 319148bd4b05091d24576a7535b10aad7bec0c2d..2f25a363068cf9723e8b418e8c1942a6d3ca4029 100644 (file)
@@ -268,6 +268,22 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
 
        efi_scratch.use_pgd = true;
 
+       /*
+        * Certain firmware versions are way too sentimential and still believe
+        * they are exclusive and unquestionable owners of the first physical page,
+        * even though they explicitly mark it as EFI_CONVENTIONAL_MEMORY
+        * (but then write-access it later during SetVirtualAddressMap()).
+        *
+        * Create a 1:1 mapping for this page, to avoid triple faults during early
+        * boot with such firmware. We are free to hand this page to the BIOS,
+        * as trim_bios_range() will reserve the first page and isolate it away
+        * from memory allocators anyway.
+        */
+       if (kernel_map_pages_in_pgd(pgd, 0x0, 0x0, 1, _PAGE_RW)) {
+               pr_err("Failed to create 1:1 mapping for the first page!\n");
+               return 1;
+       }
+
        /*
         * When making calls to the firmware everything needs to be 1:1
         * mapped and addressable with 32-bit pointers. Map the kernel
index 10aca63a50d7bbff9fa94dec60e0df00591ccbd5..30031d5293c483202c526d5045cda23be6617359 100644 (file)
@@ -214,7 +214,7 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
 
        new_size = efi.memmap.desc_size * num_entries;
 
-       new_phys = memblock_alloc(new_size, 0);
+       new_phys = efi_memmap_alloc(num_entries);
        if (!new_phys) {
                pr_err("Could not allocate boot services memmap\n");
                return;
@@ -355,7 +355,7 @@ void __init efi_free_boot_services(void)
        }
 
        new_size = efi.memmap.desc_size * num_entries;
-       new_phys = memblock_alloc(new_size, 0);
+       new_phys = efi_memmap_alloc(num_entries);
        if (!new_phys) {
                pr_err("Failed to allocate new EFI memmap\n");
                return;
index 61b5ed2b7d400339053d933d82c3938c94bbc766..90e4f2a6625b6ae2a87cf7c5ec9792a5459cd0e1 100644 (file)
@@ -15,7 +15,7 @@ obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o
 obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
 obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
 # SPI Devices
-obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_spidev.o
+obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_mrfld_spidev.o
 # I2C Devices
 obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
 obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c b/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c
new file mode 100644 (file)
index 0000000..27186ad
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * spidev platform data initilization file
+ *
+ * (C) Copyright 2014, 2016 Intel Corporation
+ * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *         Dan O'Donovan <dan@emutex.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; version 2
+ * of the License.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/spi.h>
+
+#include <asm/intel-mid.h>
+
+#define MRFLD_SPI_DEFAULT_DMA_BURST    8
+#define MRFLD_SPI_DEFAULT_TIMEOUT      500
+
+/* GPIO pin for spidev chipselect */
+#define MRFLD_SPIDEV_GPIO_CS           111
+
+static struct pxa2xx_spi_chip spidev_spi_chip = {
+       .dma_burst_size         = MRFLD_SPI_DEFAULT_DMA_BURST,
+       .timeout                = MRFLD_SPI_DEFAULT_TIMEOUT,
+       .gpio_cs                = MRFLD_SPIDEV_GPIO_CS,
+};
+
+static void __init *spidev_platform_data(void *info)
+{
+       struct spi_board_info *spi_info = info;
+
+       if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
+               return ERR_PTR(-ENODEV);
+
+       spi_info->mode = SPI_MODE_0;
+       spi_info->controller_data = &spidev_spi_chip;
+
+       return NULL;
+}
+
+static const struct devs_id spidev_dev_id __initconst = {
+       .name                   = "spidev",
+       .type                   = SFI_DEV_TYPE_SPI,
+       .delay                  = 0,
+       .get_platform_data      = &spidev_platform_data,
+};
+
+sfi_device(spidev_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_spidev.c b/arch/x86/platform/intel-mid/device_libs/platform_spidev.c
deleted file mode 100644 (file)
index 30c601b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * spidev platform data initilization file
- *
- * (C) Copyright 2014, 2016 Intel Corporation
- * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
- *         Dan O'Donovan <dan@emutex.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; version 2
- * of the License.
- */
-
-#include <linux/init.h>
-#include <linux/sfi.h>
-#include <linux/spi/pxa2xx_spi.h>
-#include <linux/spi/spi.h>
-
-#include <asm/intel-mid.h>
-
-#define MRFLD_SPI_DEFAULT_DMA_BURST    8
-#define MRFLD_SPI_DEFAULT_TIMEOUT      500
-
-/* GPIO pin for spidev chipselect */
-#define MRFLD_SPIDEV_GPIO_CS           111
-
-static struct pxa2xx_spi_chip spidev_spi_chip = {
-       .dma_burst_size         = MRFLD_SPI_DEFAULT_DMA_BURST,
-       .timeout                = MRFLD_SPI_DEFAULT_TIMEOUT,
-       .gpio_cs                = MRFLD_SPIDEV_GPIO_CS,
-};
-
-static void __init *spidev_platform_data(void *info)
-{
-       struct spi_board_info *spi_info = info;
-
-       spi_info->mode = SPI_MODE_0;
-       spi_info->controller_data = &spidev_spi_chip;
-
-       return NULL;
-}
-
-static const struct devs_id spidev_dev_id __initconst = {
-       .name                   = "spidev",
-       .type                   = SFI_DEV_TYPE_SPI,
-       .delay                  = 0,
-       .get_platform_data      = &spidev_platform_data,
-};
-
-sfi_device(spidev_dev_id);
index a9fafb5c873897eec1685861180cf4ac5fd826e3..a0b36a9d5df149e6370fb3b6be0d5894bae72bd7 100644 (file)
@@ -48,7 +48,7 @@ int __init pci_xen_swiotlb_detect(void)
         * activate this IOMMU. If running as PV privileged, activate it
         * irregardless.
         */
-       if ((xen_initial_domain() || swiotlb || swiotlb_force))
+       if (xen_initial_domain() || swiotlb || swiotlb_force == SWIOTLB_FORCE)
                xen_swiotlb = 1;
 
        /* If we are running under Xen, we MUST disable the native SWIOTLB.
index 8c394e30e5fe2afcafa32b8e7fee658b5b1c27f3..f3f7b41116f7afcd3a37880d6e814b67cac0f005 100644 (file)
@@ -713,10 +713,9 @@ static void __init xen_reserve_xen_mfnlist(void)
                size = PFN_PHYS(xen_start_info->nr_p2m_frames);
        }
 
-       if (!xen_is_e820_reserved(start, size)) {
-               memblock_reserve(start, size);
+       memblock_reserve(start, size);
+       if (!xen_is_e820_reserved(start, size))
                return;
-       }
 
 #ifdef CONFIG_X86_32
        /*
@@ -727,6 +726,7 @@ static void __init xen_reserve_xen_mfnlist(void)
        BUG();
 #else
        xen_relocate_p2m();
+       memblock_free(start, size);
 #endif
 }
 
index 848e8568fb3c4a90c2eb89783c0420f8b5526cd6..8fd4be610607c2683b16a3e0da4249f4aea732e4 100644 (file)
@@ -419,7 +419,7 @@ subsys_initcall(topology_init);
 
 void cpu_reset(void)
 {
-#if XCHAL_HAVE_PTP_MMU
+#if XCHAL_HAVE_PTP_MMU && IS_ENABLED(CONFIG_MMU)
        local_irq_disable();
        /*
         * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must
index ed89c8f4b2a0497af0e45f075e4781dbb5cf87d2..ed1e78e24db0053e993555e14bf730c1cfb868c2 100644 (file)
@@ -301,23 +301,11 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
        if ((sector | nr_sects) & bs_mask)
                return -EINVAL;
 
-       if (discard) {
-               ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
-                               BLKDEV_DISCARD_ZERO, biop);
-               if (ret == 0 || (ret && ret != -EOPNOTSUPP))
-                       goto out;
-       }
-
        ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
                        biop);
        if (ret == 0 || (ret && ret != -EOPNOTSUPP))
                goto out;
 
-       ret = __blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
-                       ZERO_PAGE(0), biop);
-       if (ret == 0 || (ret && ret != -EOPNOTSUPP))
-               goto out;
-
        ret = 0;
        while (nr_sects != 0) {
                bio = next_bio(bio, min(nr_sects, (sector_t)BIO_MAX_PAGES),
@@ -370,6 +358,16 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
        struct bio *bio = NULL;
        struct blk_plug plug;
 
+       if (discard) {
+               if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
+                               BLKDEV_DISCARD_ZERO))
+                       return 0;
+       }
+
+       if (!blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
+                       ZERO_PAGE(0)))
+               return 0;
+
        blk_start_plug(&plug);
        ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
                        &bio, discard);
index a8e67a155d04f6d937e890473b1647fbe95d210f..c3400b5444a7da9842622cb4b0c94b2f1b5ddd64 100644 (file)
@@ -912,7 +912,6 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
 static void blk_mq_process_rq_list(struct blk_mq_hw_ctx *hctx)
 {
        LIST_HEAD(rq_list);
-       LIST_HEAD(driver_list);
 
        if (unlikely(blk_mq_hctx_stopped(hctx)))
                return;
index 472211fa183a6488ef93676a2f89b2f345947c9a..3bd15d8095b101233455d7985b834f828d89be92 100644 (file)
@@ -16,7 +16,7 @@
 static inline sector_t blk_zone_start(struct request_queue *q,
                                      sector_t sector)
 {
-       sector_t zone_mask = blk_queue_zone_size(q) - 1;
+       sector_t zone_mask = blk_queue_zone_sectors(q) - 1;
 
        return sector & ~zone_mask;
 }
@@ -222,7 +222,7 @@ int blkdev_reset_zones(struct block_device *bdev,
                return -EINVAL;
 
        /* Check alignment (handle eventual smaller last zone) */
-       zone_sectors = blk_queue_zone_size(q);
+       zone_sectors = blk_queue_zone_sectors(q);
        if (sector & (zone_sectors - 1))
                return -EINVAL;
 
index c73a6fcaeb9d52c7e2aa1ebbcf725e86cdc707f4..838f07e2b64a207c0f4d46477a4ffb81d0e4a60b 100644 (file)
@@ -3758,7 +3758,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 }
 
 #ifdef CONFIG_CFQ_GROUP_IOSCHED
-static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
+static bool check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
 {
        struct cfq_data *cfqd = cic_to_cfqd(cic);
        struct cfq_queue *cfqq;
@@ -3775,15 +3775,7 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
         * spuriously on a newly created cic but there's no harm.
         */
        if (unlikely(!cfqd) || likely(cic->blkcg_serial_nr == serial_nr))
-               return;
-
-       /*
-        * If we have a non-root cgroup, we can depend on that to
-        * do proper throttling of writes. Turn off wbt for that
-        * case, if it was enabled by default.
-        */
-       if (nonroot_cg)
-               wbt_disable_default(cfqd->queue);
+               return nonroot_cg;
 
        /*
         * Drop reference to queues.  New queues will be assigned in new
@@ -3804,9 +3796,13 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
        }
 
        cic->blkcg_serial_nr = serial_nr;
+       return nonroot_cg;
 }
 #else
-static inline void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio) { }
+static inline bool check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio)
+{
+       return false;
+}
 #endif  /* CONFIG_CFQ_GROUP_IOSCHED */
 
 static struct cfq_queue **
@@ -4448,11 +4444,12 @@ cfq_set_request(struct request_queue *q, struct request *rq, struct bio *bio,
        const int rw = rq_data_dir(rq);
        const bool is_sync = rq_is_sync(rq);
        struct cfq_queue *cfqq;
+       bool disable_wbt;
 
        spin_lock_irq(q->queue_lock);
 
        check_ioprio_changed(cic, bio);
-       check_blkcg_changed(cic, bio);
+       disable_wbt = check_blkcg_changed(cic, bio);
 new_queue:
        cfqq = cic_to_cfqq(cic, is_sync);
        if (!cfqq || cfqq == &cfqd->oom_cfqq) {
@@ -4488,6 +4485,10 @@ new_queue:
        rq->elv.priv[0] = cfqq;
        rq->elv.priv[1] = cfqq->cfqg;
        spin_unlock_irq(q->queue_lock);
+
+       if (disable_wbt)
+               wbt_disable_default(q);
+
        return 0;
 }
 
index d7beb6bbbf668fe62083cece4d7a6cb1eafe9443..7afb9907821fb7abe61d76ac1f3ce408bb14dbd5 100644 (file)
@@ -434,7 +434,7 @@ static bool part_zone_aligned(struct gendisk *disk,
                              struct block_device *bdev,
                              sector_t from, sector_t size)
 {
-       unsigned int zone_size = bdev_zone_size(bdev);
+       unsigned int zone_sectors = bdev_zone_sectors(bdev);
 
        /*
         * If this function is called, then the disk is a zoned block device
@@ -446,7 +446,7 @@ static bool part_zone_aligned(struct gendisk *disk,
         * regular block devices (no zone operation) and their zone size will
         * be reported as 0. Allow this case.
         */
-       if (!zone_size)
+       if (!zone_sectors)
                return true;
 
        /*
@@ -455,24 +455,24 @@ static bool part_zone_aligned(struct gendisk *disk,
         * use it. Check the zone size too: it should be a power of 2 number
         * of sectors.
         */
-       if (WARN_ON_ONCE(!is_power_of_2(zone_size))) {
+       if (WARN_ON_ONCE(!is_power_of_2(zone_sectors))) {
                u32 rem;
 
-               div_u64_rem(from, zone_size, &rem);
+               div_u64_rem(from, zone_sectors, &rem);
                if (rem)
                        return false;
                if ((from + size) < get_capacity(disk)) {
-                       div_u64_rem(size, zone_size, &rem);
+                       div_u64_rem(size, zone_sectors, &rem);
                        if (rem)
                                return false;
                }
 
        } else {
 
-               if (from & (zone_size - 1))
+               if (from & (zone_sectors - 1))
                        return false;
                if ((from + size) < get_capacity(disk) &&
-                   (size & (zone_size - 1)))
+                   (size & (zone_sectors - 1)))
                        return false;
 
        }
index df939b54b09f731eac02657957f3f573c51a1ec5..1fad2a6b3bbbf0d1d4ee07f585bdc4d501467b5d 100644 (file)
@@ -356,6 +356,7 @@ int crypto_register_alg(struct crypto_alg *alg)
        struct crypto_larval *larval;
        int err;
 
+       alg->cra_flags &= ~CRYPTO_ALG_DEAD;
        err = crypto_check_alg(alg);
        if (err)
                return err;
index f849311e9fd4c94e57d81ba97279ec5fb0cb0ded..533265f110e0297b9fc1e14a7a215a54d634b8d8 100644 (file)
@@ -661,9 +661,9 @@ static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
 unlock:
        list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) {
                af_alg_free_sg(&rsgl->sgl);
+               list_del(&rsgl->list);
                if (rsgl != &ctx->first_rsgl)
                        sock_kfree_s(sk, rsgl, sizeof(*rsgl));
-               list_del(&rsgl->list);
        }
        INIT_LIST_HEAD(&ctx->list);
        aead_wmem_wakeup(sk);
index 13caebd679f5b07503941f1023cf468901aeec36..8c4e0a18460a78df600067da69537e6256d6bc1c 100644 (file)
@@ -114,7 +114,7 @@ void __init acpi_watchdog_init(void)
        pdev = platform_device_register_simple("wdat_wdt", PLATFORM_DEVID_NONE,
                                               resources, nresources);
        if (IS_ERR(pdev))
-               pr_err("Failed to create platform device\n");
+               pr_err("Device creation failed: %ld\n", PTR_ERR(pdev));
 
        kfree(resources);
 
index 82b0b571097960919ce6ed36a703402422ac3cc7..b0399e8f6d27df774b175cb2a3aa7c8f3cce7189 100644 (file)
@@ -852,23 +852,18 @@ acpi_tb_install_and_load_table(acpi_physical_address address,
 
        ACPI_FUNCTION_TRACE(tb_install_and_load_table);
 
-       (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
-
        /* Install the table and load it into the namespace */
 
        status = acpi_tb_install_standard_table(address, flags, TRUE,
                                                override, &i);
        if (ACPI_FAILURE(status)) {
-               goto unlock_and_exit;
+               goto exit;
        }
 
-       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
        status = acpi_tb_load_table(i, acpi_gbl_root_node);
-       (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
-unlock_and_exit:
+exit:
        *table_index = i;
-       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
        return_ACPI_STATUS(status);
 }
 
index 5fdf251a9f9797a2a00f479880d6449dfa6dd940..01e1b3d63fc0dc8ae0e0b17767dae535be2bec68 100644 (file)
@@ -217,6 +217,10 @@ acpi_tb_install_standard_table(acpi_physical_address address,
                goto release_and_exit;
        }
 
+       /* Acquire the table lock */
+
+       (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
        if (reload) {
                /*
                 * Validate the incoming table signature.
@@ -244,7 +248,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
                                         new_table_desc.signature.integer));
 
                        status = AE_BAD_SIGNATURE;
-                       goto release_and_exit;
+                       goto unlock_and_exit;
                }
 
                /* Check if table is already registered */
@@ -279,7 +283,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
                                /* Table is still loaded, this is an error */
 
                                status = AE_ALREADY_EXISTS;
-                               goto release_and_exit;
+                               goto unlock_and_exit;
                        } else {
                                /*
                                 * Table was unloaded, allow it to be reloaded.
@@ -290,6 +294,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
                                 * indicate the re-installation.
                                 */
                                acpi_tb_uninstall_table(&new_table_desc);
+                               (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
                                *table_index = i;
                                return_ACPI_STATUS(AE_OK);
                        }
@@ -303,11 +308,19 @@ acpi_tb_install_standard_table(acpi_physical_address address,
 
        /* Invoke table handler if present */
 
+       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
        if (acpi_gbl_table_handler) {
                (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_INSTALL,
                                             new_table_desc.pointer,
                                             acpi_gbl_table_handler_context);
        }
+       (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
+unlock_and_exit:
+
+       /* Release the table lock */
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 
 release_and_exit:
 
index f8d65647ea790dd161b07221b9be2bdead4447d0..fb19e1cdb6415ac8d1913e7017106911dcb7a7dd 100644 (file)
@@ -98,7 +98,15 @@ static int find_child_checks(struct acpi_device *adev, bool check_children)
        if (check_children && list_empty(&adev->children))
                return -ENODEV;
 
-       return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
+       /*
+        * If the device has a _HID (or _CID) returning a valid ACPI/PNP
+        * device ID, it is better to make it look less attractive here, so that
+        * the other device with the same _ADR value (that may not have a valid
+        * device ID) can be matched going forward.  [This means a second spec
+        * violation in a row, so whatever we do here is best effort anyway.]
+        */
+       return sta_present && list_empty(&adev->pnp.ids) ?
+                       FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
 }
 
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
@@ -250,7 +258,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
        return 0;
 
  err:
-       acpi_dma_deconfigure(dev);
        ACPI_COMPANION_SET(dev, NULL);
        put_device(dev);
        put_device(&acpi_dev->dev);
index 1b41a2739dac1dcab72aa352e9add209b2313711..0c452265c11110213ddde5c5c4440e52d2a523a5 100644 (file)
@@ -37,6 +37,7 @@ void acpi_amba_init(void);
 static inline void acpi_amba_init(void) {}
 #endif
 int acpi_sysfs_init(void);
+void acpi_gpe_apply_masked_gpes(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
 #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
index 2f82b8eba360e7f369338b7d7a340060d6519f4f..7361d00818e2bb61f5d280c6817db2a2e8d01fc4 100644 (file)
@@ -2704,6 +2704,7 @@ 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 device *dev = acpi_desc->dev;
        struct acpi_nfit_flush_work flush;
+       int rc;
 
        /* bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
        device_lock(dev);
@@ -2716,7 +2717,10 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
        INIT_WORK_ONSTACK(&flush.work, flush_probe);
        COMPLETION_INITIALIZER_ONSTACK(flush.cmp);
        queue_work(nfit_wq, &flush.work);
-       return wait_for_completion_interruptible(&flush.cmp);
+
+       rc = wait_for_completion_interruptible(&flush.cmp);
+       cancel_work_sync(&flush.work);
+       return rc;
 }
 
 static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
index 45dec874ea55b820281457a3ae5de2fe1f12403c..192691880d55c9499e1d77e68058a56d8e5318f3 100644 (file)
@@ -2074,6 +2074,7 @@ int __init acpi_scan_init(void)
                }
        }
 
+       acpi_gpe_apply_masked_gpes();
        acpi_update_all_gpes();
        acpi_ec_ecdt_start();
 
index 9b6cebe227a08562985ce304463dcbe1f1ee1154..54abb26b736639ca54aa7051ae742d6657a501bc 100644 (file)
@@ -674,14 +674,6 @@ static void acpi_sleep_suspend_setup(void)
                if (acpi_sleep_state_supported(i))
                        sleep_states[i] = 1;
 
-       /*
-        * Use suspend-to-idle by default if ACPI_FADT_LOW_POWER_S0 is set and
-        * the default suspend mode was not selected from the command line.
-        */
-       if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0 &&
-           mem_sleep_default > PM_SUSPEND_MEM)
-               mem_sleep_default = PM_SUSPEND_FREEZE;
-
        suspend_set_ops(old_suspend_ordering ?
                &acpi_suspend_ops_old : &acpi_suspend_ops);
        freeze_set_ops(&acpi_freeze_ops);
index 703c26e7022cbf186d9a1ed3a60cd25c6fd1c049..cf05ae973381178cc066e1c235c38afb419e1f01 100644 (file)
@@ -708,6 +708,62 @@ end:
        return result ? result : size;
 }
 
+/*
+ * A Quirk Mechanism for GPE Flooding Prevention:
+ *
+ * Quirks may be needed to prevent GPE flooding on a specific GPE. The
+ * flooding typically cannot be detected and automatically prevented by
+ * ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
+ * the AML tables. This normally indicates a feature gap in Linux, thus
+ * instead of providing endless quirk tables, we provide a boot parameter
+ * for those who want this quirk. For example, if the users want to prevent
+ * the GPE flooding for GPE 00, they need to specify the following boot
+ * parameter:
+ *   acpi_mask_gpe=0x00
+ * The masking status can be modified by the following runtime controlling
+ * interface:
+ *   echo unmask > /sys/firmware/acpi/interrupts/gpe00
+ */
+
+/*
+ * Currently, the GPE flooding prevention only supports to mask the GPEs
+ * numbered from 00 to 7f.
+ */
+#define ACPI_MASKABLE_GPE_MAX  0x80
+
+static u64 __initdata acpi_masked_gpes;
+
+static int __init acpi_gpe_set_masked_gpes(char *val)
+{
+       u8 gpe;
+
+       if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
+               return -EINVAL;
+       acpi_masked_gpes |= ((u64)1<<gpe);
+
+       return 1;
+}
+__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
+
+void __init acpi_gpe_apply_masked_gpes(void)
+{
+       acpi_handle handle;
+       acpi_status status;
+       u8 gpe;
+
+       for (gpe = 0;
+            gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
+            gpe++) {
+               if (acpi_masked_gpes & ((u64)1<<gpe)) {
+                       status = acpi_get_gpe_device(gpe, &handle);
+                       if (ACPI_SUCCESS(status)) {
+                               pr_info("Masking GPE 0x%x.\n", gpe);
+                               (void)acpi_mask_gpe(handle, gpe, TRUE);
+                       }
+               }
+       }
+}
+
 void acpi_irq_stats_init(void)
 {
        acpi_status status;
index 02ded25c82e4a06e1e79bf2f0a4855aa933b3df1..7f48156cbc0c0b47a22943b60bf374d8a86ea6e3 100644 (file)
@@ -305,17 +305,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
                },
        },
-       {
-       /* https://bugzilla.redhat.com/show_bug.cgi?id=1204476 */
-       /* https://bugs.launchpad.net/ubuntu/+source/linux-lts-trusty/+bug/1416940 */
-       .callback = video_detect_force_native,
-       .ident = "HP Pavilion dv6",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6 Notebook PC"),
-               },
-       },
-
        { },
 };
 
index 9cd0a2d4181699d94f73f2af82490e59f23373e2..c2d3785ec2279f42013cdc4816beb60785279d95 100644 (file)
@@ -1702,6 +1702,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
 
                if (qc->err_mask & ~AC_ERR_OTHER)
                        qc->err_mask &= ~AC_ERR_OTHER;
+       } else if (qc->tf.command == ATA_CMD_REQ_SENSE_DATA) {
+               qc->result_tf.command |= ATA_SENSE;
        }
 
        /* finish up */
@@ -4356,10 +4358,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "ST380013AS",         "3.20",         ATA_HORKAGE_MAX_SEC_1024 },
 
        /*
-        * Device times out with higher max sects.
+        * These devices time out with higher max sects.
         * https://bugzilla.kernel.org/show_bug.cgi?id=121671
         */
-       { "LITEON CX1-JB256-HP", NULL,          ATA_HORKAGE_MAX_SEC_1024 },
+       { "LITEON CX1-JB*-HP",  NULL,           ATA_HORKAGE_MAX_SEC_1024 },
 
        /* Devices we expect to fail diagnostics */
 
index 823e938c9a7877a1cadefde9127d447832630061..2f32782cea6d9c584797d1f7d9dc8e99eac0b796 100644 (file)
@@ -4132,6 +4132,9 @@ static int mv_platform_probe(struct platform_device *pdev)
        host->iomap = NULL;
        hpriv->base = devm_ioremap(&pdev->dev, res->start,
                                   resource_size(res));
+       if (!hpriv->base)
+               return -ENOMEM;
+
        hpriv->base -= SATAHC0_REG_BASE;
 
        hpriv->clk = clk_get(&pdev->dev, NULL);
index 4ef4c5caed4f57bece96aa4efdae4a2ea34313f1..8a8e403644d6e0d6ce838105dfceb30ae5625460 100644 (file)
@@ -132,9 +132,9 @@ config HT16K33
        tristate "Holtek Ht16K33 LED controller with keyscan"
        depends on FB && OF && I2C && INPUT
        select FB_SYS_FOPS
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
        select INPUT_MATRIXKMAP
        select FB_BACKLIGHT
        help
index ada9dce34e6d8a8373d3d08d5c28b3f6b55ac427..e19b1008e5fb08b1099e5f5d8f0dc86dfc24bde5 100644 (file)
@@ -141,8 +141,6 @@ extern void device_unblock_probing(void);
 extern struct kset *devices_kset;
 extern void devices_kset_move_last(struct device *dev);
 
-extern struct device_attribute dev_attr_deferred_probe;
-
 #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
 extern void module_add_driver(struct module *mod, struct device_driver *drv);
 extern void module_remove_driver(struct device_driver *drv);
index 020ea7f0552073c62c91e55d62e0c0151917251e..8c25e68e67d7354005dc81a92342eb10519449ed 100644 (file)
@@ -1060,14 +1060,8 @@ static int device_add_attrs(struct device *dev)
                        goto err_remove_dev_groups;
        }
 
-       error = device_create_file(dev, &dev_attr_deferred_probe);
-       if (error)
-               goto err_remove_online;
-
        return 0;
 
- err_remove_online:
-       device_remove_file(dev, &dev_attr_online);
  err_remove_dev_groups:
        device_remove_groups(dev, dev->groups);
  err_remove_type_groups:
@@ -1085,7 +1079,6 @@ static void device_remove_attrs(struct device *dev)
        struct class *class = dev->class;
        const struct device_type *type = dev->type;
 
-       device_remove_file(dev, &dev_attr_deferred_probe);
        device_remove_file(dev, &dev_attr_online);
        device_remove_groups(dev, dev->groups);
 
index a8b258e5407bae02c48b03b39941ee238c22a2e3..a1fbf55c4d3abbea786ef5585b96d769ca3a144a 100644 (file)
@@ -53,19 +53,6 @@ static LIST_HEAD(deferred_probe_pending_list);
 static LIST_HEAD(deferred_probe_active_list);
 static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
 
-static ssize_t deferred_probe_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       bool value;
-
-       mutex_lock(&deferred_probe_mutex);
-       value = !list_empty(&dev->p->deferred_probe);
-       mutex_unlock(&deferred_probe_mutex);
-
-       return sprintf(buf, "%d\n", value);
-}
-DEVICE_ATTR_RO(deferred_probe);
-
 /*
  * In some cases, like suspend to RAM or hibernation, It might be reasonable
  * to prohibit probing of devices as it could be unsafe.
index 4497d263209fb861e08e1650ddf654a98f2102e3..ac350c518e0c9479c05c4d9ff9f6ae918f26b96c 100644 (file)
@@ -558,9 +558,6 @@ static void fw_load_abort(struct firmware_priv *fw_priv)
        struct firmware_buf *buf = fw_priv->buf;
 
        __fw_load_abort(buf);
-
-       /* avoid user action after loading abort */
-       fw_priv->buf = NULL;
 }
 
 static LIST_HEAD(pending_fw_head);
@@ -713,7 +710,7 @@ static ssize_t firmware_loading_store(struct device *dev,
 
        mutex_lock(&fw_lock);
        fw_buf = fw_priv->buf;
-       if (!fw_buf)
+       if (fw_state_is_aborted(&fw_buf->fw_st))
                goto out;
 
        switch (loading) {
index 8ab8ea1253e62310a68d9e6bf039d8d866ee4019..fa26ffd25fa61bae95bd441699a54ee8e16818d2 100644 (file)
@@ -389,33 +389,33 @@ static ssize_t show_valid_zones(struct device *dev,
 {
        struct memory_block *mem = to_memory_block(dev);
        unsigned long start_pfn, end_pfn;
+       unsigned long valid_start, valid_end, valid_pages;
        unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-       struct page *first_page;
        struct zone *zone;
        int zone_shift = 0;
 
        start_pfn = section_nr_to_pfn(mem->start_section_nr);
        end_pfn = start_pfn + nr_pages;
-       first_page = pfn_to_page(start_pfn);
 
        /* The block contains more than one zone can not be offlined. */
-       if (!test_pages_in_a_zone(start_pfn, end_pfn))
+       if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
                return sprintf(buf, "none\n");
 
-       zone = page_zone(first_page);
+       zone = page_zone(pfn_to_page(valid_start));
+       valid_pages = valid_end - valid_start;
 
        /* MMOP_ONLINE_KEEP */
        sprintf(buf, "%s", zone->name);
 
        /* MMOP_ONLINE_KERNEL */
-       zone_shift = zone_can_shift(start_pfn, nr_pages, ZONE_NORMAL);
+       zone_can_shift(valid_start, valid_pages, ZONE_NORMAL, &zone_shift);
        if (zone_shift) {
                strcat(buf, " ");
                strcat(buf, (zone + zone_shift)->name);
        }
 
        /* MMOP_ONLINE_MOVABLE */
-       zone_shift = zone_can_shift(start_pfn, nr_pages, ZONE_MOVABLE);
+       zone_can_shift(valid_start, valid_pages, ZONE_MOVABLE, &zone_shift);
        if (zone_shift) {
                strcat(buf, " ");
                strcat(buf, (zone + zone_shift)->name);
index a5e1262b964b8f987480152cb5feb0dbc9d81e47..2997026b4dfb00c1daec88f1f18264656a61ffb0 100644 (file)
@@ -626,6 +626,7 @@ static int genpd_runtime_resume(struct device *dev)
 
  out:
        /* Measure resume latency. */
+       time_start = 0;
        if (timed && runtime_pm)
                time_start = ktime_get();
 
index 872eac4cb1dfdcd069136856e681f741332708e2..a14fac6a01d316a0249fdd45de3e676e0dffed7c 100644 (file)
@@ -966,13 +966,13 @@ int __pm_runtime_idle(struct device *dev, int rpmflags)
        unsigned long flags;
        int retval;
 
-       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
-
        if (rpmflags & RPM_GET_PUT) {
                if (!atomic_dec_and_test(&dev->power.usage_count))
                        return 0;
        }
 
+       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
        spin_lock_irqsave(&dev->power.lock, flags);
        retval = rpm_idle(dev, rpmflags);
        spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -998,13 +998,13 @@ int __pm_runtime_suspend(struct device *dev, int rpmflags)
        unsigned long flags;
        int retval;
 
-       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
-
        if (rpmflags & RPM_GET_PUT) {
                if (!atomic_dec_and_test(&dev->power.usage_count))
                        return 0;
        }
 
+       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
        spin_lock_irqsave(&dev->power.lock, flags);
        retval = rpm_suspend(dev, rpmflags);
        spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -1029,7 +1029,8 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
        unsigned long flags;
        int retval;
 
-       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+       might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
+                       dev->power.runtime_status != RPM_ACTIVE);
 
        if (rpmflags & RPM_GET_PUT)
                atomic_inc(&dev->power.usage_count);
index f642c4264c277bc05d98dc99eb15ac8091886ba5..168fa175d65a08319f5e92ad10f8f5ff4baea54a 100644 (file)
@@ -45,6 +45,9 @@ int bcma_sprom_get(struct bcma_bus *bus);
 void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
 void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
 void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
 
 /* driver_chipcommon_b.c */
 int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb);
index b4f6520e74f05b8b7a0c1ec710042c0f38a02d7d..62f5bfa5065d919ee3acd9e596373923070e574a 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
 
-static void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
-
 static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
                                         u32 mask, u32 value)
 {
@@ -186,9 +184,6 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
        if (cc->capabilities & BCMA_CC_CAP_PMU)
                bcma_pmu_early_init(cc);
 
-       if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC)
-               bcma_chipco_serial_init(cc);
-
        if (bus->hosttype == BCMA_HOSTTYPE_SOC)
                bcma_core_chipcommon_flash_detect(cc);
 
@@ -378,9 +373,9 @@ u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
        return res;
 }
 
-static void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
 {
-#if IS_BUILTIN(CONFIG_BCM47XX)
        unsigned int irq;
        u32 baud_base;
        u32 i;
@@ -422,5 +417,5 @@ static void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
                ports[i].baud_base = baud_base;
                ports[i].reg_shift = 0;
        }
-#endif /* CONFIG_BCM47XX */
 }
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
index 96f17132820080843e9216523bc1328b2f8f7939..89af807cf29ce49e38f60e9e1c3e177ceb0e261a 100644 (file)
@@ -278,9 +278,12 @@ static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore)
 
 void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
 {
+       struct bcma_bus *bus = mcore->core->bus;
+
        if (mcore->early_setup_done)
                return;
 
+       bcma_chipco_serial_init(&bus->drv_cc);
        bcma_core_mips_nvram_init(mcore);
 
        mcore->early_setup_done = true;
index 38c576f76d36fca1f43bc37b6c733ba6bb222849..9fd06eeb1a17b3880e2ad574f4ca081903a67961 100644 (file)
@@ -271,7 +271,7 @@ static inline int sock_send_bvec(struct nbd_device *nbd, int index,
 static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 {
        struct request *req = blk_mq_rq_from_pdu(cmd);
-       int result, flags;
+       int result;
        struct nbd_request request;
        unsigned long size = blk_rq_bytes(req);
        struct bio *bio;
@@ -310,7 +310,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
        if (type != NBD_CMD_WRITE)
                return 0;
 
-       flags = 0;
        bio = req->bio;
        while (bio) {
                struct bio *next = bio->bi_next;
@@ -319,9 +318,8 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 
                bio_for_each_segment(bvec, bio, iter) {
                        bool is_last = !next && bio_iter_last(bvec, iter);
+                       int flags = is_last ? 0 : MSG_MORE;
 
-                       if (is_last)
-                               flags = MSG_MORE;
                        dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
                                cmd, bvec.bv_len);
                        result = sock_send_bvec(nbd, index, &bvec, flags);
@@ -1042,6 +1040,7 @@ static int __init nbd_init(void)
                return -ENOMEM;
 
        for (i = 0; i < nbds_max; i++) {
+               struct request_queue *q;
                struct gendisk *disk = alloc_disk(1 << part_shift);
                if (!disk)
                        goto out;
@@ -1067,12 +1066,13 @@ static int __init nbd_init(void)
                 * every gendisk to have its very own request_queue struct.
                 * These structs are big so we dynamically allocate them.
                 */
-               disk->queue = blk_mq_init_queue(&nbd_dev[i].tag_set);
-               if (!disk->queue) {
+               q = blk_mq_init_queue(&nbd_dev[i].tag_set);
+               if (IS_ERR(q)) {
                        blk_mq_free_tag_set(&nbd_dev[i].tag_set);
                        put_disk(disk);
                        goto out;
                }
+               disk->queue = q;
 
                /*
                 * Tell the block layer that we are not a rotational device
index 5545a679abd8887123fc83d57beb37dede77a685..10332c24f9610d7e80b154bf36eebb0354ac4576 100644 (file)
@@ -56,6 +56,7 @@ struct virtblk_req {
        struct virtio_blk_outhdr out_hdr;
        struct virtio_scsi_inhdr in_hdr;
        u8 status;
+       u8 sense[SCSI_SENSE_BUFFERSIZE];
        struct scatterlist sg[];
 };
 
@@ -102,7 +103,8 @@ static int __virtblk_add_req(struct virtqueue *vq,
        }
 
        if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
-               sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
+               memcpy(vbr->sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
+               sg_init_one(&sense, vbr->sense, SCSI_SENSE_BUFFERSIZE);
                sgs[num_out + num_in++] = &sense;
                sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
                sgs[num_out + num_in++] = &inhdr;
@@ -628,11 +630,12 @@ static int virtblk_probe(struct virtio_device *vdev)
        if (err)
                goto out_put_disk;
 
-       q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set);
+       q = blk_mq_init_queue(&vblk->tag_set);
        if (IS_ERR(q)) {
                err = -ENOMEM;
                goto out_free_tags;
        }
+       vblk->disk->queue = q;
 
        q->queuedata = vblk;
 
index b2bdfa81f9297cd588ffcb1168f7db1cd5a48228..265f1a7072e9a1fed8212520d509adaecdbef04b 100644 (file)
@@ -197,13 +197,13 @@ struct blkfront_info
        /* Number of pages per ring buffer. */
        unsigned int nr_ring_pages;
        struct request_queue *rq;
-       unsigned int feature_flush;
-       unsigned int feature_fua;
+       unsigned int feature_flush:1;
+       unsigned int feature_fua:1;
        unsigned int feature_discard:1;
        unsigned int feature_secdiscard:1;
+       unsigned int feature_persistent:1;
        unsigned int discard_granularity;
        unsigned int discard_alignment;
-       unsigned int feature_persistent:1;
        /* Number of 4KB segments handled */
        unsigned int max_indirect_segments;
        int is_ready;
@@ -2223,7 +2223,7 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
        }
        else
                grants = info->max_indirect_segments;
-       psegs = grants / GRANTS_PER_PSEG;
+       psegs = DIV_ROUND_UP(grants, GRANTS_PER_PSEG);
 
        err = fill_grant_buffer(rinfo,
                                (grants + INDIRECT_GREFS(grants)) * BLK_RING_SIZE(info));
@@ -2323,13 +2323,16 @@ static void blkfront_gather_backend_features(struct blkfront_info *info)
                blkfront_setup_discard(info);
 
        info->feature_persistent =
-               xenbus_read_unsigned(info->xbdev->otherend,
-                                    "feature-persistent", 0);
+               !!xenbus_read_unsigned(info->xbdev->otherend,
+                                      "feature-persistent", 0);
 
        indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
                                        "feature-max-indirect-segments", 0);
-       info->max_indirect_segments = min(indirect_segments,
-                                         xen_blkif_max_segments);
+       if (indirect_segments > xen_blkif_max_segments)
+               indirect_segments = xen_blkif_max_segments;
+       if (indirect_segments <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
+               indirect_segments = 0;
+       info->max_indirect_segments = indirect_segments;
 }
 
 /*
@@ -2652,6 +2655,9 @@ static int __init xlblk_init(void)
        if (!xen_domain())
                return -ENODEV;
 
+       if (xen_blkif_max_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST)
+               xen_blkif_max_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+
        if (xen_blkif_max_ring_order > XENBUS_MAX_RING_GRANT_ORDER) {
                pr_info("Invalid max_ring_order (%d), will use default max: %d.\n",
                        xen_blkif_max_ring_order, XENBUS_MAX_RING_GRANT_ORDER);
index 15f58ab44d0b429fc7b5ebf0ba7e1cdfcc6c914d..e5ab7d9e8c452f2feac3e2f374c6e1639317756b 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/genhd.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
+#include <linux/backing-dev.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/err.h>
@@ -112,6 +113,14 @@ static inline bool is_partial_io(struct bio_vec *bvec)
        return bvec->bv_len != PAGE_SIZE;
 }
 
+static void zram_revalidate_disk(struct zram *zram)
+{
+       revalidate_disk(zram->disk);
+       /* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */
+       zram->disk->queue->backing_dev_info.capabilities |=
+               BDI_CAP_STABLE_WRITES;
+}
+
 /*
  * Check if request is within bounds and aligned on zram logical blocks.
  */
@@ -1095,15 +1104,9 @@ static ssize_t disksize_store(struct device *dev,
        zram->comp = comp;
        zram->disksize = disksize;
        set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
+       zram_revalidate_disk(zram);
        up_write(&zram->init_lock);
 
-       /*
-        * Revalidate disk out of the init_lock to avoid lockdep splat.
-        * It's okay because disk's capacity is protected by init_lock
-        * so that revalidate_disk always sees up-to-date capacity.
-        */
-       revalidate_disk(zram->disk);
-
        return len;
 
 out_destroy_comp:
@@ -1149,7 +1152,7 @@ static ssize_t reset_store(struct device *dev,
        /* Make sure all the pending I/O are finished */
        fsync_bdev(bdev);
        zram_reset_device(zram);
-       revalidate_disk(zram->disk);
+       zram_revalidate_disk(zram);
        bdput(bdev);
 
        mutex_lock(&bdev->bd_mutex);
index 6ce5ce8be2f2dda80a52790ee611106097fabdbe..87fba424817e509e6d87bc931079b5a34ffcb706 100644 (file)
@@ -92,7 +92,6 @@ static void add_early_randomness(struct hwrng *rng)
        mutex_unlock(&reading_mutex);
        if (bytes_read > 0)
                add_device_randomness(rng_buffer, bytes_read);
-       memset(rng_buffer, 0, size);
 }
 
 static inline void cleanup_rng(struct kref *kref)
@@ -288,7 +287,6 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
                }
        }
 out:
-       memset(rng_buffer, 0, rng_buffer_size());
        return ret ? : err;
 
 out_unlock_reading:
@@ -427,7 +425,6 @@ static int hwrng_fillfn(void *unused)
                /* Outside lock, sure, but y'know: randomness. */
                add_hwgenerator_randomness((void *)rng_fillbuf, rc,
                                           rc * current_quality * 8 >> 10);
-               memset(rng_fillbuf, 0, rng_buffer_size());
        }
        hwrng_fill = NULL;
        return 0;
index 5bb1985ec484aef267e3c551c3068ec0dee14b1c..6d9cc2d39d22306fd68f30bac6f4a60e6cfa5a87 100644 (file)
@@ -381,9 +381,6 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
        char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
        int err = 0;
 
-       if (!pfn_valid(PFN_DOWN(p)))
-               return -EIO;
-
        read = 0;
        if (p < (unsigned long) high_memory) {
                low_count = count;
@@ -412,6 +409,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
                         * by the kernel or data corruption may occur
                         */
                        kbuf = xlate_dev_kmem_ptr((void *)p);
+                       if (!virt_addr_valid(kbuf))
+                               return -ENXIO;
 
                        if (copy_to_user(buf, kbuf, sz))
                                return -EFAULT;
@@ -482,6 +481,8 @@ static ssize_t do_write_kmem(unsigned long p, const char __user *buf,
                 * corruption may occur.
                 */
                ptr = xlate_dev_kmem_ptr((void *)p);
+               if (!virt_addr_valid(ptr))
+                       return -ENXIO;
 
                copied = copy_from_user(ptr, buf, sz);
                if (copied) {
@@ -512,9 +513,6 @@ static ssize_t write_kmem(struct file *file, const char __user *buf,
        char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
        int err = 0;
 
-       if (!pfn_valid(PFN_DOWN(p)))
-               return -EIO;
-
        if (p < (unsigned long) high_memory) {
                unsigned long to_write = min_t(unsigned long, count,
                                               (unsigned long)high_memory - p);
index 02819e0703c8eef503baf8333c88f105a591444b..87885d146dbb02ed9ed08979dda96579bd5bc652 100644 (file)
@@ -290,6 +290,7 @@ static int register_device(int minor, struct pp_struct *pp)
        struct pardevice *pdev = NULL;
        char *name;
        struct pardev_cb ppdev_cb;
+       int rc = 0;
 
        name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
        if (name == NULL)
@@ -298,8 +299,8 @@ static int register_device(int minor, struct pp_struct *pp)
        port = parport_find_number(minor);
        if (!port) {
                pr_warn("%s: no associated port!\n", name);
-               kfree(name);
-               return -ENXIO;
+               rc = -ENXIO;
+               goto err;
        }
 
        memset(&ppdev_cb, 0, sizeof(ppdev_cb));
@@ -308,16 +309,18 @@ static int register_device(int minor, struct pp_struct *pp)
        ppdev_cb.private = pp;
        pdev = parport_register_dev_model(port, name, &ppdev_cb, minor);
        parport_put_port(port);
-       kfree(name);
 
        if (!pdev) {
                pr_warn("%s: failed to register device!\n", name);
-               return -ENXIO;
+               rc = -ENXIO;
+               goto err;
        }
 
        pp->pdev = pdev;
        dev_dbg(&pdev->dev, "registered pardevice\n");
-       return 0;
+err:
+       kfree(name);
+       return rc;
 }
 
 static enum ieee1284_phase init_phase(int mode)
index 8b00e79c2683a4812126fb73c7134ea157554ef2..17857beb489294b2c1b5bbd068a18ba013ab3fae 100644 (file)
@@ -1862,7 +1862,7 @@ static void config_work_handler(struct work_struct *work)
 {
        struct ports_device *portdev;
 
-       portdev = container_of(work, struct ports_device, control_work);
+       portdev = container_of(work, struct ports_device, config_work);
        if (!use_multiport(portdev)) {
                struct virtio_device *vdev;
                struct port *port;
index 5eb05dbf59b84d27d79106adeb7405d15de1433a..fc585f370549a336ea12cc5c323dbc77aec69825 100644 (file)
@@ -768,5 +768,5 @@ fail:
        kfree(clks);
        iounmap(base);
 }
-CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
-CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
index 9375777776d994071a476d2e198be933838db685..b533f99550e1b97dd55944a85cbf5d64153309f5 100644 (file)
  * @smstpcr: module stop control register
  * @mstpsr: module stop status register (optional)
  * @lock: protects writes to SMSTPCR
+ * @width_8bit: registers are 8-bit, not 32-bit
  */
 struct mstp_clock_group {
        struct clk_onecell_data data;
        void __iomem *smstpcr;
        void __iomem *mstpsr;
        spinlock_t lock;
+       bool width_8bit;
 };
 
 /**
@@ -59,6 +61,18 @@ struct mstp_clock {
 
 #define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
 
+static inline u32 cpg_mstp_read(struct mstp_clock_group *group,
+                               u32 __iomem *reg)
+{
+       return group->width_8bit ? readb(reg) : clk_readl(reg);
+}
+
+static inline void cpg_mstp_write(struct mstp_clock_group *group, u32 val,
+                                 u32 __iomem *reg)
+{
+       group->width_8bit ? writeb(val, reg) : clk_writel(val, reg);
+}
+
 static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
 {
        struct mstp_clock *clock = to_mstp_clock(hw);
@@ -70,12 +84,12 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
 
        spin_lock_irqsave(&group->lock, flags);
 
-       value = clk_readl(group->smstpcr);
+       value = cpg_mstp_read(group, group->smstpcr);
        if (enable)
                value &= ~bitmask;
        else
                value |= bitmask;
-       clk_writel(value, group->smstpcr);
+       cpg_mstp_write(group, value, group->smstpcr);
 
        spin_unlock_irqrestore(&group->lock, flags);
 
@@ -83,7 +97,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
                return 0;
 
        for (i = 1000; i > 0; --i) {
-               if (!(clk_readl(group->mstpsr) & bitmask))
+               if (!(cpg_mstp_read(group, group->mstpsr) & bitmask))
                        break;
                cpu_relax();
        }
@@ -114,9 +128,9 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
        u32 value;
 
        if (group->mstpsr)
-               value = clk_readl(group->mstpsr);
+               value = cpg_mstp_read(group, group->mstpsr);
        else
-               value = clk_readl(group->smstpcr);
+               value = cpg_mstp_read(group, group->smstpcr);
 
        return !(value & BIT(clock->bit_index));
 }
@@ -188,6 +202,9 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
                return;
        }
 
+       if (of_device_is_compatible(np, "renesas,r7s72100-mstp-clocks"))
+               group->width_8bit = true;
+
        for (i = 0; i < MSTP_MAX_CLOCKS; ++i)
                clks[i] = ERR_PTR(-ENOENT);
 
index 8c8b495cbf0d502daa51c5c1403125b4e7ea15f3..cdc092a1d9effd7815fbd43314977059a52e0ec8 100644 (file)
@@ -586,7 +586,7 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
        GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
                                GATE_BUS_TOP, 24, 0, 0),
        GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
-                               GATE_BUS_TOP, 27, 0, 0),
+                               GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
 };
 
 static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
@@ -956,20 +956,20 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk333_g2d", GATE_IP_G2D, 7, 0, 0),
 
        GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys",
-                       GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0),
+                       GATE_BUS_FSYS0, 9, CLK_IS_CRITICAL, 0),
        GATE(0, "aclk200_fsys2", "mout_user_aclk200_fsys2",
                        GATE_BUS_FSYS0, 10, CLK_IGNORE_UNUSED, 0),
 
        GATE(0, "aclk333_g2d", "mout_user_aclk333_g2d",
                        GATE_BUS_TOP, 0, CLK_IGNORE_UNUSED, 0),
        GATE(0, "aclk266_g2d", "mout_user_aclk266_g2d",
-                       GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0),
+                       GATE_BUS_TOP, 1, CLK_IS_CRITICAL, 0),
        GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg",
                        GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0),
        GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0",
                        GATE_BUS_TOP, 5, 0, 0),
        GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl",
-                       GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0),
+                       GATE_BUS_TOP, 6, CLK_IS_CRITICAL, 0),
        GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl",
                        GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0),
        GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp",
@@ -983,20 +983,20 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = {
        GATE(0, "aclk166", "mout_user_aclk166",
                        GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK333, "aclk333", "mout_user_aclk333",
-                       GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0),
+                       GATE_BUS_TOP, 15, CLK_IS_CRITICAL, 0),
        GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
                        GATE_BUS_TOP, 16, 0, 0),
        GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl",
                        GATE_BUS_TOP, 17, 0, 0),
        GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1",
-                       GATE_BUS_TOP, 18, 0, 0),
+                       GATE_BUS_TOP, 18, CLK_IS_CRITICAL, 0),
        GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24",
                        GATE_BUS_TOP, 28, 0, 0),
        GATE(CLK_SCLK_HSIC_12M, "sclk_hsic_12m", "ff_hsic_12m",
                        GATE_BUS_TOP, 29, 0, 0),
 
        GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1",
-                       SRC_MASK_TOP2, 24, 0, 0),
+                       SRC_MASK_TOP2, 24, CLK_IS_CRITICAL, 0),
 
        GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
                        SRC_MASK_TOP7, 20, 0, 0),
index 4da1dc2278bd7fc34caa9e00d29f71ec1ebd015f..670ff0f25b6712ea8e2875a5ecc2a4c46cb1c554 100644 (file)
@@ -495,6 +495,7 @@ static int exynos4_mct_dying_cpu(unsigned int cpu)
        if (mct_int_type == MCT_INT_SPI) {
                if (evt->irq != -1)
                        disable_irq_nosync(evt->irq);
+               exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
        } else {
                disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
        }
index 4fda623e55bb728e910ac0f0995cc7d8cb34f330..c94360671f41e54db9861a8ca86a8da7ddc2e5fe 100644 (file)
@@ -784,8 +784,19 @@ static int brcm_avs_target_index(struct cpufreq_policy *policy,
 static int brcm_avs_suspend(struct cpufreq_policy *policy)
 {
        struct private_data *priv = policy->driver_data;
+       int ret;
+
+       ret = brcm_avs_get_pmap(priv, &priv->pmap);
+       if (ret)
+               return ret;
 
-       return brcm_avs_get_pmap(priv, &priv->pmap);
+       /*
+        * We can't use the P-state returned by brcm_avs_get_pmap(), since
+        * that's the initial P-state from when the P-map was downloaded to the
+        * AVS co-processor, not necessarily the P-state we are running at now.
+        * So, we get the current P-state explicitly.
+        */
+       return brcm_avs_get_pstate(priv, &priv->pmap.state);
 }
 
 static int brcm_avs_resume(struct cpufreq_policy *policy)
@@ -954,9 +965,9 @@ static ssize_t show_brcm_avs_pmap(struct cpufreq_policy *policy, char *buf)
        brcm_avs_parse_p1(pmap.p1, &mdiv_p0, &pdiv, &ndiv);
        brcm_avs_parse_p2(pmap.p2, &mdiv_p1, &mdiv_p2, &mdiv_p3, &mdiv_p4);
 
-       return sprintf(buf, "0x%08x 0x%08x %u %u %u %u %u %u %u\n",
+       return sprintf(buf, "0x%08x 0x%08x %u %u %u %u %u %u %u %u %u\n",
                pmap.p1, pmap.p2, ndiv, pdiv, mdiv_p0, mdiv_p1, mdiv_p2,
-               mdiv_p3, mdiv_p4);
+               mdiv_p3, mdiv_p4, pmap.mode, pmap.state);
 }
 
 static ssize_t show_brcm_avs_voltage(struct cpufreq_policy *policy, char *buf)
index bc97b6a4b1cf67a4897a412ff785e1350b4ee0ce..7fcaf26e8f819b7665f6e9bf83c07a1b705b1d65 100644 (file)
@@ -26,6 +26,8 @@ static const struct of_device_id machines[] __initconst = {
        { .compatible = "allwinner,sun8i-a83t", },
        { .compatible = "allwinner,sun8i-h3", },
 
+       { .compatible = "apm,xgene-shadowcat", },
+
        { .compatible = "arm,integrator-ap", },
        { .compatible = "arm,integrator-cp", },
 
index 6acbd4af632e2bdab99f984cd0b311e5f7a32e29..50bd6d987fc3a0bf2e1a344a44b9b41d084899cb 100644 (file)
@@ -857,13 +857,13 @@ static struct freq_attr *hwp_cpufreq_attrs[] = {
        NULL,
 };
 
-static void intel_pstate_hwp_set(const struct cpumask *cpumask)
+static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
 {
        int min, hw_min, max, hw_max, cpu, range, adj_range;
        struct perf_limits *perf_limits = limits;
        u64 value, cap;
 
-       for_each_cpu(cpu, cpumask) {
+       for_each_cpu(cpu, policy->cpus) {
                int max_perf_pct, min_perf_pct;
                struct cpudata *cpu_data = all_cpu_data[cpu];
                s16 epp;
@@ -949,7 +949,7 @@ skip_epp:
 static int intel_pstate_hwp_set_policy(struct cpufreq_policy *policy)
 {
        if (hwp_active)
-               intel_pstate_hwp_set(policy->cpus);
+               intel_pstate_hwp_set(policy);
 
        return 0;
 }
@@ -968,19 +968,28 @@ static int intel_pstate_hwp_save_state(struct cpufreq_policy *policy)
 
 static int intel_pstate_resume(struct cpufreq_policy *policy)
 {
+       int ret;
+
        if (!hwp_active)
                return 0;
 
+       mutex_lock(&intel_pstate_limits_lock);
+
        all_cpu_data[policy->cpu]->epp_policy = 0;
 
-       return intel_pstate_hwp_set_policy(policy);
+       ret = intel_pstate_hwp_set_policy(policy);
+
+       mutex_unlock(&intel_pstate_limits_lock);
+
+       return ret;
 }
 
-static void intel_pstate_hwp_set_online_cpus(void)
+static void intel_pstate_update_policies(void)
 {
-       get_online_cpus();
-       intel_pstate_hwp_set(cpu_online_mask);
-       put_online_cpus();
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               cpufreq_update_policy(cpu);
 }
 
 /************************** debugfs begin ************************/
@@ -1018,10 +1027,6 @@ static void __init intel_pstate_debug_expose_params(void)
        struct dentry *debugfs_parent;
        int i = 0;
 
-       if (hwp_active ||
-           pstate_funcs.get_target_pstate == get_target_pstate_use_cpu_load)
-               return;
-
        debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
        if (IS_ERR_OR_NULL(debugfs_parent))
                return;
@@ -1105,11 +1110,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
 
        limits->no_turbo = clamp_t(int, input, 0, 1);
 
-       if (hwp_active)
-               intel_pstate_hwp_set_online_cpus();
-
        mutex_unlock(&intel_pstate_limits_lock);
 
+       intel_pstate_update_policies();
+
        return count;
 }
 
@@ -1134,11 +1138,10 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
                                   limits->max_perf_pct);
        limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
 
-       if (hwp_active)
-               intel_pstate_hwp_set_online_cpus();
-
        mutex_unlock(&intel_pstate_limits_lock);
 
+       intel_pstate_update_policies();
+
        return count;
 }
 
@@ -1163,11 +1166,10 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
                                   limits->min_perf_pct);
        limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
 
-       if (hwp_active)
-               intel_pstate_hwp_set_online_cpus();
-
        mutex_unlock(&intel_pstate_limits_lock);
 
+       intel_pstate_update_policies();
+
        return count;
 }
 
@@ -1233,6 +1235,25 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata)
                cpudata->epp_default = intel_pstate_get_epp(cpudata, 0);
 }
 
+#define MSR_IA32_POWER_CTL_BIT_EE      19
+
+/* Disable energy efficiency optimization */
+static void intel_pstate_disable_ee(int cpu)
+{
+       u64 power_ctl;
+       int ret;
+
+       ret = rdmsrl_on_cpu(cpu, MSR_IA32_POWER_CTL, &power_ctl);
+       if (ret)
+               return;
+
+       if (!(power_ctl & BIT(MSR_IA32_POWER_CTL_BIT_EE))) {
+               pr_info("Disabling energy efficiency optimization\n");
+               power_ctl |= BIT(MSR_IA32_POWER_CTL_BIT_EE);
+               wrmsrl_on_cpu(cpu, MSR_IA32_POWER_CTL, power_ctl);
+       }
+}
+
 static int atom_get_min_pstate(void)
 {
        u64 value;
@@ -1843,6 +1864,11 @@ static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
        {}
 };
 
+static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = {
+       ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, core_params),
+       {}
+};
+
 static int intel_pstate_init_cpu(unsigned int cpunum)
 {
        struct cpudata *cpu;
@@ -1873,6 +1899,12 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
        cpu->cpu = cpunum;
 
        if (hwp_active) {
+               const struct x86_cpu_id *id;
+
+               id = x86_match_cpu(intel_pstate_cpu_ee_disable_ids);
+               if (id)
+                       intel_pstate_disable_ee(cpunum);
+
                intel_pstate_hwp_enable(cpu);
                pid_params.sample_rate_ms = 50;
                pid_params.sample_rate_ns = 50 * NSEC_PER_MSEC;
@@ -2003,7 +2035,8 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                        limits = &performance_limits;
                        perf_limits = limits;
                }
-               if (policy->max >= policy->cpuinfo.max_freq) {
+               if (policy->max >= policy->cpuinfo.max_freq &&
+                   !limits->no_turbo) {
                        pr_debug("set performance\n");
                        intel_pstate_set_performance_limits(perf_limits);
                        goto out;
@@ -2045,6 +2078,17 @@ static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
            policy->policy != CPUFREQ_POLICY_PERFORMANCE)
                return -EINVAL;
 
+       /* When per-CPU limits are used, sysfs limits are not used */
+       if (!per_cpu_limits) {
+               unsigned int max_freq, min_freq;
+
+               max_freq = policy->cpuinfo.max_freq *
+                                               limits->max_sysfs_pct / 100;
+               min_freq = policy->cpuinfo.max_freq *
+                                               limits->min_sysfs_pct / 100;
+               cpufreq_verify_within_limits(policy, min_freq, max_freq);
+       }
+
        return 0;
 }
 
@@ -2153,8 +2197,12 @@ static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
        if (per_cpu_limits)
                perf_limits = cpu->perf_limits;
 
+       mutex_lock(&intel_pstate_limits_lock);
+
        intel_pstate_update_perf_limits(policy, perf_limits);
 
+       mutex_unlock(&intel_pstate_limits_lock);
+
        return 0;
 }
 
@@ -2487,7 +2535,10 @@ hwp_cpu_matched:
        if (rc)
                goto out;
 
-       intel_pstate_debug_expose_params();
+       if (intel_pstate_driver == &intel_pstate && !hwp_active &&
+           pstate_funcs.get_target_pstate != get_target_pstate_use_cpu_load)
+               intel_pstate_debug_expose_params();
+
        intel_pstate_sysfs_expose_params();
 
        if (hwp_active)
index e2ce8190ecc9a5c0baf3f6e642a4cff17f89862c..612898b4aaad045f7e96429ac325ecbec91a4295 100644 (file)
@@ -959,7 +959,7 @@ static irqreturn_t ccp5_irq_handler(int irq, void *data)
 static void ccp5_config(struct ccp_device *ccp)
 {
        /* Public side */
-       iowrite32(0x00001249, ccp->io_regs + CMD5_REQID_CONFIG_OFFSET);
+       iowrite32(0x0, ccp->io_regs + CMD5_REQID_CONFIG_OFFSET);
 }
 
 static void ccp5other_config(struct ccp_device *ccp)
index 830f35e6005f0e002457d57fab70a8557fb85e24..649e5610a5cea7d08a95767af1c8f8e0153e0b7a 100644 (file)
@@ -238,6 +238,7 @@ struct ccp_dma_chan {
        struct ccp_device *ccp;
 
        spinlock_t lock;
+       struct list_head created;
        struct list_head pending;
        struct list_head active;
        struct list_head complete;
index 6553912804f73f1c061aec9bdd3afd0f0d7426bc..e5d9278f40197427e913993fe9249d405585fe87 100644 (file)
@@ -63,6 +63,7 @@ static void ccp_free_chan_resources(struct dma_chan *dma_chan)
        ccp_free_desc_resources(chan->ccp, &chan->complete);
        ccp_free_desc_resources(chan->ccp, &chan->active);
        ccp_free_desc_resources(chan->ccp, &chan->pending);
+       ccp_free_desc_resources(chan->ccp, &chan->created);
 
        spin_unlock_irqrestore(&chan->lock, flags);
 }
@@ -273,6 +274,7 @@ static dma_cookie_t ccp_tx_submit(struct dma_async_tx_descriptor *tx_desc)
        spin_lock_irqsave(&chan->lock, flags);
 
        cookie = dma_cookie_assign(tx_desc);
+       list_del(&desc->entry);
        list_add_tail(&desc->entry, &chan->pending);
 
        spin_unlock_irqrestore(&chan->lock, flags);
@@ -426,7 +428,7 @@ static struct ccp_dma_desc *ccp_create_desc(struct dma_chan *dma_chan,
 
        spin_lock_irqsave(&chan->lock, sflags);
 
-       list_add_tail(&desc->entry, &chan->pending);
+       list_add_tail(&desc->entry, &chan->created);
 
        spin_unlock_irqrestore(&chan->lock, sflags);
 
@@ -610,6 +612,7 @@ static int ccp_terminate_all(struct dma_chan *dma_chan)
        /*TODO: Purge the complete list? */
        ccp_free_desc_resources(chan->ccp, &chan->active);
        ccp_free_desc_resources(chan->ccp, &chan->pending);
+       ccp_free_desc_resources(chan->ccp, &chan->created);
 
        spin_unlock_irqrestore(&chan->lock, flags);
 
@@ -679,6 +682,7 @@ int ccp_dmaengine_register(struct ccp_device *ccp)
                chan->ccp = ccp;
 
                spin_lock_init(&chan->lock);
+               INIT_LIST_HEAD(&chan->created);
                INIT_LIST_HEAD(&chan->pending);
                INIT_LIST_HEAD(&chan->active);
                INIT_LIST_HEAD(&chan->complete);
index 2ed1e24b44a8ba07b24a1ef4a9d7cca4e57522d4..b4b78b37f8a684698d79bc053be0b2f9db7e654f 100644 (file)
@@ -158,7 +158,7 @@ int chcr_handle_resp(struct crypto_async_request *req, unsigned char *input,
        case CRYPTO_ALG_TYPE_AEAD:
                ctx_req.req.aead_req = (struct aead_request *)req;
                ctx_req.ctx.reqctx = aead_request_ctx(ctx_req.req.aead_req);
-               dma_unmap_sg(&u_ctx->lldi.pdev->dev, ctx_req.req.aead_req->dst,
+               dma_unmap_sg(&u_ctx->lldi.pdev->dev, ctx_req.ctx.reqctx->dst,
                             ctx_req.ctx.reqctx->dst_nents, DMA_FROM_DEVICE);
                if (ctx_req.ctx.reqctx->skb) {
                        kfree_skb(ctx_req.ctx.reqctx->skb);
@@ -1362,8 +1362,7 @@ static struct sk_buff *create_authenc_wr(struct aead_request *req,
        struct chcr_wr *chcr_req;
        struct cpl_rx_phys_dsgl *phys_cpl;
        struct phys_sge_parm sg_param;
-       struct scatterlist *src, *dst;
-       struct scatterlist src_sg[2], dst_sg[2];
+       struct scatterlist *src;
        unsigned int frags = 0, transhdr_len;
        unsigned int ivsize = crypto_aead_ivsize(tfm), dst_size = 0;
        unsigned int   kctx_len = 0;
@@ -1383,19 +1382,21 @@ static struct sk_buff *create_authenc_wr(struct aead_request *req,
 
        if (sg_nents_for_len(req->src, req->assoclen + req->cryptlen) < 0)
                goto err;
-       src = scatterwalk_ffwd(src_sg, req->src, req->assoclen);
-       dst = src;
+       src = scatterwalk_ffwd(reqctx->srcffwd, req->src, req->assoclen);
+       reqctx->dst = src;
+
        if (req->src != req->dst) {
                err = chcr_copy_assoc(req, aeadctx);
                if (err)
                        return ERR_PTR(err);
-               dst = scatterwalk_ffwd(dst_sg, req->dst, req->assoclen);
+               reqctx->dst = scatterwalk_ffwd(reqctx->dstffwd, req->dst,
+                                              req->assoclen);
        }
        if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_NULL) {
                null = 1;
                assoclen = 0;
        }
-       reqctx->dst_nents = sg_nents_for_len(dst, req->cryptlen +
+       reqctx->dst_nents = sg_nents_for_len(reqctx->dst, req->cryptlen +
                                             (op_type ? -authsize : authsize));
        if (reqctx->dst_nents <= 0) {
                pr_err("AUTHENC:Invalid Destination sg entries\n");
@@ -1460,7 +1461,7 @@ static struct sk_buff *create_authenc_wr(struct aead_request *req,
        sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
        sg_param.qid = qid;
        sg_param.align = 0;
-       if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, dst,
+       if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, reqctx->dst,
                                  &sg_param))
                goto dstmap_fail;
 
@@ -1711,8 +1712,7 @@ static struct sk_buff *create_aead_ccm_wr(struct aead_request *req,
        struct chcr_wr *chcr_req;
        struct cpl_rx_phys_dsgl *phys_cpl;
        struct phys_sge_parm sg_param;
-       struct scatterlist *src, *dst;
-       struct scatterlist src_sg[2], dst_sg[2];
+       struct scatterlist *src;
        unsigned int frags = 0, transhdr_len, ivsize = AES_BLOCK_SIZE;
        unsigned int dst_size = 0, kctx_len;
        unsigned int sub_type;
@@ -1728,17 +1728,19 @@ static struct sk_buff *create_aead_ccm_wr(struct aead_request *req,
        if (sg_nents_for_len(req->src, req->assoclen + req->cryptlen) < 0)
                goto err;
        sub_type = get_aead_subtype(tfm);
-       src = scatterwalk_ffwd(src_sg, req->src, req->assoclen);
-       dst = src;
+       src = scatterwalk_ffwd(reqctx->srcffwd, req->src, req->assoclen);
+       reqctx->dst = src;
+
        if (req->src != req->dst) {
                err = chcr_copy_assoc(req, aeadctx);
                if (err) {
                        pr_err("AAD copy to destination buffer fails\n");
                        return ERR_PTR(err);
                }
-               dst = scatterwalk_ffwd(dst_sg, req->dst, req->assoclen);
+               reqctx->dst = scatterwalk_ffwd(reqctx->dstffwd, req->dst,
+                                              req->assoclen);
        }
-       reqctx->dst_nents = sg_nents_for_len(dst, req->cryptlen +
+       reqctx->dst_nents = sg_nents_for_len(reqctx->dst, req->cryptlen +
                                             (op_type ? -authsize : authsize));
        if (reqctx->dst_nents <= 0) {
                pr_err("CCM:Invalid Destination sg entries\n");
@@ -1777,7 +1779,7 @@ static struct sk_buff *create_aead_ccm_wr(struct aead_request *req,
        sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
        sg_param.qid = qid;
        sg_param.align = 0;
-       if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, dst,
+       if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, reqctx->dst,
                                  &sg_param))
                goto dstmap_fail;
 
@@ -1809,8 +1811,7 @@ static struct sk_buff *create_gcm_wr(struct aead_request *req,
        struct chcr_wr *chcr_req;
        struct cpl_rx_phys_dsgl *phys_cpl;
        struct phys_sge_parm sg_param;
-       struct scatterlist *src, *dst;
-       struct scatterlist src_sg[2], dst_sg[2];
+       struct scatterlist *src;
        unsigned int frags = 0, transhdr_len;
        unsigned int ivsize = AES_BLOCK_SIZE;
        unsigned int dst_size = 0, kctx_len;
@@ -1832,13 +1833,14 @@ static struct sk_buff *create_gcm_wr(struct aead_request *req,
        if (sg_nents_for_len(req->src, req->assoclen + req->cryptlen) < 0)
                goto err;
 
-       src = scatterwalk_ffwd(src_sg, req->src, req->assoclen);
-       dst = src;
+       src = scatterwalk_ffwd(reqctx->srcffwd, req->src, req->assoclen);
+       reqctx->dst = src;
        if (req->src != req->dst) {
                err = chcr_copy_assoc(req, aeadctx);
                if (err)
                        return  ERR_PTR(err);
-               dst = scatterwalk_ffwd(dst_sg, req->dst, req->assoclen);
+               reqctx->dst = scatterwalk_ffwd(reqctx->dstffwd, req->dst,
+                                              req->assoclen);
        }
 
        if (!req->cryptlen)
@@ -1848,7 +1850,7 @@ static struct sk_buff *create_gcm_wr(struct aead_request *req,
                crypt_len = AES_BLOCK_SIZE;
        else
                crypt_len = req->cryptlen;
-       reqctx->dst_nents = sg_nents_for_len(dst, req->cryptlen +
+       reqctx->dst_nents = sg_nents_for_len(reqctx->dst, req->cryptlen +
                                             (op_type ? -authsize : authsize));
        if (reqctx->dst_nents <= 0) {
                pr_err("GCM:Invalid Destination sg entries\n");
@@ -1923,7 +1925,7 @@ static struct sk_buff *create_gcm_wr(struct aead_request *req,
        sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
        sg_param.qid = qid;
        sg_param.align = 0;
-       if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, dst,
+       if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, reqctx->dst,
                                  &sg_param))
                goto dstmap_fail;
 
@@ -1937,7 +1939,8 @@ static struct sk_buff *create_gcm_wr(struct aead_request *req,
                write_sg_to_skb(skb, &frags, src, req->cryptlen);
        } else {
                aes_gcm_empty_pld_pad(req->dst, authsize - 1);
-               write_sg_to_skb(skb, &frags, dst, crypt_len);
+               write_sg_to_skb(skb, &frags, reqctx->dst, crypt_len);
+
        }
 
        create_wreq(ctx, chcr_req, req, skb, kctx_len, size, 1,
@@ -2189,8 +2192,8 @@ static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key,
        unsigned int ck_size;
        int ret = 0, key_ctx_size = 0;
 
-       if (get_aead_subtype(aead) ==
-           CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) {
+       if (get_aead_subtype(aead) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 &&
+           keylen > 3) {
                keylen -= 4;  /* nonce/salt is present in the last 4 bytes */
                memcpy(aeadctx->salt, key + keylen, 4);
        }
index 918da8e6e2d8a587ef7e397e149a9779a8c4a21f..1c65f07e1cc9a56f9dc88b30c10ba57e13b875ed 100644 (file)
@@ -52,6 +52,7 @@ static struct cxgb4_uld_info chcr_uld_info = {
 int assign_chcr_device(struct chcr_dev **dev)
 {
        struct uld_ctx *u_ctx;
+       int ret = -ENXIO;
 
        /*
         * Which device to use if multiple devices are available TODO
@@ -59,15 +60,14 @@ int assign_chcr_device(struct chcr_dev **dev)
         * must go to the same device to maintain the ordering.
         */
        mutex_lock(&dev_mutex); /* TODO ? */
-       u_ctx = list_first_entry(&uld_ctx_list, struct uld_ctx, entry);
-       if (!u_ctx) {
-               mutex_unlock(&dev_mutex);
-               return -ENXIO;
+       list_for_each_entry(u_ctx, &uld_ctx_list, entry)
+               if (u_ctx && u_ctx->dev) {
+                       *dev = u_ctx->dev;
+                       ret = 0;
+                       break;
        }
-
-       *dev = u_ctx->dev;
        mutex_unlock(&dev_mutex);
-       return 0;
+       return ret;
 }
 
 static int chcr_dev_add(struct uld_ctx *u_ctx)
@@ -202,10 +202,8 @@ static int chcr_uld_state_change(void *handle, enum cxgb4_state state)
 
 static int __init chcr_crypto_init(void)
 {
-       if (cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info)) {
+       if (cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info))
                pr_err("ULD register fail: No chcr crypto support in cxgb4");
-               return -1;
-       }
 
        return 0;
 }
index d5af7d64a763bc8ad4ce45d60bada6226059bff1..7ec0a8f124753d1fbcdf7b248d14177330bab977 100644 (file)
@@ -158,6 +158,9 @@ struct ablk_ctx {
 };
 struct chcr_aead_reqctx {
        struct  sk_buff *skb;
+       struct scatterlist *dst;
+       struct scatterlist srcffwd[2];
+       struct scatterlist dstffwd[2];
        short int dst_nents;
        u16 verify;
        u8 iv[CHCR_MAX_CRYPTO_IV_LEN];
index bc5cbc193aae5c6167559ea3d2b9975acc7e6a5a..5b2d78a5b5aaaffd9ba3a858269c8664cd4f89b7 100644 (file)
@@ -233,7 +233,7 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                              &hw_data->accel_capabilities_mask);
 
        /* Find and map all the device's BARS */
-       i = 0;
+       i = (hw_data->fuses & ADF_DEVICE_FUSECTL_MASK) ? 1 : 0;
        bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
        for_each_set_bit(bar_nr, (const unsigned long *)&bar_mask,
                         ADF_PCI_MAX_BARS * 2) {
index e8822536530b99666f2f5137c25b36f7b451fe06..33f0a6251e385c8f5f72fc0f384106c368329c86 100644 (file)
@@ -69,6 +69,7 @@
 #define ADF_ERRSOU5 (0x3A000 + 0xD8)
 #define ADF_DEVICE_FUSECTL_OFFSET 0x40
 #define ADF_DEVICE_LEGFUSE_OFFSET 0x4C
+#define ADF_DEVICE_FUSECTL_MASK 0x80000000
 #define ADF_PCI_MAX_BARS 3
 #define ADF_DEVICE_NAME_LENGTH 32
 #define ADF_ETR_MAX_RINGS_PER_BANK 16
index 1e480f140663530a699d8bf51b402bce394a935e..8c4fd255a601b2d6c60e2300f5c878f8a512f57d 100644 (file)
@@ -456,7 +456,7 @@ static int qat_hal_init_esram(struct icp_qat_fw_loader_handle *handle)
        unsigned int csr_val;
        int times = 30;
 
-       if (handle->pci_dev->device == ADF_C3XXX_PCI_DEVICE_ID)
+       if (handle->pci_dev->device != ADF_DH895XCC_PCI_DEVICE_ID)
                return 0;
 
        csr_val = ADF_CSR_RD(csr_addr, 0);
@@ -716,7 +716,7 @@ int qat_hal_init(struct adf_accel_dev *accel_dev)
                (void __iomem *)((uintptr_t)handle->hal_cap_ae_xfer_csr_addr_v +
                                 LOCAL_TO_XFER_REG_OFFSET);
        handle->pci_dev = pci_info->pci_dev;
-       if (handle->pci_dev->device != ADF_C3XXX_PCI_DEVICE_ID) {
+       if (handle->pci_dev->device == ADF_DH895XCC_PCI_DEVICE_ID) {
                sram_bar =
                        &pci_info->pci_bars[hw_data->get_sram_bar_id(hw_data)];
                handle->hal_sram_addr_v = sram_bar->virt_addr;
index a324801d6a664cd707d70d673611cade4d43bd9d..47206a21bb901f424c4e331c9db6eaedef69d93d 100644 (file)
@@ -593,11 +593,16 @@ struct devfreq *devfreq_add_device(struct device *dev,
        list_add(&devfreq->node, &devfreq_list);
 
        governor = find_devfreq_governor(devfreq->governor_name);
-       if (!IS_ERR(governor))
-               devfreq->governor = governor;
-       if (devfreq->governor)
-               err = devfreq->governor->event_handler(devfreq,
-                                       DEVFREQ_GOV_START, NULL);
+       if (IS_ERR(governor)) {
+               dev_err(dev, "%s: Unable to find governor for the device\n",
+                       __func__);
+               err = PTR_ERR(governor);
+               goto err_init;
+       }
+
+       devfreq->governor = governor;
+       err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
+                                               NULL);
        if (err) {
                dev_err(dev, "%s: Unable to start governor for the device\n",
                        __func__);
index a8ed7792ece2f199adaedd588b86375c49da6f17..9af86f46fbec0fc0779e4cf211c16227b804510d 100644 (file)
@@ -497,7 +497,7 @@ passive:
        if (IS_ERR(bus->devfreq)) {
                dev_err(dev,
                        "failed to add devfreq dev with passive governor\n");
-               ret = -EPROBE_DEFER;
+               ret = PTR_ERR(bus->devfreq);
                goto err;
        }
 
index d5ba43a87a682b6e718d5e2ad7c804498bad61de..200828c60db9ffce12b968956271954a88ac54d0 100644 (file)
@@ -153,6 +153,8 @@ struct cppi41_dd {
 
        /* context for suspend/resume */
        unsigned int dma_tdfdq;
+
+       bool is_suspended;
 };
 
 #define FIST_COMPLETION_QUEUE  93
@@ -257,6 +259,10 @@ static struct cppi41_channel *desc_to_chan(struct cppi41_dd *cdd, u32 desc)
        BUG_ON(desc_num >= ALLOC_DECS_NUM);
        c = cdd->chan_busy[desc_num];
        cdd->chan_busy[desc_num] = NULL;
+
+       /* Usecount for chan_busy[], paired with push_desc_queue() */
+       pm_runtime_put(cdd->ddev.dev);
+
        return c;
 }
 
@@ -317,12 +323,12 @@ static irqreturn_t cppi41_irq(int irq, void *data)
 
                while (val) {
                        u32 desc, len;
-                       int error;
 
-                       error = pm_runtime_get(cdd->ddev.dev);
-                       if (error < 0)
-                               dev_err(cdd->ddev.dev, "%s pm runtime get: %i\n",
-                                       __func__, error);
+                       /*
+                        * This should never trigger, see the comments in
+                        * push_desc_queue()
+                        */
+                       WARN_ON(cdd->is_suspended);
 
                        q_num = __fls(val);
                        val &= ~(1 << q_num);
@@ -343,9 +349,6 @@ static irqreturn_t cppi41_irq(int irq, void *data)
                        c->residue = pd_trans_len(c->desc->pd6) - len;
                        dma_cookie_complete(&c->txd);
                        dmaengine_desc_get_callback_invoke(&c->txd, NULL);
-
-                       pm_runtime_mark_last_busy(cdd->ddev.dev);
-                       pm_runtime_put_autosuspend(cdd->ddev.dev);
                }
        }
        return IRQ_HANDLED;
@@ -447,6 +450,15 @@ static void push_desc_queue(struct cppi41_channel *c)
         */
        __iowmb();
 
+       /*
+        * DMA transfers can take at least 200ms to complete with USB mass
+        * storage connected. To prevent autosuspend timeouts, we must use
+        * pm_runtime_get/put() when chan_busy[] is modified. This will get
+        * cleared in desc_to_chan() or cppi41_stop_chan() depending on the
+        * outcome of the transfer.
+        */
+       pm_runtime_get(cdd->ddev.dev);
+
        desc_phys = lower_32_bits(c->desc_phys);
        desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
        WARN_ON(cdd->chan_busy[desc_num]);
@@ -457,20 +469,26 @@ static void push_desc_queue(struct cppi41_channel *c)
        cppi_writel(reg, cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
 }
 
-static void pending_desc(struct cppi41_channel *c)
+/*
+ * Caller must hold cdd->lock to prevent push_desc_queue()
+ * getting called out of order. We have both cppi41_dma_issue_pending()
+ * and cppi41_runtime_resume() call this function.
+ */
+static void cppi41_run_queue(struct cppi41_dd *cdd)
 {
-       struct cppi41_dd *cdd = c->cdd;
-       unsigned long flags;
+       struct cppi41_channel *c, *_c;
 
-       spin_lock_irqsave(&cdd->lock, flags);
-       list_add_tail(&c->node, &cdd->pending);
-       spin_unlock_irqrestore(&cdd->lock, flags);
+       list_for_each_entry_safe(c, _c, &cdd->pending, node) {
+               push_desc_queue(c);
+               list_del(&c->node);
+       }
 }
 
 static void cppi41_dma_issue_pending(struct dma_chan *chan)
 {
        struct cppi41_channel *c = to_cpp41_chan(chan);
        struct cppi41_dd *cdd = c->cdd;
+       unsigned long flags;
        int error;
 
        error = pm_runtime_get(cdd->ddev.dev);
@@ -482,10 +500,11 @@ static void cppi41_dma_issue_pending(struct dma_chan *chan)
                return;
        }
 
-       if (likely(pm_runtime_active(cdd->ddev.dev)))
-               push_desc_queue(c);
-       else
-               pending_desc(c);
+       spin_lock_irqsave(&cdd->lock, flags);
+       list_add_tail(&c->node, &cdd->pending);
+       if (!cdd->is_suspended)
+               cppi41_run_queue(cdd);
+       spin_unlock_irqrestore(&cdd->lock, flags);
 
        pm_runtime_mark_last_busy(cdd->ddev.dev);
        pm_runtime_put_autosuspend(cdd->ddev.dev);
@@ -705,6 +724,9 @@ static int cppi41_stop_chan(struct dma_chan *chan)
        WARN_ON(!cdd->chan_busy[desc_num]);
        cdd->chan_busy[desc_num] = NULL;
 
+       /* Usecount for chan_busy[], paired with push_desc_queue() */
+       pm_runtime_put(cdd->ddev.dev);
+
        return 0;
 }
 
@@ -1150,8 +1172,12 @@ static int __maybe_unused cppi41_resume(struct device *dev)
 static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
 {
        struct cppi41_dd *cdd = dev_get_drvdata(dev);
+       unsigned long flags;
 
+       spin_lock_irqsave(&cdd->lock, flags);
+       cdd->is_suspended = true;
        WARN_ON(!list_empty(&cdd->pending));
+       spin_unlock_irqrestore(&cdd->lock, flags);
 
        return 0;
 }
@@ -1159,14 +1185,11 @@ static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
 static int __maybe_unused cppi41_runtime_resume(struct device *dev)
 {
        struct cppi41_dd *cdd = dev_get_drvdata(dev);
-       struct cppi41_channel *c, *_c;
        unsigned long flags;
 
        spin_lock_irqsave(&cdd->lock, flags);
-       list_for_each_entry_safe(c, _c, &cdd->pending, node) {
-               push_desc_queue(c);
-               list_del(&c->node);
-       }
+       cdd->is_suspended = false;
+       cppi41_run_queue(cdd);
        spin_unlock_irqrestore(&cdd->lock, flags);
 
        return 0;
index e00c9b022964702c076b1a192df35b9bbbf7e113..5a37b9fcf40ddf813a6cf5d2c401bc221fd5e83b 100644 (file)
@@ -24,5 +24,5 @@ config DW_DMAC_PCI
        select DW_DMAC_CORE
        help
          Support the Synopsys DesignWare AHB DMA controller on the
-         platfroms that enumerate it as a PCI device. For example,
+         platforms that enumerate it as a PCI device. For example,
          Intel Medfield has integrated this GPDMA controller.
index 8e67895bcca3a2db74e5b72e00374e2118ce95f7..abcc51b343cecd1629700233e8ca9d8882da2dff 100644 (file)
@@ -64,6 +64,8 @@
 #define PCI_DEVICE_ID_INTEL_IOAT_BDX8  0x6f2e
 #define PCI_DEVICE_ID_INTEL_IOAT_BDX9  0x6f2f
 
+#define PCI_DEVICE_ID_INTEL_IOAT_SKX   0x2021
+
 #define IOAT_VER_1_2            0x12    /* Version 1.2 */
 #define IOAT_VER_2_0            0x20    /* Version 2.0 */
 #define IOAT_VER_3_0            0x30    /* Version 3.0 */
index 90eddd9f07e4fc1b354bad70a935a8cfec20e246..cc5259b881d47ffa48322e2a537397317e8b8be1 100644 (file)
@@ -106,6 +106,8 @@ static struct pci_device_id ioat_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SKX) },
+
        /* I/OAT v3.3 platforms */
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
@@ -243,10 +245,15 @@ static bool is_bdx_ioat(struct pci_dev *pdev)
        }
 }
 
+static inline bool is_skx_ioat(struct pci_dev *pdev)
+{
+       return (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SKX) ? true : false;
+}
+
 static bool is_xeon_cb32(struct pci_dev *pdev)
 {
        return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
-               is_hsw_ioat(pdev) || is_bdx_ioat(pdev);
+               is_hsw_ioat(pdev) || is_bdx_ioat(pdev) || is_skx_ioat(pdev);
 }
 
 bool is_bwd_ioat(struct pci_dev *pdev)
@@ -693,7 +700,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c)
        /* doing 2 32bit writes to mmio since 1 64b write doesn't work */
        ioat_chan->completion =
                dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
-                               GFP_KERNEL, &ioat_chan->completion_dma);
+                               GFP_NOWAIT, &ioat_chan->completion_dma);
        if (!ioat_chan->completion)
                return -ENOMEM;
 
@@ -703,7 +710,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c)
               ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
        order = IOAT_MAX_ORDER;
-       ring = ioat_alloc_ring(c, order, GFP_KERNEL);
+       ring = ioat_alloc_ring(c, order, GFP_NOWAIT);
        if (!ring)
                return -ENOMEM;
 
@@ -1357,6 +1364,8 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        device->version = readb(device->reg_base + IOAT_VER_OFFSET);
        if (device->version >= IOAT_VER_3_0) {
+               if (is_skx_ioat(pdev))
+                       device->version = IOAT_VER_3_2;
                err = ioat3_dma_probe(device, ioat_dca_enabled);
 
                if (device->version >= IOAT_VER_3_3)
index ac68666cd3f4e99cd3bc2f4ae346f5e78cd218ce..daf479cce69158e480757d269630d4bed7d6bca2 100644 (file)
@@ -938,21 +938,14 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
                d->ccr |= CCR_DST_AMODE_POSTINC;
                if (port_window) {
                        d->ccr |= CCR_SRC_AMODE_DBLIDX;
-                       d->ei = 1;
-                       /*
-                        * One frame covers the port_window and by  configure
-                        * the source frame index to be -1 * (port_window - 1)
-                        * we instruct the sDMA that after a frame is processed
-                        * it should move back to the start of the window.
-                        */
-                       d->fi = -(port_window_bytes - 1);
 
                        if (port_window_bytes >= 64)
-                               d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
+                               d->csdp |= CSDP_SRC_BURST_64;
                        else if (port_window_bytes >= 32)
-                               d->csdp = CSDP_SRC_BURST_32 | CSDP_SRC_PACKED;
+                               d->csdp |= CSDP_SRC_BURST_32;
                        else if (port_window_bytes >= 16)
-                               d->csdp = CSDP_SRC_BURST_16 | CSDP_SRC_PACKED;
+                               d->csdp |= CSDP_SRC_BURST_16;
+
                } else {
                        d->ccr |= CCR_SRC_AMODE_CONSTANT;
                }
@@ -962,13 +955,21 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
                d->ccr |= CCR_SRC_AMODE_POSTINC;
                if (port_window) {
                        d->ccr |= CCR_DST_AMODE_DBLIDX;
+                       d->ei = 1;
+                       /*
+                        * One frame covers the port_window and by  configure
+                        * the source frame index to be -1 * (port_window - 1)
+                        * we instruct the sDMA that after a frame is processed
+                        * it should move back to the start of the window.
+                        */
+                       d->fi = -(port_window_bytes - 1);
 
                        if (port_window_bytes >= 64)
-                               d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
+                               d->csdp |= CSDP_DST_BURST_64;
                        else if (port_window_bytes >= 32)
-                               d->csdp = CSDP_DST_BURST_32 | CSDP_DST_PACKED;
+                               d->csdp |= CSDP_DST_BURST_32;
                        else if (port_window_bytes >= 16)
-                               d->csdp = CSDP_DST_BURST_16 | CSDP_DST_PACKED;
+                               d->csdp |= CSDP_DST_BURST_16;
                } else {
                        d->ccr |= CCR_DST_AMODE_CONSTANT;
                }
@@ -1017,7 +1018,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
                osg->addr = sg_dma_address(sgent);
                osg->en = en;
                osg->fn = sg_dma_len(sgent) / frame_bytes;
-               if (port_window && dir == DMA_MEM_TO_DEV) {
+               if (port_window && dir == DMA_DEV_TO_MEM) {
                        osg->ei = 1;
                        /*
                         * One frame covers the port_window and by  configure
@@ -1452,6 +1453,7 @@ static int omap_dma_probe(struct platform_device *pdev)
        struct omap_dmadev *od;
        struct resource *res;
        int rc, i, irq;
+       u32 lch_count;
 
        od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
        if (!od)
@@ -1494,20 +1496,31 @@ static int omap_dma_probe(struct platform_device *pdev)
        spin_lock_init(&od->lock);
        spin_lock_init(&od->irq_lock);
 
-       if (!pdev->dev.of_node) {
-               od->dma_requests = od->plat->dma_attr->lch_count;
-               if (unlikely(!od->dma_requests))
-                       od->dma_requests = OMAP_SDMA_REQUESTS;
-       } else if (of_property_read_u32(pdev->dev.of_node, "dma-requests",
-                                       &od->dma_requests)) {
+       /* Number of DMA requests */
+       od->dma_requests = OMAP_SDMA_REQUESTS;
+       if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
+                                                     "dma-requests",
+                                                     &od->dma_requests)) {
                dev_info(&pdev->dev,
                         "Missing dma-requests property, using %u.\n",
                         OMAP_SDMA_REQUESTS);
-               od->dma_requests = OMAP_SDMA_REQUESTS;
        }
 
-       od->lch_map = devm_kcalloc(&pdev->dev, od->dma_requests,
-                                  sizeof(*od->lch_map), GFP_KERNEL);
+       /* Number of available logical channels */
+       if (!pdev->dev.of_node) {
+               lch_count = od->plat->dma_attr->lch_count;
+               if (unlikely(!lch_count))
+                       lch_count = OMAP_SDMA_CHANNELS;
+       } else if (of_property_read_u32(pdev->dev.of_node, "dma-channels",
+                                       &lch_count)) {
+               dev_info(&pdev->dev,
+                        "Missing dma-channels property, using %u.\n",
+                        OMAP_SDMA_CHANNELS);
+               lch_count = OMAP_SDMA_CHANNELS;
+       }
+
+       od->lch_map = devm_kcalloc(&pdev->dev, lch_count, sizeof(*od->lch_map),
+                                  GFP_KERNEL);
        if (!od->lch_map)
                return -ENOMEM;
 
index 87fd01539fcb74daa0c80a62a268311b7125dce1..7539f73df9e0edbf71b424a66bcabc7d8df01e44 100644 (file)
@@ -448,6 +448,9 @@ struct dma_pl330_chan {
 
        /* for cyclic capability */
        bool cyclic;
+
+       /* for runtime pm tracking */
+       bool active;
 };
 
 struct pl330_dmac {
@@ -1696,7 +1699,6 @@ static bool _chan_ns(const struct pl330_dmac *pl330, int i)
 static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
 {
        struct pl330_thread *thrd = NULL;
-       unsigned long flags;
        int chans, i;
 
        if (pl330->state == DYING)
@@ -1704,8 +1706,6 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
 
        chans = pl330->pcfg.num_chan;
 
-       spin_lock_irqsave(&pl330->lock, flags);
-
        for (i = 0; i < chans; i++) {
                thrd = &pl330->channels[i];
                if ((thrd->free) && (!_manager_ns(thrd) ||
@@ -1723,8 +1723,6 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
                thrd = NULL;
        }
 
-       spin_unlock_irqrestore(&pl330->lock, flags);
-
        return thrd;
 }
 
@@ -1742,7 +1740,6 @@ static inline void _free_event(struct pl330_thread *thrd, int ev)
 static void pl330_release_channel(struct pl330_thread *thrd)
 {
        struct pl330_dmac *pl330;
-       unsigned long flags;
 
        if (!thrd || thrd->free)
                return;
@@ -1754,10 +1751,8 @@ static void pl330_release_channel(struct pl330_thread *thrd)
 
        pl330 = thrd->dmac;
 
-       spin_lock_irqsave(&pl330->lock, flags);
        _free_event(thrd, thrd->ev);
        thrd->free = true;
-       spin_unlock_irqrestore(&pl330->lock, flags);
 }
 
 /* Initialize the structure for PL330 configuration, that can be used
@@ -2033,6 +2028,7 @@ static void pl330_tasklet(unsigned long data)
                _stop(pch->thread);
                spin_unlock(&pch->thread->dmac->lock);
                power_down = true;
+               pch->active = false;
        } else {
                /* Make sure the PL330 Channel thread is active */
                spin_lock(&pch->thread->dmac->lock);
@@ -2052,6 +2048,7 @@ static void pl330_tasklet(unsigned long data)
                        desc->status = PREP;
                        list_move_tail(&desc->node, &pch->work_list);
                        if (power_down) {
+                               pch->active = true;
                                spin_lock(&pch->thread->dmac->lock);
                                _start(pch->thread);
                                spin_unlock(&pch->thread->dmac->lock);
@@ -2117,20 +2114,20 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
        struct pl330_dmac *pl330 = pch->dmac;
        unsigned long flags;
 
-       spin_lock_irqsave(&pch->lock, flags);
+       spin_lock_irqsave(&pl330->lock, flags);
 
        dma_cookie_init(chan);
        pch->cyclic = false;
 
        pch->thread = pl330_request_channel(pl330);
        if (!pch->thread) {
-               spin_unlock_irqrestore(&pch->lock, flags);
+               spin_unlock_irqrestore(&pl330->lock, flags);
                return -ENOMEM;
        }
 
        tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
 
-       spin_unlock_irqrestore(&pch->lock, flags);
+       spin_unlock_irqrestore(&pl330->lock, flags);
 
        return 1;
 }
@@ -2166,6 +2163,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
        unsigned long flags;
        struct pl330_dmac *pl330 = pch->dmac;
        LIST_HEAD(list);
+       bool power_down = false;
 
        pm_runtime_get_sync(pl330->ddma.dev);
        spin_lock_irqsave(&pch->lock, flags);
@@ -2176,6 +2174,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
        pch->thread->req[0].desc = NULL;
        pch->thread->req[1].desc = NULL;
        pch->thread->req_running = -1;
+       power_down = pch->active;
+       pch->active = false;
 
        /* Mark all desc done */
        list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2193,6 +2193,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
        list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
        spin_unlock_irqrestore(&pch->lock, flags);
        pm_runtime_mark_last_busy(pl330->ddma.dev);
+       if (power_down)
+               pm_runtime_put_autosuspend(pl330->ddma.dev);
        pm_runtime_put_autosuspend(pl330->ddma.dev);
 
        return 0;
@@ -2228,12 +2230,13 @@ static int pl330_pause(struct dma_chan *chan)
 static void pl330_free_chan_resources(struct dma_chan *chan)
 {
        struct dma_pl330_chan *pch = to_pchan(chan);
+       struct pl330_dmac *pl330 = pch->dmac;
        unsigned long flags;
 
        tasklet_kill(&pch->task);
 
        pm_runtime_get_sync(pch->dmac->ddma.dev);
-       spin_lock_irqsave(&pch->lock, flags);
+       spin_lock_irqsave(&pl330->lock, flags);
 
        pl330_release_channel(pch->thread);
        pch->thread = NULL;
@@ -2241,7 +2244,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
        if (pch->cyclic)
                list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
 
-       spin_unlock_irqrestore(&pch->lock, flags);
+       spin_unlock_irqrestore(&pl330->lock, flags);
        pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
        pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
 }
@@ -2357,6 +2360,7 @@ static void pl330_issue_pending(struct dma_chan *chan)
                 * updated on work_list emptiness status.
                 */
                WARN_ON(list_empty(&pch->submitted_list));
+               pch->active = true;
                pm_runtime_get_sync(pch->dmac->ddma.dev);
        }
        list_splice_tail_init(&pch->submitted_list, &pch->work_list);
index 2e441d0ccd79a37a5486d394310839c2cdc47f01..4c357d47546594c6bd0c9b1ca16e27c658a720cf 100644 (file)
@@ -986,6 +986,7 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
 {
        struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
        struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
+       struct rcar_dmac_chan_map *map = &rchan->map;
        struct rcar_dmac_desc_page *page, *_page;
        struct rcar_dmac_desc *desc;
        LIST_HEAD(list);
@@ -1019,6 +1020,13 @@ static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
                free_page((unsigned long)page);
        }
 
+       /* Remove slave mapping if present. */
+       if (map->slave.xfer_size) {
+               dma_unmap_resource(chan->device->dev, map->addr,
+                                  map->slave.xfer_size, map->dir, 0);
+               map->slave.xfer_size = 0;
+       }
+
        pm_runtime_put(chan->device->dev);
 }
 
index 3688d0873a3e1c844470c31105ecabd3b5d49be3..3056ce7f8c69d01c61fe3ab0eeff6ad299f538f7 100644 (file)
@@ -880,7 +880,7 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
        struct virt_dma_desc *vdesc;
        enum dma_status status;
        unsigned long flags;
-       u32 residue;
+       u32 residue = 0;
 
        status = dma_cookie_status(c, cookie, state);
        if ((status == DMA_COMPLETE) || (!state))
@@ -888,16 +888,12 @@ static enum dma_status stm32_dma_tx_status(struct dma_chan *c,
 
        spin_lock_irqsave(&chan->vchan.lock, flags);
        vdesc = vchan_find_desc(&chan->vchan, cookie);
-       if (cookie == chan->desc->vdesc.tx.cookie) {
+       if (chan->desc && cookie == chan->desc->vdesc.tx.cookie)
                residue = stm32_dma_desc_residue(chan, chan->desc,
                                                 chan->next_sg);
-       } else if (vdesc) {
+       else if (vdesc)
                residue = stm32_dma_desc_residue(chan,
                                                 to_stm32_dma_desc(vdesc), 0);
-       } else {
-               residue = 0;
-       }
-
        dma_set_residue(state, residue);
 
        spin_unlock_irqrestore(&chan->vchan.lock, flags);
@@ -972,21 +968,18 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
        struct stm32_dma_chan *chan;
        struct dma_chan *c;
 
-       if (dma_spec->args_count < 3)
+       if (dma_spec->args_count < 4)
                return NULL;
 
        cfg.channel_id = dma_spec->args[0];
        cfg.request_line = dma_spec->args[1];
        cfg.stream_config = dma_spec->args[2];
-       cfg.threshold = 0;
+       cfg.threshold = dma_spec->args[3];
 
        if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
                                STM32_DMA_MAX_REQUEST_ID))
                return NULL;
 
-       if (dma_spec->args_count > 3)
-               cfg.threshold = dma_spec->args[3];
-
        chan = &dmadev->chan[cfg.channel_id];
 
        c = dma_get_slave_channel(&chan->vchan.chan);
index 3f24aeb48c0e6735f13995ded459cac776b2620f..2403475a37cf9203eb0651ae7f412ef5f63f45d6 100644 (file)
@@ -149,6 +149,7 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev)
        match = of_match_node(ti_am335x_master_match, dma_node);
        if (!match) {
                dev_err(&pdev->dev, "DMA master is not supported\n");
+               of_node_put(dma_node);
                return -EINVAL;
        }
 
@@ -339,6 +340,7 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
        match = of_match_node(ti_dra7_master_match, dma_node);
        if (!match) {
                dev_err(&pdev->dev, "DMA master is not supported\n");
+               of_node_put(dma_node);
                return -EINVAL;
        }
 
index 78298460d1686a79864c57d228ac6af5e114acf9..7c1e3a7b14e0c1f540a0bbe7d6b924b124561729 100644 (file)
@@ -453,7 +453,7 @@ int extcon_sync(struct extcon_dev *edev, unsigned int id)
                dev_err(&edev->dev, "out of memory in extcon_set_state\n");
                kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
 
-               return 0;
+               return -ENOMEM;
        }
 
        length = name_show(&edev->dev, NULL, prop_buf);
index 70e13230d8db835ec201590762ea0ac5331f7ca2..9ad0b1934be9a31173ede1ed6c1c3705cc0c1e05 100644 (file)
@@ -721,11 +721,17 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
 
        ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
                                &buf, sizeof(buf));
-       if (!ret)
+       if (ret)
+               return ret;
+
+       if (scpi_info->is_legacy)
+               /* only 32-bits supported, hi_val can be junk */
+               *val = le32_to_cpu(buf.lo_val);
+       else
                *val = (u64)le32_to_cpu(buf.hi_val) << 32 |
                        le32_to_cpu(buf.lo_val);
 
-       return ret;
+       return 0;
 }
 
 static int scpi_device_get_power_state(u16 dev_id)
index 520a40e5e0e431129cf1fe66a7604d32d7e20061..6c7d60c239b5b459b1f45e1d1110f7ed5a265cb6 100644 (file)
@@ -71,8 +71,7 @@ void __init efi_fake_memmap(void)
        }
 
        /* allocate memory for new EFI memmap */
-       new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map,
-                                       PAGE_SIZE);
+       new_memmap_phy = efi_memmap_alloc(new_nr_map);
        if (!new_memmap_phy)
                return;
 
index b98824e3800abbb57b110d7cc92c0ca8417791d2..0e2a96b12cb3647635db19912ec0ab4004f71572 100644 (file)
@@ -39,14 +39,6 @@ efi_status_t efi_file_close(void *handle);
 
 unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-                       unsigned long orig_fdt_size,
-                       void *fdt, int new_fdt_size, char *cmdline_ptr,
-                       u64 initrd_addr, u64 initrd_size,
-                       efi_memory_desc_t *memory_map,
-                       unsigned long map_size, unsigned long desc_size,
-                       u32 desc_ver);
-
 efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
                                            void *handle,
                                            unsigned long *new_fdt_addr,
index a6a93116a8f053f6c14911376ffa6da7f1dff44e..260c4b4b492ec38735715859522068da40c21381 100644 (file)
 
 #include "efistub.h"
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-                       unsigned long orig_fdt_size,
-                       void *fdt, int new_fdt_size, char *cmdline_ptr,
-                       u64 initrd_addr, u64 initrd_size,
-                       efi_memory_desc_t *memory_map,
-                       unsigned long map_size, unsigned long desc_size,
-                       u32 desc_ver)
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+                              unsigned long orig_fdt_size,
+                              void *fdt, int new_fdt_size, char *cmdline_ptr,
+                              u64 initrd_addr, u64 initrd_size)
 {
        int node, num_rsv;
        int status;
@@ -101,25 +98,23 @@ efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
        if (status)
                goto fdt_set_fail;
 
-       fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+       fdt_val64 = U64_MAX; /* placeholder */
        status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
                             &fdt_val64,  sizeof(fdt_val64));
        if (status)
                goto fdt_set_fail;
 
-       fdt_val32 = cpu_to_fdt32(map_size);
+       fdt_val32 = U32_MAX; /* placeholder */
        status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
                             &fdt_val32,  sizeof(fdt_val32));
        if (status)
                goto fdt_set_fail;
 
-       fdt_val32 = cpu_to_fdt32(desc_size);
        status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
                             &fdt_val32, sizeof(fdt_val32));
        if (status)
                goto fdt_set_fail;
 
-       fdt_val32 = cpu_to_fdt32(desc_ver);
        status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
                             &fdt_val32, sizeof(fdt_val32));
        if (status)
@@ -148,6 +143,43 @@ fdt_set_fail:
        return EFI_LOAD_ERROR;
 }
 
+static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
+{
+       int node = fdt_path_offset(fdt, "/chosen");
+       u64 fdt_val64;
+       u32 fdt_val32;
+       int err;
+
+       if (node < 0)
+               return EFI_LOAD_ERROR;
+
+       fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
+       err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start",
+                                 &fdt_val64, sizeof(fdt_val64));
+       if (err)
+               return EFI_LOAD_ERROR;
+
+       fdt_val32 = cpu_to_fdt32(*map->map_size);
+       err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size",
+                                 &fdt_val32, sizeof(fdt_val32));
+       if (err)
+               return EFI_LOAD_ERROR;
+
+       fdt_val32 = cpu_to_fdt32(*map->desc_size);
+       err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size",
+                                 &fdt_val32, sizeof(fdt_val32));
+       if (err)
+               return EFI_LOAD_ERROR;
+
+       fdt_val32 = cpu_to_fdt32(*map->desc_ver);
+       err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver",
+                                 &fdt_val32, sizeof(fdt_val32));
+       if (err)
+               return EFI_LOAD_ERROR;
+
+       return EFI_SUCCESS;
+}
+
 #ifndef EFI_FDT_ALIGN
 #define EFI_FDT_ALIGN EFI_PAGE_SIZE
 #endif
@@ -155,6 +187,7 @@ fdt_set_fail:
 struct exit_boot_struct {
        efi_memory_desc_t *runtime_map;
        int *runtime_entry_count;
+       void *new_fdt_addr;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -170,7 +203,7 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
        efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
                        p->runtime_map, p->runtime_entry_count);
 
-       return EFI_SUCCESS;
+       return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
 /*
@@ -243,20 +276,10 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
                        goto fail;
                }
 
-               /*
-                * Now that we have done our final memory allocation (and free)
-                * we can get the memory map key  needed for
-                * exit_boot_services().
-                */
-               status = efi_get_memory_map(sys_table, &map);
-               if (status != EFI_SUCCESS)
-                       goto fail_free_new_fdt;
-
                status = update_fdt(sys_table,
                                    (void *)fdt_addr, fdt_size,
                                    (void *)*new_fdt_addr, new_fdt_size,
-                                   cmdline_ptr, initrd_addr, initrd_size,
-                                   memory_map, map_size, desc_size, desc_ver);
+                                   cmdline_ptr, initrd_addr, initrd_size);
 
                /* Succeeding the first time is the expected case. */
                if (status == EFI_SUCCESS)
@@ -266,22 +289,19 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
                        /*
                         * We need to allocate more space for the new
                         * device tree, so free existing buffer that is
-                        * too small.  Also free memory map, as we will need
-                        * to get new one that reflects the free/alloc we do
-                        * on the device tree buffer.
+                        * too small.
                         */
                        efi_free(sys_table, new_fdt_size, *new_fdt_addr);
-                       sys_table->boottime->free_pool(memory_map);
                        new_fdt_size += EFI_PAGE_SIZE;
                } else {
                        pr_efi_err(sys_table, "Unable to construct new device tree.\n");
-                       goto fail_free_mmap;
+                       goto fail_free_new_fdt;
                }
        }
 
-       sys_table->boottime->free_pool(memory_map);
        priv.runtime_map = runtime_map;
        priv.runtime_entry_count = &runtime_entry_count;
+       priv.new_fdt_addr = (void *)*new_fdt_addr;
        status = efi_exit_boot_services(sys_table, handle, &map, &priv,
                                        exit_boot_func);
 
@@ -319,9 +339,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 
        pr_efi_err(sys_table, "Exit boot services failed.\n");
 
-fail_free_mmap:
-       sys_table->boottime->free_pool(memory_map);
-
 fail_free_new_fdt:
        efi_free(sys_table, new_fdt_size, *new_fdt_addr);
 
index f03ddecd232b542ce4c7163506b69da0d29ad2c7..78686443cb378abf616c7cfe595b82d3a51c9cd6 100644 (file)
@@ -9,6 +9,44 @@
 #include <linux/efi.h>
 #include <linux/io.h>
 #include <asm/early_ioremap.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+
+static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
+{
+       return memblock_alloc(size, 0);
+}
+
+static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
+{
+       unsigned int order = get_order(size);
+       struct page *p = alloc_pages(GFP_KERNEL, order);
+
+       if (!p)
+               return 0;
+
+       return PFN_PHYS(page_to_pfn(p));
+}
+
+/**
+ * efi_memmap_alloc - Allocate memory for the EFI memory map
+ * @num_entries: Number of entries in the allocated map.
+ *
+ * Depending on whether mm_init() has already been invoked or not,
+ * either memblock or "normal" page allocation is used.
+ *
+ * Returns the physical address of the allocated memory map on
+ * success, zero on failure.
+ */
+phys_addr_t __init efi_memmap_alloc(unsigned int num_entries)
+{
+       unsigned long size = num_entries * efi.memmap.desc_size;
+
+       if (slab_is_available())
+               return __efi_memmap_alloc_late(size);
+
+       return __efi_memmap_alloc_early(size);
+}
 
 /**
  * __efi_memmap_init - Common code for mapping the EFI memory map
index 44bdb78f837b4d89f2aaef6e7d0764b8c2783d87..29d58feaf67535d0efc470339de02124ed92cd44 100644 (file)
@@ -270,8 +270,7 @@ static int suspend_test_thread(void *arg)
        struct cpuidle_device *dev;
        struct cpuidle_driver *drv;
        /* No need for an actual callback, we just want to wake up the CPU. */
-       struct timer_list wakeup_timer =
-               TIMER_INITIALIZER(dummy_callback, 0, 0);
+       struct timer_list wakeup_timer;
 
        /* Wait for the main thread to give the start signal. */
        wait_for_completion(&suspend_threads_started);
@@ -287,6 +286,7 @@ static int suspend_test_thread(void *arg)
        pr_info("CPU %d entering suspend cycles, states 1 through %d\n",
                cpu, drv->state_count - 1);
 
+       setup_timer_on_stack(&wakeup_timer, dummy_callback, 0);
        for (i = 0; i < NUM_SUSPEND_CYCLE; ++i) {
                int index;
                /*
index 1e8fde8cb803d7406dd98d51673b63eb69fdfd23..2292742eac8f5441642469f8fa05e04ca0979afb 100644 (file)
@@ -205,7 +205,7 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
        return 0;
 }
 
-static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
+static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
index f4c26c7826cdfc0b5163632e596c0e664586549b..a07ae9e37930767643302ccbec4a7284275a0f25 100644 (file)
@@ -1317,12 +1317,12 @@ void gpiochip_remove(struct gpio_chip *chip)
 
        /* FIXME: should the legacy sysfs handling be moved to gpio_device? */
        gpiochip_sysfs_unregister(gdev);
+       gpiochip_free_hogs(chip);
        /* Numb the device, cancelling all outstanding operations */
        gdev->chip = NULL;
        gpiochip_irqchip_remove(chip);
        acpi_gpiochip_remove(chip);
        gpiochip_remove_pin_ranges(chip);
-       gpiochip_free_hogs(chip);
        of_gpiochip_remove(chip);
        /*
         * We accept no more calls into the driver from this point, so
@@ -1723,7 +1723,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
 }
 
 /**
- * _gpiochip_irqchip_add() - adds an irqchip to a gpiochip
+ * gpiochip_irqchip_add_key() - adds an irqchip to a gpiochip
  * @gpiochip: the gpiochip to add the irqchip to
  * @irqchip: the irqchip to add to the gpiochip
  * @first_irq: if not dynamically assigned, the base (first) IRQ to
@@ -1749,13 +1749,13 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
  * the pins on the gpiochip can generate a unique IRQ. Everything else
  * need to be open coded.
  */
-int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
-                         struct irq_chip *irqchip,
-                         unsigned int first_irq,
-                         irq_flow_handler_t handler,
-                         unsigned int type,
-                         bool nested,
-                         struct lock_class_key *lock_key)
+int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
+                            struct irq_chip *irqchip,
+                            unsigned int first_irq,
+                            irq_flow_handler_t handler,
+                            unsigned int type,
+                            bool nested,
+                            struct lock_class_key *lock_key)
 {
        struct device_node *of_node;
        bool irq_base_set = false;
@@ -1840,7 +1840,7 @@ int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add);
+EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);
 
 #else /* CONFIG_GPIOLIB_IRQCHIP */
 
index 9ada56c16a589d01e43162f656c0a25c8d926284..4c851fde1e82231d04366b1916da170d0b24cb0e 100644 (file)
@@ -840,6 +840,9 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                                else if (type == CGS_UCODE_ID_SMU_SK)
                                        strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
                                break;
+                       case CHIP_POLARIS12:
+                               strcpy(fw_name, "amdgpu/polaris12_smc.bin");
+                               break;
                        default:
                                DRM_ERROR("SMC firmware not supported\n");
                                return -EINVAL;
index 29d6d84d1c28b1e847715c08b6fac8f9d2a9aac3..41e41f90265df07af3299f65022feaf731e99ce7 100644 (file)
@@ -83,6 +83,13 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
                }
                break;
        }
+
+       if (!(*out_ring && (*out_ring)->adev)) {
+               DRM_ERROR("Ring %d is not initialized on IP %d\n",
+                         ring, ip_type);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
index 60bd4afe45c8c550b48e4484bf4d42f279f161c5..fe3bb94fe58df1fed0df7160c47932f358a513e8 100644 (file)
@@ -73,6 +73,7 @@ static const char *amdgpu_asic_name[] = {
        "STONEY",
        "POLARIS10",
        "POLARIS11",
+       "POLARIS12",
        "LAST",
 };
 
@@ -1277,6 +1278,7 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
        case CHIP_FIJI:
        case CHIP_POLARIS11:
        case CHIP_POLARIS10:
+       case CHIP_POLARIS12:
        case CHIP_CARRIZO:
        case CHIP_STONEY:
                if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
index 8cb937b2bfcc7fac0e3308aaa5cdc70cd53021c2..2534adaebe30f2d11a27fbaa121ff23cf6fce561 100644 (file)
@@ -418,6 +418,13 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
        {0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
        {0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+       /* Polaris12 */
+       {0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+       {0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
 
        {0, 0, 0}
 };
index fc592c2b0e166825100c1908691f02ac2f49a642..95a568df8551e589701b9cb2d1be6c04d97bf14a 100644 (file)
@@ -98,6 +98,7 @@ static int amdgpu_pp_early_init(void *handle)
        switch (adev->asic_type) {
        case CHIP_POLARIS11:
        case CHIP_POLARIS10:
+       case CHIP_POLARIS12:
        case CHIP_TONGA:
        case CHIP_FIJI:
        case CHIP_TOPAZ:
index a81dfaeeb8c0713e61b66046cf35fb8f89f86161..1d564beb0fde67541eab9be4ee76a39eb89197e1 100644 (file)
@@ -65,6 +65,7 @@
 #define FIRMWARE_STONEY                "amdgpu/stoney_uvd.bin"
 #define FIRMWARE_POLARIS10     "amdgpu/polaris10_uvd.bin"
 #define FIRMWARE_POLARIS11     "amdgpu/polaris11_uvd.bin"
+#define FIRMWARE_POLARIS12     "amdgpu/polaris12_uvd.bin"
 
 /**
  * amdgpu_uvd_cs_ctx - Command submission parser context
@@ -98,6 +99,7 @@ MODULE_FIRMWARE(FIRMWARE_FIJI);
 MODULE_FIRMWARE(FIRMWARE_STONEY);
 MODULE_FIRMWARE(FIRMWARE_POLARIS10);
 MODULE_FIRMWARE(FIRMWARE_POLARIS11);
+MODULE_FIRMWARE(FIRMWARE_POLARIS12);
 
 static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
 
@@ -149,6 +151,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
        case CHIP_POLARIS11:
                fw_name = FIRMWARE_POLARIS11;
                break;
+       case CHIP_POLARIS12:
+               fw_name = FIRMWARE_POLARIS12;
+               break;
        default:
                return -EINVAL;
        }
index 69b66b9e7f57e4ffaab3f83d6c17fb3a7161df34..8fec802d3908c05459c1e0ca2737cd19450ce9a4 100644 (file)
@@ -52,6 +52,7 @@
 #define FIRMWARE_STONEY                "amdgpu/stoney_vce.bin"
 #define FIRMWARE_POLARIS10     "amdgpu/polaris10_vce.bin"
 #define FIRMWARE_POLARIS11         "amdgpu/polaris11_vce.bin"
+#define FIRMWARE_POLARIS12         "amdgpu/polaris12_vce.bin"
 
 #ifdef CONFIG_DRM_AMDGPU_CIK
 MODULE_FIRMWARE(FIRMWARE_BONAIRE);
@@ -66,6 +67,7 @@ MODULE_FIRMWARE(FIRMWARE_FIJI);
 MODULE_FIRMWARE(FIRMWARE_STONEY);
 MODULE_FIRMWARE(FIRMWARE_POLARIS10);
 MODULE_FIRMWARE(FIRMWARE_POLARIS11);
+MODULE_FIRMWARE(FIRMWARE_POLARIS12);
 
 static void amdgpu_vce_idle_work_handler(struct work_struct *work);
 
@@ -121,6 +123,9 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
        case CHIP_POLARIS11:
                fw_name = FIRMWARE_POLARIS11;
                break;
+       case CHIP_POLARIS12:
+               fw_name = FIRMWARE_POLARIS12;
+               break;
 
        default:
                return -EINVAL;
index 9999dc71b998599f909464c32e98ca8cc1be5ddb..ccb5e02e7b20ffb3f8cb1776ea6a67a1b879cb33 100644 (file)
@@ -2512,6 +2512,8 @@ static int dce_v10_0_cursor_move_locked(struct drm_crtc *crtc,
 
        WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
        WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
+       WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+              ((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
        return 0;
 }
@@ -2537,7 +2539,6 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
                                      int32_t hot_y)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
        struct drm_gem_object *obj;
        struct amdgpu_bo *aobj;
        int ret;
@@ -2578,7 +2579,9 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
        dce_v10_0_lock_cursor(crtc, true);
 
-       if (hot_x != amdgpu_crtc->cursor_hot_x ||
+       if (width != amdgpu_crtc->cursor_width ||
+           height != amdgpu_crtc->cursor_height ||
+           hot_x != amdgpu_crtc->cursor_hot_x ||
            hot_y != amdgpu_crtc->cursor_hot_y) {
                int x, y;
 
@@ -2587,16 +2590,10 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
                dce_v10_0_cursor_move_locked(crtc, x, y);
 
-               amdgpu_crtc->cursor_hot_x = hot_x;
-               amdgpu_crtc->cursor_hot_y = hot_y;
-       }
-
-       if (width != amdgpu_crtc->cursor_width ||
-           height != amdgpu_crtc->cursor_height) {
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (width - 1) << 16 | (height - 1));
                amdgpu_crtc->cursor_width = width;
                amdgpu_crtc->cursor_height = height;
+               amdgpu_crtc->cursor_hot_x = hot_x;
+               amdgpu_crtc->cursor_hot_y = hot_y;
        }
 
        dce_v10_0_show_cursor(crtc);
@@ -2620,7 +2617,6 @@ unpin:
 static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
 
        if (amdgpu_crtc->cursor_bo) {
                dce_v10_0_lock_cursor(crtc, true);
@@ -2628,10 +2624,6 @@ static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
                dce_v10_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
                                             amdgpu_crtc->cursor_y);
 
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (amdgpu_crtc->cursor_width - 1) << 16 |
-                      (amdgpu_crtc->cursor_height - 1));
-
                dce_v10_0_show_cursor(crtc);
 
                dce_v10_0_lock_cursor(crtc, false);
index b3d62b909f4372db1e569308e29a436de873d0c9..a7af5b33a5e30e1279619c096295e12e415acafe 100644 (file)
@@ -167,6 +167,7 @@ static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
                                                 (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                amdgpu_program_register_sequence(adev,
                                                 polaris11_golden_settings_a11,
                                                 (const u32)ARRAY_SIZE(polaris11_golden_settings_a11));
@@ -608,6 +609,7 @@ static int dce_v11_0_get_num_crtc (struct amdgpu_device *adev)
                num_crtc = 6;
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                num_crtc = 5;
                break;
        default:
@@ -1589,6 +1591,7 @@ static int dce_v11_0_audio_init(struct amdgpu_device *adev)
                adev->mode_info.audio.num_pins = 8;
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                adev->mode_info.audio.num_pins = 6;
                break;
        default:
@@ -2388,7 +2391,8 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc)
        int pll;
 
        if ((adev->asic_type == CHIP_POLARIS10) ||
-           (adev->asic_type == CHIP_POLARIS11)) {
+           (adev->asic_type == CHIP_POLARIS11) ||
+           (adev->asic_type == CHIP_POLARIS12)) {
                struct amdgpu_encoder *amdgpu_encoder =
                        to_amdgpu_encoder(amdgpu_crtc->encoder);
                struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
@@ -2528,6 +2532,8 @@ static int dce_v11_0_cursor_move_locked(struct drm_crtc *crtc,
 
        WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
        WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
+       WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+              ((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
        return 0;
 }
@@ -2553,7 +2559,6 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
                                      int32_t hot_y)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
        struct drm_gem_object *obj;
        struct amdgpu_bo *aobj;
        int ret;
@@ -2594,7 +2599,9 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
        dce_v11_0_lock_cursor(crtc, true);
 
-       if (hot_x != amdgpu_crtc->cursor_hot_x ||
+       if (width != amdgpu_crtc->cursor_width ||
+           height != amdgpu_crtc->cursor_height ||
+           hot_x != amdgpu_crtc->cursor_hot_x ||
            hot_y != amdgpu_crtc->cursor_hot_y) {
                int x, y;
 
@@ -2603,16 +2610,10 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
                dce_v11_0_cursor_move_locked(crtc, x, y);
 
-               amdgpu_crtc->cursor_hot_x = hot_x;
-               amdgpu_crtc->cursor_hot_y = hot_y;
-       }
-
-       if (width != amdgpu_crtc->cursor_width ||
-           height != amdgpu_crtc->cursor_height) {
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (width - 1) << 16 | (height - 1));
                amdgpu_crtc->cursor_width = width;
                amdgpu_crtc->cursor_height = height;
+               amdgpu_crtc->cursor_hot_x = hot_x;
+               amdgpu_crtc->cursor_hot_y = hot_y;
        }
 
        dce_v11_0_show_cursor(crtc);
@@ -2636,7 +2637,6 @@ unpin:
 static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
 
        if (amdgpu_crtc->cursor_bo) {
                dce_v11_0_lock_cursor(crtc, true);
@@ -2644,10 +2644,6 @@ static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
                dce_v11_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
                                             amdgpu_crtc->cursor_y);
 
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (amdgpu_crtc->cursor_width - 1) << 16 |
-                      (amdgpu_crtc->cursor_height - 1));
-
                dce_v11_0_show_cursor(crtc);
 
                dce_v11_0_lock_cursor(crtc, false);
@@ -2822,7 +2818,8 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc,
                return -EINVAL;
 
        if ((adev->asic_type == CHIP_POLARIS10) ||
-           (adev->asic_type == CHIP_POLARIS11)) {
+           (adev->asic_type == CHIP_POLARIS11) ||
+           (adev->asic_type == CHIP_POLARIS12)) {
                struct amdgpu_encoder *amdgpu_encoder =
                        to_amdgpu_encoder(amdgpu_crtc->encoder);
                int encoder_mode =
@@ -2992,6 +2989,7 @@ static int dce_v11_0_early_init(void *handle)
                adev->mode_info.num_dig = 6;
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                adev->mode_info.num_hpd = 5;
                adev->mode_info.num_dig = 5;
                break;
@@ -3101,7 +3099,8 @@ static int dce_v11_0_hw_init(void *handle)
        amdgpu_atombios_crtc_powergate_init(adev);
        amdgpu_atombios_encoder_init_dig(adev);
        if ((adev->asic_type == CHIP_POLARIS10) ||
-           (adev->asic_type == CHIP_POLARIS11)) {
+           (adev->asic_type == CHIP_POLARIS11) ||
+           (adev->asic_type == CHIP_POLARIS12)) {
                amdgpu_atombios_crtc_set_dce_clock(adev, adev->clock.default_dispclk,
                                                   DCE_CLOCK_TYPE_DISPCLK, ATOM_GCK_DFS);
                amdgpu_atombios_crtc_set_dce_clock(adev, 0,
index b4e4ec630e8cfd5d38d55b61199f3cc60269e0c2..39df6a50637f5a9de0d98099c12e78188dc3ef4a 100644 (file)
@@ -1859,6 +1859,8 @@ static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc,
        struct amdgpu_device *adev = crtc->dev->dev_private;
        int xorigin = 0, yorigin = 0;
 
+       int w = amdgpu_crtc->cursor_width;
+
        amdgpu_crtc->cursor_x = x;
        amdgpu_crtc->cursor_y = y;
 
@@ -1878,6 +1880,8 @@ static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc,
 
        WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
        WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
+       WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+              ((w - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
        return 0;
 }
@@ -1903,7 +1907,6 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
                                     int32_t hot_y)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
        struct drm_gem_object *obj;
        struct amdgpu_bo *aobj;
        int ret;
@@ -1944,7 +1947,9 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
        dce_v6_0_lock_cursor(crtc, true);
 
-       if (hot_x != amdgpu_crtc->cursor_hot_x ||
+       if (width != amdgpu_crtc->cursor_width ||
+           height != amdgpu_crtc->cursor_height ||
+           hot_x != amdgpu_crtc->cursor_hot_x ||
            hot_y != amdgpu_crtc->cursor_hot_y) {
                int x, y;
 
@@ -1953,16 +1958,10 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
                dce_v6_0_cursor_move_locked(crtc, x, y);
 
-               amdgpu_crtc->cursor_hot_x = hot_x;
-               amdgpu_crtc->cursor_hot_y = hot_y;
-       }
-
-       if (width != amdgpu_crtc->cursor_width ||
-           height != amdgpu_crtc->cursor_height) {
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (width - 1) << 16 | (height - 1));
                amdgpu_crtc->cursor_width = width;
                amdgpu_crtc->cursor_height = height;
+               amdgpu_crtc->cursor_hot_x = hot_x;
+               amdgpu_crtc->cursor_hot_y = hot_y;
        }
 
        dce_v6_0_show_cursor(crtc);
@@ -1986,7 +1985,6 @@ unpin:
 static void dce_v6_0_cursor_reset(struct drm_crtc *crtc)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
 
        if (amdgpu_crtc->cursor_bo) {
                dce_v6_0_lock_cursor(crtc, true);
@@ -1994,10 +1992,6 @@ static void dce_v6_0_cursor_reset(struct drm_crtc *crtc)
                dce_v6_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
                                            amdgpu_crtc->cursor_y);
 
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (amdgpu_crtc->cursor_width - 1) << 16 |
-                      (amdgpu_crtc->cursor_height - 1));
-
                dce_v6_0_show_cursor(crtc);
                dce_v6_0_lock_cursor(crtc, false);
        }
index 584abe834a3ce4658de0e54f6aae416729ad868f..28102bb1704d0b618318a9bcf4b9668bce899150 100644 (file)
@@ -2363,6 +2363,8 @@ static int dce_v8_0_cursor_move_locked(struct drm_crtc *crtc,
 
        WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
        WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
+       WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
+              ((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
        return 0;
 }
@@ -2388,7 +2390,6 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
                                     int32_t hot_y)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
        struct drm_gem_object *obj;
        struct amdgpu_bo *aobj;
        int ret;
@@ -2429,7 +2430,9 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
        dce_v8_0_lock_cursor(crtc, true);
 
-       if (hot_x != amdgpu_crtc->cursor_hot_x ||
+       if (width != amdgpu_crtc->cursor_width ||
+           height != amdgpu_crtc->cursor_height ||
+           hot_x != amdgpu_crtc->cursor_hot_x ||
            hot_y != amdgpu_crtc->cursor_hot_y) {
                int x, y;
 
@@ -2438,16 +2441,10 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
 
                dce_v8_0_cursor_move_locked(crtc, x, y);
 
-               amdgpu_crtc->cursor_hot_x = hot_x;
-               amdgpu_crtc->cursor_hot_y = hot_y;
-       }
-
-       if (width != amdgpu_crtc->cursor_width ||
-           height != amdgpu_crtc->cursor_height) {
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (width - 1) << 16 | (height - 1));
                amdgpu_crtc->cursor_width = width;
                amdgpu_crtc->cursor_height = height;
+               amdgpu_crtc->cursor_hot_x = hot_x;
+               amdgpu_crtc->cursor_hot_y = hot_y;
        }
 
        dce_v8_0_show_cursor(crtc);
@@ -2471,7 +2468,6 @@ unpin:
 static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-       struct amdgpu_device *adev = crtc->dev->dev_private;
 
        if (amdgpu_crtc->cursor_bo) {
                dce_v8_0_lock_cursor(crtc, true);
@@ -2479,10 +2475,6 @@ static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
                dce_v8_0_cursor_move_locked(crtc, amdgpu_crtc->cursor_x,
                                            amdgpu_crtc->cursor_y);
 
-               WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
-                      (amdgpu_crtc->cursor_width - 1) << 16 |
-                      (amdgpu_crtc->cursor_height - 1));
-
                dce_v8_0_show_cursor(crtc);
 
                dce_v8_0_lock_cursor(crtc, false);
index 762f8e82ceb7465f56aa8cfcd7124ce0fc28acda..e9a176891e13319d77e10b643a44b9e893e562ac 100644 (file)
@@ -627,11 +627,8 @@ static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs =
 
 static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
 {
-       struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
-
-       kfree(amdgpu_encoder->enc_priv);
        drm_encoder_cleanup(encoder);
-       kfree(amdgpu_encoder);
+       kfree(encoder);
 }
 
 static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
index d0ec00986f3826c32957ab432c677c53c24091c2..373374164bd59edc0970e3f73a77ca31b17652e7 100644 (file)
@@ -139,6 +139,13 @@ MODULE_FIRMWARE("amdgpu/polaris10_mec.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_mec2.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_rlc.bin");
 
+MODULE_FIRMWARE("amdgpu/polaris12_ce.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_pfp.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_me.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_mec.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_mec2.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_rlc.bin");
+
 static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] =
 {
        {mmGDS_VMID0_BASE, mmGDS_VMID0_SIZE, mmGDS_GWS_VMID0, mmGDS_OA_VMID0},
@@ -689,6 +696,7 @@ static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
                                                 (const u32)ARRAY_SIZE(tonga_golden_common_all));
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                amdgpu_program_register_sequence(adev,
                                                 golden_settings_polaris11_a11,
                                                 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -903,6 +911,9 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
        case CHIP_POLARIS10:
                chip_name = "polaris10";
                break;
+       case CHIP_POLARIS12:
+               chip_name = "polaris12";
+               break;
        case CHIP_STONEY:
                chip_name = "stoney";
                break;
@@ -1768,6 +1779,7 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
                gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                ret = amdgpu_atombios_get_gfx_info(adev);
                if (ret)
                        return ret;
@@ -2682,6 +2694,7 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev)
 
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
                                PIPE_CONFIG(ADDR_SURF_P4_16x16) |
                                TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
@@ -3503,6 +3516,7 @@ gfx_v8_0_raster_config(struct amdgpu_device *adev, u32 *rconf, u32 *rconf1)
                *rconf1 |= 0x0;
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                *rconf |= RB_MAP_PKR0(2) | RB_XSEL2(1) | SE_MAP(2) |
                          SE_XSEL(1) | SE_YSEL(1);
                *rconf1 |= 0x0;
@@ -4021,7 +4035,8 @@ static void gfx_v8_0_init_pg(struct amdgpu_device *adev)
                        cz_enable_cp_power_gating(adev, true);
                else
                        cz_enable_cp_power_gating(adev, false);
-       } else if (adev->asic_type == CHIP_POLARIS11) {
+       } else if ((adev->asic_type == CHIP_POLARIS11) ||
+                  (adev->asic_type == CHIP_POLARIS12)) {
                gfx_v8_0_init_csb(adev);
                gfx_v8_0_init_save_restore_list(adev);
                gfx_v8_0_enable_save_restore_machine(adev);
@@ -4095,7 +4110,8 @@ static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev)
                 RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
        WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);
        if (adev->asic_type == CHIP_POLARIS11 ||
-           adev->asic_type == CHIP_POLARIS10) {
+           adev->asic_type == CHIP_POLARIS10 ||
+           adev->asic_type == CHIP_POLARIS12) {
                tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D);
                tmp &= ~0x3;
                WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp);
@@ -4283,6 +4299,7 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
                amdgpu_ring_write(ring, 0x0000002A);
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                amdgpu_ring_write(ring, 0x16000012);
                amdgpu_ring_write(ring, 0x00000000);
                break;
@@ -4664,7 +4681,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
                            (adev->asic_type == CHIP_FIJI) ||
                            (adev->asic_type == CHIP_STONEY) ||
                            (adev->asic_type == CHIP_POLARIS11) ||
-                           (adev->asic_type == CHIP_POLARIS10)) {
+                           (adev->asic_type == CHIP_POLARIS10) ||
+                           (adev->asic_type == CHIP_POLARIS12)) {
                                WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
                                       AMDGPU_DOORBELL_KIQ << 2);
                                WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -4700,7 +4718,8 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
                mqd->cp_hqd_persistent_state = tmp;
                if (adev->asic_type == CHIP_STONEY ||
                        adev->asic_type == CHIP_POLARIS11 ||
-                       adev->asic_type == CHIP_POLARIS10) {
+                       adev->asic_type == CHIP_POLARIS10 ||
+                       adev->asic_type == CHIP_POLARIS12) {
                        tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
                        tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
                        WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
@@ -5279,7 +5298,8 @@ static int gfx_v8_0_late_init(void *handle)
 static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev,
                                                       bool enable)
 {
-       if (adev->asic_type == CHIP_POLARIS11)
+       if ((adev->asic_type == CHIP_POLARIS11) ||
+           (adev->asic_type == CHIP_POLARIS12))
                /* Send msg to SMU via Powerplay */
                amdgpu_set_powergating_state(adev,
                                             AMD_IP_BLOCK_TYPE_SMC,
@@ -5353,6 +5373,7 @@ static int gfx_v8_0_set_powergating_state(void *handle,
                        gfx_v8_0_enable_gfx_dynamic_mg_power_gating(adev, false);
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
                        gfx_v8_0_enable_gfx_static_mg_power_gating(adev, true);
                else
index 45a573e63d4ae9778cff0b022ef53e22163e9a7b..0635829b18cf3aed41239079e4208336b00cda0f 100644 (file)
@@ -44,6 +44,7 @@ MODULE_FIRMWARE("radeon/tahiti_mc.bin");
 MODULE_FIRMWARE("radeon/pitcairn_mc.bin");
 MODULE_FIRMWARE("radeon/verde_mc.bin");
 MODULE_FIRMWARE("radeon/oland_mc.bin");
+MODULE_FIRMWARE("radeon/si58_mc.bin");
 
 #define MC_SEQ_MISC0__MT__MASK   0xf0000000
 #define MC_SEQ_MISC0__MT__GDDR1  0x10000000
@@ -113,6 +114,7 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
        const char *chip_name;
        char fw_name[30];
        int err;
+       bool is_58_fw = false;
 
        DRM_DEBUG("\n");
 
@@ -135,7 +137,14 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev)
        default: BUG();
        }
 
-       snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+       /* this memory configuration requires special firmware */
+       if (((RREG32(mmMC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
+               is_58_fw = true;
+
+       if (is_58_fw)
+               snprintf(fw_name, sizeof(fw_name), "radeon/si58_mc.bin");
+       else
+               snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
        err = request_firmware(&adev->mc.fw, fw_name, adev->dev);
        if (err)
                goto out;
@@ -245,6 +254,9 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
        }
        WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
 
+       if (adev->mode_info.num_crtc)
+               amdgpu_display_set_vga_render_state(adev, false);
+
        gmc_v6_0_mc_stop(adev, &save);
 
        if (gmc_v6_0_wait_for_idle((void *)adev)) {
@@ -274,7 +286,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
                dev_warn(adev->dev, "Wait for MC idle timedout !\n");
        }
        gmc_v6_0_mc_resume(adev, &save);
-       amdgpu_display_set_vga_render_state(adev, false);
 }
 
 static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
@@ -463,19 +474,11 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
        WREG32(mmVM_CONTEXT1_CNTL,
               VM_CONTEXT1_CNTL__ENABLE_CONTEXT_MASK |
               (1UL << VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH__SHIFT) |
-              ((amdgpu_vm_block_size - 9) << VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT) |
-              VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
-              VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
-              VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
-              VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
-              VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
-              VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
-              VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
-              VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
-              VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
-              VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT_MASK |
-              VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
-              VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK);
+              ((amdgpu_vm_block_size - 9) << VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT));
+       if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
+               gmc_v6_0_set_fault_enable_default(adev, false);
+       else
+               gmc_v6_0_set_fault_enable_default(adev, true);
 
        gmc_v6_0_gart_flush_gpu_tlb(adev, 0);
        dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n",
@@ -754,7 +757,10 @@ static int gmc_v6_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+       if (amdgpu_vm_fault_stop != AMDGPU_VM_FAULT_STOP_ALWAYS)
+               return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+       else
+               return 0;
 }
 
 static int gmc_v6_0_sw_init(void *handle)
index 0daac3a5be79572e65a2fff812453c2bd541940c..476bc9f1954b9daee41d154a94b17ee0896e59ed 100644 (file)
@@ -46,6 +46,7 @@ static int gmc_v8_0_wait_for_idle(void *handle);
 MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_mc.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_mc.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_mc.bin");
 
 static const u32 golden_settings_tonga_a11[] =
 {
@@ -130,6 +131,7 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
                                                 (const u32)ARRAY_SIZE(golden_settings_tonga_a11));
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                amdgpu_program_register_sequence(adev,
                                                 golden_settings_polaris11_a11,
                                                 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -225,6 +227,9 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
        case CHIP_POLARIS10:
                chip_name = "polaris10";
                break;
+       case CHIP_POLARIS12:
+               chip_name = "polaris12";
+               break;
        case CHIP_FIJI:
        case CHIP_CARRIZO:
        case CHIP_STONEY:
index 1170a64a3184f6788c58cf1f6038bacaf45c4e62..034ace79ed492951d1ed06b9dc1543419b1948bf 100644 (file)
@@ -60,6 +60,8 @@ MODULE_FIRMWARE("amdgpu/polaris10_sdma.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_sdma1.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_sdma.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_sdma1.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_sdma.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_sdma1.bin");
 
 
 static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
@@ -206,6 +208,7 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
                                                 (const u32)ARRAY_SIZE(golden_settings_tonga_a11));
                break;
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                amdgpu_program_register_sequence(adev,
                                                 golden_settings_polaris11_a11,
                                                 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -278,6 +281,9 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
        case CHIP_POLARIS10:
                chip_name = "polaris10";
                break;
+       case CHIP_POLARIS12:
+               chip_name = "polaris12";
+               break;
        case CHIP_CARRIZO:
                chip_name = "carrizo";
                break;
index 6c65a1a2de798b5630d6b356065a32fe578608c5..6e150db8f380417870cea60283ecacaf1c14fa7d 100644 (file)
@@ -56,7 +56,6 @@
 #define BIOS_SCRATCH_4                                    0x5cd
 
 MODULE_FIRMWARE("radeon/tahiti_smc.bin");
-MODULE_FIRMWARE("radeon/tahiti_k_smc.bin");
 MODULE_FIRMWARE("radeon/pitcairn_smc.bin");
 MODULE_FIRMWARE("radeon/pitcairn_k_smc.bin");
 MODULE_FIRMWARE("radeon/verde_smc.bin");
@@ -65,6 +64,7 @@ MODULE_FIRMWARE("radeon/oland_smc.bin");
 MODULE_FIRMWARE("radeon/oland_k_smc.bin");
 MODULE_FIRMWARE("radeon/hainan_smc.bin");
 MODULE_FIRMWARE("radeon/hainan_k_smc.bin");
+MODULE_FIRMWARE("radeon/banks_k_2_smc.bin");
 
 union power_info {
        struct _ATOM_POWERPLAY_INFO info;
@@ -3488,30 +3488,6 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
                    (adev->pdev->device == 0x6817) ||
                    (adev->pdev->device == 0x6806))
                        max_mclk = 120000;
-       } else if (adev->asic_type == CHIP_VERDE) {
-               if ((adev->pdev->revision == 0x81) ||
-                   (adev->pdev->revision == 0x83) ||
-                   (adev->pdev->revision == 0x87) ||
-                   (adev->pdev->device == 0x6820) ||
-                   (adev->pdev->device == 0x6821) ||
-                   (adev->pdev->device == 0x6822) ||
-                   (adev->pdev->device == 0x6823) ||
-                   (adev->pdev->device == 0x682A) ||
-                   (adev->pdev->device == 0x682B)) {
-                       max_sclk = 75000;
-                       max_mclk = 80000;
-               }
-       } else if (adev->asic_type == CHIP_OLAND) {
-               if ((adev->pdev->revision == 0xC7) ||
-                   (adev->pdev->revision == 0x80) ||
-                   (adev->pdev->revision == 0x81) ||
-                   (adev->pdev->revision == 0x83) ||
-                   (adev->pdev->revision == 0x87) ||
-                   (adev->pdev->device == 0x6604) ||
-                   (adev->pdev->device == 0x6605)) {
-                       max_sclk = 75000;
-                       max_mclk = 80000;
-               }
        } else if (adev->asic_type == CHIP_HAINAN) {
                if ((adev->pdev->revision == 0x81) ||
                    (adev->pdev->revision == 0x83) ||
@@ -3520,7 +3496,6 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
                    (adev->pdev->device == 0x6665) ||
                    (adev->pdev->device == 0x6667)) {
                        max_sclk = 75000;
-                       max_mclk = 80000;
                }
        }
        /* Apply dpm quirks */
@@ -7687,50 +7662,51 @@ static int si_dpm_init_microcode(struct amdgpu_device *adev)
                chip_name = "tahiti";
                break;
        case CHIP_PITCAIRN:
-               if ((adev->pdev->revision == 0x81) ||
-                   (adev->pdev->device == 0x6810) ||
-                   (adev->pdev->device == 0x6811) ||
-                   (adev->pdev->device == 0x6816) ||
-                   (adev->pdev->device == 0x6817) ||
-                   (adev->pdev->device == 0x6806))
+               if ((adev->pdev->revision == 0x81) &&
+                   ((adev->pdev->device == 0x6810) ||
+                   (adev->pdev->device == 0x6811)))
                        chip_name = "pitcairn_k";
                else
                        chip_name = "pitcairn";
                break;
        case CHIP_VERDE:
-               if ((adev->pdev->revision == 0x81) ||
-                   (adev->pdev->revision == 0x83) ||
-                   (adev->pdev->revision == 0x87) ||
-                   (adev->pdev->device == 0x6820) ||
-                   (adev->pdev->device == 0x6821) ||
-                   (adev->pdev->device == 0x6822) ||
-                   (adev->pdev->device == 0x6823) ||
-                   (adev->pdev->device == 0x682A) ||
-                   (adev->pdev->device == 0x682B))
+               if (((adev->pdev->device == 0x6820) &&
+                       ((adev->pdev->revision == 0x81) ||
+                       (adev->pdev->revision == 0x83))) ||
+                   ((adev->pdev->device == 0x6821) &&
+                       ((adev->pdev->revision == 0x83) ||
+                       (adev->pdev->revision == 0x87))) ||
+                   ((adev->pdev->revision == 0x87) &&
+                       ((adev->pdev->device == 0x6823) ||
+                       (adev->pdev->device == 0x682b))))
                        chip_name = "verde_k";
                else
                        chip_name = "verde";
                break;
        case CHIP_OLAND:
-               if ((adev->pdev->revision == 0xC7) ||
-                   (adev->pdev->revision == 0x80) ||
-                   (adev->pdev->revision == 0x81) ||
-                   (adev->pdev->revision == 0x83) ||
-                   (adev->pdev->revision == 0x87) ||
-                   (adev->pdev->device == 0x6604) ||
-                   (adev->pdev->device == 0x6605))
+               if (((adev->pdev->revision == 0x81) &&
+                       ((adev->pdev->device == 0x6600) ||
+                       (adev->pdev->device == 0x6604) ||
+                       (adev->pdev->device == 0x6605) ||
+                       (adev->pdev->device == 0x6610))) ||
+                   ((adev->pdev->revision == 0x83) &&
+                       (adev->pdev->device == 0x6610)))
                        chip_name = "oland_k";
                else
                        chip_name = "oland";
                break;
        case CHIP_HAINAN:
-               if ((adev->pdev->revision == 0x81) ||
-                   (adev->pdev->revision == 0x83) ||
-                   (adev->pdev->revision == 0xC3) ||
-                   (adev->pdev->device == 0x6664) ||
-                   (adev->pdev->device == 0x6665) ||
-                   (adev->pdev->device == 0x6667))
+               if (((adev->pdev->revision == 0x81) &&
+                       (adev->pdev->device == 0x6660)) ||
+                   ((adev->pdev->revision == 0x83) &&
+                       ((adev->pdev->device == 0x6660) ||
+                       (adev->pdev->device == 0x6663) ||
+                       (adev->pdev->device == 0x6665) ||
+                        (adev->pdev->device == 0x6667))))
                        chip_name = "hainan_k";
+               else if ((adev->pdev->revision == 0xc3) &&
+                        (adev->pdev->device == 0x6665))
+                       chip_name = "banks_k_2";
                else
                        chip_name = "hainan";
                break;
index 96444e4d862af3f011c3b3de8481aafe39529414..7fb9137dd89b1c2bc064c3ea516c243721b5dafe 100644 (file)
 #include "smu/smu_7_0_1_sh_mask.h"
 
 static void uvd_v4_2_mc_resume(struct amdgpu_device *adev);
-static void uvd_v4_2_init_cg(struct amdgpu_device *adev);
 static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev);
 static void uvd_v4_2_set_irq_funcs(struct amdgpu_device *adev);
 static int uvd_v4_2_start(struct amdgpu_device *adev);
 static void uvd_v4_2_stop(struct amdgpu_device *adev);
 static int uvd_v4_2_set_clockgating_state(void *handle,
                                enum amd_clockgating_state state);
+static void uvd_v4_2_set_dcm(struct amdgpu_device *adev,
+                            bool sw_mode);
 /**
  * uvd_v4_2_ring_get_rptr - get read pointer
  *
@@ -140,7 +141,8 @@ static int uvd_v4_2_sw_fini(void *handle)
 
        return r;
 }
-
+static void uvd_v4_2_enable_mgcg(struct amdgpu_device *adev,
+                                bool enable);
 /**
  * uvd_v4_2_hw_init - start and test UVD block
  *
@@ -155,8 +157,7 @@ static int uvd_v4_2_hw_init(void *handle)
        uint32_t tmp;
        int r;
 
-       uvd_v4_2_init_cg(adev);
-       uvd_v4_2_set_clockgating_state(adev, AMD_CG_STATE_GATE);
+       uvd_v4_2_enable_mgcg(adev, true);
        amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
        r = uvd_v4_2_start(adev);
        if (r)
@@ -266,11 +267,13 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
        struct amdgpu_ring *ring = &adev->uvd.ring;
        uint32_t rb_bufsz;
        int i, j, r;
-
        /* disable byte swapping */
        u32 lmi_swap_cntl = 0;
        u32 mp_swap_cntl = 0;
 
+       WREG32(mmUVD_CGC_GATE, 0);
+       uvd_v4_2_set_dcm(adev, true);
+
        uvd_v4_2_mc_resume(adev);
 
        /* disable interupt */
@@ -406,6 +409,8 @@ static void uvd_v4_2_stop(struct amdgpu_device *adev)
 
        /* Unstall UMC and register bus */
        WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));
+
+       uvd_v4_2_set_dcm(adev, false);
 }
 
 /**
@@ -619,19 +624,6 @@ static void uvd_v4_2_set_dcm(struct amdgpu_device *adev,
        WREG32_UVD_CTX(ixUVD_CGC_CTRL2, tmp2);
 }
 
-static void uvd_v4_2_init_cg(struct amdgpu_device *adev)
-{
-       bool hw_mode = true;
-
-       if (hw_mode) {
-               uvd_v4_2_set_dcm(adev, false);
-       } else {
-               u32 tmp = RREG32(mmUVD_CGC_CTRL);
-               tmp &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
-               WREG32(mmUVD_CGC_CTRL, tmp);
-       }
-}
-
 static bool uvd_v4_2_is_idle(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -685,17 +677,6 @@ static int uvd_v4_2_process_interrupt(struct amdgpu_device *adev,
 static int uvd_v4_2_set_clockgating_state(void *handle,
                                          enum amd_clockgating_state state)
 {
-       bool gate = false;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
-               return 0;
-
-       if (state == AMD_CG_STATE_GATE)
-               gate = true;
-
-       uvd_v4_2_enable_mgcg(adev, gate);
-
        return 0;
 }
 
@@ -711,9 +692,6 @@ static int uvd_v4_2_set_powergating_state(void *handle,
         */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
-               return 0;
-
        if (state == AMD_PG_STATE_GATE) {
                uvd_v4_2_stop(adev);
                return 0;
index a79e283590fbe7fc9b627a097ccec81b99d1a66c..6de6becce74567d962eb498dcd33cbd1aedc62c6 100644 (file)
@@ -791,15 +791,10 @@ static int uvd_v5_0_set_clockgating_state(void *handle,
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
-       static int curstate = -1;
 
        if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
                return 0;
 
-       if (curstate == state)
-               return 0;
-
-       curstate = state;
        if (enable) {
                /* wait for STATUS to clear */
                if (uvd_v5_0_wait_for_idle(handle))
index 6b3293a1c7b8b92d9d47d780de7c883a0beac195..37ca685e5a9a9e358eaab6d32b9d5758fec90565 100644 (file)
 
 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT    0x04
 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK      0x10
+#define GRBM_GFX_INDEX__VCE_ALL_PIPE           0x07
+
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0        0x8616
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1        0x8617
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2        0x8618
+#define mmGRBM_GFX_INDEX_DEFAULT 0xE0000000
+
 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK  0x02
 
 #define VCE_V3_0_FW_SIZE       (384 * 1024)
@@ -54,6 +58,9 @@
 
 #define FW_52_8_3      ((52 << 24) | (8 << 16) | (3 << 8))
 
+#define GET_VCE_INSTANCE(i)  ((i) << GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT \
+                                       | GRBM_GFX_INDEX__VCE_ALL_PIPE)
+
 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -175,7 +182,7 @@ static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev,
                WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
 
                data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
-               data &= ~0xffc00000;
+               data &= ~0x3ff;
                WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
 
                data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
@@ -249,7 +256,7 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
                if (adev->vce.harvest_config & (1 << idx))
                        continue;
 
-               WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
                vce_v3_0_mc_resume(adev, idx);
                WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
 
@@ -273,7 +280,7 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
                }
        }
 
-       WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+       WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
        mutex_unlock(&adev->grbm_idx_mutex);
 
        return 0;
@@ -288,7 +295,7 @@ static int vce_v3_0_stop(struct amdgpu_device *adev)
                if (adev->vce.harvest_config & (1 << idx))
                        continue;
 
-               WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
 
                if (adev->asic_type >= CHIP_STONEY)
                        WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x200001);
@@ -306,7 +313,7 @@ static int vce_v3_0_stop(struct amdgpu_device *adev)
                        vce_v3_0_set_vce_sw_clock_gating(adev, false);
        }
 
-       WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+       WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
        mutex_unlock(&adev->grbm_idx_mutex);
 
        return 0;
@@ -320,11 +327,12 @@ static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
 {
        u32 tmp;
 
-       /* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
+       /* Fiji, Stoney, Polaris10, Polaris11, Polaris12 are single pipe */
        if ((adev->asic_type == CHIP_FIJI) ||
            (adev->asic_type == CHIP_STONEY) ||
            (adev->asic_type == CHIP_POLARIS10) ||
-           (adev->asic_type == CHIP_POLARIS11))
+           (adev->asic_type == CHIP_POLARIS11) ||
+           (adev->asic_type == CHIP_POLARIS12))
                return AMDGPU_VCE_HARVEST_VCE1;
 
        /* Tonga and CZ are dual or single pipe */
@@ -585,17 +593,17 @@ static bool vce_v3_0_check_soft_reset(void *handle)
         * VCE team suggest use bit 3--bit 6 for busy status check
         */
        mutex_lock(&adev->grbm_idx_mutex);
-       WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+       WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
        if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
                srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
                srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
        }
-       WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10);
+       WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
        if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
                srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
                srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
        }
-       WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+       WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
        mutex_unlock(&adev->grbm_idx_mutex);
 
        if (srbm_soft_reset) {
@@ -733,7 +741,7 @@ static int vce_v3_0_set_clockgating_state(void *handle,
                if (adev->vce.harvest_config & (1 << i))
                        continue;
 
-               WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, i);
+               WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(i));
 
                if (enable) {
                        /* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
@@ -752,7 +760,7 @@ static int vce_v3_0_set_clockgating_state(void *handle,
                vce_v3_0_set_vce_sw_clock_gating(adev, enable);
        }
 
-       WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+       WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
        mutex_unlock(&adev->grbm_idx_mutex);
 
        return 0;
index bf088d6d9bf1f96430d7afda1ec3fbeae6e82768..c2ac54f1134179457db3823eb64161817ee8f5b3 100644 (file)
@@ -88,6 +88,7 @@ MODULE_FIRMWARE("amdgpu/polaris10_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_smc.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_smc.bin");
 
 /*
  * Indirect registers accessor
@@ -312,6 +313,7 @@ static void vi_init_golden_registers(struct amdgpu_device *adev)
                break;
        case CHIP_POLARIS11:
        case CHIP_POLARIS10:
+       case CHIP_POLARIS12:
        default:
                break;
        }
@@ -671,6 +673,7 @@ static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
        case CHIP_TONGA:
        case CHIP_POLARIS11:
        case CHIP_POLARIS10:
+       case CHIP_POLARIS12:
        case CHIP_CARRIZO:
        case CHIP_STONEY:
                asic_register_table = cz_allowed_read_registers;
@@ -994,6 +997,11 @@ static int vi_common_early_init(void *handle)
                adev->pg_flags = 0;
                adev->external_rev_id = adev->rev_id + 0x50;
                break;
+       case CHIP_POLARIS12:
+               adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
+               adev->pg_flags = 0;
+               adev->external_rev_id = adev->rev_id + 0x64;
+               break;
        case CHIP_CARRIZO:
                adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
                        AMD_CG_SUPPORT_GFX_MGCG |
@@ -1346,6 +1354,7 @@ static int vi_common_set_clockgating_state(void *handle,
        case CHIP_TONGA:
        case CHIP_POLARIS10:
        case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
                vi_common_set_clockgating_state_by_smu(adev, state);
        default:
                break;
@@ -1429,6 +1438,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
                break;
        case CHIP_POLARIS11:
        case CHIP_POLARIS10:
+       case CHIP_POLARIS12:
                amdgpu_ip_block_add(adev, &vi_common_ip_block);
                amdgpu_ip_block_add(adev, &gmc_v8_1_ip_block);
                amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
index c02469ada9f131f417e2a4fdb1d0c6b1fac4eafa..85f358764bbc8f2475e0bbf36df5013312354cab 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef __AMD_SHARED_H__
 #define __AMD_SHARED_H__
 
-#define AMD_MAX_USEC_TIMEOUT           100000  /* 100 ms */
+#define AMD_MAX_USEC_TIMEOUT           200000  /* 200 ms */
 
 /*
  * Supported ASIC types
@@ -46,6 +46,7 @@ enum amd_asic_type {
        CHIP_STONEY,
        CHIP_POLARIS10,
        CHIP_POLARIS11,
+       CHIP_POLARIS12,
        CHIP_LAST,
 };
 
index b0c63c5f54c9ca95bc29eb069191455d1b56c0cd..6bb79c94cb9ffb5d7bec4fb104f9e32b7c3b3046 100644 (file)
@@ -200,7 +200,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
                                cgs_set_clockgating_state(
                                                        hwmgr->device,
                                                        AMD_IP_BLOCK_TYPE_VCE,
-                                                       AMD_CG_STATE_UNGATE);
+                                                       AMD_CG_STATE_GATE);
                                cgs_set_powergating_state(
                                                        hwmgr->device,
                                                        AMD_IP_BLOCK_TYPE_VCE,
@@ -218,7 +218,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
                                cgs_set_clockgating_state(
                                                        hwmgr->device,
                                                        AMD_IP_BLOCK_TYPE_VCE,
-                                                       AMD_PG_STATE_GATE);
+                                                       AMD_PG_STATE_UNGATE);
                                cz_dpm_update_vce_dpm(hwmgr);
                                cz_enable_disable_vce_dpm(hwmgr, true);
                                return 0;
index 4b14f259a147039e8e0eacc92da77f6266a2571e..0fb4e8c8f5e13866120de7325dd801c59f1d940f 100644 (file)
@@ -1402,14 +1402,22 @@ int  cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr)
                                             cz_hwmgr->vce_dpm.hard_min_clk,
                                                PPSMC_MSG_SetEclkHardMin));
        } else {
-               /*EPR# 419220 -HW limitation to to */
-               cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
-               smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-                                           PPSMC_MSG_SetEclkHardMin,
-                                           cz_get_eclk_level(hwmgr,
-                                    cz_hwmgr->vce_dpm.hard_min_clk,
-                                         PPSMC_MSG_SetEclkHardMin));
-
+               /*Program HardMin based on the vce_arbiter.ecclk */
+               if (hwmgr->vce_arbiter.ecclk == 0) {
+                       smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                                           PPSMC_MSG_SetEclkHardMin, 0);
+               /* disable ECLK DPM 0. Otherwise VCE could hang if
+                * switching SCLK from DPM 0 to 6/7 */
+                       smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                                       PPSMC_MSG_SetEclkSoftMin, 1);
+               } else {
+                       cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
+                       smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                                               PPSMC_MSG_SetEclkHardMin,
+                                               cz_get_eclk_level(hwmgr,
+                                               cz_hwmgr->vce_dpm.hard_min_clk,
+                                               PPSMC_MSG_SetEclkHardMin));
+               }
        }
        return 0;
 }
index dc6700aee18f624266a47d773abfb20bea573e03..b03606405a53399ea1a6755fecc637fa9bc09b23 100644 (file)
@@ -95,6 +95,7 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
                        break;
                case CHIP_POLARIS11:
                case CHIP_POLARIS10:
+               case CHIP_POLARIS12:
                        polaris_set_asic_special_caps(hwmgr);
                        hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
                        break;
@@ -745,7 +746,7 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                PHM_PlatformCaps_TablelessHardwareInterface);
 
-       if (hwmgr->chip_id == CHIP_POLARIS11)
+       if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12))
                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                        PHM_PlatformCaps_SPLLShutdownSupport);
        return 0;
index 26477f0f09dcc7045db5626abb7a9da8b4a2b3cc..6cd1287a7a8fda1cfe38482cd47899223496b2fd 100644 (file)
@@ -521,7 +521,7 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr)
                                PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
                                result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10);
                                PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
-                       } else if (hwmgr->chip_id == CHIP_POLARIS11) {
+                       } else if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12)) {
                                result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11);
                                PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
                                result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11);
index e5812aa456f3b1440e525f0592d299672db14759..6e618aa20719d27f56b05db5ed2a76b7b7829c97 100644 (file)
@@ -65,6 +65,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
                        break;
                case CHIP_POLARIS11:
                case CHIP_POLARIS10:
+               case CHIP_POLARIS12:
                        polaris10_smum_init(smumgr);
                        break;
                default:
index 908011d2c8f5200e92cc8db772b85315d5c16343..7abda94fc2cf3bb43ec686ac4e699a43b77a11d0 100644 (file)
@@ -113,6 +113,7 @@ struct ast_private {
        struct ttm_bo_kmap_obj cache_kmap;
        int next_cursor;
        bool support_wide_screen;
+       bool DisableP2A;
 
        enum ast_tx_chip tx_chip_type;
        u8 dp501_maxclk;
index f75c6421db6239c9435ed39dc7d6244d13894920..533e762d036dc272afbdf4d2bce146b6f1b450d9 100644 (file)
@@ -124,6 +124,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
        } else
                *need_post = false;
 
+       /* Check P2A Access */
+       ast->DisableP2A = true;
+       data = ast_read32(ast, 0xf004);
+       if (data != 0xFFFFFFFF)
+               ast->DisableP2A = false;
+
        /* Check if we support wide screen */
        switch (ast->chip) {
        case AST1180:
@@ -140,15 +146,17 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
                        ast->support_wide_screen = true;
                else {
                        ast->support_wide_screen = false;
-                       /* Read SCU7c (silicon revision register) */
-                       ast_write32(ast, 0xf004, 0x1e6e0000);
-                       ast_write32(ast, 0xf000, 0x1);
-                       data = ast_read32(ast, 0x1207c);
-                       data &= 0x300;
-                       if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
-                               ast->support_wide_screen = true;
-                       if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
-                               ast->support_wide_screen = true;
+                       if (ast->DisableP2A == false) {
+                               /* Read SCU7c (silicon revision register) */
+                               ast_write32(ast, 0xf004, 0x1e6e0000);
+                               ast_write32(ast, 0xf000, 0x1);
+                               data = ast_read32(ast, 0x1207c);
+                               data &= 0x300;
+                               if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
+                                       ast->support_wide_screen = true;
+                               if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
+                                       ast->support_wide_screen = true;
+                       }
                }
                break;
        }
@@ -216,80 +224,81 @@ static int ast_get_dram_info(struct drm_device *dev)
        uint32_t data, data2;
        uint32_t denum, num, div, ref_pll;
 
-       ast_write32(ast, 0xf004, 0x1e6e0000);
-       ast_write32(ast, 0xf000, 0x1);
-
-
-       ast_write32(ast, 0x10000, 0xfc600309);
-
-       do {
-               if (pci_channel_offline(dev->pdev))
-                       return -EIO;
-       } while (ast_read32(ast, 0x10000) != 0x01);
-       data = ast_read32(ast, 0x10004);
-
-       if (data & 0x40)
+       if (ast->DisableP2A)
+       {
                ast->dram_bus_width = 16;
+               ast->dram_type = AST_DRAM_1Gx16;
+               ast->mclk = 396;
+       }
        else
-               ast->dram_bus_width = 32;
+       {
+               ast_write32(ast, 0xf004, 0x1e6e0000);
+               ast_write32(ast, 0xf000, 0x1);
+               data = ast_read32(ast, 0x10004);
+
+               if (data & 0x40)
+                       ast->dram_bus_width = 16;
+               else
+                       ast->dram_bus_width = 32;
+
+               if (ast->chip == AST2300 || ast->chip == AST2400) {
+                       switch (data & 0x03) {
+                       case 0:
+                               ast->dram_type = AST_DRAM_512Mx16;
+                               break;
+                       default:
+                       case 1:
+                               ast->dram_type = AST_DRAM_1Gx16;
+                               break;
+                       case 2:
+                               ast->dram_type = AST_DRAM_2Gx16;
+                               break;
+                       case 3:
+                               ast->dram_type = AST_DRAM_4Gx16;
+                               break;
+                       }
+               } else {
+                       switch (data & 0x0c) {
+                       case 0:
+                       case 4:
+                               ast->dram_type = AST_DRAM_512Mx16;
+                               break;
+                       case 8:
+                               if (data & 0x40)
+                                       ast->dram_type = AST_DRAM_1Gx16;
+                               else
+                                       ast->dram_type = AST_DRAM_512Mx32;
+                               break;
+                       case 0xc:
+                               ast->dram_type = AST_DRAM_1Gx32;
+                               break;
+                       }
+               }
 
-       if (ast->chip == AST2300 || ast->chip == AST2400) {
-               switch (data & 0x03) {
-               case 0:
-                       ast->dram_type = AST_DRAM_512Mx16;
-                       break;
-               default:
-               case 1:
-                       ast->dram_type = AST_DRAM_1Gx16;
-                       break;
-               case 2:
-                       ast->dram_type = AST_DRAM_2Gx16;
-                       break;
+               data = ast_read32(ast, 0x10120);
+               data2 = ast_read32(ast, 0x10170);
+               if (data2 & 0x2000)
+                       ref_pll = 14318;
+               else
+                       ref_pll = 12000;
+
+               denum = data & 0x1f;
+               num = (data & 0x3fe0) >> 5;
+               data = (data & 0xc000) >> 14;
+               switch (data) {
                case 3:
-                       ast->dram_type = AST_DRAM_4Gx16;
-                       break;
-               }
-       } else {
-               switch (data & 0x0c) {
-               case 0:
-               case 4:
-                       ast->dram_type = AST_DRAM_512Mx16;
+                       div = 0x4;
                        break;
-               case 8:
-                       if (data & 0x40)
-                               ast->dram_type = AST_DRAM_1Gx16;
-                       else
-                               ast->dram_type = AST_DRAM_512Mx32;
+               case 2:
+               case 1:
+                       div = 0x2;
                        break;
-               case 0xc:
-                       ast->dram_type = AST_DRAM_1Gx32;
+               default:
+                       div = 0x1;
                        break;
                }
+               ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
        }
-
-       data = ast_read32(ast, 0x10120);
-       data2 = ast_read32(ast, 0x10170);
-       if (data2 & 0x2000)
-               ref_pll = 14318;
-       else
-               ref_pll = 12000;
-
-       denum = data & 0x1f;
-       num = (data & 0x3fe0) >> 5;
-       data = (data & 0xc000) >> 14;
-       switch (data) {
-       case 3:
-               div = 0x4;
-               break;
-       case 2:
-       case 1:
-               div = 0x2;
-               break;
-       default:
-               div = 0x1;
-               break;
-       }
-       ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
        return 0;
 }
 
index 810c51d92b99f81a441f37d02e319ed25b7768e5..5331ee1df086e7ae3950e33efc38975b544abdd4 100644 (file)
@@ -379,12 +379,20 @@ void ast_post_gpu(struct drm_device *dev)
        ast_open_key(ast);
        ast_set_def_ext_reg(dev);
 
-       if (ast->chip == AST2300 || ast->chip == AST2400)
-               ast_init_dram_2300(dev);
-       else
-               ast_init_dram_reg(dev);
+       if (ast->DisableP2A == false)
+       {
+               if (ast->chip == AST2300 || ast->chip == AST2400)
+                       ast_init_dram_2300(dev);
+               else
+                       ast_init_dram_reg(dev);
 
-       ast_init_3rdtx(dev);
+               ast_init_3rdtx(dev);
+       }
+       else
+       {
+               if (ast->tx_chip_type != AST_TX_NONE)
+                       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);        /* Enable DVO */
+       }
 }
 
 /* AST 2300 DRAM settings */
index eb9bf8786c249744418b601bae38bb78ae04f2a7..18eefdcbf1ba9f39bb225b371ac9b822bb277485 100644 (file)
@@ -1382,6 +1382,7 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
 
        pm_runtime_enable(dev);
 
+       pm_runtime_get_sync(dev);
        phy_power_on(dp->phy);
 
        analogix_dp_init_dp(dp);
@@ -1414,9 +1415,15 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
                goto err_disable_pm_runtime;
        }
 
+       phy_power_off(dp->phy);
+       pm_runtime_put(dev);
+
        return 0;
 
 err_disable_pm_runtime:
+
+       phy_power_off(dp->phy);
+       pm_runtime_put(dev);
        pm_runtime_disable(dev);
 
        return ret;
index 04b3c161dfae6fc9c643229f2a312eb44abca62a..7f4cc6e172abaeab8b4007497daf309058c5e554 100644 (file)
@@ -7,3 +7,12 @@ config DRM_CIRRUS_QEMU
         This is a KMS driver for emulated cirrus device in qemu.
         It is *NOT* intended for real cirrus devices. This requires
         the modesetting userspace X.org driver.
+
+        Cirrus is obsolete, the hardware was designed in the 90ies
+        and can't keep up with todays needs.  More background:
+        https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
+
+        Better alternatives are:
+          - stdvga (DRM_BOCHS, qemu -vga std, default in qemu 2.2+)
+          - qxl (DRM_QXL, qemu -vga qxl, works best with spice)
+          - virtio (DRM_VIRTIO_GPU), qemu -vga virtio)
index 60697482b94c8136ea2720dbf3b9f81c94e1d823..fdfb1ec17e660efa0b1f2c1f7273fa8d6fd8567a 100644 (file)
@@ -291,15 +291,15 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 EXPORT_SYMBOL(drm_atomic_get_crtc_state);
 
 static void set_out_fence_for_crtc(struct drm_atomic_state *state,
-                                  struct drm_crtc *crtc, s64 __user *fence_ptr)
+                                  struct drm_crtc *crtc, s32 __user *fence_ptr)
 {
        state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
 }
 
-static s64 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
+static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
                                          struct drm_crtc *crtc)
 {
-       s64 __user *fence_ptr;
+       s32 __user *fence_ptr;
 
        fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
        state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
@@ -512,7 +512,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
                state->color_mgmt_changed |= replaced;
                return ret;
        } else if (property == config->prop_out_fence_ptr) {
-               s64 __user *fence_ptr = u64_to_user_ptr(val);
+               s32 __user *fence_ptr = u64_to_user_ptr(val);
 
                if (!fence_ptr)
                        return 0;
@@ -1915,7 +1915,7 @@ EXPORT_SYMBOL(drm_atomic_clean_old_fb);
  */
 
 struct drm_out_fence_state {
-       s64 __user *out_fence_ptr;
+       s32 __user *out_fence_ptr;
        struct sync_file *sync_file;
        int fd;
 };
@@ -1952,7 +1952,7 @@ static int prepare_crtc_signaling(struct drm_device *dev,
                return 0;
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
-               u64 __user *fence_ptr;
+               s32 __user *fence_ptr;
 
                fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
 
@@ -2032,13 +2032,16 @@ static void complete_crtc_signaling(struct drm_device *dev,
        }
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               struct drm_pending_vblank_event *event = crtc_state->event;
                /*
-                * TEST_ONLY and PAGE_FLIP_EVENT are mutually
-                * exclusive, if they weren't, this code should be
-                * called on success for TEST_ONLY too.
+                * Free the allocated event. drm_atomic_helper_setup_commit
+                * can allocate an event too, so only free it if it's ours
+                * to prevent a double free in drm_atomic_state_clear.
                 */
-               if (crtc_state->event)
-                       drm_event_cancel_free(dev, &crtc_state->event->base);
+               if (event && (event->base.fence || event->base.file_priv)) {
+                       drm_event_cancel_free(dev, &event->base);
+                       crtc_state->event = NULL;
+               }
        }
 
        if (!fence_state)
index 583f47f27b36de20a7ec1e273ce02559aa3fdae0..4594477dee00bc0ffb7847da556985848df717e7 100644 (file)
@@ -1259,8 +1259,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 
        if (!nonblock) {
                ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-               if (ret)
+               if (ret) {
+                       drm_atomic_helper_cleanup_planes(dev, state);
                        return ret;
+               }
        }
 
        /*
@@ -1664,9 +1666,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
 
                funcs = plane->helper_private;
 
-               if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
-                       continue;
-
                if (funcs->prepare_fb) {
                        ret = funcs->prepare_fb(plane, plane_state);
                        if (ret)
@@ -1683,9 +1682,6 @@ fail:
                if (j >= i)
                        continue;
 
-               if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
-                       continue;
-
                funcs = plane->helper_private;
 
                if (funcs->cleanup_fb)
@@ -1952,9 +1948,6 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
        for_each_plane_in_state(old_state, plane, plane_state, i) {
                const struct drm_plane_helper_funcs *funcs;
 
-               if (!drm_atomic_helper_framebuffer_changed(dev, old_state, plane_state->crtc))
-                       continue;
-
                funcs = plane->helper_private;
 
                if (funcs->cleanup_fb)
index 5a452628939272969c54239498b9a1ca86cd4a67..7a7019ac93884eeeba046ad62b3c81037796beb7 100644 (file)
@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device *dev,
 
        INIT_LIST_HEAD(&connector->probed_modes);
        INIT_LIST_HEAD(&connector->modes);
+       mutex_init(&connector->mutex);
        connector->edid_blob_ptr = NULL;
        connector->status = connector_status_unknown;
 
@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
                connector->funcs->atomic_destroy_state(connector,
                                                       connector->state);
 
+       mutex_destroy(&connector->mutex);
+
        memset(connector, 0, sizeof(*connector));
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
@@ -374,14 +377,18 @@ EXPORT_SYMBOL(drm_connector_cleanup);
  */
 int drm_connector_register(struct drm_connector *connector)
 {
-       int ret;
+       int ret = 0;
 
-       if (connector->registered)
+       if (!connector->dev->registered)
                return 0;
 
+       mutex_lock(&connector->mutex);
+       if (connector->registered)
+               goto unlock;
+
        ret = drm_sysfs_connector_add(connector);
        if (ret)
-               return ret;
+               goto unlock;
 
        ret = drm_debugfs_connector_add(connector);
        if (ret) {
@@ -397,12 +404,14 @@ int drm_connector_register(struct drm_connector *connector)
        drm_mode_object_register(connector->dev, &connector->base);
 
        connector->registered = true;
-       return 0;
+       goto unlock;
 
 err_debugfs:
        drm_debugfs_connector_remove(connector);
 err_sysfs:
        drm_sysfs_connector_remove(connector);
+unlock:
+       mutex_unlock(&connector->mutex);
        return ret;
 }
 EXPORT_SYMBOL(drm_connector_register);
@@ -415,8 +424,11 @@ EXPORT_SYMBOL(drm_connector_register);
  */
 void drm_connector_unregister(struct drm_connector *connector)
 {
-       if (!connector->registered)
+       mutex_lock(&connector->mutex);
+       if (!connector->registered) {
+               mutex_unlock(&connector->mutex);
                return;
+       }
 
        if (connector->funcs->early_unregister)
                connector->funcs->early_unregister(connector);
@@ -425,6 +437,7 @@ void drm_connector_unregister(struct drm_connector *connector)
        drm_debugfs_connector_remove(connector);
 
        connector->registered = false;
+       mutex_unlock(&connector->mutex);
 }
 EXPORT_SYMBOL(drm_connector_unregister);
 
index aa644487749c9cbab104f2ea77c819baf7d6b250..f59771da52eec030270d1d3e2d2038dc64e0d9f1 100644 (file)
@@ -1817,7 +1817,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
                                mgr->payloads[i].vcpi = req_payload.vcpi;
                        } else if (mgr->payloads[i].num_slots) {
                                mgr->payloads[i].num_slots = 0;
-                               drm_dp_destroy_payload_step1(mgr, port, port->vcpi.vcpi, &mgr->payloads[i]);
+                               drm_dp_destroy_payload_step1(mgr, port, mgr->payloads[i].vcpi, &mgr->payloads[i]);
                                req_payload.payload_state = mgr->payloads[i].payload_state;
                                mgr->payloads[i].start_slot = 0;
                        }
index a525751b4559e9f3cc99850d5aac6e5c3eb6f16c..6594b4088f11bc8e5aa6a6c308ba3fdf633921a3 100644 (file)
@@ -745,6 +745,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
        if (ret)
                goto err_minors;
 
+       dev->registered = true;
+
        if (dev->driver->load) {
                ret = dev->driver->load(dev, flags);
                if (ret)
@@ -785,6 +787,8 @@ void drm_dev_unregister(struct drm_device *dev)
 
        drm_lastclose(dev);
 
+       dev->registered = false;
+
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                drm_modeset_unregister_all(dev);
 
index ac6a35212501eb56784cf14c25867fbfeda88f47..e6b19bc9021ae0634eb524af3e9f30d8b5f445ab 100644 (file)
@@ -1460,6 +1460,13 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
                return NULL;
 
        mode->type |= DRM_MODE_TYPE_USERDEF;
+       /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
+       if (cmd->xres == 1366 && mode->hdisplay == 1368) {
+               mode->hdisplay = 1366;
+               mode->hsync_start--;
+               mode->hsync_end--;
+               drm_mode_set_name(mode);
+       }
        drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
        return mode;
 }
index ac953f037be7efb7edac1c67d43e46b20b3be365..cf8f0128c161ed6e1034322066c49d53a80b9e92 100644 (file)
@@ -143,8 +143,18 @@ void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
        }
 
        if (dev->mode_config.delayed_event) {
+               /*
+                * FIXME:
+                *
+                * Use short (1s) delay to handle the initial delayed event.
+                * This delay should not be needed, but Optimus/nouveau will
+                * fail in a mysterious way if the delayed event is handled as
+                * soon as possible like it is done in
+                * drm_helper_probe_single_connector_modes() in case the poll
+                * was enabled before.
+                */
                poll = true;
-               delay = 0;
+               delay = HZ;
        }
 
        if (poll)
index 169ac96e8f0861f9648e0e3ca3292ca1da61556c..fe0e85b41310a8fa24ba0f6caaa598edc669a99c 100644 (file)
@@ -116,9 +116,14 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu *mmu,
                struct list_head list;
                bool found;
 
+               /*
+                * XXX: The DRM_MM_SEARCH_BELOW is really a hack to trick
+                * drm_mm into giving out a low IOVA after address space
+                * rollover. This needs a proper fix.
+                */
                ret = drm_mm_insert_node_in_range(&mmu->mm, node,
                        size, 0, mmu->last_iova, ~0UL,
-                       DRM_MM_SEARCH_DEFAULT);
+                       mmu->last_iova ? DRM_MM_SEARCH_DEFAULT : DRM_MM_SEARCH_BELOW);
 
                if (ret != -ENOSPC)
                        break;
index 6ca1f3117fe8d524fbb4dfed89692c527c5bd41c..75eeb831ed6a1d5d00fa6659d967f9b0b2ad34ff 100644 (file)
@@ -46,7 +46,8 @@ enum decon_flag_bits {
        BIT_CLKS_ENABLED,
        BIT_IRQS_ENABLED,
        BIT_WIN_UPDATED,
-       BIT_SUSPENDED
+       BIT_SUSPENDED,
+       BIT_REQUEST_UPDATE
 };
 
 struct decon_context {
@@ -141,12 +142,6 @@ static void decon_commit(struct exynos_drm_crtc *crtc)
                m->crtc_vsync_end = m->crtc_vsync_start + 1;
        }
 
-       decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID, 0);
-
-       /* enable clock gate */
-       val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F;
-       writel(val, ctx->addr + DECON_CMU);
-
        if (ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))
                decon_setup_trigger(ctx);
 
@@ -315,6 +310,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 
        /* window enable */
        decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
+       set_bit(BIT_REQUEST_UPDATE, &ctx->flags);
 }
 
 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -327,6 +323,7 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,
                return;
 
        decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
+       set_bit(BIT_REQUEST_UPDATE, &ctx->flags);
 }
 
 static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
@@ -340,8 +337,8 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
        for (i = ctx->first_win; i < WINDOWS_NR; i++)
                decon_shadow_protect_win(ctx, i, false);
 
-       /* standalone update */
-       decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
+       if (test_and_clear_bit(BIT_REQUEST_UPDATE, &ctx->flags))
+               decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 
        if (ctx->out_type & IFTYPE_I80)
                set_bit(BIT_WIN_UPDATED, &ctx->flags);
index 0d41ebc4aea63a6a7e101b5439739a8faad989fd..f7bce8603958da2760080fe2bd2b30ff83553d9d 100644 (file)
 #include "i915_drv.h"
 #include "gvt.h"
 
-#define MB_TO_BYTES(mb) ((mb) << 20ULL)
-#define BYTES_TO_MB(b) ((b) >> 20ULL)
-
-#define HOST_LOW_GM_SIZE MB_TO_BYTES(128)
-#define HOST_HIGH_GM_SIZE MB_TO_BYTES(384)
-#define HOST_FENCE 4
-
 static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
 {
        struct intel_gvt *gvt = vgpu->gvt;
@@ -165,6 +158,14 @@ void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
        POSTING_READ(fence_reg_lo);
 }
 
+static void _clear_vgpu_fence(struct intel_vgpu *vgpu)
+{
+       int i;
+
+       for (i = 0; i < vgpu_fence_sz(vgpu); i++)
+               intel_vgpu_write_fence(vgpu, i, 0);
+}
+
 static void free_vgpu_fence(struct intel_vgpu *vgpu)
 {
        struct intel_gvt *gvt = vgpu->gvt;
@@ -178,9 +179,9 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
        intel_runtime_pm_get(dev_priv);
 
        mutex_lock(&dev_priv->drm.struct_mutex);
+       _clear_vgpu_fence(vgpu);
        for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
                reg = vgpu->fence.regs[i];
-               intel_vgpu_write_fence(vgpu, i, 0);
                list_add_tail(&reg->link,
                              &dev_priv->mm.fence_list);
        }
@@ -208,13 +209,14 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
                        continue;
                list_del(pos);
                vgpu->fence.regs[i] = reg;
-               intel_vgpu_write_fence(vgpu, i, 0);
                if (++i == vgpu_fence_sz(vgpu))
                        break;
        }
        if (i != vgpu_fence_sz(vgpu))
                goto out_free_fence;
 
+       _clear_vgpu_fence(vgpu);
+
        mutex_unlock(&dev_priv->drm.struct_mutex);
        intel_runtime_pm_put(dev_priv);
        return 0;
@@ -313,6 +315,22 @@ void intel_vgpu_free_resource(struct intel_vgpu *vgpu)
        free_resource(vgpu);
 }
 
+/**
+ * intel_vgpu_reset_resource - reset resource state owned by a vGPU
+ * @vgpu: a vGPU
+ *
+ * This function is used to reset resource state owned by a vGPU.
+ *
+ */
+void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
+{
+       struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+       intel_runtime_pm_get(dev_priv);
+       _clear_vgpu_fence(vgpu);
+       intel_runtime_pm_put(dev_priv);
+}
+
 /**
  * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
  * @vgpu: vGPU
index db516382a4d4b2ae375f41cde6cf3f8bfe5b5bb9..4a6a2ed65732e1fde39457148165274deda52db6 100644 (file)
@@ -123,6 +123,7 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
        u8 changed = old ^ new;
        int ret;
 
+       memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
        if (!(changed & PCI_COMMAND_MEMORY))
                return 0;
 
@@ -142,7 +143,6 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
                        return ret;
        }
 
-       memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
        return 0;
 }
 
@@ -240,7 +240,7 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
        if (WARN_ON(bytes > 4))
                return -EINVAL;
 
-       if (WARN_ON(offset + bytes >= INTEL_GVT_MAX_CFG_SPACE_SZ))
+       if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ))
                return -EINVAL;
 
        /* First check if it's PCI_COMMAND */
@@ -282,3 +282,77 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
        }
        return 0;
 }
+
+/**
+ * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU
+ *
+ * @vgpu: a vGPU
+ * @primary: is the vGPU presented as primary
+ *
+ */
+void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
+                              bool primary)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+       const struct intel_gvt_device_info *info = &gvt->device_info;
+       u16 *gmch_ctl;
+       int i;
+
+       memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
+              info->cfg_space_size);
+
+       if (!primary) {
+               vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
+                       INTEL_GVT_PCI_CLASS_VGA_OTHER;
+               vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
+                       INTEL_GVT_PCI_CLASS_VGA_OTHER;
+       }
+
+       /* Show guest that there isn't any stolen memory.*/
+       gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
+       *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
+
+       intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
+                                gvt_aperture_pa_base(gvt), true);
+
+       vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
+                                            | PCI_COMMAND_MEMORY
+                                            | PCI_COMMAND_MASTER);
+       /*
+        * Clear the bar upper 32bit and let guest to assign the new value
+        */
+       memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
+       memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
+       memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
+
+       for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
+               vgpu->cfg_space.bar[i].size = pci_resource_len(
+                                             gvt->dev_priv->drm.pdev, i * 2);
+               vgpu->cfg_space.bar[i].tracked = false;
+       }
+}
+
+/**
+ * intel_vgpu_reset_cfg_space - reset vGPU configuration space
+ *
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu)
+{
+       u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND];
+       bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] !=
+                               INTEL_GVT_PCI_CLASS_VGA_OTHER;
+
+       if (cmd & PCI_COMMAND_MEMORY) {
+               trap_gttmmio(vgpu, false);
+               map_aperture(vgpu, false);
+       }
+
+       /**
+        * Currently we only do such reset when vGPU is not
+        * owned by any VM, so we simply restore entire cfg
+        * space to default value.
+        */
+       intel_vgpu_init_cfg_space(vgpu, primary);
+}
index d26a092c70e8c8fe2a14df28dd22e4253f739a16..e4563984cb1e8106cda73e8d0e12f12d10f6a1d2 100644 (file)
@@ -481,7 +481,6 @@ struct parser_exec_state {
        (s->vgpu->gvt->device_info.gmadr_bytes_in_cmd >> 2)
 
 static unsigned long bypass_scan_mask = 0;
-static bool bypass_batch_buffer_scan = true;
 
 /* ring ALL, type = 0 */
 static struct sub_op_bits sub_op_mi[] = {
@@ -1525,9 +1524,6 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s)
 {
        struct intel_gvt *gvt = s->vgpu->gvt;
 
-       if (bypass_batch_buffer_scan)
-               return 0;
-
        if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
                /* BDW decides privilege based on address space */
                if (cmd_val(s, 0) & (1 << 8))
index f32bb6f6495ce0aafddf35d920298c5d315af9bc..34083731669d8cbe55b94de2e5b3585aa73a7039 100644 (file)
@@ -364,58 +364,30 @@ static void free_workload(struct intel_vgpu_workload *workload)
 #define get_desc_from_elsp_dwords(ed, i) \
        ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2]))
 
-
-#define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2))
-#define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U))
-static int set_gma_to_bb_cmd(struct intel_shadow_bb_entry *entry_obj,
-                            unsigned long add, int gmadr_bytes)
-{
-       if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8))
-               return -1;
-
-       *((u32 *)(entry_obj->bb_start_cmd_va + (1 << 2))) = add &
-               BATCH_BUFFER_ADDR_MASK;
-       if (gmadr_bytes == 8) {
-               *((u32 *)(entry_obj->bb_start_cmd_va + (2 << 2))) =
-                       add & BATCH_BUFFER_ADDR_HIGH_MASK;
-       }
-
-       return 0;
-}
-
 static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)
 {
-       int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+       const int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+       struct intel_shadow_bb_entry *entry_obj;
 
        /* pin the gem object to ggtt */
-       if (!list_empty(&workload->shadow_bb)) {
-               struct intel_shadow_bb_entry *entry_obj =
-                       list_first_entry(&workload->shadow_bb,
-                                        struct intel_shadow_bb_entry,
-                                        list);
-               struct intel_shadow_bb_entry *temp;
+       list_for_each_entry(entry_obj, &workload->shadow_bb, list) {
+               struct i915_vma *vma;
 
-               list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb,
-                               list) {
-                       struct i915_vma *vma;
-
-                       vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0,
-                                                      4, 0);
-                       if (IS_ERR(vma)) {
-                               gvt_err("Cannot pin\n");
-                               return;
-                       }
-
-                       /* FIXME: we are not tracking our pinned VMA leaving it
-                        * up to the core to fix up the stray pin_count upon
-                        * free.
-                        */
-
-                       /* update the relocate gma with shadow batch buffer*/
-                       set_gma_to_bb_cmd(entry_obj,
-                                         i915_ggtt_offset(vma),
-                                         gmadr_bytes);
+               vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0);
+               if (IS_ERR(vma)) {
+                       gvt_err("Cannot pin\n");
+                       return;
                }
+
+               /* FIXME: we are not tracking our pinned VMA leaving it
+                * up to the core to fix up the stray pin_count upon
+                * free.
+                */
+
+               /* update the relocate gma with shadow batch buffer*/
+               entry_obj->bb_start_cmd_va[1] = i915_ggtt_offset(vma);
+               if (gmadr_bytes == 8)
+                       entry_obj->bb_start_cmd_va[2] = 0;
        }
 }
 
@@ -826,7 +798,7 @@ int intel_vgpu_init_execlist(struct intel_vgpu *vgpu)
                INIT_LIST_HEAD(&vgpu->workload_q_head[i]);
        }
 
-       vgpu->workloads = kmem_cache_create("gvt-g vgpu workload",
+       vgpu->workloads = kmem_cache_create("gvt-g_vgpu_workload",
                        sizeof(struct intel_vgpu_workload), 0,
                        SLAB_HWCACHE_ALIGN,
                        NULL);
index 7eaaf1c9ed2bf47e935bf0592a4c00658838086d..47dec4acf7ff12951eb592e2b115953e961f6bdf 100644 (file)
@@ -240,15 +240,8 @@ static inline int get_pse_type(int type)
 static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index)
 {
        void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
-       u64 pte;
 
-#ifdef readq
-       pte = readq(addr);
-#else
-       pte = ioread32(addr);
-       pte |= (u64)ioread32(addr + 4) << 32;
-#endif
-       return pte;
+       return readq(addr);
 }
 
 static void write_pte64(struct drm_i915_private *dev_priv,
@@ -256,12 +249,8 @@ static void write_pte64(struct drm_i915_private *dev_priv,
 {
        void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
 
-#ifdef writeq
        writeq(pte, addr);
-#else
-       iowrite32((u32)pte, addr);
-       iowrite32(pte >> 32, addr + 4);
-#endif
+
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
 }
@@ -1380,8 +1369,7 @@ static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm)
                        info->gtt_entry_size;
                mem = kzalloc(mm->has_shadow_page_table ?
                        mm->page_table_entry_size * 2
-                               : mm->page_table_entry_size,
-                       GFP_ATOMIC);
+                               : mm->page_table_entry_size, GFP_KERNEL);
                if (!mem)
                        return -ENOMEM;
                mm->virtual_page_table = mem;
@@ -1532,7 +1520,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
        struct intel_vgpu_mm *mm;
        int ret;
 
-       mm = kzalloc(sizeof(*mm), GFP_ATOMIC);
+       mm = kzalloc(sizeof(*mm), GFP_KERNEL);
        if (!mm) {
                ret = -ENOMEM;
                goto fail;
@@ -1886,30 +1874,27 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
        struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
        int page_entry_num = GTT_PAGE_SIZE >>
                                vgpu->gvt->device_info.gtt_entry_size_shift;
-       struct page *scratch_pt;
+       void *scratch_pt;
        unsigned long mfn;
        int i;
-       void *p;
 
        if (WARN_ON(type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX))
                return -EINVAL;
 
-       scratch_pt = alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
+       scratch_pt = (void *)get_zeroed_page(GFP_KERNEL);
        if (!scratch_pt) {
                gvt_err("fail to allocate scratch page\n");
                return -ENOMEM;
        }
 
-       p = kmap_atomic(scratch_pt);
-       mfn = intel_gvt_hypervisor_virt_to_mfn(p);
+       mfn = intel_gvt_hypervisor_virt_to_mfn(scratch_pt);
        if (mfn == INTEL_GVT_INVALID_ADDR) {
-               gvt_err("fail to translate vaddr:0x%llx\n", (u64)p);
-               kunmap_atomic(p);
-               __free_page(scratch_pt);
+               gvt_err("fail to translate vaddr:0x%lx\n", (unsigned long)scratch_pt);
+               free_page((unsigned long)scratch_pt);
                return -EFAULT;
        }
        gtt->scratch_pt[type].page_mfn = mfn;
-       gtt->scratch_pt[type].page = scratch_pt;
+       gtt->scratch_pt[type].page = virt_to_page(scratch_pt);
        gvt_dbg_mm("vgpu%d create scratch_pt: type %d mfn=0x%lx\n",
                        vgpu->id, type, mfn);
 
@@ -1918,7 +1903,7 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
         * scratch_pt[type] indicate the scratch pt/scratch page used by the
         * 'type' pt.
         * e.g. scratch_pt[GTT_TYPE_PPGTT_PDE_PT] is used by
-        * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scatch_pt it self
+        * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scratch_pt it self
         * is GTT_TYPE_PPGTT_PTE_PT, and full filled by scratch page mfn.
         */
        if (type > GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) {
@@ -1936,11 +1921,9 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
                        se.val64 |= PPAT_CACHED_INDEX;
 
                for (i = 0; i < page_entry_num; i++)
-                       ops->set_entry(p, &se, i, false, 0, vgpu);
+                       ops->set_entry(scratch_pt, &se, i, false, 0, vgpu);
        }
 
-       kunmap_atomic(p);
-
        return 0;
 }
 
@@ -1998,6 +1981,8 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
        INIT_LIST_HEAD(&gtt->oos_page_list_head);
        INIT_LIST_HEAD(&gtt->post_shadow_list_head);
 
+       intel_vgpu_reset_ggtt(vgpu);
+
        ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
                        NULL, 1, 0);
        if (IS_ERR(ggtt_mm)) {
@@ -2206,6 +2191,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
 int intel_gvt_init_gtt(struct intel_gvt *gvt)
 {
        int ret;
+       void *page;
 
        gvt_dbg_core("init gtt\n");
 
@@ -2218,6 +2204,20 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
                return -ENODEV;
        }
 
+       page = (void *)get_zeroed_page(GFP_KERNEL);
+       if (!page) {
+               gvt_err("fail to allocate scratch ggtt page\n");
+               return -ENOMEM;
+       }
+       gvt->gtt.scratch_ggtt_page = virt_to_page(page);
+
+       gvt->gtt.scratch_ggtt_mfn = intel_gvt_hypervisor_virt_to_mfn(page);
+       if (gvt->gtt.scratch_ggtt_mfn == INTEL_GVT_INVALID_ADDR) {
+               gvt_err("fail to translate scratch ggtt page\n");
+               __free_page(gvt->gtt.scratch_ggtt_page);
+               return -EFAULT;
+       }
+
        if (enable_out_of_sync) {
                ret = setup_spt_oos(gvt);
                if (ret) {
@@ -2239,6 +2239,68 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
  */
 void intel_gvt_clean_gtt(struct intel_gvt *gvt)
 {
+       __free_page(gvt->gtt.scratch_ggtt_page);
+
        if (enable_out_of_sync)
                clean_spt_oos(gvt);
 }
+
+/**
+ * intel_vgpu_reset_ggtt - reset the GGTT entry
+ * @vgpu: a vGPU
+ *
+ * This function is called at the vGPU create stage
+ * to reset all the GGTT entries.
+ *
+ */
+void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+       struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+       u32 index;
+       u32 offset;
+       u32 num_entries;
+       struct intel_gvt_gtt_entry e;
+
+       memset(&e, 0, sizeof(struct intel_gvt_gtt_entry));
+       e.type = GTT_TYPE_GGTT_PTE;
+       ops->set_pfn(&e, gvt->gtt.scratch_ggtt_mfn);
+       e.val64 |= _PAGE_PRESENT;
+
+       index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT;
+       num_entries = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT;
+       for (offset = 0; offset < num_entries; offset++)
+               ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
+
+       index = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT;
+       num_entries = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT;
+       for (offset = 0; offset < num_entries; offset++)
+               ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
+}
+
+/**
+ * intel_vgpu_reset_gtt - reset the all GTT related status
+ * @vgpu: a vGPU
+ * @dmlr: true for vGPU Device Model Level Reset, false for GT Reset
+ *
+ * This function is called from vfio core to reset reset all
+ * GTT related status, including GGTT, PPGTT, scratch page.
+ *
+ */
+void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)
+{
+       int i;
+
+       ppgtt_free_all_shadow_page(vgpu);
+       if (!dmlr)
+               return;
+
+       intel_vgpu_reset_ggtt(vgpu);
+
+       /* clear scratch page for security */
+       for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
+               if (vgpu->gtt.scratch_pt[i].page != NULL)
+                       memset(page_address(vgpu->gtt.scratch_pt[i].page),
+                               0, PAGE_SIZE);
+       }
+}
index d250013bc37b053f45b3b747668d791fa477de26..f88eb5e89bea09f7b6e8aba2e521748d54d28b77 100644 (file)
@@ -81,6 +81,9 @@ struct intel_gvt_gtt {
        struct list_head oos_page_use_list_head;
        struct list_head oos_page_free_list_head;
        struct list_head mm_lru_list_head;
+
+       struct page *scratch_ggtt_page;
+       unsigned long scratch_ggtt_mfn;
 };
 
 enum {
@@ -202,8 +205,10 @@ struct intel_vgpu_gtt {
 
 extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
 extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
+void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
 
 extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
+extern void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr);
 extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
 
 extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
index 398877c3d2fd98a19ba8f45712ef444a4fcb0896..e6bf5c533fbe5c795a7cef6baef2815aea797ce7 100644 (file)
@@ -201,6 +201,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
        intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt);
        intel_gvt_clean_vgpu_types(gvt);
 
+       idr_destroy(&gvt->vgpu_idr);
+
        kfree(dev_priv->gvt);
        dev_priv->gvt = NULL;
 }
@@ -237,6 +239,8 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
 
        gvt_dbg_core("init gvt device\n");
 
+       idr_init(&gvt->vgpu_idr);
+
        mutex_init(&gvt->lock);
        gvt->dev_priv = dev_priv;
 
@@ -244,7 +248,7 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
 
        ret = intel_gvt_setup_mmio_info(gvt);
        if (ret)
-               return ret;
+               goto out_clean_idr;
 
        ret = intel_gvt_load_firmware(gvt);
        if (ret)
@@ -313,6 +317,8 @@ out_free_firmware:
        intel_gvt_free_firmware(gvt);
 out_clean_mmio_info:
        intel_gvt_clean_mmio_info(gvt);
+out_clean_idr:
+       idr_destroy(&gvt->vgpu_idr);
        kfree(gvt);
        return ret;
 }
index ad0e9364ee703a65ce2a33834321bb4a9fce34f1..e227caf5859ebdfd2c420bc994d42a5734ba4272 100644 (file)
@@ -175,6 +175,7 @@ struct intel_vgpu {
                struct notifier_block group_notifier;
                struct kvm *kvm;
                struct work_struct release_work;
+               atomic_t released;
        } vdev;
 #endif
 };
@@ -322,6 +323,7 @@ struct intel_vgpu_creation_params {
 
 int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
                              struct intel_vgpu_creation_params *param);
+void intel_vgpu_reset_resource(struct intel_vgpu *vgpu);
 void intel_vgpu_free_resource(struct intel_vgpu *vgpu);
 void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
        u32 fence, u64 value);
@@ -374,6 +376,8 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt);
 struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
                                         struct intel_vgpu_type *type);
 void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
+void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
+                                unsigned int engine_mask);
 void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu);
 
 
@@ -410,6 +414,10 @@ int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index,
 int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index,
                             unsigned long *g_index);
 
+void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
+               bool primary);
+void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu);
+
 int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
                void *p_data, unsigned int bytes);
 
@@ -423,7 +431,6 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
 int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
 
 int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
-int setup_vgpu_mmio(struct intel_vgpu *vgpu);
 void populate_pvinfo_page(struct intel_vgpu *vgpu);
 
 struct intel_gvt_ops {
index 522809710312c25767209656133651971dd6a01f..ab2ea157da4cd6ab0a39fbba8bae196806b843c6 100644 (file)
@@ -93,7 +93,8 @@ static void write_vreg(struct intel_vgpu *vgpu, unsigned int offset,
 static int new_mmio_info(struct intel_gvt *gvt,
                u32 offset, u32 flags, u32 size,
                u32 addr_mask, u32 ro_mask, u32 device,
-               void *read, void *write)
+               int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int),
+               int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int))
 {
        struct intel_gvt_mmio_info *info, *p;
        u32 start, end, i;
@@ -219,7 +220,7 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu,
                default:
                        /*should not hit here*/
                        gvt_err("invalid forcewake offset 0x%x\n", offset);
-                       return 1;
+                       return -EINVAL;
                }
        } else {
                ack_reg_offset = FORCEWAKE_ACK_HSW_REG;
@@ -230,77 +231,45 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu,
        return 0;
 }
 
-static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset,
-               void *p_data, unsigned int bytes, unsigned long bitmap)
-{
-       struct intel_gvt_workload_scheduler *scheduler =
-               &vgpu->gvt->scheduler;
-
-       vgpu->resetting = true;
-
-       intel_vgpu_stop_schedule(vgpu);
-       /*
-        * The current_vgpu will set to NULL after stopping the
-        * scheduler when the reset is triggered by current vgpu.
-        */
-       if (scheduler->current_vgpu == NULL) {
-               mutex_unlock(&vgpu->gvt->lock);
-               intel_gvt_wait_vgpu_idle(vgpu);
-               mutex_lock(&vgpu->gvt->lock);
-       }
-
-       intel_vgpu_reset_execlist(vgpu, bitmap);
-
-       /* full GPU reset */
-       if (bitmap == 0xff) {
-               mutex_unlock(&vgpu->gvt->lock);
-               intel_vgpu_clean_gtt(vgpu);
-               mutex_lock(&vgpu->gvt->lock);
-               setup_vgpu_mmio(vgpu);
-               populate_pvinfo_page(vgpu);
-               intel_vgpu_init_gtt(vgpu);
-       }
-
-       vgpu->resetting = false;
-
-       return 0;
-}
-
 static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
-               void *p_data, unsigned int bytes)
+                           void *p_data, unsigned int bytes)
 {
+       unsigned int engine_mask = 0;
        u32 data;
-       u64 bitmap = 0;
 
        write_vreg(vgpu, offset, p_data, bytes);
        data = vgpu_vreg(vgpu, offset);
 
        if (data & GEN6_GRDOM_FULL) {
                gvt_dbg_mmio("vgpu%d: request full GPU reset\n", vgpu->id);
-               bitmap = 0xff;
-       }
-       if (data & GEN6_GRDOM_RENDER) {
-               gvt_dbg_mmio("vgpu%d: request RCS reset\n", vgpu->id);
-               bitmap |= (1 << RCS);
-       }
-       if (data & GEN6_GRDOM_MEDIA) {
-               gvt_dbg_mmio("vgpu%d: request VCS reset\n", vgpu->id);
-               bitmap |= (1 << VCS);
-       }
-       if (data & GEN6_GRDOM_BLT) {
-               gvt_dbg_mmio("vgpu%d: request BCS Reset\n", vgpu->id);
-               bitmap |= (1 << BCS);
-       }
-       if (data & GEN6_GRDOM_VECS) {
-               gvt_dbg_mmio("vgpu%d: request VECS Reset\n", vgpu->id);
-               bitmap |= (1 << VECS);
-       }
-       if (data & GEN8_GRDOM_MEDIA2) {
-               gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id);
-               if (HAS_BSD2(vgpu->gvt->dev_priv))
-                       bitmap |= (1 << VCS2);
+               engine_mask = ALL_ENGINES;
+       } else {
+               if (data & GEN6_GRDOM_RENDER) {
+                       gvt_dbg_mmio("vgpu%d: request RCS reset\n", vgpu->id);
+                       engine_mask |= (1 << RCS);
+               }
+               if (data & GEN6_GRDOM_MEDIA) {
+                       gvt_dbg_mmio("vgpu%d: request VCS reset\n", vgpu->id);
+                       engine_mask |= (1 << VCS);
+               }
+               if (data & GEN6_GRDOM_BLT) {
+                       gvt_dbg_mmio("vgpu%d: request BCS Reset\n", vgpu->id);
+                       engine_mask |= (1 << BCS);
+               }
+               if (data & GEN6_GRDOM_VECS) {
+                       gvt_dbg_mmio("vgpu%d: request VECS Reset\n", vgpu->id);
+                       engine_mask |= (1 << VECS);
+               }
+               if (data & GEN8_GRDOM_MEDIA2) {
+                       gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id);
+                       if (HAS_BSD2(vgpu->gvt->dev_priv))
+                               engine_mask |= (1 << VCS2);
+               }
        }
-       return handle_device_reset(vgpu, offset, p_data, bytes, bitmap);
+
+       intel_gvt_reset_vgpu_locked(vgpu, false, engine_mask);
+
+       return 0;
 }
 
 static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
@@ -974,7 +943,7 @@ static int sbi_data_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
        return 0;
 }
 
-static bool sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+static int sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                void *p_data, unsigned int bytes)
 {
        u32 data;
@@ -1366,7 +1335,6 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu,
                unsigned int offset, void *p_data, unsigned int bytes)
 {
-       int rc = 0;
        unsigned int id = 0;
 
        write_vreg(vgpu, offset, p_data, bytes);
@@ -1389,12 +1357,11 @@ static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu,
                id = VECS;
                break;
        default:
-               rc = -EINVAL;
-               break;
+               return -EINVAL;
        }
        set_bit(id, (void *)vgpu->tlb_handle_pending);
 
-       return rc;
+       return 0;
 }
 
 static int ring_reset_ctl_write(struct intel_vgpu *vgpu,
index 4dd6722a733933224c269825d6f12f53525bf9c7..3f656e3a6e5a79a598934381d7f3a59e09eb8cd7 100644 (file)
@@ -114,12 +114,15 @@ out:
 static kvm_pfn_t gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
 {
        struct gvt_dma *entry;
+       kvm_pfn_t pfn;
 
        mutex_lock(&vgpu->vdev.cache_lock);
+
        entry = __gvt_cache_find(vgpu, gfn);
-       mutex_unlock(&vgpu->vdev.cache_lock);
+       pfn = (entry == NULL) ? 0 : entry->pfn;
 
-       return entry == NULL ? 0 : entry->pfn;
+       mutex_unlock(&vgpu->vdev.cache_lock);
+       return pfn;
 }
 
 static void gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn, kvm_pfn_t pfn)
@@ -166,7 +169,7 @@ static void __gvt_cache_remove_entry(struct intel_vgpu *vgpu,
 
 static void gvt_cache_remove(struct intel_vgpu *vgpu, gfn_t gfn)
 {
-       struct device *dev = &vgpu->vdev.mdev->dev;
+       struct device *dev = mdev_dev(vgpu->vdev.mdev);
        struct gvt_dma *this;
        unsigned long g1;
        int rc;
@@ -195,7 +198,7 @@ static void gvt_cache_destroy(struct intel_vgpu *vgpu)
 {
        struct gvt_dma *dma;
        struct rb_node *node = NULL;
-       struct device *dev = &vgpu->vdev.mdev->dev;
+       struct device *dev = mdev_dev(vgpu->vdev.mdev);
        unsigned long gfn;
 
        mutex_lock(&vgpu->vdev.cache_lock);
@@ -227,8 +230,8 @@ static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,
        return NULL;
 }
 
-static ssize_t available_instance_show(struct kobject *kobj, struct device *dev,
-               char *buf)
+static ssize_t available_instances_show(struct kobject *kobj,
+                                       struct device *dev, char *buf)
 {
        struct intel_vgpu_type *type;
        unsigned int num = 0;
@@ -266,12 +269,12 @@ static ssize_t description_show(struct kobject *kobj, struct device *dev,
                                type->fence);
 }
 
-static MDEV_TYPE_ATTR_RO(available_instance);
+static MDEV_TYPE_ATTR_RO(available_instances);
 static MDEV_TYPE_ATTR_RO(device_api);
 static MDEV_TYPE_ATTR_RO(description);
 
 static struct attribute *type_attrs[] = {
-       &mdev_type_attr_available_instance.attr,
+       &mdev_type_attr_available_instances.attr,
        &mdev_type_attr_device_api.attr,
        &mdev_type_attr_description.attr,
        NULL,
@@ -395,21 +398,24 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
        struct intel_vgpu_type *type;
        struct device *pdev;
        void *gvt;
+       int ret;
 
-       pdev = mdev->parent->dev;
+       pdev = mdev_parent_dev(mdev);
        gvt = kdev_to_i915(pdev)->gvt;
 
        type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
        if (!type) {
                gvt_err("failed to find type %s to create\n",
                                                kobject_name(kobj));
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        vgpu = intel_gvt_ops->vgpu_create(gvt, type);
        if (IS_ERR_OR_NULL(vgpu)) {
-               gvt_err("create intel vgpu failed\n");
-               return -EINVAL;
+               ret = vgpu == NULL ? -EFAULT : PTR_ERR(vgpu);
+               gvt_err("failed to create intel vgpu: %d\n", ret);
+               goto out;
        }
 
        INIT_WORK(&vgpu->vdev.release_work, intel_vgpu_release_work);
@@ -418,8 +424,11 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
        mdev_set_drvdata(mdev, vgpu);
 
        gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
-                    dev_name(&mdev->dev));
-       return 0;
+                    dev_name(mdev_dev(mdev)));
+       ret = 0;
+
+out:
+       return ret;
 }
 
 static int intel_vgpu_remove(struct mdev_device *mdev)
@@ -482,7 +491,7 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        vgpu->vdev.group_notifier.notifier_call = intel_vgpu_group_notifier;
 
        events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
-       ret = vfio_register_notifier(&mdev->dev, VFIO_IOMMU_NOTIFY, &events,
+       ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, &events,
                                &vgpu->vdev.iommu_notifier);
        if (ret != 0) {
                gvt_err("vfio_register_notifier for iommu failed: %d\n", ret);
@@ -490,17 +499,26 @@ static int intel_vgpu_open(struct mdev_device *mdev)
        }
 
        events = VFIO_GROUP_NOTIFY_SET_KVM;
-       ret = vfio_register_notifier(&mdev->dev, VFIO_GROUP_NOTIFY, &events,
+       ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, &events,
                                &vgpu->vdev.group_notifier);
        if (ret != 0) {
                gvt_err("vfio_register_notifier for group failed: %d\n", ret);
                goto undo_iommu;
        }
 
-       return kvmgt_guest_init(mdev);
+       ret = kvmgt_guest_init(mdev);
+       if (ret)
+               goto undo_group;
+
+       atomic_set(&vgpu->vdev.released, 0);
+       return ret;
+
+undo_group:
+       vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
+                                       &vgpu->vdev.group_notifier);
 
 undo_iommu:
-       vfio_unregister_notifier(&mdev->dev, VFIO_IOMMU_NOTIFY,
+       vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
                                        &vgpu->vdev.iommu_notifier);
 out:
        return ret;
@@ -509,17 +527,26 @@ out:
 static void __intel_vgpu_release(struct intel_vgpu *vgpu)
 {
        struct kvmgt_guest_info *info;
+       int ret;
 
        if (!handle_valid(vgpu->handle))
                return;
 
-       vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_IOMMU_NOTIFY,
+       if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1))
+               return;
+
+       ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_IOMMU_NOTIFY,
                                        &vgpu->vdev.iommu_notifier);
-       vfio_unregister_notifier(&vgpu->vdev.mdev->dev, VFIO_GROUP_NOTIFY,
+       WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret);
+
+       ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_GROUP_NOTIFY,
                                        &vgpu->vdev.group_notifier);
+       WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret);
 
        info = (struct kvmgt_guest_info *)vgpu->handle;
        kvmgt_guest_exit(info);
+
+       vgpu->vdev.kvm = NULL;
        vgpu->handle = 0;
 }
 
@@ -534,6 +561,7 @@ static void intel_vgpu_release_work(struct work_struct *work)
 {
        struct intel_vgpu *vgpu = container_of(work, struct intel_vgpu,
                                        vdev.release_work);
+
        __intel_vgpu_release(vgpu);
 }
 
@@ -1089,7 +1117,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
        return 0;
 }
 
-static const struct parent_ops intel_vgpu_ops = {
+static const struct mdev_parent_ops intel_vgpu_ops = {
        .supported_type_groups  = intel_vgpu_type_groups,
        .create                 = intel_vgpu_create,
        .remove                 = intel_vgpu_remove,
@@ -1134,6 +1162,10 @@ static int kvmgt_write_protect_add(unsigned long handle, u64 gfn)
 
        idx = srcu_read_lock(&kvm->srcu);
        slot = gfn_to_memslot(kvm, gfn);
+       if (!slot) {
+               srcu_read_unlock(&kvm->srcu, idx);
+               return -EINVAL;
+       }
 
        spin_lock(&kvm->mmu_lock);
 
@@ -1164,6 +1196,10 @@ static int kvmgt_write_protect_remove(unsigned long handle, u64 gfn)
 
        idx = srcu_read_lock(&kvm->srcu);
        slot = gfn_to_memslot(kvm, gfn);
+       if (!slot) {
+               srcu_read_unlock(&kvm->srcu, idx);
+               return -EINVAL;
+       }
 
        spin_lock(&kvm->mmu_lock);
 
@@ -1311,18 +1347,14 @@ static int kvmgt_guest_init(struct mdev_device *mdev)
 
 static bool kvmgt_guest_exit(struct kvmgt_guest_info *info)
 {
-       struct intel_vgpu *vgpu;
-
        if (!info) {
                gvt_err("kvmgt_guest_info invalid\n");
                return false;
        }
 
-       vgpu = info->vgpu;
-
        kvm_page_track_unregister_notifier(info->kvm, &info->track_node);
        kvmgt_protect_table_destroy(info);
-       gvt_cache_destroy(vgpu);
+       gvt_cache_destroy(info->vgpu);
        vfree(info);
 
        return true;
@@ -1372,7 +1404,7 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
                return pfn;
 
        pfn = INTEL_GVT_INVALID_ADDR;
-       dev = &info->vgpu->vdev.mdev->dev;
+       dev = mdev_dev(info->vgpu->vdev.mdev);
        rc = vfio_pin_pages(dev, &gfn, 1, IOMMU_READ | IOMMU_WRITE, &pfn);
        if (rc != 1) {
                gvt_err("vfio_pin_pages failed for gfn 0x%lx: %d\n", gfn, rc);
index 09c9450a19462e940eb4df2e71af1e10974ef878..4df078bc5d042b1f4fc411fbb0f98c83a3cba729 100644 (file)
@@ -125,25 +125,12 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
        if (WARN_ON(!reg_is_mmio(gvt, offset + bytes - 1)))
                goto err;
 
-       mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));
-       if (!mmio && !vgpu->mmio.disable_warn_untrack) {
-               gvt_err("vgpu%d: read untracked MMIO %x len %d val %x\n",
-                               vgpu->id, offset, bytes, *(u32 *)p_data);
-
-               if (offset == 0x206c) {
-                       gvt_err("------------------------------------------\n");
-                       gvt_err("vgpu%d: likely triggers a gfx reset\n",
-                       vgpu->id);
-                       gvt_err("------------------------------------------\n");
-                       vgpu->mmio.disable_warn_untrack = true;
-               }
-       }
-
        if (!intel_gvt_mmio_is_unalign(gvt, offset)) {
                if (WARN_ON(!IS_ALIGNED(offset, bytes)))
                        goto err;
        }
 
+       mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));
        if (mmio) {
                if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) {
                        if (WARN_ON(offset + bytes > mmio->offset + mmio->size))
@@ -152,9 +139,23 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
                                goto err;
                }
                ret = mmio->read(vgpu, offset, p_data, bytes);
-       } else
+       } else {
                ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
 
+               if (!vgpu->mmio.disable_warn_untrack) {
+                       gvt_err("vgpu%d: read untracked MMIO %x(%dB) val %x\n",
+                               vgpu->id, offset, bytes, *(u32 *)p_data);
+
+                       if (offset == 0x206c) {
+                               gvt_err("------------------------------------------\n");
+                               gvt_err("vgpu%d: likely triggers a gfx reset\n",
+                                       vgpu->id);
+                               gvt_err("------------------------------------------\n");
+                               vgpu->mmio.disable_warn_untrack = true;
+                       }
+               }
+       }
+
        if (ret)
                goto err;
 
@@ -302,3 +303,56 @@ err:
        mutex_unlock(&gvt->lock);
        return ret;
 }
+
+
+/**
+ * intel_vgpu_reset_mmio - reset virtual MMIO space
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+       const struct intel_gvt_device_info *info = &gvt->device_info;
+
+       memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size);
+       memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size);
+
+       vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;
+
+       /* set the bit 0:2(Core C-State ) to C0 */
+       vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0;
+}
+
+/**
+ * intel_vgpu_init_mmio - init MMIO  space
+ * @vgpu: a vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_init_mmio(struct intel_vgpu *vgpu)
+{
+       const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+
+       vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);
+       if (!vgpu->mmio.vreg)
+               return -ENOMEM;
+
+       vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size;
+
+       intel_vgpu_reset_mmio(vgpu);
+
+       return 0;
+}
+
+/**
+ * intel_vgpu_clean_mmio - clean MMIO space
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_clean_mmio(struct intel_vgpu *vgpu)
+{
+       vfree(vgpu->mmio.vreg);
+       vgpu->mmio.vreg = vgpu->mmio.sreg = NULL;
+}
index 87d5b5e366a3c97e7b2da79c1b8e66d97823e916..3bc620f56f351e774dc8658c9f06c79d0b24446b 100644 (file)
@@ -86,6 +86,10 @@ struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
        *offset; \
 })
 
+int intel_vgpu_init_mmio(struct intel_vgpu *vgpu);
+void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu);
+void intel_vgpu_clean_mmio(struct intel_vgpu *vgpu);
+
 int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa);
 
 int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, u64 pa,
index d2a0fbc896c3cb2ca0734a9371b603fb8669a643..d9fb41ab71198cb19b1ade4796f687af49444c80 100644 (file)
@@ -36,9 +36,9 @@ static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
                        vgpu->id))
                return -EINVAL;
 
-       vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_ATOMIC |
-                       GFP_DMA32 | __GFP_ZERO,
-                       INTEL_GVT_OPREGION_PORDER);
+       vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL |
+                       __GFP_ZERO,
+                       get_order(INTEL_GVT_OPREGION_SIZE));
 
        if (!vgpu_opregion(vgpu)->va)
                return -ENOMEM;
@@ -65,7 +65,7 @@ static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
        int i, ret;
 
        for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) {
-               mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu)
+               mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu)->va
                        + i * PAGE_SIZE);
                if (mfn == INTEL_GVT_INVALID_ADDR) {
                        gvt_err("fail to get MFN from VA\n");
@@ -97,7 +97,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
        if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
                map_vgpu_opregion(vgpu, false);
                free_pages((unsigned long)vgpu_opregion(vgpu)->va,
-                               INTEL_GVT_OPREGION_PORDER);
+                               get_order(INTEL_GVT_OPREGION_SIZE));
 
                vgpu_opregion(vgpu)->va = NULL;
        }
index 0dfe789d8f02b64ade88381b2a69fbca09f2862a..fbd023a16f18163d6dcb52bcf795675e3c16a4f7 100644 (file)
@@ -50,8 +50,7 @@
 #define INTEL_GVT_OPREGION_PARM                   0x204
 
 #define INTEL_GVT_OPREGION_PAGES       2
-#define INTEL_GVT_OPREGION_PORDER      1
-#define INTEL_GVT_OPREGION_SIZE                (2 * 4096)
+#define INTEL_GVT_OPREGION_SIZE                (INTEL_GVT_OPREGION_PAGES * PAGE_SIZE)
 
 #define VGT_SPRSTRIDE(pipe)    _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B)
 
index 4db24225023520b879b12fce1a924cc236384bd5..e91885dffeff8d76d73f1942a9e3c91b5087639c 100644 (file)
@@ -350,13 +350,15 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 {
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
        struct intel_vgpu_workload *workload;
+       struct intel_vgpu *vgpu;
        int event;
 
        mutex_lock(&gvt->lock);
 
        workload = scheduler->current_workload[ring_id];
+       vgpu = workload->vgpu;
 
-       if (!workload->status && !workload->vgpu->resetting) {
+       if (!workload->status && !vgpu->resetting) {
                wait_event(workload->shadow_ctx_status_wq,
                           !atomic_read(&workload->shadow_ctx_active));
 
@@ -364,8 +366,7 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 
                for_each_set_bit(event, workload->pending_events,
                                 INTEL_GVT_EVENT_MAX)
-                       intel_vgpu_trigger_virtual_event(workload->vgpu,
-                                       event);
+                       intel_vgpu_trigger_virtual_event(vgpu, event);
        }
 
        gvt_dbg_sched("ring id %d complete workload %p status %d\n",
@@ -373,11 +374,10 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 
        scheduler->current_workload[ring_id] = NULL;
 
-       atomic_dec(&workload->vgpu->running_workload_num);
-
        list_del_init(&workload->list);
        workload->complete(workload);
 
+       atomic_dec(&vgpu->running_workload_num);
        wake_up(&scheduler->workload_complete_wq);
        mutex_unlock(&gvt->lock);
 }
@@ -459,11 +459,11 @@ complete:
                gvt_dbg_sched("will complete workload %p\n, status: %d\n",
                                workload, workload->status);
 
-               complete_current_workload(gvt, ring_id);
-
                if (workload->req)
                        i915_gem_request_put(fetch_and_zero(&workload->req));
 
+               complete_current_workload(gvt, ring_id);
+
                if (need_force_wake)
                        intel_uncore_forcewake_put(gvt->dev_priv,
                                        FORCEWAKE_ALL);
index 3b30c28bff515f0fd1ce7e385ea89d6f17ccc834..2833dfa8c9aed8e9b6c8f86bbd2ad9a45c461b0c 100644 (file)
@@ -113,7 +113,7 @@ struct intel_shadow_bb_entry {
        struct drm_i915_gem_object *obj;
        void *va;
        unsigned long len;
-       void *bb_start_cmd_va;
+       u32 *bb_start_cmd_va;
 };
 
 #define workload_q_head(vgpu, ring_id) \
index 536d2b9d577732f57a1775f54bdb4a7bce8a7e39..7295bc8e12fb240eeaf6f9434d2bba713453ad3c 100644 (file)
 #include "gvt.h"
 #include "i915_pvinfo.h"
 
-static void clean_vgpu_mmio(struct intel_vgpu *vgpu)
-{
-       vfree(vgpu->mmio.vreg);
-       vgpu->mmio.vreg = vgpu->mmio.sreg = NULL;
-}
-
-int setup_vgpu_mmio(struct intel_vgpu *vgpu)
-{
-       struct intel_gvt *gvt = vgpu->gvt;
-       const struct intel_gvt_device_info *info = &gvt->device_info;
-
-       if (vgpu->mmio.vreg)
-               memset(vgpu->mmio.vreg, 0, info->mmio_size * 2);
-       else {
-               vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);
-               if (!vgpu->mmio.vreg)
-                       return -ENOMEM;
-       }
-
-       vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size;
-
-       memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size);
-       memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size);
-
-       vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;
-
-       /* set the bit 0:2(Core C-State ) to C0 */
-       vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0;
-       return 0;
-}
-
-static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu,
-       struct intel_vgpu_creation_params *param)
-{
-       struct intel_gvt *gvt = vgpu->gvt;
-       const struct intel_gvt_device_info *info = &gvt->device_info;
-       u16 *gmch_ctl;
-       int i;
-
-       memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
-              info->cfg_space_size);
-
-       if (!param->primary) {
-               vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
-                       INTEL_GVT_PCI_CLASS_VGA_OTHER;
-               vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
-                       INTEL_GVT_PCI_CLASS_VGA_OTHER;
-       }
-
-       /* Show guest that there isn't any stolen memory.*/
-       gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
-       *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
-
-       intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
-                                gvt_aperture_pa_base(gvt), true);
-
-       vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
-                                            | PCI_COMMAND_MEMORY
-                                            | PCI_COMMAND_MASTER);
-       /*
-        * Clear the bar upper 32bit and let guest to assign the new value
-        */
-       memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
-       memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
-       memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
-
-       for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
-               vgpu->cfg_space.bar[i].size = pci_resource_len(
-                                             gvt->dev_priv->drm.pdev, i * 2);
-               vgpu->cfg_space.bar[i].tracked = false;
-       }
-}
-
 void populate_pvinfo_page(struct intel_vgpu *vgpu)
 {
        /* setup the ballooning information */
@@ -177,7 +104,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
                if (low_avail / min_low == 0)
                        break;
                gvt->types[i].low_gm_size = min_low;
-               gvt->types[i].high_gm_size = 3 * gvt->types[i].low_gm_size;
+               gvt->types[i].high_gm_size = max((min_low<<3), MB_TO_BYTES(384U));
                gvt->types[i].fence = 4;
                gvt->types[i].max_instance = low_avail / min_low;
                gvt->types[i].avail_instance = gvt->types[i].max_instance;
@@ -217,7 +144,7 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
         */
        low_gm_avail = MB_TO_BYTES(256) - HOST_LOW_GM_SIZE -
                gvt->gm.vgpu_allocated_low_gm_size;
-       high_gm_avail = MB_TO_BYTES(256) * 3 - HOST_HIGH_GM_SIZE -
+       high_gm_avail = MB_TO_BYTES(256) * 8UL - HOST_HIGH_GM_SIZE -
                gvt->gm.vgpu_allocated_high_gm_size;
        fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
                gvt->fence.vgpu_allocated_fence_num;
@@ -268,7 +195,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
        intel_vgpu_clean_gtt(vgpu);
        intel_gvt_hypervisor_detach_vgpu(vgpu);
        intel_vgpu_free_resource(vgpu);
-       clean_vgpu_mmio(vgpu);
+       intel_vgpu_clean_mmio(vgpu);
        vfree(vgpu);
 
        intel_gvt_update_vgpu_types(gvt);
@@ -300,11 +227,11 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
        vgpu->gvt = gvt;
        bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
 
-       setup_vgpu_cfg_space(vgpu, param);
+       intel_vgpu_init_cfg_space(vgpu, param->primary);
 
-       ret = setup_vgpu_mmio(vgpu);
+       ret = intel_vgpu_init_mmio(vgpu);
        if (ret)
-               goto out_free_vgpu;
+               goto out_clean_idr;
 
        ret = intel_vgpu_alloc_resource(vgpu, param);
        if (ret)
@@ -354,7 +281,9 @@ out_detach_hypervisor_vgpu:
 out_clean_vgpu_resource:
        intel_vgpu_free_resource(vgpu);
 out_clean_vgpu_mmio:
-       clean_vgpu_mmio(vgpu);
+       intel_vgpu_clean_mmio(vgpu);
+out_clean_idr:
+       idr_remove(&gvt->vgpu_idr, vgpu->id);
 out_free_vgpu:
        vfree(vgpu);
        mutex_unlock(&gvt->lock);
@@ -398,7 +327,75 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
 }
 
 /**
- * intel_gvt_reset_vgpu - reset a virtual GPU
+ * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset
+ * @vgpu: virtual GPU
+ * @dmlr: vGPU Device Model Level Reset or GT Reset
+ * @engine_mask: engines to reset for GT reset
+ *
+ * This function is called when user wants to reset a virtual GPU through
+ * device model reset or GT reset. The caller should hold the gvt lock.
+ *
+ * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset
+ * the whole vGPU to default state as when it is created. This vGPU function
+ * is required both for functionary and security concerns.The ultimate goal
+ * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we
+ * assign a vGPU to a virtual machine we must isse such reset first.
+ *
+ * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines
+ * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec.
+ * Unlike the FLR, GT reset only reset particular resource of a vGPU per
+ * the reset request. Guest driver can issue a GT reset by programming the
+ * virtual GDRST register to reset specific virtual GPU engine or all
+ * engines.
+ *
+ * The parameter dev_level is to identify if we will do DMLR or GT reset.
+ * The parameter engine_mask is to specific the engines that need to be
+ * resetted. If value ALL_ENGINES is given for engine_mask, it means
+ * the caller requests a full GT reset that we will reset all virtual
+ * GPU engines. For FLR, engine_mask is ignored.
+ */
+void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
+                                unsigned int engine_mask)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+       struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+
+       gvt_dbg_core("------------------------------------------\n");
+       gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n",
+                    vgpu->id, dmlr, engine_mask);
+       vgpu->resetting = true;
+
+       intel_vgpu_stop_schedule(vgpu);
+       /*
+        * The current_vgpu will set to NULL after stopping the
+        * scheduler when the reset is triggered by current vgpu.
+        */
+       if (scheduler->current_vgpu == NULL) {
+               mutex_unlock(&gvt->lock);
+               intel_gvt_wait_vgpu_idle(vgpu);
+               mutex_lock(&gvt->lock);
+       }
+
+       intel_vgpu_reset_execlist(vgpu, dmlr ? ALL_ENGINES : engine_mask);
+
+       /* full GPU reset or device model level reset */
+       if (engine_mask == ALL_ENGINES || dmlr) {
+               intel_vgpu_reset_gtt(vgpu, dmlr);
+               intel_vgpu_reset_resource(vgpu);
+               intel_vgpu_reset_mmio(vgpu);
+               populate_pvinfo_page(vgpu);
+
+               if (dmlr)
+                       intel_vgpu_reset_cfg_space(vgpu);
+       }
+
+       vgpu->resetting = false;
+       gvt_dbg_core("reset vgpu%d done\n", vgpu->id);
+       gvt_dbg_core("------------------------------------------\n");
+}
+
+/**
+ * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level)
  * @vgpu: virtual GPU
  *
  * This function is called when user wants to reset a virtual GPU.
@@ -406,4 +403,7 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
  */
 void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu)
 {
+       mutex_lock(&vgpu->gvt->lock);
+       intel_gvt_reset_vgpu_locked(vgpu, true, 0);
+       mutex_unlock(&vgpu->gvt->lock);
 }
index 445fec9c2841ad61282e538d4cfdbe1436e04fb3..728ca3ea74d2c85df8734ddaa9285e126bc2c82c 100644 (file)
@@ -213,7 +213,8 @@ static void intel_detect_pch(struct drm_device *dev)
                        } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) {
                                dev_priv->pch_type = PCH_KBP;
                                DRM_DEBUG_KMS("Found KabyPoint PCH\n");
-                               WARN_ON(!IS_KABYLAKE(dev_priv));
+                               WARN_ON(!IS_SKYLAKE(dev_priv) &&
+                                       !IS_KABYLAKE(dev_priv));
                        } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
                                   (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
                                   ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
@@ -2378,7 +2379,7 @@ static int intel_runtime_suspend(struct device *kdev)
 
        assert_forcewakes_inactive(dev_priv);
 
-       if (!IS_VALLEYVIEW(dev_priv) || !IS_CHERRYVIEW(dev_priv))
+       if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
                intel_hpd_poll_init(dev_priv);
 
        DRM_DEBUG_KMS("Device suspended\n");
@@ -2427,6 +2428,7 @@ static int intel_runtime_resume(struct device *kdev)
         * we can do is to hope that things will still work (and disable RPM).
         */
        i915_gem_init_swizzling(dev_priv);
+       i915_gem_restore_fences(dev_priv);
 
        intel_runtime_pm_enable_interrupts(dev_priv);
 
index 243224aeabf82f111ab14c4d6995ce868c0d36c1..8493e19b563a134ba588e9df39c3fb5785a25a69 100644 (file)
@@ -1012,6 +1012,8 @@ struct intel_fbc {
        struct work_struct underrun_work;
 
        struct intel_fbc_state_cache {
+               struct i915_vma *vma;
+
                struct {
                        unsigned int mode_flags;
                        uint32_t hsw_bdw_pixel_rate;
@@ -1025,15 +1027,14 @@ struct intel_fbc {
                } plane;
 
                struct {
-                       u64 ilk_ggtt_offset;
                        uint32_t pixel_format;
                        unsigned int stride;
-                       int fence_reg;
-                       unsigned int tiling_mode;
                } fb;
        } state_cache;
 
        struct intel_fbc_reg_params {
+               struct i915_vma *vma;
+
                struct {
                        enum pipe pipe;
                        enum plane plane;
@@ -1041,10 +1042,8 @@ struct intel_fbc {
                } crtc;
 
                struct {
-                       u64 ggtt_offset;
                        uint32_t pixel_format;
                        unsigned int stride;
-                       int fence_reg;
                } fb;
 
                int cfb_size;
@@ -1977,6 +1976,11 @@ struct drm_i915_private {
 
        struct i915_frontbuffer_tracking fb_tracking;
 
+       struct intel_atomic_helper {
+               struct llist_head free_list;
+               struct work_struct free_work;
+       } atomic_helper;
+
        u16 orig_clock;
 
        bool mchbar_need_disable;
@@ -3163,13 +3167,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj,
        return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
 }
 
-static inline unsigned long
-i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
-                           const struct i915_ggtt_view *view)
-{
-       return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
-}
-
 /* i915_gem_fence_reg.c */
 int __must_check i915_vma_get_fence(struct i915_vma *vma);
 int __must_check i915_vma_put_fence(struct i915_vma *vma);
index 4a31b7a891ecaf3e2732c9f2d6ce62fa633419f6..24b5b046754b37e8b8e3ab2c04a9f890b41eecf9 100644 (file)
@@ -244,14 +244,16 @@ err_phys:
 
 static void
 __i915_gem_object_release_shmem(struct drm_i915_gem_object *obj,
-                               struct sg_table *pages)
+                               struct sg_table *pages,
+                               bool needs_clflush)
 {
        GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED);
 
        if (obj->mm.madv == I915_MADV_DONTNEED)
                obj->mm.dirty = false;
 
-       if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0 &&
+       if (needs_clflush &&
+           (obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0 &&
            !cpu_cache_is_coherent(obj->base.dev, obj->cache_level))
                drm_clflush_sg(pages);
 
@@ -263,7 +265,7 @@ static void
 i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
                               struct sg_table *pages)
 {
-       __i915_gem_object_release_shmem(obj, pages);
+       __i915_gem_object_release_shmem(obj, pages, false);
 
        if (obj->mm.dirty) {
                struct address_space *mapping = obj->base.filp->f_mapping;
@@ -593,47 +595,21 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
                     struct drm_i915_gem_pwrite *args,
                     struct drm_file *file)
 {
-       struct drm_device *dev = obj->base.dev;
        void *vaddr = obj->phys_handle->vaddr + args->offset;
        char __user *user_data = u64_to_user_ptr(args->data_ptr);
-       int ret;
 
        /* We manually control the domain here and pretend that it
         * remains coherent i.e. in the GTT domain, like shmem_pwrite.
         */
-       lockdep_assert_held(&obj->base.dev->struct_mutex);
-       ret = i915_gem_object_wait(obj,
-                                  I915_WAIT_INTERRUPTIBLE |
-                                  I915_WAIT_LOCKED |
-                                  I915_WAIT_ALL,
-                                  MAX_SCHEDULE_TIMEOUT,
-                                  to_rps_client(file));
-       if (ret)
-               return ret;
-
        intel_fb_obj_invalidate(obj, ORIGIN_CPU);
-       if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
-               unsigned long unwritten;
-
-               /* The physical object once assigned is fixed for the lifetime
-                * of the obj, so we can safely drop the lock and continue
-                * to access vaddr.
-                */
-               mutex_unlock(&dev->struct_mutex);
-               unwritten = copy_from_user(vaddr, user_data, args->size);
-               mutex_lock(&dev->struct_mutex);
-               if (unwritten) {
-                       ret = -EFAULT;
-                       goto out;
-               }
-       }
+       if (copy_from_user(vaddr, user_data, args->size))
+               return -EFAULT;
 
        drm_clflush_virt_range(vaddr, args->size);
-       i915_gem_chipset_flush(to_i915(dev));
+       i915_gem_chipset_flush(to_i915(obj->base.dev));
 
-out:
        intel_fb_obj_flush(obj, false, ORIGIN_CPU);
-       return ret;
+       return 0;
 }
 
 void *i915_gem_object_alloc(struct drm_device *dev)
@@ -2034,8 +2010,16 @@ void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
        for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
 
-               if (WARN_ON(reg->pin_count))
-                       continue;
+               /* Ideally we want to assert that the fence register is not
+                * live at this point (i.e. that no piece of code will be
+                * trying to write through fence + GTT, as that both violates
+                * our tracking of activity and associated locking/barriers,
+                * but also is illegal given that the hw is powered down).
+                *
+                * Previously we used reg->pin_count as a "liveness" indicator.
+                * That is not sufficient, and we need a more fine-grained
+                * tool if we want to have a sanity check here.
+                */
 
                if (!reg->vma)
                        continue;
@@ -2231,7 +2215,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
        struct sgt_iter sgt_iter;
        struct page *page;
 
-       __i915_gem_object_release_shmem(obj, pages);
+       __i915_gem_object_release_shmem(obj, pages, true);
 
        i915_gem_gtt_finish_pages(obj, pages);
 
@@ -2304,15 +2288,6 @@ unlock:
        mutex_unlock(&obj->mm.lock);
 }
 
-static unsigned int swiotlb_max_size(void)
-{
-#if IS_ENABLED(CONFIG_SWIOTLB)
-       return rounddown(swiotlb_nr_tbl() << IO_TLB_SHIFT, PAGE_SIZE);
-#else
-       return 0;
-#endif
-}
-
 static void i915_sg_trim(struct sg_table *orig_st)
 {
        struct sg_table new_st;
@@ -2322,7 +2297,7 @@ static void i915_sg_trim(struct sg_table *orig_st)
        if (orig_st->nents == orig_st->orig_nents)
                return;
 
-       if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL))
+       if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL | __GFP_NOWARN))
                return;
 
        new_sg = new_st.sgl;
@@ -2360,7 +2335,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
        GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
        GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
 
-       max_segment = swiotlb_max_size();
+       max_segment = swiotlb_max_segment();
        if (!max_segment)
                max_segment = rounddown(UINT_MAX, PAGE_SIZE);
 
@@ -2728,6 +2703,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
        struct drm_i915_gem_request *request;
        struct i915_gem_context *incomplete_ctx;
        struct intel_timeline *timeline;
+       unsigned long flags;
        bool ring_hung;
 
        if (engine->irq_seqno_barrier)
@@ -2763,13 +2739,20 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)
        if (i915_gem_context_is_default(incomplete_ctx))
                return;
 
+       timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine);
+
+       spin_lock_irqsave(&engine->timeline->lock, flags);
+       spin_lock(&timeline->lock);
+
        list_for_each_entry_continue(request, &engine->timeline->requests, link)
                if (request->ctx == incomplete_ctx)
                        reset_request(request);
 
-       timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine);
        list_for_each_entry(request, &timeline->requests, link)
                reset_request(request);
+
+       spin_unlock(&timeline->lock);
+       spin_unlock_irqrestore(&engine->timeline->lock, flags);
 }
 
 void i915_gem_reset(struct drm_i915_private *dev_priv)
@@ -3503,7 +3486,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
        vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
 
        /* Treat this as an end-of-frame, like intel_user_framebuffer_dirty() */
-       if (obj->cache_dirty) {
+       if (obj->cache_dirty || obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
                i915_gem_clflush_object(obj, true);
                intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
        }
index bd08814b015cb238c639e2becec6917901890d4e..d534a316a16ee412420c7e5cc01fb37c03755480 100644 (file)
@@ -199,6 +199,7 @@ found:
        }
 
        /* Unbinding will emit any required flushes */
+       ret = 0;
        while (!list_empty(&eviction_list)) {
                vma = list_first_entry(&eviction_list,
                                       struct i915_vma,
index 097d9d8c2315e061a3600615532c6d51531ee42c..b8b877c91b0a9b36b1a9ac318b2e5255b096a46e 100644 (file)
@@ -1181,14 +1181,14 @@ validate_exec_list(struct drm_device *dev,
                        if (exec[i].offset !=
                            gen8_canonical_addr(exec[i].offset & PAGE_MASK))
                                return -EINVAL;
-
-                       /* From drm_mm perspective address space is continuous,
-                        * so from this point we're always using non-canonical
-                        * form internally.
-                        */
-                       exec[i].offset = gen8_noncanonical_addr(exec[i].offset);
                }
 
+               /* From drm_mm perspective address space is continuous,
+                * so from this point we're always using non-canonical
+                * form internally.
+                */
+               exec[i].offset = gen8_noncanonical_addr(exec[i].offset);
+
                if (exec[i].alignment && !is_power_of_2(exec[i].alignment))
                        return -EINVAL;
 
index 4b3ff3e5b911167557880228d5da44bb3d2616bf..d09c74973cb37a6c8d599c007ea4a53c0e0994e0 100644 (file)
@@ -66,8 +66,16 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
 
        max_order = MAX_ORDER;
 #ifdef CONFIG_SWIOTLB
-       if (swiotlb_nr_tbl()) /* minimum max swiotlb size is IO_TLB_SEGSIZE */
-               max_order = min(max_order, ilog2(IO_TLB_SEGPAGES));
+       if (swiotlb_nr_tbl()) {
+               unsigned int max_segment;
+
+               max_segment = swiotlb_max_segment();
+               if (max_segment) {
+                       max_segment = max_t(unsigned int, max_segment,
+                                           PAGE_SIZE) >> PAGE_SHIFT;
+                       max_order = min(max_order, ilog2(max_segment));
+               }
+       }
 #endif
 
        gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE;
index e2b077df2da023107c92a818d3c74042dcf73bac..d229f47d1028bb615675f846ecbd46a43ae17197 100644 (file)
@@ -413,6 +413,25 @@ i915_gem_active_set(struct i915_gem_active *active,
        rcu_assign_pointer(active->request, request);
 }
 
+/**
+ * i915_gem_active_set_retire_fn - updates the retirement callback
+ * @active - the active tracker
+ * @fn - the routine called when the request is retired
+ * @mutex - struct_mutex used to guard retirements
+ *
+ * i915_gem_active_set_retire_fn() updates the function pointer that
+ * is called when the final request associated with the @active tracker
+ * is retired.
+ */
+static inline void
+i915_gem_active_set_retire_fn(struct i915_gem_active *active,
+                             i915_gem_retire_fn fn,
+                             struct mutex *mutex)
+{
+       lockdep_assert_held(mutex);
+       active->retire = fn ?: i915_gem_retire_noop;
+}
+
 static inline struct drm_i915_gem_request *
 __i915_gem_active_peek(const struct i915_gem_active *active)
 {
index a792dcb902b51d337f46f2c1ad7ad1ea737f4c8a..e924a95160796d1c8aa708e1c9ac0312b1015eb8 100644 (file)
@@ -185,6 +185,7 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
                        return ret;
        }
 
+       trace_i915_vma_bind(vma, bind_flags);
        ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
        if (ret)
                return ret;
index dbe9fb41ae535449f996ab36e51bd626be6651fc..8d3e515f27bade27acda9544a30d975628ac8ab3 100644 (file)
@@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane)
 
        __drm_atomic_helper_plane_duplicate_state(plane, state);
 
+       intel_state->vma = NULL;
+
        return state;
 }
 
@@ -100,6 +102,24 @@ void
 intel_plane_destroy_state(struct drm_plane *plane,
                          struct drm_plane_state *state)
 {
+       struct i915_vma *vma;
+
+       vma = fetch_and_zero(&to_intel_plane_state(state)->vma);
+
+       /*
+        * FIXME: Normally intel_cleanup_plane_fb handles destruction of vma.
+        * We currently don't clear all planes during driver unload, so we have
+        * to be able to unpin vma here for now.
+        *
+        * Normally this can only happen during unload when kmscon is disabled
+        * and userspace doesn't attempt to set a framebuffer at all.
+        */
+       if (vma) {
+               mutex_lock(&plane->dev->struct_mutex);
+               intel_unpin_fb_vma(vma);
+               mutex_unlock(&plane->dev->struct_mutex);
+       }
+
        drm_atomic_helper_plane_destroy_state(plane, state);
 }
 
index 86ecec5601d42dd59f937f7c8c2203b3aeb105bc..588470eb8d395df2719fe2e172f93f414ba88e92 100644 (file)
@@ -499,6 +499,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
        struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
        struct edid *edid;
        struct i2c_adapter *i2c;
+       bool ret = false;
 
        BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
 
@@ -515,17 +516,17 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
                 */
                if (!is_digital) {
                        DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
-                       return true;
+                       ret = true;
+               } else {
+                       DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
                }
-
-               DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
        } else {
                DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
        }
 
        kfree(edid);
 
-       return false;
+       return ret;
 }
 
 static enum drm_connector_status
index 6daad86137606d700b6101ee0ffde7a7ee35a1cd..891c86aef99dfe1b939d5641d0b604bf9b3a49de 100644 (file)
@@ -2235,24 +2235,22 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
                        i915_vma_pin_fence(vma);
        }
 
+       i915_vma_get(vma);
 err:
        intel_runtime_pm_put(dev_priv);
        return vma;
 }
 
-void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
+void intel_unpin_fb_vma(struct i915_vma *vma)
 {
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-       struct i915_ggtt_view view;
-       struct i915_vma *vma;
-
-       WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
+       lockdep_assert_held(&vma->vm->dev->struct_mutex);
 
-       intel_fill_fb_ggtt_view(&view, fb, rotation);
-       vma = i915_gem_object_to_ggtt(obj, &view);
+       if (WARN_ON_ONCE(!vma))
+               return;
 
        i915_vma_unpin_fence(vma);
        i915_gem_object_unpin_from_display_plane(vma);
+       i915_vma_put(vma);
 }
 
 static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
@@ -2585,8 +2583,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
                         * We only keep the x/y offsets, so push all of the
                         * gtt offset into the x/y offsets.
                         */
-                       _intel_adjust_tile_offset(&x, &y, tile_size,
-                                                 tile_width, tile_height, pitch_tiles,
+                       _intel_adjust_tile_offset(&x, &y,
+                                                 tile_width, tile_height,
+                                                 tile_size, pitch_tiles,
                                                  gtt_offset_rotated * tile_size, 0);
 
                        gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height;
@@ -2746,7 +2745,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_crtc *c;
-       struct intel_crtc *i;
        struct drm_i915_gem_object *obj;
        struct drm_plane *primary = intel_crtc->base.primary;
        struct drm_plane_state *plane_state = primary->state;
@@ -2771,20 +2769,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
         * an fb with another CRTC instead
         */
        for_each_crtc(dev, c) {
-               i = to_intel_crtc(c);
+               struct intel_plane_state *state;
 
                if (c == &intel_crtc->base)
                        continue;
 
-               if (!i->active)
+               if (!to_intel_crtc(c)->active)
                        continue;
 
-               fb = c->primary->fb;
-               if (!fb)
+               state = to_intel_plane_state(c->primary->state);
+               if (!state->vma)
                        continue;
 
-               obj = intel_fb_obj(fb);
-               if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) {
+               if (intel_plane_ggtt_offset(state) == plane_config->base) {
+                       fb = c->primary->fb;
                        drm_framebuffer_reference(fb);
                        goto valid_fb;
                }
@@ -2805,6 +2803,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        return;
 
 valid_fb:
+       mutex_lock(&dev->struct_mutex);
+       intel_state->vma =
+               intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
+       mutex_unlock(&dev->struct_mutex);
+       if (IS_ERR(intel_state->vma)) {
+               DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
+                         intel_crtc->pipe, PTR_ERR(intel_state->vma));
+
+               intel_state->vma = NULL;
+               drm_framebuffer_unreference(fb);
+               return;
+       }
+
        plane_state->src_x = 0;
        plane_state->src_y = 0;
        plane_state->src_w = fb->width << 16;
@@ -2967,6 +2978,9 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
        unsigned int rotation = plane_state->base.rotation;
        int ret;
 
+       if (!plane_state->base.visible)
+               return 0;
+
        /* Rotate src coordinates to match rotated GTT view */
        if (drm_rotation_90_or_270(rotation))
                drm_rect_rotate(&plane_state->base.src,
@@ -3097,13 +3111,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        if (INTEL_GEN(dev_priv) >= 4) {
                I915_WRITE(DSPSURF(plane),
-                          intel_fb_gtt_offset(fb, rotation) +
+                          intel_plane_ggtt_offset(plane_state) +
                           intel_crtc->dspaddr_offset);
                I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
                I915_WRITE(DSPLINOFF(plane), linear_offset);
        } else {
                I915_WRITE(DSPADDR(plane),
-                          intel_fb_gtt_offset(fb, rotation) +
+                          intel_plane_ggtt_offset(plane_state) +
                           intel_crtc->dspaddr_offset);
        }
        POSTING_READ(reg);
@@ -3200,7 +3214,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
 
        I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
        I915_WRITE(DSPSURF(plane),
-                  intel_fb_gtt_offset(fb, rotation) +
+                  intel_plane_ggtt_offset(plane_state) +
                   intel_crtc->dspaddr_offset);
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
                I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
@@ -3223,23 +3237,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
        }
 }
 
-u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
-                       unsigned int rotation)
-{
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-       struct i915_ggtt_view view;
-       struct i915_vma *vma;
-
-       intel_fill_fb_ggtt_view(&view, fb, rotation);
-
-       vma = i915_gem_object_to_ggtt(obj, &view);
-       if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
-                view.type))
-               return -1;
-
-       return i915_ggtt_offset(vma);
-}
-
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
 {
        struct drm_device *dev = intel_crtc->base.dev;
@@ -3434,7 +3431,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
        }
 
        I915_WRITE(PLANE_SURF(pipe, 0),
-                  intel_fb_gtt_offset(fb, rotation) + surf_addr);
+                  intel_plane_ggtt_offset(plane_state) + surf_addr);
 
        POSTING_READ(PLANE_SURF(pipe, 0));
 }
@@ -4265,10 +4262,10 @@ static void page_flip_completed(struct intel_crtc *intel_crtc)
        drm_crtc_vblank_put(&intel_crtc->base);
 
        wake_up_all(&dev_priv->pending_flip_queue);
-       queue_work(dev_priv->wq, &work->unpin_work);
-
        trace_i915_flip_complete(intel_crtc->plane,
                                 work->pending_flip_obj);
+
+       queue_work(dev_priv->wq, &work->unpin_work);
 }
 
 static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
@@ -6846,6 +6843,12 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
        }
 
        state = drm_atomic_state_alloc(crtc->dev);
+       if (!state) {
+               DRM_DEBUG_KMS("failed to disable [CRTC:%d:%s], out of memory",
+                             crtc->base.id, crtc->name);
+               return;
+       }
+
        state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
 
        /* Everything's already locked, -EDEADLK can't happen. */
@@ -11243,6 +11246,7 @@ found:
        }
 
        old->restore_state = restore_state;
+       drm_atomic_state_put(state);
 
        /* let the connector get through one full cycle before testing */
        intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
@@ -11522,7 +11526,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
                flush_work(&work->mmio_work);
 
        mutex_lock(&dev->struct_mutex);
-       intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
+       intel_unpin_fb_vma(work->old_vma);
        i915_gem_object_put(work->pending_flip_obj);
        mutex_unlock(&dev->struct_mutex);
 
@@ -12232,8 +12236,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
                goto cleanup_pending;
        }
 
-       work->gtt_offset = intel_fb_gtt_offset(fb, primary->state->rotation);
-       work->gtt_offset += intel_crtc->dspaddr_offset;
+       work->old_vma = to_intel_plane_state(primary->state)->vma;
+       to_intel_plane_state(primary->state)->vma = vma;
+
+       work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
        work->rotation = crtc->primary->state->rotation;
 
        /*
@@ -12287,7 +12293,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 cleanup_request:
        i915_add_request_no_flush(request);
 cleanup_unpin:
-       intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
+       to_intel_plane_state(primary->state)->vma = work->old_vma;
+       intel_unpin_fb_vma(vma);
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
 unlock:
@@ -14512,8 +14519,14 @@ intel_atomic_commit_ready(struct i915_sw_fence *fence,
                break;
 
        case FENCE_FREE:
-               drm_atomic_state_put(&state->base);
-               break;
+               {
+                       struct intel_atomic_helper *helper =
+                               &to_i915(state->base.dev)->atomic_helper;
+
+                       if (llist_add(&state->freed, &helper->free_list))
+                               schedule_work(&helper->free_work);
+                       break;
+               }
        }
 
        return NOTIFY_DONE;
@@ -14774,6 +14787,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                        DRM_DEBUG_KMS("failed to pin object\n");
                        return PTR_ERR(vma);
                }
+
+               to_intel_plane_state(new_state)->vma = vma;
        }
 
        return 0;
@@ -14792,19 +14807,12 @@ void
 intel_cleanup_plane_fb(struct drm_plane *plane,
                       struct drm_plane_state *old_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
-       struct intel_plane_state *old_intel_state;
-       struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
-       struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
-
-       old_intel_state = to_intel_plane_state(old_state);
-
-       if (!obj && !old_obj)
-               return;
+       struct i915_vma *vma;
 
-       if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
-           !INTEL_INFO(dev_priv)->cursor_needs_physical))
-               intel_unpin_fb_obj(old_state->fb, old_state->rotation);
+       /* Should only be called after a successful intel_prepare_plane_fb()! */
+       vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
+       if (vma)
+               intel_unpin_fb_vma(vma);
 }
 
 int
@@ -15146,7 +15154,7 @@ intel_update_cursor_plane(struct drm_plane *plane,
        if (!obj)
                addr = 0;
        else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
-               addr = i915_gem_object_ggtt_offset(obj, NULL);
+               addr = intel_plane_ggtt_offset(state);
        else
                addr = obj->phys_handle->busaddr;
 
@@ -16392,6 +16400,18 @@ fail:
        drm_modeset_acquire_fini(&ctx);
 }
 
+static void intel_atomic_helper_free_state(struct work_struct *work)
+{
+       struct drm_i915_private *dev_priv =
+               container_of(work, typeof(*dev_priv), atomic_helper.free_work);
+       struct intel_atomic_state *state, *next;
+       struct llist_node *freed;
+
+       freed = llist_del_all(&dev_priv->atomic_helper.free_list);
+       llist_for_each_entry_safe(state, next, freed, freed)
+               drm_atomic_state_put(&state->base);
+}
+
 int intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -16411,6 +16431,9 @@ int intel_modeset_init(struct drm_device *dev)
 
        dev->mode_config.funcs = &intel_mode_funcs;
 
+       INIT_WORK(&dev_priv->atomic_helper.free_work,
+                 intel_atomic_helper_free_state);
+
        intel_init_quirks(dev);
 
        intel_init_pm(dev_priv);
@@ -16791,7 +16814,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 
        for_each_intel_crtc(dev, crtc) {
                struct intel_crtc_state *crtc_state = crtc->config;
-               int pixclk = 0;
 
                __drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
                memset(crtc_state, 0, sizeof(*crtc_state));
@@ -16803,23 +16825,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                crtc->base.enabled = crtc_state->base.enable;
                crtc->active = crtc_state->base.active;
 
-               if (crtc_state->base.active) {
+               if (crtc_state->base.active)
                        dev_priv->active_crtcs |= 1 << crtc->pipe;
 
-                       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-                               pixclk = ilk_pipe_pixel_rate(crtc_state);
-                       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-                               pixclk = crtc_state->base.adjusted_mode.crtc_clock;
-                       else
-                               WARN_ON(dev_priv->display.modeset_calc_cdclk);
-
-                       /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
-                       if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
-                               pixclk = DIV_ROUND_UP(pixclk * 100, 95);
-               }
-
-               dev_priv->min_pixclk[crtc->pipe] = pixclk;
-
                readout_plane_state(crtc);
 
                DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
@@ -16892,6 +16900,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        }
 
        for_each_intel_crtc(dev, crtc) {
+               int pixclk = 0;
+
                crtc->base.hwmode = crtc->config->base.adjusted_mode;
 
                memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
@@ -16919,10 +16929,23 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                         */
                        crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
 
+                       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+                               pixclk = ilk_pipe_pixel_rate(crtc->config);
+                       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+                               pixclk = crtc->config->base.adjusted_mode.crtc_clock;
+                       else
+                               WARN_ON(dev_priv->display.modeset_calc_cdclk);
+
+                       /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
+                       if (IS_BROADWELL(dev_priv) && crtc->config->ips_enabled)
+                               pixclk = DIV_ROUND_UP(pixclk * 100, 95);
+
                        drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
                        update_scanline_offset(crtc);
                }
 
+               dev_priv->min_pixclk[crtc->pipe] = pixclk;
+
                intel_pipe_config_sanity_check(dev_priv, crtc->config);
        }
 }
@@ -17024,47 +17047,19 @@ void intel_display_resume(struct drm_device *dev)
 
        if (ret)
                DRM_ERROR("Restoring old state failed with %i\n", ret);
-       drm_atomic_state_put(state);
+       if (state)
+               drm_atomic_state_put(state);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct drm_crtc *c;
-       struct drm_i915_gem_object *obj;
 
        intel_init_gt_powersave(dev_priv);
 
        intel_modeset_init_hw(dev);
 
        intel_setup_overlay(dev_priv);
-
-       /*
-        * Make sure any fbs we allocated at startup are properly
-        * pinned & fenced.  When we do the allocation it's too early
-        * for this.
-        */
-       for_each_crtc(dev, c) {
-               struct i915_vma *vma;
-
-               obj = intel_fb_obj(c->primary->fb);
-               if (obj == NULL)
-                       continue;
-
-               mutex_lock(&dev->struct_mutex);
-               vma = intel_pin_and_fence_fb_obj(c->primary->fb,
-                                                c->primary->state->rotation);
-               mutex_unlock(&dev->struct_mutex);
-               if (IS_ERR(vma)) {
-                       DRM_ERROR("failed to pin boot fb on pipe %d\n",
-                                 to_intel_crtc(c)->pipe);
-                       drm_framebuffer_unreference(c->primary->fb);
-                       c->primary->fb = NULL;
-                       c->primary->crtc = c->primary->state->crtc = NULL;
-                       update_state_fb(c->primary);
-                       c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
-               }
-       }
 }
 
 int intel_connector_register(struct drm_connector *connector)
@@ -17094,6 +17089,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
 
+       flush_work(&dev_priv->atomic_helper.free_work);
+       WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));
+
        intel_disable_gt_powersave(dev_priv);
 
        /*
index d9bc19be855e76b9bab0f1cee082bc170bccff26..0b8e8eb85c19dfe7e2bc4404914c2f578043e4e3 100644 (file)
@@ -355,7 +355,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
                                    struct intel_dp *intel_dp);
 static void
 intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
-                                             struct intel_dp *intel_dp);
+                                             struct intel_dp *intel_dp,
+                                             bool force_disable_vdd);
 static void
 intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp);
 
@@ -516,7 +517,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 
        /* init power sequencer on this pipe and port */
        intel_dp_init_panel_power_sequencer(dev, intel_dp);
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true);
 
        /*
         * Even vdd force doesn't work until we've made
@@ -553,7 +554,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
         * Only the HW needs to be reprogrammed, the SW state is fixed and
         * has been setup during connector init.
         */
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
 
        return 0;
 }
@@ -636,7 +637,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
                      port_name(port), pipe_name(intel_dp->pps_pipe));
 
        intel_dp_init_panel_power_sequencer(dev, intel_dp);
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
 }
 
 void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
@@ -2912,7 +2913,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
 
        /* init power sequencer on this pipe and port */
        intel_dp_init_panel_power_sequencer(dev, intel_dp);
-       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+       intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true);
 }
 
 static void vlv_pre_enable_dp(struct intel_encoder *encoder,
@@ -5055,7 +5056,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 
 static void
 intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
-                                             struct intel_dp *intel_dp)
+                                             struct intel_dp *intel_dp,
+                                             bool force_disable_vdd)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        u32 pp_on, pp_off, pp_div, port_sel = 0;
@@ -5068,6 +5070,31 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 
        intel_pps_get_registers(dev_priv, intel_dp, &regs);
 
+       /*
+        * On some VLV machines the BIOS can leave the VDD
+        * enabled even on power seqeuencers which aren't
+        * hooked up to any port. This would mess up the
+        * power domain tracking the first time we pick
+        * one of these power sequencers for use since
+        * edp_panel_vdd_on() would notice that the VDD was
+        * already on and therefore wouldn't grab the power
+        * domain reference. Disable VDD first to avoid this.
+        * This also avoids spuriously turning the VDD on as
+        * soon as the new power seqeuencer gets initialized.
+        */
+       if (force_disable_vdd) {
+               u32 pp = ironlake_get_pp_control(intel_dp);
+
+               WARN(pp & PANEL_POWER_ON, "Panel power already on\n");
+
+               if (pp & EDP_FORCE_VDD)
+                       DRM_DEBUG_KMS("VDD already on, disabling first\n");
+
+               pp &= ~EDP_FORCE_VDD;
+
+               I915_WRITE(regs.pp_ctrl, pp);
+       }
+
        pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
                (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
        pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
@@ -5122,7 +5149,7 @@ static void intel_dp_pps_init(struct drm_device *dev,
                vlv_initial_power_sequencer_setup(intel_dp);
        } else {
                intel_dp_init_panel_power_sequencer(dev, intel_dp);
-               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+               intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
        }
 }
 
index 58a756f2f2244d054f80baba8ef9afb6892fc21e..a2f0e070d38d6c10001d34a8ae3969fe1e3d363c 100644 (file)
@@ -1730,7 +1730,8 @@ bxt_get_dpll(struct intel_crtc *crtc,
                return NULL;
 
        if ((encoder->type == INTEL_OUTPUT_DP ||
-            encoder->type == INTEL_OUTPUT_EDP) &&
+            encoder->type == INTEL_OUTPUT_EDP ||
+            encoder->type == INTEL_OUTPUT_DP_MST) &&
            !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
                return NULL;
 
index cd132c216a67decc86e4b1fbc22d544a8230b0ad..03a2112004f91e1d5ac011cabc255a36867e0e71 100644 (file)
@@ -370,11 +370,14 @@ struct intel_atomic_state {
        struct skl_wm_values wm_results;
 
        struct i915_sw_fence commit_ready;
+
+       struct llist_node freed;
 };
 
 struct intel_plane_state {
        struct drm_plane_state base;
        struct drm_rect clip;
+       struct i915_vma *vma;
 
        struct {
                u32 offset;
@@ -1044,6 +1047,7 @@ struct intel_flip_work {
        struct work_struct mmio_work;
 
        struct drm_crtc *crtc;
+       struct i915_vma *old_vma;
        struct drm_framebuffer *old_fb;
        struct drm_i915_gem_object *pending_flip_obj;
        struct drm_pending_vblank_event *event;
@@ -1271,7 +1275,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
                                    struct drm_modeset_acquire_ctx *ctx);
 struct i915_vma *
 intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
-void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
+void intel_unpin_fb_vma(struct i915_vma *vma);
 struct drm_framebuffer *
 __intel_framebuffer_create(struct drm_device *dev,
                           struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1360,7 +1364,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
 
-u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation);
+static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
+{
+       return i915_ggtt_offset(state->vma);
+}
 
 u32 skl_plane_ctl_format(uint32_t pixel_format);
 u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
index 62f215b12eb5274b8251d3f46d2a4fdbfc590e96..f3a1d6a5cabe9fcf76f5812dc526781b678f7e41 100644 (file)
@@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
        if (IS_I945GM(dev_priv))
                fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
        fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
-       fbc_ctl |= params->fb.fence_reg;
+       fbc_ctl |= params->vma->fence->id;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
 }
 
@@ -193,8 +193,8 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
        else
                dpfc_ctl |= DPFC_CTL_LIMIT_1X;
 
-       if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
-               dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
+       if (params->vma->fence) {
+               dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id;
                I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
        } else {
                I915_WRITE(DPFC_FENCE_YOFF, 0);
@@ -251,13 +251,14 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
                break;
        }
 
-       if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+       if (params->vma->fence) {
                dpfc_ctl |= DPFC_CTL_FENCE_EN;
                if (IS_GEN5(dev_priv))
-                       dpfc_ctl |= params->fb.fence_reg;
+                       dpfc_ctl |= params->vma->fence->id;
                if (IS_GEN6(dev_priv)) {
                        I915_WRITE(SNB_DPFC_CTL_SA,
-                                  SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
+                                  SNB_CPU_FENCE_ENABLE |
+                                  params->vma->fence->id);
                        I915_WRITE(DPFC_CPU_FENCE_OFFSET,
                                   params->crtc.fence_y_offset);
                }
@@ -269,7 +270,8 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
        }
 
        I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
-       I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
+       I915_WRITE(ILK_FBC_RT_BASE,
+                  i915_ggtt_offset(params->vma) | ILK_FBC_RT_VALID);
        /* enable it... */
        I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
@@ -319,10 +321,11 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
                break;
        }
 
-       if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+       if (params->vma->fence) {
                dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
                I915_WRITE(SNB_DPFC_CTL_SA,
-                          SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
+                          SNB_CPU_FENCE_ENABLE |
+                          params->vma->fence->id);
                I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
        } else {
                I915_WRITE(SNB_DPFC_CTL_SA,0);
@@ -727,14 +730,6 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
        return effective_w <= max_w && effective_h <= max_h;
 }
 
-/* XXX replace me when we have VMA tracking for intel_plane_state */
-static int get_fence_id(struct drm_framebuffer *fb)
-{
-       struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);
-
-       return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
-}
-
 static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
                                         struct intel_crtc_state *crtc_state,
                                         struct intel_plane_state *plane_state)
@@ -743,7 +738,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
        struct intel_fbc *fbc = &dev_priv->fbc;
        struct intel_fbc_state_cache *cache = &fbc->state_cache;
        struct drm_framebuffer *fb = plane_state->base.fb;
-       struct drm_i915_gem_object *obj;
+
+       cache->vma = NULL;
 
        cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
@@ -758,16 +754,10 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
        if (!cache->plane.visible)
                return;
 
-       obj = intel_fb_obj(fb);
-
-       /* FIXME: We lack the proper locking here, so only run this on the
-        * platforms that need. */
-       if (IS_GEN(dev_priv, 5, 6))
-               cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
        cache->fb.pixel_format = fb->pixel_format;
        cache->fb.stride = fb->pitches[0];
-       cache->fb.fence_reg = get_fence_id(fb);
-       cache->fb.tiling_mode = i915_gem_object_get_tiling(obj);
+
+       cache->vma = plane_state->vma;
 }
 
 static bool intel_fbc_can_activate(struct intel_crtc *crtc)
@@ -784,7 +774,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
                return false;
        }
 
-       if (!cache->plane.visible) {
+       if (!cache->vma) {
                fbc->no_fbc_reason = "primary plane not visible";
                return false;
        }
@@ -807,8 +797,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
         * so have no fence associated with it) due to aperture constaints
         * at the time of pinning.
         */
-       if (cache->fb.tiling_mode != I915_TILING_X ||
-           cache->fb.fence_reg == I915_FENCE_REG_NONE) {
+       if (!cache->vma->fence) {
                fbc->no_fbc_reason = "framebuffer not tiled or fenced";
                return false;
        }
@@ -888,17 +877,16 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
         * zero. */
        memset(params, 0, sizeof(*params));
 
+       params->vma = cache->vma;
+
        params->crtc.pipe = crtc->pipe;
        params->crtc.plane = crtc->plane;
        params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
 
        params->fb.pixel_format = cache->fb.pixel_format;
        params->fb.stride = cache->fb.stride;
-       params->fb.fence_reg = cache->fb.fence_reg;
 
        params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
-
-       params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
 }
 
 static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
index beb08982dc0b5c3ea9711de7220c383e6ea41b92..f4a8c4fc57c4e654a1af91903275189c841b35bd 100644 (file)
@@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 out_destroy_fbi:
        drm_fb_helper_release_fbi(helper);
 out_unpin:
-       intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0);
+       intel_unpin_fb_vma(vma);
 out_unlock:
        mutex_unlock(&dev->struct_mutex);
        return ret;
@@ -549,7 +549,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
 
        if (ifbdev->fb) {
                mutex_lock(&ifbdev->helper.dev->struct_mutex);
-               intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0);
+               intel_unpin_fb_vma(ifbdev->vma);
                mutex_unlock(&ifbdev->helper.dev->struct_mutex);
 
                drm_framebuffer_remove(&ifbdev->fb->base);
@@ -742,6 +742,9 @@ void intel_fbdev_initial_config_async(struct drm_device *dev)
 {
        struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
 
+       if (!ifbdev)
+               return;
+
        ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
 }
 
index d4961fa20c73d0e2d390673889ae5fa82f04dd07..beabc17e7c8af1a08e7dff250186b32e49f717a5 100644 (file)
@@ -979,18 +979,8 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
                                                uint32_t *batch,
                                                uint32_t index)
 {
-       struct drm_i915_private *dev_priv = engine->i915;
        uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
 
-       /*
-        * WaDisableLSQCROPERFforOCL:kbl
-        * This WA is implemented in skl_init_clock_gating() but since
-        * this batch updates GEN8_L3SQCREG4 with default value we need to
-        * set this bit here to retain the WA during flush.
-        */
-       if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
-               l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
-
        wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
                                   MI_SRM_LRM_GLOBAL_GTT));
        wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
index fd0e4dac7cc16f35ff658466bc107a7296407354..e589e17876dc134b60bbb5958ad1fe856f2f118e 100644 (file)
@@ -216,7 +216,8 @@ static void intel_overlay_submit_request(struct intel_overlay *overlay,
 {
        GEM_BUG_ON(i915_gem_active_peek(&overlay->last_flip,
                                        &overlay->i915->drm.struct_mutex));
-       overlay->last_flip.retire = retire;
+       i915_gem_active_set_retire_fn(&overlay->last_flip, retire,
+                                     &overlay->i915->drm.struct_mutex);
        i915_gem_active_set(&overlay->last_flip, req);
        i915_add_request(req);
 }
@@ -839,8 +840,8 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
        if (ret)
                goto out_unpin;
 
-       i915_gem_track_fb(overlay->vma->obj, new_bo,
-                         INTEL_FRONTBUFFER_OVERLAY(pipe));
+       i915_gem_track_fb(overlay->vma ? overlay->vma->obj : NULL,
+                         vma->obj, INTEL_FRONTBUFFER_OVERLAY(pipe));
 
        overlay->old_vma = overlay->vma;
        overlay->vma = vma;
@@ -1430,6 +1431,8 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
        overlay->contrast = 75;
        overlay->saturation = 146;
 
+       init_request_active(&overlay->last_flip, NULL);
+
        regs = intel_overlay_map_regs(overlay);
        if (!regs)
                goto out_unpin_bo;
index aeb637dc1fdf490caeb87f7f1938357916082ab8..91cb4c422ad5d52a5d7475e408dff744feba42d4 100644 (file)
@@ -1095,14 +1095,6 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine)
                WA_SET_BIT_MASKED(HDC_CHICKEN0,
                                  HDC_FENCE_DEST_SLM_DISABLE);
 
-       /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
-        * involving this register should also be added to WA batch as required.
-        */
-       if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
-               /* WaDisableLSQCROPERFforOCL:kbl */
-               I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
-                          GEN8_LQSC_RO_PERF_DIS);
-
        /* WaToEnableHwFixForPushConstHWBug:kbl */
        if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
                WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
index 8f131a08d440cf02cbcd9ffe255b94e3f4eb6077..242a73e66d82862bea3ba881474efe327cd02d6e 100644 (file)
@@ -273,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_plane,
 
        I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
        I915_WRITE(PLANE_SURF(pipe, plane),
-                  intel_fb_gtt_offset(fb, rotation) + surf_addr);
+                  intel_plane_ggtt_offset(plane_state) + surf_addr);
        POSTING_READ(PLANE_SURF(pipe, plane));
 }
 
@@ -458,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplane,
        I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
        I915_WRITE(SPCNTR(pipe, plane), sprctl);
        I915_WRITE(SPSURF(pipe, plane),
-                  intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
+                  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
        POSTING_READ(SPSURF(pipe, plane));
 }
 
@@ -594,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane,
                I915_WRITE(SPRSCALE(pipe), sprscale);
        I915_WRITE(SPRCTL(pipe), sprctl);
        I915_WRITE(SPRSURF(pipe),
-                  intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
+                  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
        POSTING_READ(SPRSURF(pipe));
 }
 
@@ -721,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane,
        I915_WRITE(DVSSCALE(pipe), dvsscale);
        I915_WRITE(DVSCNTR(pipe), dvscntr);
        I915_WRITE(DVSSURF(pipe),
-                  intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
+                  intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
        POSTING_READ(DVSSURF(pipe));
 }
 
index 4942ca090b46fdfa1cf4b6193f3d66095804e02e..7890e30eb584570d5d87d857131db4065a8b3849 100644 (file)
@@ -51,6 +51,9 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
        struct drm_crtc_state *crtc_state;
        struct drm_rect clip = { 0, };
 
+       if (!state->crtc)
+               return 0;
+
        crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
        if (IS_ERR(crtc_state))
                return PTR_ERR(crtc_state);
index d836b2274531f83fcd49ea86d649ca49fb405489..f7c87017222048eff2bd17be8eb4f6c83f52b4a7 100644 (file)
  * - TV Panel encoding via ENCT
  */
 
+/* HHI Registers */
+#define HHI_VDAC_CNTL0         0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1         0x2F8 /* 0xbe offset in data sheet */
+#define HHI_HDMI_PHY_CNTL0     0x3a0 /* 0xe8 offset in data sheet */
+
 struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
        .mode_tag = MESON_VENC_MODE_CVBS_PAL,
        .hso_begin = 3,
@@ -242,6 +247,20 @@ void meson_venc_disable_vsync(struct meson_drm *priv)
 
 void meson_venc_init(struct meson_drm *priv)
 {
+       /* Disable CVBS VDAC */
+       regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
+       regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+
+       /* Power Down Dacs */
+       writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
+
+       /* Disable HDMI PHY */
+       regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
+
+       /* Disable HDMI */
+       writel_bits_relaxed(0x3, 0,
+                           priv->io_base + _REG(VPU_HDMI_SETTING));
+
        /* Disable all encoders */
        writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
        writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
index c809c085fd78abd61f15f3c9d2a19f14ff173d00..a2bcc70a03efaaac6ee32058f747e57161222b23 100644 (file)
@@ -167,7 +167,7 @@ static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
 
        /* Disable CVBS VDAC */
        regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
-       regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+       regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
 }
 
 static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
index a18126150e1136ea380dcdddc89aabe293d7fcbb..686a580c711a99bfe61b5867e5adc75891e5e0a0 100644 (file)
@@ -213,7 +213,14 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 void adreno_flush(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
-       uint32_t wptr = get_wptr(gpu->rb);
+       uint32_t wptr;
+
+       /*
+        * Mask wptr value that we calculate to fit in the HW range. This is
+        * to account for the possibility that the last command fit exactly into
+        * the ringbuffer and rb->next hasn't wrapped to zero yet
+        */
+       wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1);
 
        /* ensure writes to ringbuffer have hit system memory: */
        mb();
@@ -338,7 +345,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
 {
        struct adreno_platform_config *config = pdev->dev.platform_data;
        struct msm_gpu *gpu = &adreno_gpu->base;
-       struct msm_mmu *mmu;
        int ret;
 
        adreno_gpu->funcs = funcs;
@@ -378,8 +384,8 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
                return ret;
        }
 
-       mmu = gpu->aspace->mmu;
-       if (mmu) {
+       if (gpu->aspace && gpu->aspace->mmu) {
+               struct msm_mmu *mmu = gpu->aspace->mmu;
                ret = mmu->funcs->attach(mmu, iommu_ports,
                                ARRAY_SIZE(iommu_ports));
                if (ret)
index 5f6cd8745dbce78d7fec38bb6fc4b37e89c57457..c396d459a9d062769471fdc84d01120c8d1e8525 100644 (file)
@@ -119,13 +119,7 @@ static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *st
 
 static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
-       int i;
        struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-       struct drm_plane *plane;
-       struct drm_plane_state *plane_state;
-
-       for_each_plane_in_state(state, plane, plane_state, i)
-               mdp5_plane_complete_commit(plane, plane_state);
 
        if (mdp5_kms->smp)
                mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
index 17b0cc10117109bbc25a27de6a5e74d9b6f6c479..cdfc63d90c7b4bf4b7f1f116b410c347560663ef 100644 (file)
@@ -104,8 +104,6 @@ struct mdp5_plane_state {
 
        /* assigned by crtc blender */
        enum mdp_mixer_stage_id stage;
-
-       bool pending : 1;
 };
 #define to_mdp5_plane_state(x) \
                container_of(x, struct mdp5_plane_state, base)
@@ -232,8 +230,6 @@ int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms);
 void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
 
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
-void mdp5_plane_complete_commit(struct drm_plane *plane,
-       struct drm_plane_state *state);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
 struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary);
 
index c099da7bc212d52f9bdf2d42f50da98e359cf53f..25d9d0a97156765918643b7cdd440b6108d3c5ed 100644 (file)
@@ -179,7 +179,6 @@ mdp5_plane_atomic_print_state(struct drm_printer *p,
        drm_printf(p, "\tzpos=%u\n", pstate->zpos);
        drm_printf(p, "\talpha=%u\n", pstate->alpha);
        drm_printf(p, "\tstage=%s\n", stage2name(pstate->stage));
-       drm_printf(p, "\tpending=%u\n", pstate->pending);
 }
 
 static void mdp5_plane_reset(struct drm_plane *plane)
@@ -220,8 +219,6 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)
        if (mdp5_state && mdp5_state->base.fb)
                drm_framebuffer_reference(mdp5_state->base.fb);
 
-       mdp5_state->pending = false;
-
        return &mdp5_state->base;
 }
 
@@ -288,13 +285,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
        DBG("%s: check (%d -> %d)", plane->name,
                        plane_enabled(old_state), plane_enabled(state));
 
-       /* We don't allow faster-than-vblank updates.. if we did add this
-        * some day, we would need to disallow in cases where hwpipe
-        * changes
-        */
-       if (WARN_ON(to_mdp5_plane_state(old_state)->pending))
-               return -EBUSY;
-
        max_width = config->hw->lm.max_width << 16;
        max_height = config->hw->lm.max_height << 16;
 
@@ -370,12 +360,9 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
                                     struct drm_plane_state *old_state)
 {
        struct drm_plane_state *state = plane->state;
-       struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
 
        DBG("%s: update", plane->name);
 
-       mdp5_state->pending = true;
-
        if (plane_enabled(state)) {
                int ret;
 
@@ -851,15 +838,6 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
        return pstate->hwpipe->flush_mask;
 }
 
-/* called after vsync in thread context */
-void mdp5_plane_complete_commit(struct drm_plane *plane,
-       struct drm_plane_state *state)
-{
-       struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
-
-       pstate->pending = false;
-}
-
 /* initialize plane */
 struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 {
index d8bc59c7e26142b377623a6736c575b30f6eeea2..8098677a39167f51f5582893adf3694023c85768 100644 (file)
@@ -294,6 +294,8 @@ put_iova(struct drm_gem_object *obj)
        WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
        for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
+               if (!priv->aspace[id])
+                       continue;
                msm_gem_unmap_vma(priv->aspace[id],
                                &msm_obj->domain[id], msm_obj->sgt);
        }
index 166e84e4f0d48f80eacb992c3ccc8964af89b28d..489676568a10d15ac959093e6a09ee3f133abe45 100644 (file)
@@ -106,7 +106,8 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
                        pagefault_disable();
                }
 
-               if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) {
+               if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) ||
+                       !(submit_bo.flags & MSM_SUBMIT_BO_FLAGS)) {
                        DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
                        ret = -EINVAL;
                        goto out_unlock;
@@ -290,7 +291,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
 {
        uint32_t i, last_offset = 0;
        uint32_t *ptr;
-       int ret;
+       int ret = 0;
 
        if (offset % 4) {
                DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
@@ -318,12 +319,13 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
 
                ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc));
                if (ret)
-                       return -EFAULT;
+                       goto out;
 
                if (submit_reloc.submit_offset % 4) {
                        DRM_ERROR("non-aligned reloc offset: %u\n",
                                        submit_reloc.submit_offset);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
 
                /* offset in dwords: */
@@ -332,12 +334,13 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
                if ((off >= (obj->base.size / 4)) ||
                                (off < last_offset)) {
                        DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
 
                ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid);
                if (ret)
-                       return ret;
+                       goto out;
 
                if (valid)
                        continue;
@@ -354,9 +357,10 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
                last_offset = off;
        }
 
+out:
        msm_gem_put_vaddr_locked(&obj->base);
 
-       return 0;
+       return ret;
 }
 
 static void submit_cleanup(struct msm_gem_submit *submit)
index f326cf6a32e64473461e0b7859101f1a404c0318..67b34e069abf383d4c533ab7d348fd5d576ad525 100644 (file)
@@ -23,7 +23,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size)
        struct msm_ringbuffer *ring;
        int ret;
 
-       size = ALIGN(size, 4);   /* size should be dword aligned */
+       if (WARN_ON(!is_power_of_2(size)))
+               return ERR_PTR(-EINVAL);
 
        ring = kzalloc(sizeof(*ring), GFP_KERNEL);
        if (!ring) {
index 74856a8b8f35943b08a59f8aed5a546e98058d3c..e64f52464ecf55b83a17f25b434cb9e1474c10e1 100644 (file)
@@ -222,6 +222,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
                uint32_t mpllP;
 
                pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
+               mpllP = (mpllP >> 8) & 0xf;
                if (!mpllP)
                        mpllP = 4;
 
@@ -232,7 +233,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
                uint32_t clock;
 
                pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
-               return clock;
+               return clock / 1000;
        }
 
        ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);
index cef08da1da4e0bcb6a22fa73033562cdeea55006..6a157763dfc38f672f2b9384792679faf83b95d4 100644 (file)
@@ -411,7 +411,8 @@ nouveau_display_init(struct drm_device *dev)
                return ret;
 
        /* enable polling for external displays */
-       drm_kms_helper_poll_enable(dev);
+       if (!dev->mode_config.poll_enabled)
+               drm_kms_helper_poll_enable(dev);
 
        /* enable hotplug interrupts */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
index 59348fc41c77b0edf725e01655fe3ef1722a4342..bc85a45f91cde756d9763e34108ab53c711b9bd4 100644 (file)
@@ -773,7 +773,10 @@ nouveau_pmops_runtime_resume(struct device *dev)
        pci_set_master(pdev);
 
        ret = nouveau_do_resume(drm_dev, true);
-       drm_kms_helper_poll_enable(drm_dev);
+
+       if (!drm_dev->mode_config.poll_enabled)
+               drm_kms_helper_poll_enable(drm_dev);
+
        /* do magic */
        nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
        vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
index 8d5ed5bfdacb1d6c59e9db9df47a74be41462a9a..42c1fa53d4314f195b637c3de4323c86b095ae0f 100644 (file)
@@ -165,6 +165,8 @@ struct nouveau_drm {
        struct backlight_device *backlight;
        struct list_head bl_connectors;
        struct work_struct hpd_work;
+       struct work_struct fbcon_work;
+       int fbcon_new_state;
 #ifdef CONFIG_ACPI
        struct notifier_block acpi_nb;
 #endif
index 2f2a3dcd4ad777addbdcbfbb8cdc14922c7082eb..fa2d0a978cccbaac7a5640b5b6911779b6e8328f 100644 (file)
@@ -470,19 +470,43 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
        .fb_probe = nouveau_fbcon_create,
 };
 
+static void
+nouveau_fbcon_set_suspend_work(struct work_struct *work)
+{
+       struct nouveau_drm *drm = container_of(work, typeof(*drm), fbcon_work);
+       int state = READ_ONCE(drm->fbcon_new_state);
+
+       if (state == FBINFO_STATE_RUNNING)
+               pm_runtime_get_sync(drm->dev->dev);
+
+       console_lock();
+       if (state == FBINFO_STATE_RUNNING)
+               nouveau_fbcon_accel_restore(drm->dev);
+       drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
+       if (state != FBINFO_STATE_RUNNING)
+               nouveau_fbcon_accel_save_disable(drm->dev);
+       console_unlock();
+
+       if (state == FBINFO_STATE_RUNNING) {
+               pm_runtime_mark_last_busy(drm->dev->dev);
+               pm_runtime_put_sync(drm->dev->dev);
+       }
+}
+
 void
 nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
-       if (drm->fbcon) {
-               console_lock();
-               if (state == FBINFO_STATE_RUNNING)
-                       nouveau_fbcon_accel_restore(dev);
-               drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
-               if (state != FBINFO_STATE_RUNNING)
-                       nouveau_fbcon_accel_save_disable(dev);
-               console_unlock();
-       }
+
+       if (!drm->fbcon)
+               return;
+
+       drm->fbcon_new_state = state;
+       /* Since runtime resume can happen as a result of a sysfs operation,
+        * it's possible we already have the console locked. So handle fbcon
+        * init/deinit from a seperate work thread
+        */
+       schedule_work(&drm->fbcon_work);
 }
 
 int
@@ -502,6 +526,7 @@ nouveau_fbcon_init(struct drm_device *dev)
                return -ENOMEM;
 
        drm->fbcon = fbcon;
+       INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work);
 
        drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
 
index ccdce1b4eec4b8bf183235ebae2eb5395a306430..d5e58a38f160182354b8c9a126bdcbb5d459f40a 100644 (file)
@@ -99,6 +99,7 @@ struct nv84_fence_priv {
        struct nouveau_bo *bo;
        struct nouveau_bo *bo_gart;
        u32 *suspend;
+       struct mutex mutex;
 };
 
 int  nv84_fence_context_new(struct nouveau_channel *);
index 187ecdb8200273baa77c41a42fbc65c3bcb93db6..21a5775028cc612e9a6c81e280777329f18233fd 100644 (file)
@@ -42,7 +42,7 @@ nouveau_led(struct drm_device *dev)
 }
 
 /* nouveau_led.c */
-#if IS_ENABLED(CONFIG_LEDS_CLASS)
+#if IS_REACHABLE(CONFIG_LEDS_CLASS)
 int  nouveau_led_init(struct drm_device *dev);
 void nouveau_led_suspend(struct drm_device *dev);
 void nouveau_led_resume(struct drm_device *dev);
index 08f9c6fa0f7f210d3e3fd5a0fbe8f11ff40b1972..1fba3862274474f0001deaec9fefaf6b0fd324b4 100644 (file)
@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
        if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
                /* block access to objects not created via this interface */
                owner = argv->v0.owner;
-               if (argv->v0.object == 0ULL)
+               if (argv->v0.object == 0ULL &&
+                   argv->v0.type != NVIF_IOCTL_V0_DEL)
                        argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
                else
                        argv->v0.owner = NVDRM_OBJECT_USIF;
index 2c2c645076614b4f9c187d24a5e9d2667ea27778..32097fd615fd1e3a5954019c02dec36bd2e8db8c 100644 (file)
@@ -4052,6 +4052,11 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
                }
        }
 
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               if (crtc->state->event)
+                       drm_crtc_vblank_get(crtc);
+       }
+
        /* Update plane(s). */
        for_each_plane_in_state(state, plane, plane_state, i) {
                struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
@@ -4101,6 +4106,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
                        drm_crtc_send_vblank_event(crtc, crtc->state->event);
                        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                        crtc->state->event = NULL;
+                       drm_crtc_vblank_put(crtc);
                }
        }
 
index 52b87ae83e7b4d0df54e003d58783eddd8deb6f5..f0b322bec7df22de23bbae372333fb484ac6d9ed 100644 (file)
@@ -107,8 +107,10 @@ nv84_fence_context_del(struct nouveau_channel *chan)
        struct nv84_fence_chan *fctx = chan->fence;
 
        nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
+       mutex_lock(&priv->mutex);
        nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
        nouveau_bo_vma_del(priv->bo, &fctx->vma);
+       mutex_unlock(&priv->mutex);
        nouveau_fence_context_del(&fctx->base);
        chan->fence = NULL;
        nouveau_fence_context_free(&fctx->base);
@@ -134,11 +136,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
        fctx->base.sync32 = nv84_fence_sync32;
        fctx->base.sequence = nv84_fence_read(chan);
 
+       mutex_lock(&priv->mutex);
        ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
        if (ret == 0) {
                ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
                                        &fctx->vma_gart);
        }
+       mutex_unlock(&priv->mutex);
 
        if (ret)
                nv84_fence_context_del(chan);
@@ -212,6 +216,8 @@ nv84_fence_create(struct nouveau_drm *drm)
        priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
        priv->base.uevent = true;
 
+       mutex_init(&priv->mutex);
+
        /* Use VRAM if there is any ; otherwise fallback to system memory */
        domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
                         /*
index 6f0436df021953337ba29f0ff9c02c507214b07b..f8f2f16c22a2a2502bf283c63a5d1fc124d0ff89 100644 (file)
@@ -59,7 +59,7 @@ gt215_hda_eld(NV50_DISP_MTHD_V1)
                        );
                }
                for (i = 0; i < size; i++)
-                       nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
+                       nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[i]);
                for (; i < 0x60; i++)
                        nvkm_wr32(device, 0x61c440 + soff, (i << 8));
                nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003);
index 567466f93cd5d9645020e3b89c282808d88397e4..0db8efbf1c2e2e9cd84b689098bdba9d666843bc 100644 (file)
@@ -433,8 +433,6 @@ nv50_disp_dptmds_war(struct nvkm_device *device)
        case 0x94:
        case 0x96:
        case 0x98:
-       case 0xaa:
-       case 0xac:
                return true;
        default:
                break;
index fb16070b266e3f2de51243ba478f57d8fd956420..4a4f9533c53b888ab10fb0f4839fc4a5df852bd8 100644 (file)
@@ -205,8 +205,8 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
        }
 
        if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
-           x >= (crtc->x + crtc->mode.crtc_hdisplay) ||
-           y >= (crtc->y + crtc->mode.crtc_vdisplay))
+           x >= (crtc->x + crtc->mode.hdisplay) ||
+           y >= (crtc->y + crtc->mode.vdisplay))
                goto out_of_bounds;
 
        x += xorigin;
index 00ea0002b539b9e9b5b0a063f62deb3b7638fd56..30bd4a6a9d466e11755bf95cee6929473ae65adf 100644 (file)
  *   2.46.0 - Add PFP_SYNC_ME support on evergreen
  *   2.47.0 - Add UVD_NO_OP register support
  *   2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
+ *   2.49.0 - DRM_RADEON_GEM_INFO ioctl returns correct vram_size/visible values
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       48
+#define KMS_DRIVER_MINOR       49
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -366,11 +367,10 @@ static void
 radeon_pci_shutdown(struct pci_dev *pdev)
 {
        /* if we are running in a VM, make sure the device
-        * torn down properly on reboot/shutdown.
-        * unfortunately we can't detect certain
-        * hypervisors so just do this all the time.
+        * torn down properly on reboot/shutdown
         */
-       radeon_pci_remove(pdev);
+       if (radeon_device_is_virtual())
+               radeon_pci_remove(pdev);
 }
 
 static int radeon_pmops_suspend(struct device *dev)
index 0bcffd8a7bd3ceac0de37cd0b44344011963be77..96683f5b2b1b722db08de97550aa8cdf99444a1c 100644 (file)
@@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
 
        man = &rdev->mman.bdev.man[TTM_PL_VRAM];
 
-       args->vram_size = rdev->mc.real_vram_size;
-       args->vram_visible = (u64)man->size << PAGE_SHIFT;
+       args->vram_size = (u64)man->size << PAGE_SHIFT;
+       args->vram_visible = rdev->mc.visible_vram_size;
        args->vram_visible -= rdev->vram_pin_size;
        args->gart_size = rdev->mc.gtt_size;
        args->gart_size -= rdev->gart_pin_size;
index ad4d7b8b832271a8e28a1b59dc496fa19049ed34..414776811e71e0a4e9f7c97309b6c173c8f502a3 100644 (file)
@@ -50,7 +50,6 @@ MODULE_FIRMWARE("radeon/tahiti_ce.bin");
 MODULE_FIRMWARE("radeon/tahiti_mc.bin");
 MODULE_FIRMWARE("radeon/tahiti_rlc.bin");
 MODULE_FIRMWARE("radeon/tahiti_smc.bin");
-MODULE_FIRMWARE("radeon/tahiti_k_smc.bin");
 
 MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
@@ -115,6 +114,9 @@ MODULE_FIRMWARE("radeon/hainan_mc.bin");
 MODULE_FIRMWARE("radeon/hainan_rlc.bin");
 MODULE_FIRMWARE("radeon/hainan_smc.bin");
 MODULE_FIRMWARE("radeon/hainan_k_smc.bin");
+MODULE_FIRMWARE("radeon/banks_k_2_smc.bin");
+
+MODULE_FIRMWARE("radeon/si58_mc.bin");
 
 static u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
 static void si_pcie_gen3_enable(struct radeon_device *rdev);
@@ -1651,15 +1653,14 @@ static int si_init_microcode(struct radeon_device *rdev)
        int err;
        int new_fw = 0;
        bool new_smc = false;
+       bool si58_fw = false;
+       bool banks2_fw = false;
 
        DRM_DEBUG("\n");
 
        switch (rdev->family) {
        case CHIP_TAHITI:
                chip_name = "TAHITI";
-               /* XXX: figure out which Tahitis need the new ucode */
-               if (0)
-                       new_smc = true;
                new_chip_name = "tahiti";
                pfp_req_size = SI_PFP_UCODE_SIZE * 4;
                me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1671,12 +1672,9 @@ static int si_init_microcode(struct radeon_device *rdev)
                break;
        case CHIP_PITCAIRN:
                chip_name = "PITCAIRN";
-               if ((rdev->pdev->revision == 0x81) ||
-                   (rdev->pdev->device == 0x6810) ||
-                   (rdev->pdev->device == 0x6811) ||
-                   (rdev->pdev->device == 0x6816) ||
-                   (rdev->pdev->device == 0x6817) ||
-                   (rdev->pdev->device == 0x6806))
+               if ((rdev->pdev->revision == 0x81) &&
+                   ((rdev->pdev->device == 0x6810) ||
+                    (rdev->pdev->device == 0x6811)))
                        new_smc = true;
                new_chip_name = "pitcairn";
                pfp_req_size = SI_PFP_UCODE_SIZE * 4;
@@ -1689,15 +1687,15 @@ static int si_init_microcode(struct radeon_device *rdev)
                break;
        case CHIP_VERDE:
                chip_name = "VERDE";
-               if ((rdev->pdev->revision == 0x81) ||
-                   (rdev->pdev->revision == 0x83) ||
-                   (rdev->pdev->revision == 0x87) ||
-                   (rdev->pdev->device == 0x6820) ||
-                   (rdev->pdev->device == 0x6821) ||
-                   (rdev->pdev->device == 0x6822) ||
-                   (rdev->pdev->device == 0x6823) ||
-                   (rdev->pdev->device == 0x682A) ||
-                   (rdev->pdev->device == 0x682B))
+               if (((rdev->pdev->device == 0x6820) &&
+                    ((rdev->pdev->revision == 0x81) ||
+                     (rdev->pdev->revision == 0x83))) ||
+                   ((rdev->pdev->device == 0x6821) &&
+                    ((rdev->pdev->revision == 0x83) ||
+                     (rdev->pdev->revision == 0x87))) ||
+                   ((rdev->pdev->revision == 0x87) &&
+                    ((rdev->pdev->device == 0x6823) ||
+                     (rdev->pdev->device == 0x682b))))
                        new_smc = true;
                new_chip_name = "verde";
                pfp_req_size = SI_PFP_UCODE_SIZE * 4;
@@ -1710,13 +1708,13 @@ static int si_init_microcode(struct radeon_device *rdev)
                break;
        case CHIP_OLAND:
                chip_name = "OLAND";
-               if ((rdev->pdev->revision == 0xC7) ||
-                   (rdev->pdev->revision == 0x80) ||
-                   (rdev->pdev->revision == 0x81) ||
-                   (rdev->pdev->revision == 0x83) ||
-                   (rdev->pdev->revision == 0x87) ||
-                   (rdev->pdev->device == 0x6604) ||
-                   (rdev->pdev->device == 0x6605))
+               if (((rdev->pdev->revision == 0x81) &&
+                    ((rdev->pdev->device == 0x6600) ||
+                     (rdev->pdev->device == 0x6604) ||
+                     (rdev->pdev->device == 0x6605) ||
+                     (rdev->pdev->device == 0x6610))) ||
+                   ((rdev->pdev->revision == 0x83) &&
+                    (rdev->pdev->device == 0x6610)))
                        new_smc = true;
                new_chip_name = "oland";
                pfp_req_size = SI_PFP_UCODE_SIZE * 4;
@@ -1728,13 +1726,17 @@ static int si_init_microcode(struct radeon_device *rdev)
                break;
        case CHIP_HAINAN:
                chip_name = "HAINAN";
-               if ((rdev->pdev->revision == 0x81) ||
-                   (rdev->pdev->revision == 0x83) ||
-                   (rdev->pdev->revision == 0xC3) ||
-                   (rdev->pdev->device == 0x6664) ||
-                   (rdev->pdev->device == 0x6665) ||
-                   (rdev->pdev->device == 0x6667))
+               if (((rdev->pdev->revision == 0x81) &&
+                    (rdev->pdev->device == 0x6660)) ||
+                   ((rdev->pdev->revision == 0x83) &&
+                    ((rdev->pdev->device == 0x6660) ||
+                     (rdev->pdev->device == 0x6663) ||
+                     (rdev->pdev->device == 0x6665) ||
+                     (rdev->pdev->device == 0x6667))))
                        new_smc = true;
+               else if ((rdev->pdev->revision == 0xc3) &&
+                        (rdev->pdev->device == 0x6665))
+                       banks2_fw = true;
                new_chip_name = "hainan";
                pfp_req_size = SI_PFP_UCODE_SIZE * 4;
                me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1746,6 +1748,10 @@ static int si_init_microcode(struct radeon_device *rdev)
        default: BUG();
        }
 
+       /* this memory configuration requires special firmware */
+       if (((RREG32(MC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
+               si58_fw = true;
+
        DRM_INFO("Loading %s Microcode\n", new_chip_name);
 
        snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
@@ -1849,7 +1855,10 @@ static int si_init_microcode(struct radeon_device *rdev)
                }
        }
 
-       snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
+       if (si58_fw)
+               snprintf(fw_name, sizeof(fw_name), "radeon/si58_mc.bin");
+       else
+               snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
        err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
        if (err) {
                snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
@@ -1880,7 +1889,9 @@ static int si_init_microcode(struct radeon_device *rdev)
                }
        }
 
-       if (new_smc)
+       if (banks2_fw)
+               snprintf(fw_name, sizeof(fw_name), "radeon/banks_k_2_smc.bin");
+       else if (new_smc)
                snprintf(fw_name, sizeof(fw_name), "radeon/%s_k_smc.bin", new_chip_name);
        else
                snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", new_chip_name);
index 8b5e697f2549ee3f81dff2cb8cc8a05e7543c856..2944916f7102ae0395d11157f366c199d398076d 100644 (file)
@@ -3008,30 +3008,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                    (rdev->pdev->device == 0x6817) ||
                    (rdev->pdev->device == 0x6806))
                        max_mclk = 120000;
-       } else if (rdev->family == CHIP_VERDE) {
-               if ((rdev->pdev->revision == 0x81) ||
-                   (rdev->pdev->revision == 0x83) ||
-                   (rdev->pdev->revision == 0x87) ||
-                   (rdev->pdev->device == 0x6820) ||
-                   (rdev->pdev->device == 0x6821) ||
-                   (rdev->pdev->device == 0x6822) ||
-                   (rdev->pdev->device == 0x6823) ||
-                   (rdev->pdev->device == 0x682A) ||
-                   (rdev->pdev->device == 0x682B)) {
-                       max_sclk = 75000;
-                       max_mclk = 80000;
-               }
-       } else if (rdev->family == CHIP_OLAND) {
-               if ((rdev->pdev->revision == 0xC7) ||
-                   (rdev->pdev->revision == 0x80) ||
-                   (rdev->pdev->revision == 0x81) ||
-                   (rdev->pdev->revision == 0x83) ||
-                   (rdev->pdev->revision == 0x87) ||
-                   (rdev->pdev->device == 0x6604) ||
-                   (rdev->pdev->device == 0x6605)) {
-                       max_sclk = 75000;
-                       max_mclk = 80000;
-               }
        } else if (rdev->family == CHIP_HAINAN) {
                if ((rdev->pdev->revision == 0x81) ||
                    (rdev->pdev->revision == 0x83) ||
@@ -3040,7 +3016,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                    (rdev->pdev->device == 0x6665) ||
                    (rdev->pdev->device == 0x6667)) {
                        max_sclk = 75000;
-                       max_mclk = 80000;
                }
        }
        /* Apply dpm quirks */
index 725dffad5640cddf43d6aea4616cd90a035c40bc..6dfdb145f3bbb694c2750e30807640999404e91e 100644 (file)
@@ -856,7 +856,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
        struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct tilcdc_drm_private *priv = dev->dev_private;
-       uint32_t stat;
+       uint32_t stat, reg;
 
        stat = tilcdc_read_irqstatus(dev);
        tilcdc_clear_irqstatus(dev, stat);
@@ -921,17 +921,26 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
                dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
                                    __func__, stat);
                tilcdc_crtc->frame_intact = false;
-               if (tilcdc_crtc->sync_lost_count++ >
-                   SYNC_LOST_COUNT_LIMIT) {
-                       dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, recovering", __func__, stat);
-                       queue_work(system_wq, &tilcdc_crtc->recover_work);
-                       if (priv->rev == 1)
+               if (priv->rev == 1) {
+                       reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG);
+                       if (reg & LCDC_RASTER_ENABLE) {
                                tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
-                                            LCDC_V1_SYNC_LOST_INT_ENA);
-                       else
+                                            LCDC_RASTER_ENABLE);
+                               tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
+                                          LCDC_RASTER_ENABLE);
+                       }
+               } else {
+                       if (tilcdc_crtc->sync_lost_count++ >
+                           SYNC_LOST_COUNT_LIMIT) {
+                               dev_err(dev->dev,
+                                       "%s(0x%08x): Sync lost flood detected, recovering",
+                                       __func__, stat);
+                               queue_work(system_wq,
+                                          &tilcdc_crtc->recover_work);
                                tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
                                             LCDC_SYNC_LOST);
-                       tilcdc_crtc->sync_lost_count = 0;
+                               tilcdc_crtc->sync_lost_count = 0;
+                       }
                }
        }
 
index a0fd3e66bc4b39c1f5092c340ad2c705bbf431f3..7aadce1f7e7a0e56b302bded53ad8c0d5977cc22 100644 (file)
@@ -839,7 +839,7 @@ static void vc4_crtc_destroy_state(struct drm_crtc *crtc,
 
        }
 
-       __drm_atomic_helper_crtc_destroy_state(state);
+       drm_atomic_helper_crtc_destroy_state(crtc, state);
 }
 
 static const struct drm_crtc_funcs vc4_crtc_funcs = {
index db920771bfb5641c9d5d8e53a8f73cf7ee501bb7..ab3016982466c3ca35ba479050ee107d26eb50ac 100644 (file)
@@ -594,12 +594,14 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
                                          args->shader_rec_count);
        struct vc4_bo *bo;
 
-       if (uniforms_offset < shader_rec_offset ||
+       if (shader_rec_offset < args->bin_cl_size ||
+           uniforms_offset < shader_rec_offset ||
            exec_size < uniforms_offset ||
            args->shader_rec_count >= (UINT_MAX /
                                          sizeof(struct vc4_shader_state)) ||
            temp_size < exec_size) {
                DRM_ERROR("overflow in exec arguments\n");
+               ret = -EINVAL;
                goto fail;
        }
 
index 881bf489478b01b34e9e4df6013fe608c42215ee..686cdd3c86f2e9178768282a0dd173850e0bf063 100644 (file)
@@ -858,7 +858,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
                }
        }
        plane = &vc4_plane->base;
-       ret = drm_universal_plane_init(dev, plane, 0xff,
+       ret = drm_universal_plane_init(dev, plane, 0,
                                       &vc4_plane_funcs,
                                       formats, num_formats,
                                       type, NULL);
index 08886a3097577242f5c9e025fd6446d81bcc6dec..5cdd003605f57c99faf31832e3f3dd38a75b7402 100644 (file)
@@ -461,7 +461,7 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
                }
 
                ret = vc4_full_res_bounds_check(exec, *obj, surf);
-               if (!ret)
+               if (ret)
                        return ret;
 
                return 0;
index dd21f950e129d4f96d71120d64e3ab499645333d..cde9f37581064828809555bb4808c38f7497d94e 100644 (file)
@@ -331,7 +331,7 @@ static int virtio_gpufb_create(struct drm_fb_helper *helper,
        info->fbops = &virtio_gpufb_ops;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
-       info->screen_base = obj->vmap;
+       info->screen_buffer = obj->vmap;
        info->screen_size = obj->gem_base.size;
        drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
        drm_fb_helper_fill_var(info, &vfbdev->helper,
index 723fd763da8e3c49de716207cc68eb46080552c1..7a96798b9c0ac611f588c5b8d80269ed23dc157e 100644 (file)
@@ -481,8 +481,7 @@ static int vmw_fb_kms_framebuffer(struct fb_info *info)
        mode_cmd.height = var->yres;
        mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width;
        mode_cmd.pixel_format =
-               drm_mode_legacy_fb_format(var->bits_per_pixel,
-                       ((var->bits_per_pixel + 7) / 8) * mode_cmd.width);
+               drm_mode_legacy_fb_format(var->bits_per_pixel, depth);
 
        cur_fb = par->set_fb;
        if (cur_fb && cur_fb->width == mode_cmd.width &&
index cff060b56da9d6cb8cb138657cf4efca7debef61..ea36b557d5eea87b27171937fe9bc05f680b15a8 100644 (file)
@@ -2496,6 +2496,7 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
 #if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
index 717704e9ae07bd97d64f38321d2d49f07de62b83..c0303f61c26a94f1998f6883d42a0fc8cb41f432 100644 (file)
@@ -148,26 +148,36 @@ static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev)
        struct usb_interface *usbif = to_usb_interface(dev->parent);
        struct usb_device *usbdev = interface_to_usbdev(usbif);
        int brightness;
-       char data[8];
+       char *data;
+
+       data = kmalloc(8, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 
        ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
                              K90_REQUEST_STATUS,
                              USB_DIR_IN | USB_TYPE_VENDOR |
                              USB_RECIP_DEVICE, 0, 0, data, 8,
                              USB_CTRL_SET_TIMEOUT);
-       if (ret < 0) {
+       if (ret < 5) {
                dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
                         ret);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
        brightness = data[4];
        if (brightness < 0 || brightness > 3) {
                dev_warn(dev,
                         "Read invalid backlight brightness: %02hhx.\n",
                         data[4]);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
-       return brightness;
+       ret = brightness;
+out:
+       kfree(data);
+
+       return ret;
 }
 
 static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
@@ -253,17 +263,22 @@ static ssize_t k90_show_macro_mode(struct device *dev,
        struct usb_interface *usbif = to_usb_interface(dev->parent);
        struct usb_device *usbdev = interface_to_usbdev(usbif);
        const char *macro_mode;
-       char data[8];
+       char *data;
+
+       data = kmalloc(2, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 
        ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
                              K90_REQUEST_GET_MODE,
                              USB_DIR_IN | USB_TYPE_VENDOR |
                              USB_RECIP_DEVICE, 0, 0, data, 2,
                              USB_CTRL_SET_TIMEOUT);
-       if (ret < 0) {
+       if (ret < 1) {
                dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
                         ret);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
 
        switch (data[0]) {
@@ -277,10 +292,15 @@ static ssize_t k90_show_macro_mode(struct device *dev,
        default:
                dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
                         data[0]);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
 
-       return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+       ret = snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+out:
+       kfree(data);
+
+       return ret;
 }
 
 static ssize_t k90_store_macro_mode(struct device *dev,
@@ -320,26 +340,36 @@ static ssize_t k90_show_current_profile(struct device *dev,
        struct usb_interface *usbif = to_usb_interface(dev->parent);
        struct usb_device *usbdev = interface_to_usbdev(usbif);
        int current_profile;
-       char data[8];
+       char *data;
+
+       data = kmalloc(8, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
 
        ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
                              K90_REQUEST_STATUS,
                              USB_DIR_IN | USB_TYPE_VENDOR |
                              USB_RECIP_DEVICE, 0, 0, data, 8,
                              USB_CTRL_SET_TIMEOUT);
-       if (ret < 0) {
+       if (ret < 8) {
                dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
                         ret);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
        current_profile = data[7];
        if (current_profile < 1 || current_profile > 3) {
                dev_warn(dev, "Read invalid current profile: %02hhx.\n",
                         data[7]);
-               return -EIO;
+               ret = -EIO;
+               goto out;
        }
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+       ret = snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+out:
+       kfree(data);
+
+       return ret;
 }
 
 static ssize_t k90_store_current_profile(struct device *dev,
index f31a778b085148fea4a52599c6b89be203889781..b22d0f83f8e38a9ee0d0eb7381e95d6b90442b61 100644 (file)
@@ -168,7 +168,7 @@ struct cp2112_device {
        atomic_t xfer_avail;
        struct gpio_chip gc;
        u8 *in_out_buffer;
-       spinlock_t lock;
+       struct mutex lock;
 
        struct gpio_desc *desc[8];
        bool gpio_poll;
@@ -186,10 +186,9 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
        struct cp2112_device *dev = gpiochip_get_data(chip);
        struct hid_device *hdev = dev->hdev;
        u8 *buf = dev->in_out_buffer;
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&dev->lock, flags);
+       mutex_lock(&dev->lock);
 
        ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
                                 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -213,8 +212,8 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
        ret = 0;
 
 exit:
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return ret <= 0 ? ret : -EIO;
+       mutex_unlock(&dev->lock);
+       return ret < 0 ? ret : -EIO;
 }
 
 static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -222,10 +221,9 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        struct cp2112_device *dev = gpiochip_get_data(chip);
        struct hid_device *hdev = dev->hdev;
        u8 *buf = dev->in_out_buffer;
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&dev->lock, flags);
+       mutex_lock(&dev->lock);
 
        buf[0] = CP2112_GPIO_SET;
        buf[1] = value ? 0xff : 0;
@@ -237,7 +235,7 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        if (ret < 0)
                hid_err(hdev, "error setting GPIO values: %d\n", ret);
 
-       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock);
 }
 
 static int cp2112_gpio_get_all(struct gpio_chip *chip)
@@ -245,10 +243,9 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip)
        struct cp2112_device *dev = gpiochip_get_data(chip);
        struct hid_device *hdev = dev->hdev;
        u8 *buf = dev->in_out_buffer;
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&dev->lock, flags);
+       mutex_lock(&dev->lock);
 
        ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
                                 CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
@@ -262,7 +259,7 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip)
        ret = buf[1];
 
 exit:
-       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock);
 
        return ret;
 }
@@ -284,10 +281,9 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
        struct cp2112_device *dev = gpiochip_get_data(chip);
        struct hid_device *hdev = dev->hdev;
        u8 *buf = dev->in_out_buffer;
-       unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&dev->lock, flags);
+       mutex_lock(&dev->lock);
 
        ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
                                 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -308,7 +304,7 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
                goto fail;
        }
 
-       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock);
 
        /*
         * Set gpio value when output direction is already set,
@@ -319,7 +315,7 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
        return 0;
 
 fail:
-       spin_unlock_irqrestore(&dev->lock, flags);
+       mutex_unlock(&dev->lock);
        return ret < 0 ? ret : -EIO;
 }
 
@@ -1235,7 +1231,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (!dev->in_out_buffer)
                return -ENOMEM;
 
-       spin_lock_init(&dev->lock);
+       mutex_init(&dev->lock);
 
        ret = hid_parse(hdev);
        if (ret) {
index 1b764d1745f3daa693a17ee706c302ff31ae0f0e..1689568b597d4e5bb8824ccbe679f627525bf2a4 100644 (file)
@@ -39,6 +39,9 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
                return rdesc;
 
+       if (*rsize < 4)
+               return rdesc;
+
        for (i = 0; i < *rsize - 4; i++)
                if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
                        rdesc[i] = 0x19;
index 54bd22dc14110c308744f28f01a7ab4cff79ff95..350accfee8e85b2e545c0171f6582f4e62655b50 100644 (file)
@@ -76,6 +76,9 @@
 #define USB_VENDOR_ID_ALPS_JP          0x044E
 #define HID_DEVICE_ID_ALPS_U1_DUAL     0x120B
 
+#define USB_VENDOR_ID_AMI              0x046b
+#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE      0xff10
+
 #define USB_VENDOR_ID_ANTON            0x1130
 #define USB_DEVICE_ID_ANTON_TOUCH_PAD  0x3101
 
 #define USB_VENDOR_ID_PETALYNX         0x18b1
 #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE   0x0037
 
+#define USB_VENDOR_ID_PETZL            0x2122
+#define USB_DEVICE_ID_PETZL_HEADLAMP   0x1234
+
 #define USB_VENDOR_ID_PHILIPS          0x0471
 #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
 
index c5c5fbe9d60577f44085d86a7fb5cf60efb6acd3..52026dc94d5c4b0306ce585be293cbe2cb1910d9 100644 (file)
@@ -872,7 +872,7 @@ static const struct hid_device_id lg_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
                .driver_data = LG_NOGET | LG_FF4 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
-               .driver_data = LG_FF2 },
+               .driver_data = LG_NOGET | LG_FF2 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
                .driver_data = LG_FF3 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
index 78fb32a7b103446136000c8ee9ac64cf7fba7054..ea3c3546cef7f81f0f1c82b996c3ed5ab9fb26ed 100644 (file)
@@ -426,6 +426,15 @@ static int i2c_hid_hwreset(struct i2c_client *client)
        if (ret)
                goto out_unlock;
 
+       /*
+        * The HID over I2C specification states that if a DEVICE needs time
+        * after the PWR_ON request, it should utilise CLOCK stretching.
+        * However, it has been observered that the Windows driver provides a
+        * 1ms sleep between the PWR_ON and RESET requests and that some devices
+        * rely on this.
+        */
+       usleep_range(1000, 5000);
+
        i2c_hid_dbg(ihid, "resetting...\n");
 
        ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
index e9d6cc7cdfc5c8019422d45914dc0363448bcb12..30a2977e26454f10fd72b855ec0b634aa868dcae 100644 (file)
@@ -57,6 +57,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
index b9779bcbd1403f00114f9565c543df79583baa38..8aeca038cc7331244eeeb5dc0468b22ef66e7d44 100644 (file)
@@ -740,6 +740,11 @@ static int wacom_add_shared_data(struct hid_device *hdev)
                return retval;
        }
 
+       if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
+               wacom_wac->shared->touch = hdev;
+       else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
+               wacom_wac->shared->pen = hdev;
+
 out:
        mutex_unlock(&wacom_udev_list_lock);
        return retval;
@@ -2036,10 +2041,6 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
        if (error)
                goto fail;
 
-       error = wacom_add_shared_data(hdev);
-       if (error)
-               goto fail;
-
        /*
         * Bamboo Pad has a generic hid handling for the Pen, and we switch it
         * into debug mode for the touch part.
@@ -2080,10 +2081,9 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
 
        wacom_update_name(wacom, wireless ? " (WL)" : "");
 
-       if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
-               wacom_wac->shared->touch = hdev;
-       else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
-               wacom_wac->shared->pen = hdev;
+       error = wacom_add_shared_data(hdev);
+       if (error)
+               goto fail;
 
        if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) &&
             (features->quirks & WACOM_QUIRK_BATTERY)) {
index b1a9a3ca6d564c72d3f445e663b196af87743ed1..672145b0d8f584d8fce50a74e799b36319448cb4 100644 (file)
@@ -166,19 +166,21 @@ static int wacom_pl_irq(struct wacom_wac *wacom)
                wacom->id[0] = STYLUS_DEVICE_ID;
        }
 
-       pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-       if (features->pressure_max > 255)
-               pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-       pressure += (features->pressure_max + 1) / 2;
+       if (prox) {
+               pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+               if (features->pressure_max > 255)
+                       pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+               pressure += (features->pressure_max + 1) / 2;
 
-       input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-       input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-       input_report_abs(input, ABS_PRESSURE, pressure);
+               input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+               input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+               input_report_abs(input, ABS_PRESSURE, pressure);
 
-       input_report_key(input, BTN_TOUCH, data[4] & 0x08);
-       input_report_key(input, BTN_STYLUS, data[4] & 0x10);
-       /* Only allow the stylus2 button to be reported for the pen tool. */
-       input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+               input_report_key(input, BTN_TOUCH, data[4] & 0x08);
+               input_report_key(input, BTN_STYLUS, data[4] & 0x10);
+               /* Only allow the stylus2 button to be reported for the pen tool. */
+               input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+       }
 
        if (!prox)
                wacom->id[0] = 0;
@@ -2187,6 +2189,16 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
 
        wacom_report_events(hdev, report);
 
+       /*
+        * Non-input reports may be sent prior to the device being
+        * completely initialized. Since only their events need
+        * to be processed, exit after 'wacom_report_events' has
+        * been called to prevent potential crashes in the report-
+        * processing functions.
+        */
+       if (report->type != HID_INPUT_REPORT)
+               return;
+
        if (WACOM_PAD_FIELD(field)) {
                wacom_wac_pad_battery_report(hdev, report);
                if (wacom->wacom_wac.pad_input)
index cd49cb17eb7fb385ddbf507ef14b2ea2be090159..308dbda700ebdaeb02f222aa46dc7bb79c24c0da 100644 (file)
@@ -383,6 +383,7 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
                return ret;
        }
 
+       init_cached_read_index(channel);
        next_read_location = hv_get_next_read_location(inring_info);
        next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
                                                    sizeof(desc),
index 322ed9272811817324396960e63facf9df80d96c..841f2428e84a3936de0a60ee42700efd70933ed2 100644 (file)
@@ -1036,7 +1036,7 @@ static const u8 lm90_temp_emerg_index[3] = {
 };
 
 static const u8 lm90_min_alarm_bits[3] = { 5, 3, 11 };
-static const u8 lm90_max_alarm_bits[3] = { 0, 4, 12 };
+static const u8 lm90_max_alarm_bits[3] = { 6, 4, 12 };
 static const u8 lm90_crit_alarm_bits[3] = { 0, 1, 9 };
 static const u8 lm90_emergency_alarm_bits[3] = { 15, 13, 14 };
 static const u8 lm90_fault_bits[3] = { 0, 2, 10 };
index 686971263bef19a2fcc159432a6e6e46b1e16771..45d6771fac8ce1efcd093a710c6c3fad64ca33b8 100644 (file)
@@ -962,10 +962,6 @@ static int cdns_i2c_probe(struct platform_device *pdev)
                goto err_clk_dis;
        }
 
-       ret = i2c_add_adapter(&id->adap);
-       if (ret < 0)
-               goto err_clk_dis;
-
        /*
         * Cadence I2C controller has a bug wherein it generates
         * invalid read transaction after HW timeout in master receiver mode.
@@ -975,6 +971,10 @@ static int cdns_i2c_probe(struct platform_device *pdev)
         */
        cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
 
+       ret = i2c_add_adapter(&id->adap);
+       if (ret < 0)
+               goto err_clk_dis;
+
        dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
                 id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq);
 
index 6d81c56184d33d4757414fd748ace9013c8a3b14..e9db857c62268c61099cb34a91c8f7ccf3e5284a 100644 (file)
@@ -475,30 +475,28 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
 static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
 {
        struct i2c_msg *msgs = dev->msgs;
-       u32 ic_tar = 0;
+       u32 ic_con, ic_tar = 0;
 
        /* Disable the adapter */
        __i2c_dw_enable_and_wait(dev, false);
 
        /* if the slave address is ten bit address, enable 10BITADDR */
-       if (dev->dynamic_tar_update_enabled) {
+       ic_con = dw_readl(dev, DW_IC_CON);
+       if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
+               ic_con |= DW_IC_CON_10BITADDR_MASTER;
                /*
                 * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
-                * mode has to be enabled via bit 12 of IC_TAR register,
-                * otherwise bit 4 of IC_CON is used.
+                * mode has to be enabled via bit 12 of IC_TAR register.
+                * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be
+                * detected from registers.
                 */
-               if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
-                       ic_tar = DW_IC_TAR_10BITADDR_MASTER;
+               ic_tar = DW_IC_TAR_10BITADDR_MASTER;
        } else {
-               u32 ic_con = dw_readl(dev, DW_IC_CON);
-
-               if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
-                       ic_con |= DW_IC_CON_10BITADDR_MASTER;
-               else
-                       ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
-               dw_writel(dev, ic_con, DW_IC_CON);
+               ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
        }
 
+       dw_writel(dev, ic_con, DW_IC_CON);
+
        /*
         * Set the slave (target) address and enable 10-bit addressing mode
         * if applicable.
@@ -963,7 +961,6 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
 {
        struct i2c_adapter *adap = &dev->adapter;
        int r;
-       u32 reg;
 
        init_completion(&dev->cmd_complete);
 
@@ -971,26 +968,6 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
        if (r)
                return r;
 
-       r = i2c_dw_acquire_lock(dev);
-       if (r)
-               return r;
-
-       /*
-        * Test if dynamic TAR update is enabled in this controller by writing
-        * to IC_10BITADDR_MASTER field in IC_CON: when it is enabled this
-        * field is read-only so it should not succeed
-        */
-       reg = dw_readl(dev, DW_IC_CON);
-       dw_writel(dev, reg ^ DW_IC_CON_10BITADDR_MASTER, DW_IC_CON);
-
-       if ((dw_readl(dev, DW_IC_CON) & DW_IC_CON_10BITADDR_MASTER) ==
-           (reg & DW_IC_CON_10BITADDR_MASTER)) {
-               dev->dynamic_tar_update_enabled = true;
-               dev_dbg(dev->dev, "Dynamic TAR update enabled");
-       }
-
-       i2c_dw_release_lock(dev);
-
        snprintf(adap->name, sizeof(adap->name),
                 "Synopsys DesignWare I2C adapter");
        adap->retries = 3;
index 26250b425e2f1046fa0b0483f3e59fb03ed33f75..c1db3a5a340f599b6bee5c0165112703e2e082fc 100644 (file)
@@ -125,7 +125,6 @@ struct dw_i2c_dev {
        int                     (*acquire_lock)(struct dw_i2c_dev *dev);
        void                    (*release_lock)(struct dw_i2c_dev *dev);
        bool                    pm_runtime_disabled;
-       bool                    dynamic_tar_update_enabled;
 };
 
 #define ACCESS_SWAP            0x00000001
index c62b7cd475f87694bd9eeacba60ae2b75733ff79..3310f2e0dbd3b4e8ef2fb0386530c11deba4192f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -636,12 +637,31 @@ static int lpi2c_imx_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int lpi2c_imx_suspend(struct device *dev)
+{
+       pinctrl_pm_select_sleep_state(dev);
+
+       return 0;
+}
+
+static int lpi2c_imx_resume(struct device *dev)
+{
+       pinctrl_pm_select_default_state(dev);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx_lpi2c_pm, lpi2c_imx_suspend, lpi2c_imx_resume);
+
 static struct platform_driver lpi2c_imx_driver = {
        .probe = lpi2c_imx_probe,
        .remove = lpi2c_imx_remove,
        .driver = {
                .name = DRIVER_NAME,
                .of_match_table = lpi2c_imx_of_match,
+               .pm = &imx_lpi2c_pm,
        },
 };
 
index c2268cdf38e82348ae883c99d1f140a7fc2d0ecc..c21ca7bf2efe4f02d420ef53c679b321eceb8fe6 100644 (file)
@@ -58,7 +58,7 @@
 #define SMBSLVDAT      (0xC + piix4_smba)
 
 /* count for request_region */
-#define SMBIOSIZE      8
+#define SMBIOSIZE      9
 
 /* PCI Address Constants */
 #define SMBBA          0x090
@@ -585,12 +585,33 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
                 u8 command, int size, union i2c_smbus_data *data)
 {
        struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
+       unsigned short piix4_smba = adapdata->smba;
+       int retries = MAX_TIMEOUT;
+       int smbslvcnt;
        u8 smba_en_lo;
        u8 port;
        int retval;
 
        mutex_lock(&piix4_mutex_sb800);
 
+       /* Request the SMBUS semaphore, avoid conflicts with the IMC */
+       smbslvcnt  = inb_p(SMBSLVCNT);
+       do {
+               outb_p(smbslvcnt | 0x10, SMBSLVCNT);
+
+               /* Check the semaphore status */
+               smbslvcnt  = inb_p(SMBSLVCNT);
+               if (smbslvcnt & 0x10)
+                       break;
+
+               usleep_range(1000, 2000);
+       } while (--retries);
+       /* SMBus is still owned by the IMC, we give up */
+       if (!retries) {
+               mutex_unlock(&piix4_mutex_sb800);
+               return -EBUSY;
+       }
+
        outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
        smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
 
@@ -604,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
 
        outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
 
+       /* Release the semaphore */
+       outb_p(smbslvcnt | 0x20, SMBSLVCNT);
+
        mutex_unlock(&piix4_mutex_sb800);
 
        return retval;
index cf9e396d7702c6c769e2106a6938f90c6ddbb7a9..583e95042a21d86fe235d2e9784a1f6a6723205b 100644 (file)
@@ -931,7 +931,10 @@ static int i2c_device_probe(struct device *dev)
        if (!client->irq) {
                int irq = -ENOENT;
 
-               if (dev->of_node) {
+               if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
+                       dev_dbg(dev, "Using Host Notify IRQ\n");
+                       irq = i2c_smbus_host_notify_to_irq(client);
+               } else if (dev->of_node) {
                        irq = of_irq_get_byname(dev->of_node, "irq");
                        if (irq == -EINVAL || irq == -ENODATA)
                                irq = of_irq_get(dev->of_node, 0);
@@ -940,14 +943,7 @@ static int i2c_device_probe(struct device *dev)
                }
                if (irq == -EPROBE_DEFER)
                        return irq;
-               /*
-                * ACPI and OF did not find any useful IRQ, try to see
-                * if Host Notify can be used.
-                */
-               if (irq < 0) {
-                       dev_dbg(dev, "Using Host Notify IRQ\n");
-                       irq = i2c_smbus_host_notify_to_irq(client);
-               }
+
                if (irq < 0)
                        irq = 0;
 
@@ -1708,7 +1704,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
 
        if (i2c_check_addr_validity(addr, info.flags)) {
                dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
-                       info.addr, node->full_name);
+                       addr, node->full_name);
                return ERR_PTR(-EINVAL);
        }
 
@@ -1716,6 +1712,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
        info.of_node = of_node_get(node);
        info.archdata = &dev_ad;
 
+       if (of_property_read_bool(node, "host-notify"))
+               info.flags |= I2C_CLIENT_HOST_NOTIFY;
+
        if (of_get_property(node, "wakeup-source", NULL))
                info.flags |= I2C_CLIENT_WAKE;
 
@@ -3633,7 +3632,7 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
        int ret;
 
        if (!client || !slave_cb) {
-               WARN(1, "insufficent data\n");
+               WARN(1, "insufficient data\n");
                return -EINVAL;
        }
 
index 66f323fd39826ebe9a738d55724ee2e124b45419..6f638bbc922db4fd366e1e3dcdd11c8655215622 100644 (file)
@@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
                unsigned long arg)
 {
        struct i2c_smbus_ioctl_data data_arg;
-       union i2c_smbus_data temp;
+       union i2c_smbus_data temp = {};
        int datasize, res;
 
        if (copy_from_user(&data_arg,
index f6b6d42385e1148b2ad7f279feb9a43396e66894..784670e2736b4fbbc540382afc1aefe66ccc1e5c 100644 (file)
@@ -353,12 +353,12 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                                [0] = {
                                        .num = ST_ACCEL_FS_AVL_2G,
                                        .value = 0x00,
-                                       .gain = IIO_G_TO_M_S_2(1024),
+                                       .gain = IIO_G_TO_M_S_2(1000),
                                },
                                [1] = {
                                        .num = ST_ACCEL_FS_AVL_6G,
                                        .value = 0x01,
-                                       .gain = IIO_G_TO_M_S_2(340),
+                                       .gain = IIO_G_TO_M_S_2(3000),
                                },
                        },
                },
@@ -366,6 +366,14 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                        .addr = 0x21,
                        .mask = 0x40,
                },
+               /*
+                * Data Alignment Setting - needs to be set to get
+                * left-justified data like all other sensors.
+                */
+               .das = {
+                       .addr = 0x21,
+                       .mask = 0x01,
+               },
                .drdy_irq = {
                        .addr = 0x21,
                        .mask_int1 = 0x04,
index 38bc319904c4c2998c040e8a05bdcbd3f55e9088..9c8b558ba19ecb035b8f4fe789acee1663184c60 100644 (file)
@@ -561,7 +561,7 @@ config TI_ADS8688
 
 config TI_AM335X_ADC
        tristate "TI's AM335X ADC driver"
-       depends on MFD_TI_AM335X_TSCADC
+       depends on MFD_TI_AM335X_TSCADC && HAS_DMA
        select IIO_BUFFER
        select IIO_KFIFO_BUF
        help
index 2bbf0c521bebb5c44840a8ce5296024910d8d73d..7d61b566e148dddd21ce2986cba233567802f93c 100644 (file)
@@ -775,7 +775,7 @@ static int palmas_adc_wakeup_reset(struct palmas_gpadc *adc)
 
 static int palmas_gpadc_suspend(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct palmas_gpadc *adc = iio_priv(indio_dev);
        int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
        int ret;
@@ -798,7 +798,7 @@ static int palmas_gpadc_suspend(struct device *dev)
 
 static int palmas_gpadc_resume(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct palmas_gpadc *adc = iio_priv(indio_dev);
        int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
        int ret;
index fe7775bb37402ea73915189d2c4f121b0a74464d..df4045203a0717c40613b2297c9f85a855333f68 100644 (file)
@@ -30,7 +30,9 @@ static int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
 
        for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) {
                const struct iio_chan_spec *channel = &indio_dev->channels[i];
-               unsigned int bytes_to_read = channel->scan_type.realbits >> 3;
+               unsigned int bytes_to_read =
+                       DIV_ROUND_UP(channel->scan_type.realbits +
+                                    channel->scan_type.shift, 8);
                unsigned int storage_bytes =
                        channel->scan_type.storagebits >> 3;
 
index 975a1f19f74760e5e1c17c786e36d9a86ae5a2a6..79c8c7cd70d5c6d74fc2e32cad372f8644233c6b 100644 (file)
@@ -401,6 +401,15 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
                        return err;
        }
 
+       /* set DAS */
+       if (sdata->sensor_settings->das.addr) {
+               err = st_sensors_write_data_with_mask(indio_dev,
+                                       sdata->sensor_settings->das.addr,
+                                       sdata->sensor_settings->das.mask, 1);
+               if (err < 0)
+                       return err;
+       }
+
        if (sdata->int_pin_open_drain) {
                dev_info(&indio_dev->dev,
                         "set interrupt line to open drain mode\n");
@@ -483,8 +492,10 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
        int err;
        u8 *outdata;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
-       unsigned int byte_for_channel = ch->scan_type.realbits >> 3;
+       unsigned int byte_for_channel;
 
+       byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
+                                       ch->scan_type.shift, 8);
        outdata = kmalloc(byte_for_channel, GFP_KERNEL);
        if (!outdata)
                return -ENOMEM;
index 2d2ee353dde7fc7bc976ced92cd969ccd9fade53..a5913e97945eb6b5f26a418a71852fe086e6cd42 100644 (file)
@@ -153,7 +153,7 @@ static int quad8_write_raw(struct iio_dev *indio_dev,
                ior_cfg = val | priv->preset_enable[chan->channel] << 1;
 
                /* Load I/O control configuration */
-               outb(0x40 | ior_cfg, base_offset);
+               outb(0x40 | ior_cfg, base_offset + 1);
 
                return 0;
        case IIO_CHAN_INFO_SCALE:
@@ -233,7 +233,7 @@ static ssize_t quad8_read_set_to_preset_on_index(struct iio_dev *indio_dev,
        const struct quad8_iio *const priv = iio_priv(indio_dev);
 
        return snprintf(buf, PAGE_SIZE, "%u\n",
-               priv->preset_enable[chan->channel]);
+               !priv->preset_enable[chan->channel]);
 }
 
 static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
@@ -241,7 +241,7 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
        size_t len)
 {
        struct quad8_iio *const priv = iio_priv(indio_dev);
-       const int base_offset = priv->base + 2 * chan->channel;
+       const int base_offset = priv->base + 2 * chan->channel + 1;
        bool preset_enable;
        int ret;
        unsigned int ior_cfg;
@@ -250,6 +250,9 @@ static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
        if (ret)
                return ret;
 
+       /* Preset enable is active low in Input/Output Control register */
+       preset_enable = !preset_enable;
+
        priv->preset_enable[chan->channel] = preset_enable;
 
        ior_cfg = priv->ab_enable[chan->channel] |
@@ -362,7 +365,7 @@ static int quad8_set_synchronous_mode(struct iio_dev *indio_dev,
        priv->synchronous_mode[chan->channel] = synchronous_mode;
 
        /* Load Index Control configuration to Index Control Register */
-       outb(0x40 | idr_cfg, base_offset);
+       outb(0x60 | idr_cfg, base_offset);
 
        return 0;
 }
@@ -444,7 +447,7 @@ static int quad8_set_index_polarity(struct iio_dev *indio_dev,
        priv->index_polarity[chan->channel] = index_polarity;
 
        /* Load Index Control configuration to Index Control Register */
-       outb(0x40 | idr_cfg, base_offset);
+       outb(0x60 | idr_cfg, base_offset);
 
        return 0;
 }
index 9a081465c42f4225d26747a734c5daceea68c842..6bb23a49e81eb8cf304a2f81f50c5e36a91e2d48 100644 (file)
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, afe4403_of_match);
 
 static int __maybe_unused afe4403_suspend(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
        struct afe4403_data *afe = iio_priv(indio_dev);
        int ret;
 
@@ -443,7 +443,7 @@ static int __maybe_unused afe4403_suspend(struct device *dev)
 
 static int __maybe_unused afe4403_resume(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
        struct afe4403_data *afe = iio_priv(indio_dev);
        int ret;
 
index 45266404f7e3b5bd7c7790a0b05ff298fc24d5a9..964f5231a831c437c277e4bcfe292720104043f7 100644 (file)
@@ -428,7 +428,7 @@ MODULE_DEVICE_TABLE(of, afe4404_of_match);
 
 static int __maybe_unused afe4404_suspend(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct afe4404_data *afe = iio_priv(indio_dev);
        int ret;
 
@@ -449,7 +449,7 @@ static int __maybe_unused afe4404_suspend(struct device *dev)
 
 static int __maybe_unused afe4404_resume(struct device *dev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
        struct afe4404_data *afe = iio_priv(indio_dev);
        int ret;
 
index 90ab8a2d2846f8a8591ee6b1615dce2c984020ef..183c14329d6e350f6325b0e77a95dcb56de892dd 100644 (file)
@@ -238,7 +238,7 @@ static irqreturn_t max30100_interrupt_handler(int irq, void *private)
 
        mutex_lock(&data->lock);
 
-       while (cnt || (cnt = max30100_fifo_count(data) > 0)) {
+       while (cnt || (cnt = max30100_fifo_count(data)) > 0) {
                ret = max30100_read_measurement(data);
                if (ret)
                        break;
index 9c47bc98f3acdea4cb4b56b23a72e582c34a413b..2a22ad92033306d02eec60f288c00a65d5186c37 100644 (file)
@@ -71,7 +71,8 @@
  * a) select an implementation using busy loop polling on those systems
  * b) use the checksum to do some probabilistic decoding
  */
-#define DHT11_START_TRANSMISSION       18  /* ms */
+#define DHT11_START_TRANSMISSION_MIN   18000  /* us */
+#define DHT11_START_TRANSMISSION_MAX   20000  /* us */
 #define DHT11_MIN_TIMERES      34000  /* ns */
 #define DHT11_THRESHOLD                49000  /* ns */
 #define DHT11_AMBIG_LOW                23000  /* ns */
@@ -228,7 +229,8 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                ret = gpio_direction_output(dht11->gpio, 0);
                if (ret)
                        goto err;
-               msleep(DHT11_START_TRANSMISSION);
+               usleep_range(DHT11_START_TRANSMISSION_MIN,
+                            DHT11_START_TRANSMISSION_MAX);
                ret = gpio_direction_input(dht11->gpio);
                if (ret)
                        goto err;
index 5355507f8fa1493c8fc5346e4f51da37f8f4790c..c9e319bff58b314f626797f9dbf36339eb76be04 100644 (file)
 
 #define BMI160_REG_DUMMY               0x7F
 
-#define BMI160_ACCEL_PMU_MIN_USLEEP    3200
-#define BMI160_ACCEL_PMU_MAX_USLEEP    3800
-#define BMI160_GYRO_PMU_MIN_USLEEP     55000
-#define BMI160_GYRO_PMU_MAX_USLEEP     80000
+#define BMI160_ACCEL_PMU_MIN_USLEEP    3800
+#define BMI160_GYRO_PMU_MIN_USLEEP     80000
 #define BMI160_SOFTRESET_USLEEP                1000
 
 #define BMI160_CHANNEL(_type, _axis, _index) {                 \
@@ -151,20 +149,9 @@ static struct bmi160_regs bmi160_regs[] = {
        },
 };
 
-struct bmi160_pmu_time {
-       unsigned long min;
-       unsigned long max;
-};
-
-static struct bmi160_pmu_time bmi160_pmu_time[] = {
-       [BMI160_ACCEL] = {
-               .min = BMI160_ACCEL_PMU_MIN_USLEEP,
-               .max = BMI160_ACCEL_PMU_MAX_USLEEP
-       },
-       [BMI160_GYRO] = {
-               .min = BMI160_GYRO_PMU_MIN_USLEEP,
-               .max = BMI160_GYRO_PMU_MIN_USLEEP,
-       },
+static unsigned long bmi160_pmu_time[] = {
+       [BMI160_ACCEL] = BMI160_ACCEL_PMU_MIN_USLEEP,
+       [BMI160_GYRO] = BMI160_GYRO_PMU_MIN_USLEEP,
 };
 
 struct bmi160_scale {
@@ -289,7 +276,7 @@ int bmi160_set_mode(struct bmi160_data *data, enum bmi160_sensor_type t,
        if (ret < 0)
                return ret;
 
-       usleep_range(bmi160_pmu_time[t].min, bmi160_pmu_time[t].max);
+       usleep_range(bmi160_pmu_time[t], bmi160_pmu_time[t] + 1000);
 
        return 0;
 }
index a144ca3461fc91e2ad853302dcfc2241a9b3e923..81bd8e8da4a69af929760bfe1c12716fe16de972 100644 (file)
@@ -113,7 +113,7 @@ static const char max44000_int_time_avail_str[] =
        "0.100 "
        "0.025 "
        "0.00625 "
-       "0.001625";
+       "0.0015625";
 
 /* Available scales (internal to ulux) with pretty manual alignment: */
 static const int max44000_scale_avail_ulux_array[] = {
index e7dcfac877ca2eb7b86601a9115b4c2fc27f4c01..3e70a9c5d79d5a50ba3be228cb4174d1f66c98d7 100644 (file)
@@ -2811,7 +2811,8 @@ static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
        if (!src_addr || !src_addr->sa_family) {
                src_addr = (struct sockaddr *) &id->route.addr.src_addr;
                src_addr->sa_family = dst_addr->sa_family;
-               if (dst_addr->sa_family == AF_INET6) {
+               if (IS_ENABLED(CONFIG_IPV6) &&
+                   dst_addr->sa_family == AF_INET6) {
                        struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *) src_addr;
                        struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *) dst_addr;
                        src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id;
index 1e62a5f0cb28203e0732b9915840fd9f02d45701..4609b921f899c9d7481b86825f18fe076a6f732c 100644 (file)
@@ -134,6 +134,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
                 IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND));
 
        if (access & IB_ACCESS_ON_DEMAND) {
+               put_pid(umem->pid);
                ret = ib_umem_odp_get(context, umem);
                if (ret) {
                        kfree(umem);
@@ -149,6 +150,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
 
        page_list = (struct page **) __get_free_page(GFP_KERNEL);
        if (!page_list) {
+               put_pid(umem->pid);
                kfree(umem);
                return ERR_PTR(-ENOMEM);
        }
index 9d5fe1853da46e54e9d635c5d101b688f4a8119a..6262dc035f3cea4c9613d96f67ec13e76a18643e 100644 (file)
@@ -1135,16 +1135,7 @@ static int iwch_query_port(struct ib_device *ibdev,
 
        memset(props, 0, sizeof(struct ib_port_attr));
        props->max_mtu = IB_MTU_4096;
-       if (netdev->mtu >= 4096)
-               props->active_mtu = IB_MTU_4096;
-       else if (netdev->mtu >= 2048)
-               props->active_mtu = IB_MTU_2048;
-       else if (netdev->mtu >= 1024)
-               props->active_mtu = IB_MTU_1024;
-       else if (netdev->mtu >= 512)
-               props->active_mtu = IB_MTU_512;
-       else
-               props->active_mtu = IB_MTU_256;
+       props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
        if (!netif_carrier_ok(netdev))
                props->state = IB_PORT_DOWN;
index f1510cc76d2dbe7027e81f5495f53bd7b6588536..9398143d7c5e93a01d5b35c67ae0fdd4e0126483 100644 (file)
@@ -1804,20 +1804,21 @@ static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
        skb_trim(skb, dlen);
        mutex_lock(&ep->com.mutex);
 
-       /* update RX credits */
-       update_rx_credits(ep, dlen);
-
        switch (ep->com.state) {
        case MPA_REQ_SENT:
+               update_rx_credits(ep, dlen);
                ep->rcv_seq += dlen;
                disconnect = process_mpa_reply(ep, skb);
                break;
        case MPA_REQ_WAIT:
+               update_rx_credits(ep, dlen);
                ep->rcv_seq += dlen;
                disconnect = process_mpa_request(ep, skb);
                break;
        case FPDU_MODE: {
                struct c4iw_qp_attributes attrs;
+
+               update_rx_credits(ep, dlen);
                BUG_ON(!ep->com.qp);
                if (status)
                        pr_err("%s Unexpected streaming data." \
index 19c6477af19f1416d17c15363e239307542b438d..bec82a600d77c7990432c756ecb8124df6a52852 100644 (file)
@@ -504,6 +504,15 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
                goto skip_cqe;
        }
 
+       /*
+        * Special cqe for drain WR completions...
+        */
+       if (CQE_OPCODE(hw_cqe) == C4IW_DRAIN_OPCODE) {
+               *cookie = CQE_DRAIN_COOKIE(hw_cqe);
+               *cqe = *hw_cqe;
+               goto skip_cqe;
+       }
+
        /*
         * Gotta tweak READ completions:
         *      1) the cqe doesn't contain the sq_wptr from the wr.
@@ -753,6 +762,9 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
                                c4iw_invalidate_mr(qhp->rhp,
                                                   CQE_WRID_FR_STAG(&cqe));
                        break;
+               case C4IW_DRAIN_OPCODE:
+                       wc->opcode = IB_WC_SEND;
+                       break;
                default:
                        printk(KERN_ERR MOD "Unexpected opcode %d "
                               "in the CQE received for QPID=0x%0x\n",
@@ -817,15 +829,8 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
                }
        }
 out:
-       if (wq) {
-               if (unlikely(qhp->attr.state != C4IW_QP_STATE_RTS)) {
-                       if (t4_sq_empty(wq))
-                               complete(&qhp->sq_drained);
-                       if (t4_rq_empty(wq))
-                               complete(&qhp->rq_drained);
-               }
+       if (wq)
                spin_unlock(&qhp->lock);
-       }
        return ret;
 }
 
index 516b0ae6dc3f6d061cc3c7d8ba412196785a599c..40c0e7b9fc6e4e671eb4fb03682f9130594c90cb 100644 (file)
@@ -846,9 +846,17 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
                }
        }
 
+       rdev->free_workq = create_singlethread_workqueue("iw_cxgb4_free");
+       if (!rdev->free_workq) {
+               err = -ENOMEM;
+               goto err_free_status_page;
+       }
+
        rdev->status_page->db_off = 0;
 
        return 0;
+err_free_status_page:
+       free_page((unsigned long)rdev->status_page);
 destroy_ocqp_pool:
        c4iw_ocqp_pool_destroy(rdev);
 destroy_rqtpool:
@@ -862,6 +870,7 @@ destroy_resource:
 
 static void c4iw_rdev_close(struct c4iw_rdev *rdev)
 {
+       destroy_workqueue(rdev->free_workq);
        kfree(rdev->wr_log);
        free_page((unsigned long)rdev->status_page);
        c4iw_pblpool_destroy(rdev);
index 4788e1a46fdee23cce2956cc17ba8d09b0f3eb56..8cd4d054a87ed0ea27f323d47f82fdc7b3e10bff 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/kref.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 
@@ -107,6 +108,7 @@ struct c4iw_dev_ucontext {
        struct list_head qpids;
        struct list_head cqids;
        struct mutex lock;
+       struct kref kref;
 };
 
 enum c4iw_rdev_flags {
@@ -183,6 +185,7 @@ struct c4iw_rdev {
        atomic_t wr_log_idx;
        struct wr_log_entry *wr_log;
        int wr_log_size;
+       struct workqueue_struct *free_workq;
 };
 
 static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -480,8 +483,8 @@ struct c4iw_qp {
        wait_queue_head_t wait;
        struct timer_list timer;
        int sq_sig_all;
-       struct completion rq_drained;
-       struct completion sq_drained;
+       struct work_struct free_work;
+       struct c4iw_ucontext *ucontext;
 };
 
 static inline struct c4iw_qp *to_c4iw_qp(struct ib_qp *ibqp)
@@ -495,6 +498,7 @@ struct c4iw_ucontext {
        u32 key;
        spinlock_t mmap_lock;
        struct list_head mmaps;
+       struct kref kref;
 };
 
 static inline struct c4iw_ucontext *to_c4iw_ucontext(struct ib_ucontext *c)
@@ -502,6 +506,18 @@ static inline struct c4iw_ucontext *to_c4iw_ucontext(struct ib_ucontext *c)
        return container_of(c, struct c4iw_ucontext, ibucontext);
 }
 
+void _c4iw_free_ucontext(struct kref *kref);
+
+static inline void c4iw_put_ucontext(struct c4iw_ucontext *ucontext)
+{
+       kref_put(&ucontext->kref, _c4iw_free_ucontext);
+}
+
+static inline void c4iw_get_ucontext(struct c4iw_ucontext *ucontext)
+{
+       kref_get(&ucontext->kref);
+}
+
 struct c4iw_mm_entry {
        struct list_head entry;
        u64 addr;
@@ -615,6 +631,8 @@ static inline int to_ib_qp_state(int c4iw_qp_state)
        return IB_QPS_ERR;
 }
 
+#define C4IW_DRAIN_OPCODE FW_RI_SGE_EC_CR_RETURN
+
 static inline u32 c4iw_ib_to_tpt_access(int a)
 {
        return (a & IB_ACCESS_REMOTE_WRITE ? FW_RI_MEM_ACCESS_REM_WRITE : 0) |
@@ -997,8 +1015,6 @@ extern int c4iw_wr_log;
 extern int db_fc_threshold;
 extern int db_coalescing_threshold;
 extern int use_dsgl;
-void c4iw_drain_rq(struct ib_qp *qp);
-void c4iw_drain_sq(struct ib_qp *qp);
 void c4iw_invalidate_mr(struct c4iw_dev *rhp, u32 rkey);
 
 #endif
index 49b51b7e0fd786bf49dc2187e6c661f14087f3ae..3345e1c312f771cfaa8e31858624ca9892267467 100644 (file)
@@ -93,17 +93,28 @@ static int c4iw_process_mad(struct ib_device *ibdev, int mad_flags,
        return -ENOSYS;
 }
 
-static int c4iw_dealloc_ucontext(struct ib_ucontext *context)
+void _c4iw_free_ucontext(struct kref *kref)
 {
-       struct c4iw_dev *rhp = to_c4iw_dev(context->device);
-       struct c4iw_ucontext *ucontext = to_c4iw_ucontext(context);
+       struct c4iw_ucontext *ucontext;
+       struct c4iw_dev *rhp;
        struct c4iw_mm_entry *mm, *tmp;
 
-       PDBG("%s context %p\n", __func__, context);
+       ucontext = container_of(kref, struct c4iw_ucontext, kref);
+       rhp = to_c4iw_dev(ucontext->ibucontext.device);
+
+       PDBG("%s ucontext %p\n", __func__, ucontext);
        list_for_each_entry_safe(mm, tmp, &ucontext->mmaps, entry)
                kfree(mm);
        c4iw_release_dev_ucontext(&rhp->rdev, &ucontext->uctx);
        kfree(ucontext);
+}
+
+static int c4iw_dealloc_ucontext(struct ib_ucontext *context)
+{
+       struct c4iw_ucontext *ucontext = to_c4iw_ucontext(context);
+
+       PDBG("%s context %p\n", __func__, context);
+       c4iw_put_ucontext(ucontext);
        return 0;
 }
 
@@ -127,6 +138,7 @@ static struct ib_ucontext *c4iw_alloc_ucontext(struct ib_device *ibdev,
        c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx);
        INIT_LIST_HEAD(&context->mmaps);
        spin_lock_init(&context->mmap_lock);
+       kref_init(&context->kref);
 
        if (udata->outlen < sizeof(uresp) - sizeof(uresp.reserved)) {
                if (!warned++)
@@ -361,16 +373,7 @@ static int c4iw_query_port(struct ib_device *ibdev, u8 port,
 
        memset(props, 0, sizeof(struct ib_port_attr));
        props->max_mtu = IB_MTU_4096;
-       if (netdev->mtu >= 4096)
-               props->active_mtu = IB_MTU_4096;
-       else if (netdev->mtu >= 2048)
-               props->active_mtu = IB_MTU_2048;
-       else if (netdev->mtu >= 1024)
-               props->active_mtu = IB_MTU_1024;
-       else if (netdev->mtu >= 512)
-               props->active_mtu = IB_MTU_512;
-       else
-               props->active_mtu = IB_MTU_256;
+       props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
        if (!netif_carrier_ok(netdev))
                props->state = IB_PORT_DOWN;
@@ -607,8 +610,6 @@ int c4iw_register_device(struct c4iw_dev *dev)
        dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
        dev->ibdev.get_port_immutable = c4iw_port_immutable;
        dev->ibdev.get_dev_fw_str = get_dev_fw_str;
-       dev->ibdev.drain_sq = c4iw_drain_sq;
-       dev->ibdev.drain_rq = c4iw_drain_rq;
 
        dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
        if (!dev->ibdev.iwcm)
index cda5542e13a206347447a49f18f9e8cb930e7c8c..04c1c382dedb42bda631f3c62c80395df848a3c9 100644 (file)
@@ -715,13 +715,32 @@ static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
        return 0;
 }
 
-static void _free_qp(struct kref *kref)
+static void free_qp_work(struct work_struct *work)
+{
+       struct c4iw_ucontext *ucontext;
+       struct c4iw_qp *qhp;
+       struct c4iw_dev *rhp;
+
+       qhp = container_of(work, struct c4iw_qp, free_work);
+       ucontext = qhp->ucontext;
+       rhp = qhp->rhp;
+
+       PDBG("%s qhp %p ucontext %p\n", __func__, qhp, ucontext);
+       destroy_qp(&rhp->rdev, &qhp->wq,
+                  ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+
+       if (ucontext)
+               c4iw_put_ucontext(ucontext);
+       kfree(qhp);
+}
+
+static void queue_qp_free(struct kref *kref)
 {
        struct c4iw_qp *qhp;
 
        qhp = container_of(kref, struct c4iw_qp, kref);
        PDBG("%s qhp %p\n", __func__, qhp);
-       kfree(qhp);
+       queue_work(qhp->rhp->rdev.free_workq, &qhp->free_work);
 }
 
 void c4iw_qp_add_ref(struct ib_qp *qp)
@@ -733,7 +752,7 @@ void c4iw_qp_add_ref(struct ib_qp *qp)
 void c4iw_qp_rem_ref(struct ib_qp *qp)
 {
        PDBG("%s ib_qp %p\n", __func__, qp);
-       kref_put(&to_c4iw_qp(qp)->kref, _free_qp);
+       kref_put(&to_c4iw_qp(qp)->kref, queue_qp_free);
 }
 
 static void add_to_fc_list(struct list_head *head, struct list_head *entry)
@@ -776,6 +795,64 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc)
        return 0;
 }
 
+static void complete_sq_drain_wr(struct c4iw_qp *qhp, struct ib_send_wr *wr)
+{
+       struct t4_cqe cqe = {};
+       struct c4iw_cq *schp;
+       unsigned long flag;
+       struct t4_cq *cq;
+
+       schp = to_c4iw_cq(qhp->ibqp.send_cq);
+       cq = &schp->cq;
+
+       cqe.u.drain_cookie = wr->wr_id;
+       cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) |
+                                CQE_OPCODE_V(C4IW_DRAIN_OPCODE) |
+                                CQE_TYPE_V(1) |
+                                CQE_SWCQE_V(1) |
+                                CQE_QPID_V(qhp->wq.sq.qid));
+
+       spin_lock_irqsave(&schp->lock, flag);
+       cqe.bits_type_ts = cpu_to_be64(CQE_GENBIT_V((u64)cq->gen));
+       cq->sw_queue[cq->sw_pidx] = cqe;
+       t4_swcq_produce(cq);
+       spin_unlock_irqrestore(&schp->lock, flag);
+
+       spin_lock_irqsave(&schp->comp_handler_lock, flag);
+       (*schp->ibcq.comp_handler)(&schp->ibcq,
+                                  schp->ibcq.cq_context);
+       spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
+}
+
+static void complete_rq_drain_wr(struct c4iw_qp *qhp, struct ib_recv_wr *wr)
+{
+       struct t4_cqe cqe = {};
+       struct c4iw_cq *rchp;
+       unsigned long flag;
+       struct t4_cq *cq;
+
+       rchp = to_c4iw_cq(qhp->ibqp.recv_cq);
+       cq = &rchp->cq;
+
+       cqe.u.drain_cookie = wr->wr_id;
+       cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) |
+                                CQE_OPCODE_V(C4IW_DRAIN_OPCODE) |
+                                CQE_TYPE_V(0) |
+                                CQE_SWCQE_V(1) |
+                                CQE_QPID_V(qhp->wq.sq.qid));
+
+       spin_lock_irqsave(&rchp->lock, flag);
+       cqe.bits_type_ts = cpu_to_be64(CQE_GENBIT_V((u64)cq->gen));
+       cq->sw_queue[cq->sw_pidx] = cqe;
+       t4_swcq_produce(cq);
+       spin_unlock_irqrestore(&rchp->lock, flag);
+
+       spin_lock_irqsave(&rchp->comp_handler_lock, flag);
+       (*rchp->ibcq.comp_handler)(&rchp->ibcq,
+                                  rchp->ibcq.cq_context);
+       spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
+}
+
 int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                   struct ib_send_wr **bad_wr)
 {
@@ -794,8 +871,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
        spin_lock_irqsave(&qhp->lock, flag);
        if (t4_wq_in_error(&qhp->wq)) {
                spin_unlock_irqrestore(&qhp->lock, flag);
-               *bad_wr = wr;
-               return -EINVAL;
+               complete_sq_drain_wr(qhp, wr);
+               return err;
        }
        num_wrs = t4_sq_avail(&qhp->wq);
        if (num_wrs == 0) {
@@ -937,8 +1014,8 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
        spin_lock_irqsave(&qhp->lock, flag);
        if (t4_wq_in_error(&qhp->wq)) {
                spin_unlock_irqrestore(&qhp->lock, flag);
-               *bad_wr = wr;
-               return -EINVAL;
+               complete_rq_drain_wr(qhp, wr);
+               return err;
        }
        num_wrs = t4_rq_avail(&qhp->wq);
        if (num_wrs == 0) {
@@ -1550,7 +1627,12 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                }
                break;
        case C4IW_QP_STATE_CLOSING:
-               if (!internal) {
+
+               /*
+                * Allow kernel users to move to ERROR for qp draining.
+                */
+               if (!internal && (qhp->ibqp.uobject || attrs->next_state !=
+                                 C4IW_QP_STATE_ERROR)) {
                        ret = -EINVAL;
                        goto out;
                }
@@ -1643,7 +1725,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
        struct c4iw_dev *rhp;
        struct c4iw_qp *qhp;
        struct c4iw_qp_attributes attrs;
-       struct c4iw_ucontext *ucontext;
 
        qhp = to_c4iw_qp(ib_qp);
        rhp = qhp->rhp;
@@ -1663,11 +1744,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
        spin_unlock_irq(&rhp->lock);
        free_ird(rhp, qhp->attr.max_ird);
 
-       ucontext = ib_qp->uobject ?
-                  to_c4iw_ucontext(ib_qp->uobject->context) : NULL;
-       destroy_qp(&rhp->rdev, &qhp->wq,
-                  ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
-
        c4iw_qp_rem_ref(ib_qp);
 
        PDBG("%s ib_qp %p qpid 0x%0x\n", __func__, ib_qp, qhp->wq.sq.qid);
@@ -1763,11 +1839,10 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        qhp->attr.max_ird = 0;
        qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
        spin_lock_init(&qhp->lock);
-       init_completion(&qhp->sq_drained);
-       init_completion(&qhp->rq_drained);
        mutex_init(&qhp->mutex);
        init_waitqueue_head(&qhp->wait);
        kref_init(&qhp->kref);
+       INIT_WORK(&qhp->free_work, free_qp_work);
 
        ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
        if (ret)
@@ -1854,6 +1929,9 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
                        ma_sync_key_mm->len = PAGE_SIZE;
                        insert_mmap(ucontext, ma_sync_key_mm);
                }
+
+               c4iw_get_ucontext(ucontext);
+               qhp->ucontext = ucontext;
        }
        qhp->ibqp.qp_num = qhp->wq.sq.qid;
        init_timer(&(qhp->timer));
@@ -1958,40 +2036,3 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
        return 0;
 }
-
-static void move_qp_to_err(struct c4iw_qp *qp)
-{
-       struct c4iw_qp_attributes attrs = { .next_state = C4IW_QP_STATE_ERROR };
-
-       (void)c4iw_modify_qp(qp->rhp, qp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
-}
-
-void c4iw_drain_sq(struct ib_qp *ibqp)
-{
-       struct c4iw_qp *qp = to_c4iw_qp(ibqp);
-       unsigned long flag;
-       bool need_to_wait;
-
-       move_qp_to_err(qp);
-       spin_lock_irqsave(&qp->lock, flag);
-       need_to_wait = !t4_sq_empty(&qp->wq);
-       spin_unlock_irqrestore(&qp->lock, flag);
-
-       if (need_to_wait)
-               wait_for_completion(&qp->sq_drained);
-}
-
-void c4iw_drain_rq(struct ib_qp *ibqp)
-{
-       struct c4iw_qp *qp = to_c4iw_qp(ibqp);
-       unsigned long flag;
-       bool need_to_wait;
-
-       move_qp_to_err(qp);
-       spin_lock_irqsave(&qp->lock, flag);
-       need_to_wait = !t4_rq_empty(&qp->wq);
-       spin_unlock_irqrestore(&qp->lock, flag);
-
-       if (need_to_wait)
-               wait_for_completion(&qp->rq_drained);
-}
index 862381aa83c824bb8712e408df39e49f47f11975..640d22148a3eeb86fdc2d5c795dcf02271bf57fb 100644 (file)
@@ -179,6 +179,7 @@ struct t4_cqe {
                        __be32 wrid_hi;
                        __be32 wrid_low;
                } gen;
+               u64 drain_cookie;
        } u;
        __be64 reserved;
        __be64 bits_type_ts;
@@ -238,6 +239,7 @@ struct t4_cqe {
 /* generic accessor macros */
 #define CQE_WRID_HI(x)         (be32_to_cpu((x)->u.gen.wrid_hi))
 #define CQE_WRID_LOW(x)                (be32_to_cpu((x)->u.gen.wrid_low))
+#define CQE_DRAIN_COOKIE(x)    ((x)->u.drain_cookie)
 
 /* macros for flit 3 of the cqe */
 #define CQE_GENBIT_S   63
index 29e97df9e1a7f87c784ebf33f4ebccfae217f433..4c000d60d5c6f865ae17aa28654497e3dbbb913c 100644 (file)
@@ -100,16 +100,7 @@ static int i40iw_query_port(struct ib_device *ibdev,
        memset(props, 0, sizeof(*props));
 
        props->max_mtu = IB_MTU_4096;
-       if (netdev->mtu >= 4096)
-               props->active_mtu = IB_MTU_4096;
-       else if (netdev->mtu >= 2048)
-               props->active_mtu = IB_MTU_2048;
-       else if (netdev->mtu >= 1024)
-               props->active_mtu = IB_MTU_1024;
-       else if (netdev->mtu >= 512)
-               props->active_mtu = IB_MTU_512;
-       else
-               props->active_mtu = IB_MTU_256;
+       props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
        props->lid = 1;
        if (netif_carrier_ok(iwdev->netdev))
index aff9fb14768be9006e05145b2bdd7b6f7dbee8ff..5a31f3c6a4211d507cc4634c49df53021bba505b 100644 (file)
@@ -478,17 +478,7 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr
        memset(props, 0, sizeof(*props));
 
        props->max_mtu = IB_MTU_4096;
-
-       if (netdev->mtu  >= 4096)
-               props->active_mtu = IB_MTU_4096;
-       else if (netdev->mtu  >= 2048)
-               props->active_mtu = IB_MTU_2048;
-       else if (netdev->mtu  >= 1024)
-               props->active_mtu = IB_MTU_1024;
-       else if (netdev->mtu  >= 512)
-               props->active_mtu = IB_MTU_512;
-       else
-               props->active_mtu = IB_MTU_256;
+       props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
        props->lid = 1;
        props->lmc = 0;
index 7b74d09a8217ca0f30de8d5065bb4b829100c56f..3ac8aa5ef37de2c5242125077eef78035d565901 100644 (file)
@@ -576,8 +576,7 @@ static int qedr_set_device_attr(struct qedr_dev *dev)
        return 0;
 }
 
-void qedr_unaffiliated_event(void *context,
-                            u8 event_code)
+void qedr_unaffiliated_event(void *context, u8 event_code)
 {
        pr_err("unaffiliated event not implemented yet\n");
 }
@@ -792,6 +791,9 @@ static struct qedr_dev *qedr_add(struct qed_dev *cdev, struct pci_dev *pdev,
                if (device_create_file(&dev->ibdev.dev, qedr_attributes[i]))
                        goto sysfs_err;
 
+       if (!test_and_set_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
+               qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ACTIVE);
+
        DP_DEBUG(dev, QEDR_MSG_INIT, "qedr driver loaded successfully\n");
        return dev;
 
@@ -824,11 +826,10 @@ static void qedr_remove(struct qedr_dev *dev)
        ib_dealloc_device(&dev->ibdev);
 }
 
-static int qedr_close(struct qedr_dev *dev)
+static void qedr_close(struct qedr_dev *dev)
 {
-       qedr_ib_dispatch_event(dev, 1, IB_EVENT_PORT_ERR);
-
-       return 0;
+       if (test_and_clear_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
+               qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ERR);
 }
 
 static void qedr_shutdown(struct qedr_dev *dev)
@@ -837,6 +838,12 @@ static void qedr_shutdown(struct qedr_dev *dev)
        qedr_remove(dev);
 }
 
+static void qedr_open(struct qedr_dev *dev)
+{
+       if (!test_and_set_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
+               qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ACTIVE);
+}
+
 static void qedr_mac_address_change(struct qedr_dev *dev)
 {
        union ib_gid *sgid = &dev->sgid_tbl[0];
@@ -863,7 +870,7 @@ static void qedr_mac_address_change(struct qedr_dev *dev)
 
        ether_addr_copy(dev->gsi_ll2_mac_address, dev->ndev->dev_addr);
 
-       qedr_ib_dispatch_event(dev, 1, IB_EVENT_GID_CHANGE);
+       qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_GID_CHANGE);
 
        if (rc)
                DP_ERR(dev, "Error updating mac filter\n");
@@ -877,7 +884,7 @@ static void qedr_notify(struct qedr_dev *dev, enum qede_roce_event event)
 {
        switch (event) {
        case QEDE_UP:
-               qedr_ib_dispatch_event(dev, 1, IB_EVENT_PORT_ACTIVE);
+               qedr_open(dev);
                break;
        case QEDE_DOWN:
                qedr_close(dev);
index 620badd7d4fbd7f6ceaa61aff95ef1e41161f0be..bb32e4792ec9f022d201c0585bcce7a7cbae179c 100644 (file)
@@ -113,6 +113,8 @@ struct qedr_device_attr {
        struct qed_rdma_events events;
 };
 
+#define QEDR_ENET_STATE_BIT    (0)
+
 struct qedr_dev {
        struct ib_device        ibdev;
        struct qed_dev          *cdev;
@@ -153,6 +155,8 @@ struct qedr_dev {
        struct qedr_cq          *gsi_sqcq;
        struct qedr_cq          *gsi_rqcq;
        struct qedr_qp          *gsi_qp;
+
+       unsigned long enet_state;
 };
 
 #define QEDR_MAX_SQ_PBL                        (0x8000)
@@ -188,6 +192,7 @@ struct qedr_dev {
 #define QEDR_ROCE_MAX_CNQ_SIZE         (0x4000)
 
 #define QEDR_MAX_PORT                  (1)
+#define QEDR_PORT                      (1)
 
 #define QEDR_UVERBS(CMD_NAME) (1ull << IB_USER_VERBS_CMD_##CMD_NAME)
 
@@ -251,9 +256,6 @@ struct qedr_cq {
 
        u16 icid;
 
-       /* Lock to protect completion handler */
-       spinlock_t comp_handler_lock;
-
        /* Lock to protect multiplem CQ's */
        spinlock_t cq_lock;
        u8 arm_flags;
index 63890ebb72bdff1c525e87786f59b124b2ea8d3f..a9a8d8745d2e7f9ca20a5c849e042fdc6af261d6 100644 (file)
@@ -87,11 +87,8 @@ void qedr_ll2_tx_cb(void *_qdev, struct qed_roce_ll2_packet *pkt)
        qedr_inc_sw_gsi_cons(&qp->sq);
        spin_unlock_irqrestore(&qp->q_lock, flags);
 
-       if (cq->ibcq.comp_handler) {
-               spin_lock_irqsave(&cq->comp_handler_lock, flags);
+       if (cq->ibcq.comp_handler)
                (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
-               spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
-       }
 }
 
 void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
@@ -113,11 +110,8 @@ void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
 
        spin_unlock_irqrestore(&qp->q_lock, flags);
 
-       if (cq->ibcq.comp_handler) {
-               spin_lock_irqsave(&cq->comp_handler_lock, flags);
+       if (cq->ibcq.comp_handler)
                (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
-               spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
-       }
 }
 
 static void qedr_destroy_gsi_cq(struct qedr_dev *dev,
@@ -404,9 +398,9 @@ static inline int qedr_gsi_build_packet(struct qedr_dev *dev,
        }
 
        if (ether_addr_equal(udh.eth.smac_h, udh.eth.dmac_h))
-               packet->tx_dest = QED_ROCE_LL2_TX_DEST_NW;
-       else
                packet->tx_dest = QED_ROCE_LL2_TX_DEST_LB;
+       else
+               packet->tx_dest = QED_ROCE_LL2_TX_DEST_NW;
 
        packet->roce_mode = roce_mode;
        memcpy(packet->header.vaddr, ud_header_buffer, header_size);
index 57c8de2080773b161272774a69eaebf02cc411ed..c7d6c9a783bd615627e720eb8f043444c99c5f3c 100644 (file)
@@ -471,8 +471,6 @@ struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,
                            struct ib_ucontext *context, struct ib_udata *udata)
 {
        struct qedr_dev *dev = get_qedr_dev(ibdev);
-       struct qedr_ucontext *uctx = NULL;
-       struct qedr_alloc_pd_uresp uresp;
        struct qedr_pd *pd;
        u16 pd_id;
        int rc;
@@ -489,21 +487,33 @@ struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,
        if (!pd)
                return ERR_PTR(-ENOMEM);
 
-       dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id);
+       rc = dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id);
+       if (rc)
+               goto err;
 
-       uresp.pd_id = pd_id;
        pd->pd_id = pd_id;
 
        if (udata && context) {
+               struct qedr_alloc_pd_uresp uresp;
+
+               uresp.pd_id = pd_id;
+
                rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
-               if (rc)
+               if (rc) {
                        DP_ERR(dev, "copy error pd_id=0x%x.\n", pd_id);
-               uctx = get_qedr_ucontext(context);
-               uctx->pd = pd;
-               pd->uctx = uctx;
+                       dev->ops->rdma_dealloc_pd(dev->rdma_ctx, pd_id);
+                       goto err;
+               }
+
+               pd->uctx = get_qedr_ucontext(context);
+               pd->uctx->pd = pd;
        }
 
        return &pd->ibpd;
+
+err:
+       kfree(pd);
+       return ERR_PTR(rc);
 }
 
 int qedr_dealloc_pd(struct ib_pd *ibpd)
@@ -1600,7 +1610,7 @@ err0:
        return ERR_PTR(-EFAULT);
 }
 
-enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
+static enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
 {
        switch (qp_state) {
        case QED_ROCE_QP_STATE_RESET:
@@ -1621,7 +1631,8 @@ enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
        return IB_QPS_ERR;
 }
 
-enum qed_roce_qp_state qedr_get_state_from_ibqp(enum ib_qp_state qp_state)
+static enum qed_roce_qp_state qedr_get_state_from_ibqp(
+                                       enum ib_qp_state qp_state)
 {
        switch (qp_state) {
        case IB_QPS_RESET:
@@ -1657,7 +1668,7 @@ static int qedr_update_qp_state(struct qedr_dev *dev,
        int status = 0;
 
        if (new_state == qp->state)
-               return 1;
+               return 0;
 
        switch (qp->state) {
        case QED_ROCE_QP_STATE_RESET:
@@ -1733,6 +1744,14 @@ static int qedr_update_qp_state(struct qedr_dev *dev,
                /* ERR->XXX */
                switch (new_state) {
                case QED_ROCE_QP_STATE_RESET:
+                       if ((qp->rq.prod != qp->rq.cons) ||
+                           (qp->sq.prod != qp->sq.cons)) {
+                               DP_NOTICE(dev,
+                                         "Error->Reset with rq/sq not empty rq.prod=%x rq.cons=%x sq.prod=%x sq.cons=%x\n",
+                                         qp->rq.prod, qp->rq.cons, qp->sq.prod,
+                                         qp->sq.cons);
+                               status = -EINVAL;
+                       }
                        break;
                default:
                        status = -EINVAL;
@@ -1865,7 +1884,6 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
                         qp_params.sgid.dwords[2], qp_params.sgid.dwords[3]);
                DP_DEBUG(dev, QEDR_MSG_QP, "remote_mac=[%pM]\n",
                         qp_params.remote_mac_addr);
-;
 
                qp_params.mtu = qp->mtu;
                qp_params.lb_indication = false;
@@ -2016,7 +2034,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
 
        qp_attr->qp_state = qedr_get_ibqp_state(params.state);
        qp_attr->cur_qp_state = qedr_get_ibqp_state(params.state);
-       qp_attr->path_mtu = iboe_get_mtu(params.mtu);
+       qp_attr->path_mtu = ib_mtu_int_to_enum(params.mtu);
        qp_attr->path_mig_state = IB_MIG_MIGRATED;
        qp_attr->rq_psn = params.rq_psn;
        qp_attr->sq_psn = params.sq_psn;
@@ -2028,7 +2046,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
        qp_attr->cap.max_recv_wr = qp->rq.max_wr;
        qp_attr->cap.max_send_sge = qp->sq.max_sges;
        qp_attr->cap.max_recv_sge = qp->rq.max_sges;
-       qp_attr->cap.max_inline_data = qp->max_inline_data;
+       qp_attr->cap.max_inline_data = ROCE_REQ_MAX_INLINE_DATA_SIZE;
        qp_init_attr->cap = qp_attr->cap;
 
        memcpy(&qp_attr->ah_attr.grh.dgid.raw[0], &params.dgid.bytes[0],
@@ -2302,7 +2320,8 @@ int qedr_dereg_mr(struct ib_mr *ib_mr)
        return rc;
 }
 
-struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd, int max_page_list_len)
+static struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd,
+                                      int max_page_list_len)
 {
        struct qedr_pd *pd = get_qedr_pd(ibpd);
        struct qedr_dev *dev = get_qedr_dev(ibpd->device);
@@ -2704,7 +2723,7 @@ static int qedr_prepare_reg(struct qedr_qp *qp,
        return 0;
 }
 
-enum ib_wc_opcode qedr_ib_to_wc_opcode(enum ib_wr_opcode opcode)
+static enum ib_wc_opcode qedr_ib_to_wc_opcode(enum ib_wr_opcode opcode)
 {
        switch (opcode) {
        case IB_WR_RDMA_WRITE:
@@ -2729,7 +2748,7 @@ enum ib_wc_opcode qedr_ib_to_wc_opcode(enum ib_wr_opcode opcode)
        }
 }
 
-inline bool qedr_can_post_send(struct qedr_qp *qp, struct ib_send_wr *wr)
+static inline bool qedr_can_post_send(struct qedr_qp *qp, struct ib_send_wr *wr)
 {
        int wq_is_full, err_wr, pbl_is_full;
        struct qedr_dev *dev = qp->dev;
@@ -2766,7 +2785,7 @@ inline bool qedr_can_post_send(struct qedr_qp *qp, struct ib_send_wr *wr)
        return true;
 }
 
-int __qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+static int __qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                     struct ib_send_wr **bad_wr)
 {
        struct qedr_dev *dev = get_qedr_dev(ibqp->device);
@@ -3234,9 +3253,10 @@ static int qedr_poll_cq_req(struct qedr_dev *dev,
                                  IB_WC_SUCCESS, 0);
                break;
        case RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR:
-               DP_ERR(dev,
-                      "Error: POLL CQ with RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR. CQ icid=0x%x, QP icid=0x%x\n",
-                      cq->icid, qp->icid);
+               if (qp->state != QED_ROCE_QP_STATE_ERR)
+                       DP_ERR(dev,
+                              "Error: POLL CQ with RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR. CQ icid=0x%x, QP icid=0x%x\n",
+                              cq->icid, qp->icid);
                cnt = process_req(dev, qp, cq, num_entries, wc, req->sq_cons,
                                  IB_WC_WR_FLUSH_ERR, 1);
                break;
index 231a1ce1f4bec845d6ecfc58f53cd0d4ea5762a1..bd8fbd3d2032d390cc41268e7d32544ff0c98308 100644 (file)
@@ -1029,7 +1029,7 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
        if (ret) {
                dev_err(&pdev->dev, "failed to allocate interrupts\n");
                ret = -ENOMEM;
-               goto err_netdevice;
+               goto err_free_cq_ring;
        }
 
        /* Allocate UAR table. */
@@ -1092,8 +1092,6 @@ err_free_uar_table:
 err_free_intrs:
        pvrdma_free_irq(dev);
        pvrdma_disable_msi_all(dev);
-err_netdevice:
-       unregister_netdevice_notifier(&dev->nb_netdev);
 err_free_cq_ring:
        pvrdma_page_dir_cleanup(dev, &dev->cq_pdir);
 err_free_async_ring:
index 54891370d18a5beef151816c882b40fb705a9ec5..c2aa52638dcb81ea4539b61c43d61f55edefb2b3 100644 (file)
@@ -306,7 +306,7 @@ struct ib_ucontext *pvrdma_alloc_ucontext(struct ib_device *ibdev,
        union pvrdma_cmd_resp rsp;
        struct pvrdma_cmd_create_uc *cmd = &req.create_uc;
        struct pvrdma_cmd_create_uc_resp *resp = &rsp.create_uc_resp;
-       struct pvrdma_alloc_ucontext_resp uresp;
+       struct pvrdma_alloc_ucontext_resp uresp = {0};
        int ret;
        void *ptr;
 
index d0faca294006f4f53a40ebcf40839f9758b52c09..86a6585b847df90f07256dd4027eeab426be7f77 100644 (file)
@@ -59,9 +59,11 @@ int mem_check_range(struct rxe_mem *mem, u64 iova, size_t length)
 
        case RXE_MEM_TYPE_MR:
        case RXE_MEM_TYPE_FMR:
-               return ((iova < mem->iova) ||
-                       ((iova + length) > (mem->iova + mem->length))) ?
-                       -EFAULT : 0;
+               if (iova < mem->iova ||
+                   length > mem->length ||
+                   iova > mem->iova + mem->length - length)
+                       return -EFAULT;
+               return 0;
 
        default:
                return -EFAULT;
index 342e78163613dfdc719b171e1396d01fd44432eb..4abdeb359fb4f52cbacde5c3e1f488296c6064c5 100644 (file)
@@ -555,7 +555,7 @@ struct rxe_dev *rxe_net_add(struct net_device *ndev)
        }
 
        spin_lock_bh(&dev_list_lock);
-       list_add_tail(&rxe_dev_list, &rxe->list);
+       list_add_tail(&rxe->list, &rxe_dev_list);
        spin_unlock_bh(&dev_list_lock);
        return rxe;
 }
index 486d576e55bc016dda1f8ddad6b8f00941f66727..44b2108253bd988ec1f5222da999575ed37d3bed 100644 (file)
@@ -813,8 +813,7 @@ void rxe_qp_destroy(struct rxe_qp *qp)
        del_timer_sync(&qp->rnr_nak_timer);
 
        rxe_cleanup_task(&qp->req.task);
-       if (qp_type(qp) == IB_QPT_RC)
-               rxe_cleanup_task(&qp->comp.task);
+       rxe_cleanup_task(&qp->comp.task);
 
        /* flush out any receive wr's or pending requests */
        __rxe_do_task(&qp->req.task);
index 3435efff879960cece0c7e122b5960a057f2d4a1..5bcf073289729bd881960e8f797af1aa82e3b5bc 100644 (file)
@@ -479,7 +479,7 @@ static enum resp_states check_rkey(struct rxe_qp *qp,
                                goto err2;
                        }
 
-                       resid = mtu;
+                       qp->resp.resid = mtu;
                } else {
                        if (pktlen != resid) {
                                state = RESPST_ERR_LENGTH;
index 9104e6b8cac9f7b66322d7ebc573ab6a32fa525a..e71af717e71b0f5e6d82eb36b65d887c6005dc09 100644 (file)
@@ -651,13 +651,6 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
                                                   SHOST_DIX_GUARD_CRC);
                }
 
-               /*
-                * Limit the sg_tablesize and max_sectors based on the device
-                * max fastreg page list length.
-                */
-               shost->sg_tablesize = min_t(unsigned short, shost->sg_tablesize,
-                       ib_conn->device->ib_device->attrs.max_fast_reg_page_list_len);
-
                if (iscsi_host_add(shost,
                                   ib_conn->device->ib_device->dma_device)) {
                        mutex_unlock(&iser_conn->state_mutex);
@@ -679,6 +672,10 @@ iscsi_iser_session_create(struct iscsi_endpoint *ep,
        max_fr_sectors = ((shost->sg_tablesize - 1) * PAGE_SIZE) >> 9;
        shost->max_sectors = min(iser_max_sectors, max_fr_sectors);
 
+       iser_dbg("iser_conn %p, sg_tablesize %u, max_sectors %u\n",
+                iser_conn, shost->sg_tablesize,
+                shost->max_sectors);
+
        if (cmds_max > max_cmds) {
                iser_info("cmds_max changed from %u to %u\n",
                          cmds_max, max_cmds);
index 0be6a7c5ddb5aea294be7c10a8247895adbc2dde..9d0b22ad58c15759c3b92472083da15af5c42bac 100644 (file)
@@ -496,7 +496,6 @@ struct ib_conn {
  * @rx_descs:         rx buffers array (cyclic buffer)
  * @num_rx_descs:     number of rx descriptors
  * @scsi_sg_tablesize: scsi host sg_tablesize
- * @scsi_max_sectors: scsi host max sectors
  */
 struct iser_conn {
        struct ib_conn               ib_conn;
@@ -519,7 +518,6 @@ struct iser_conn {
        struct iser_rx_desc          *rx_descs;
        u32                          num_rx_descs;
        unsigned short               scsi_sg_tablesize;
-       unsigned int                 scsi_max_sectors;
        bool                         snd_w_inv;
 };
 
index 8ae7a3beddb728ee22825e28382b37bc467bbe94..6a9d1cb548ee8f7f34cfe1a1f9ad7c54de133271 100644 (file)
@@ -707,18 +707,7 @@ iser_calc_scsi_params(struct iser_conn *iser_conn,
        sup_sg_tablesize = min_t(unsigned, ISCSI_ISER_MAX_SG_TABLESIZE,
                                 device->ib_device->attrs.max_fast_reg_page_list_len);
 
-       if (sg_tablesize > sup_sg_tablesize) {
-               sg_tablesize = sup_sg_tablesize;
-               iser_conn->scsi_max_sectors = sg_tablesize * SIZE_4K / 512;
-       } else {
-               iser_conn->scsi_max_sectors = max_sectors;
-       }
-
-       iser_conn->scsi_sg_tablesize = sg_tablesize;
-
-       iser_dbg("iser_conn %p, sg_tablesize %u, max_sectors %u\n",
-                iser_conn, iser_conn->scsi_sg_tablesize,
-                iser_conn->scsi_max_sectors);
+       iser_conn->scsi_sg_tablesize = min(sg_tablesize, sup_sg_tablesize);
 }
 
 /**
index 8ddc071231931157ec459a6db4a0947d7b05f539..79bf48477ddb104097471a7a6040bcef2dfa0533 100644 (file)
@@ -371,6 +371,7 @@ static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
        struct srp_fr_desc *d;
        struct ib_mr *mr;
        int i, ret = -EINVAL;
+       enum ib_mr_type mr_type;
 
        if (pool_size <= 0)
                goto err;
@@ -384,9 +385,13 @@ static struct srp_fr_pool *srp_create_fr_pool(struct ib_device *device,
        spin_lock_init(&pool->lock);
        INIT_LIST_HEAD(&pool->free_list);
 
+       if (device->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)
+               mr_type = IB_MR_TYPE_SG_GAPS;
+       else
+               mr_type = IB_MR_TYPE_MEM_REG;
+
        for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
-               mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
-                                max_page_list_len);
+               mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
                if (IS_ERR(mr)) {
                        ret = PTR_ERR(mr);
                        if (ret == -ENOMEM)
@@ -3694,6 +3699,12 @@ static int __init srp_init_module(void)
                indirect_sg_entries = cmd_sg_entries;
        }
 
+       if (indirect_sg_entries > SG_MAX_SEGMENTS) {
+               pr_warn("Clamping indirect_sg_entries to %u\n",
+                       SG_MAX_SEGMENTS);
+               indirect_sg_entries = SG_MAX_SEGMENTS;
+       }
+
        srp_remove_wq = create_workqueue("srp_remove");
        if (!srp_remove_wq) {
                ret = -ENOMEM;
index f3135ae22df429c743c771c40c29d049869091f5..abd18f31b24f68e27c28f1120e52aa96b9347887 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/init.h>
index 6d949965867190458abaa653636ed4ab6702a4aa..c7d5b2b643d10798eb7da917f16888a2cff2bc3b 100644 (file)
@@ -1377,6 +1377,12 @@ static int xpad_init_input(struct usb_xpad *xpad)
        input_dev->name = xpad->name;
        input_dev->phys = xpad->phys;
        usb_to_input_id(xpad->udev, &input_dev->id);
+
+       if (xpad->xtype == XTYPE_XBOX360W) {
+               /* x360w controllers and the receiver have different ids */
+               input_dev->id.product = 0x02a1;
+       }
+
        input_dev->dev.parent = &xpad->intf->dev;
 
        input_set_drvdata(input_dev, xpad);
index a8b0a2eec344e863bd292251095a4e84f3a0b98b..7fed92fb8cc137c28e9e54a08d5bea4f1233ba08 100644 (file)
@@ -136,7 +136,6 @@ static const struct i2c_device_id adxl34x_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, adxl34x_id);
 
-#ifdef CONFIG_OF
 static const struct of_device_id adxl34x_of_id[] = {
        /*
         * The ADXL346 is backward-compatible with the ADXL345. Differences are
@@ -153,13 +152,12 @@ static const struct of_device_id adxl34x_of_id[] = {
 };
 
 MODULE_DEVICE_TABLE(of, adxl34x_of_id);
-#endif
 
 static struct i2c_driver adxl34x_driver = {
        .driver = {
                .name = "adxl34x",
                .pm = &adxl34x_i2c_pm,
-               .of_match_table = of_match_ptr(adxl34x_of_id),
+               .of_match_table = adxl34x_of_id,
        },
        .probe    = adxl34x_i2c_probe,
        .remove   = adxl34x_i2c_remove,
index 92595b98e7ede7b96dc4c9dd44f4629262f6e3a6..022be0e22eba97b10b95e653f48cee44f1d4ba36 100644 (file)
@@ -263,13 +263,21 @@ static int uinput_create_device(struct uinput_device *udev)
                return -EINVAL;
        }
 
-       if (test_bit(ABS_MT_SLOT, dev->absbit)) {
-               nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
-               error = input_mt_init_slots(dev, nslot, 0);
-               if (error)
+       if (test_bit(EV_ABS, dev->evbit)) {
+               input_alloc_absinfo(dev);
+               if (!dev->absinfo) {
+                       error = -EINVAL;
                        goto fail1;
-       } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
-               input_set_events_per_packet(dev, 60);
+               }
+
+               if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+                       nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+                       error = input_mt_init_slots(dev, nslot, 0);
+                       if (error)
+                               goto fail1;
+               } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+                       input_set_events_per_packet(dev, 60);
+               }
        }
 
        if (test_bit(EV_FF, dev->evbit) && !udev->ff_effects_max) {
index cde6f4bd8ea2e3f0f70fbccf3f684e5cd079ec04..6d279aa27cb9a10d70a2e732fe9599297883cbc0 100644 (file)
@@ -114,7 +114,7 @@ enum SS4_PACKET_ID {
                                 (_b[1] & 0x7F)         \
                                )
 
-#define SS4_TS_Y_V2(_b)                (s8)(                           \
+#define SS4_TS_Y_V2(_b)                -(s8)(                          \
                                 ((_b[3] & 0x01) << 7) |        \
                                 (_b[2] & 0x7F)         \
                                )
index fa598f7f4372c1ed0167b941a57a4b663a5361de..1e1d0ad406f2b7178bbb8cdcf1f320ade13ea0a1 100644 (file)
@@ -1231,6 +1231,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0000", 0 },
        { "ELAN0100", 0 },
        { "ELAN0600", 0 },
+       { "ELAN0605", 0 },
        { "ELAN1000", 0 },
        { }
 };
index aa7c5da608005cfb471279b484bcc46f39fe3c82..cb2bf203f4cabac152d8fedd13fe9ec55826f136 100644 (file)
@@ -29,7 +29,7 @@
  * after soft reset, we should wait for 1 ms
  * before the device becomes operational
  */
-#define SOFT_RESET_DELAY_MS    3
+#define SOFT_RESET_DELAY_US    3000
 /* and after hard reset, we should wait for max 500ms */
 #define HARD_RESET_DELAY_MS    500
 
@@ -311,7 +311,7 @@ static int synaptics_i2c_reset_config(struct i2c_client *client)
        if (ret) {
                dev_err(&client->dev, "Unable to reset device\n");
        } else {
-               msleep(SOFT_RESET_DELAY_MS);
+               usleep_range(SOFT_RESET_DELAY_US, SOFT_RESET_DELAY_US + 100);
                ret = synaptics_i2c_config(client);
                if (ret)
                        dev_err(&client->dev, "Unable to config device\n");
index 30cc627a4f4531ff93014ea94bf9835b0b37e8bc..bb7762bf2879b3a7383b2d326a859833adbbf360 100644 (file)
@@ -41,13 +41,20 @@ config RMI4_SMB
 
 config RMI4_F03
         bool "RMI4 Function 03 (PS2 Guest)"
-        depends on RMI4_CORE && SERIO
+       depends on RMI4_CORE
         help
           Say Y here if you want to add support for RMI4 function 03.
 
           Function 03 provides PS2 guest support for RMI4 devices. This
           includes support for TrackPoints on TouchPads.
 
+config RMI4_F03_SERIO
+       tristate
+       depends on RMI4_CORE
+       depends on RMI4_F03
+       default RMI4_CORE
+       select SERIO
+
 config RMI4_2D_SENSOR
        bool
        depends on RMI4_CORE
index 11447ab1055cd4beadf7eca752bdf9494d76cef1..bf5c36e229bacd63dd7e77d028aa65fb4555ce89 100644 (file)
@@ -901,7 +901,7 @@ void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake)
        data->enabled = true;
        if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
                retval = disable_irq_wake(irq);
-               if (!retval)
+               if (retval)
                        dev_warn(&rmi_dev->dev,
                                 "Failed to disable irq for wake: %d\n",
                                 retval);
@@ -936,7 +936,7 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
        disable_irq(irq);
        if (enable_wake && device_may_wakeup(rmi_dev->xport->dev)) {
                retval = enable_irq_wake(irq);
-               if (!retval)
+               if (retval)
                        dev_warn(&rmi_dev->dev,
                                 "Failed to enable irq for wake: %d\n",
                                 retval);
index 77551f52220275c0589419ced9f7037cc11062b0..a7618776705ab929e42d4c3e870b4911f1a30d9c 100644 (file)
@@ -211,6 +211,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+               },
+       },
        { }
 };
 
index 02aec284decac37b1a93b16b609007c077db7f98..3e6003d32e565c748a43730574b9424eeb294d33 100644 (file)
@@ -914,9 +914,9 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
 
                case QUEUE_HEADER_NORMAL:
                        report_count = ts->buf[FW_HDR_COUNT];
-                       if (report_count > 3) {
+                       if (report_count == 0 || report_count > 3) {
                                dev_err(&client->dev,
-                                       "too large report count: %*ph\n",
+                                       "bad report count: %*ph\n",
                                        HEADER_SIZE, ts->buf);
                                break;
                        }
index 83cf11312fd971e0cacc16bd70eb474dd9c13b52..c9d1c91e1887094f2ef740d9eee3af8d16ee6f82 100644 (file)
@@ -682,7 +682,7 @@ static int wm97xx_probe(struct device *dev)
        }
        platform_set_drvdata(wm->battery_dev, wm);
        wm->battery_dev->dev.parent = dev;
-       wm->battery_dev->dev.platform_data = pdata->batt_pdata;
+       wm->battery_dev->dev.platform_data = pdata ? pdata->batt_pdata : NULL;
        ret = platform_device_add(wm->battery_dev);
        if (ret < 0)
                goto batt_reg_err;
index 019e02707cd5e3c893b3b6602a1847260b3ba401..3ef0f42984f2b1ec716509203988f9ebb70533cb 100644 (file)
@@ -1023,7 +1023,7 @@ again:
        next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
        left      = (head - next_tail) % CMD_BUFFER_SIZE;
 
-       if (left <= 2) {
+       if (left <= 0x20) {
                struct iommu_cmd sync_cmd;
                int ret;
 
index a88576d50740b2dbdbe6e65b2bfe1985f01c81ca..8ccbd7023194ee592fa91dafb67565d1ad9928aa 100644 (file)
@@ -903,8 +903,10 @@ int __init detect_intel_iommu(void)
                x86_init.iommu.iommu_init = intel_iommu_init;
 #endif
 
-       acpi_put_table(dmar_tbl);
-       dmar_tbl = NULL;
+       if (dmar_tbl) {
+               acpi_put_table(dmar_tbl);
+               dmar_tbl = NULL;
+       }
        up_write(&dmar_global_lock);
 
        return ret ? 1 : -ENODEV;
index c66c273dfd8ab1058030433961fcfaaf2046f846..8a185250ae5a5923d8ab9f34d811caa0f5e09b79 100644 (file)
@@ -2037,6 +2037,25 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
        if (context_present(context))
                goto out_unlock;
 
+       /*
+        * For kdump cases, old valid entries may be cached due to the
+        * in-flight DMA and copied pgtable, but there is no unmapping
+        * behaviour for them, thus we need an explicit cache flush for
+        * the newly-mapped device. For kdump, at this point, the device
+        * is supposed to finish reset at its driver probe stage, so no
+        * in-flight DMA will exist, and we don't need to worry anymore
+        * hereafter.
+        */
+       if (context_copied(context)) {
+               u16 did_old = context_domain_id(context);
+
+               if (did_old >= 0 && did_old < cap_ndoms(iommu->cap))
+                       iommu->flush.flush_context(iommu, did_old,
+                                                  (((u16)bus) << 8) | devfn,
+                                                  DMA_CCMD_MASK_NOBIT,
+                                                  DMA_CCMD_DEVICE_INVL);
+       }
+
        pgd = domain->pgd;
 
        context_clear_entry(context);
@@ -5185,6 +5204,25 @@ static void intel_iommu_remove_device(struct device *dev)
 }
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
+#define MAX_NR_PASID_BITS (20)
+static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu)
+{
+       /*
+        * Convert ecap_pss to extend context entry pts encoding, also
+        * respect the soft pasid_max value set by the iommu.
+        * - number of PASID bits = ecap_pss + 1
+        * - number of PASID table entries = 2^(pts + 5)
+        * Therefore, pts = ecap_pss - 4
+        * e.g. KBL ecap_pss = 0x13, PASID has 20 bits, pts = 15
+        */
+       if (ecap_pss(iommu->ecap) < 5)
+               return 0;
+
+       /* pasid_max is encoded as actual number of entries not the bits */
+       return find_first_bit((unsigned long *)&iommu->pasid_max,
+                       MAX_NR_PASID_BITS) - 5;
+}
+
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
 {
        struct device_domain_info *info;
@@ -5217,7 +5255,9 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd
 
        if (!(ctx_lo & CONTEXT_PASIDE)) {
                context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
-               context[1].lo = (u64)virt_to_phys(iommu->pasid_table) | ecap_pss(iommu->ecap);
+               context[1].lo = (u64)virt_to_phys(iommu->pasid_table) |
+                       intel_iommu_get_pts(iommu);
+
                wmb();
                /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
                 * extended to permit requests-with-PASID if the PASIDE bit
index 54a5e870a8f56d627f9622a4a9fb03e07347aa0a..efbcf8435185244cfbfac87f3f36661d88a13ceb 100644 (file)
@@ -19,9 +19,9 @@
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/syscon.h>
@@ -39,6 +39,7 @@ struct keystone_irq_device {
        struct irq_domain       *irqd;
        struct regmap           *devctrl_regs;
        u32                     devctrl_offset;
+       raw_spinlock_t          wa_lock;
 };
 
 static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq)
@@ -83,17 +84,15 @@ static void keystone_irq_ack(struct irq_data *d)
        /* nothing to do here */
 }
 
-static void keystone_irq_handler(struct irq_desc *desc)
+static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
-       struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc);
+       struct keystone_irq_device *kirq = keystone_irq;
+       unsigned long wa_lock_flags;
        unsigned long pending;
        int src, virq;
 
        dev_dbg(kirq->dev, "start irq %d\n", irq);
 
-       chained_irq_enter(irq_desc_get_chip(desc), desc);
-
        pending = keystone_irq_readl(kirq);
        keystone_irq_writel(kirq, pending);
 
@@ -111,13 +110,15 @@ static void keystone_irq_handler(struct irq_desc *desc)
                        if (!virq)
                                dev_warn(kirq->dev, "spurious irq detected hwirq %d, virq %d\n",
                                         src, virq);
+                       raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags);
                        generic_handle_irq(virq);
+                       raw_spin_unlock_irqrestore(&kirq->wa_lock,
+                                                  wa_lock_flags);
                }
        }
 
-       chained_irq_exit(irq_desc_get_chip(desc), desc);
-
        dev_dbg(kirq->dev, "end irq %d\n", irq);
+       return IRQ_HANDLED;
 }
 
 static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
@@ -182,9 +183,16 @@ static int keystone_irq_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       raw_spin_lock_init(&kirq->wa_lock);
+
        platform_set_drvdata(pdev, kirq);
 
-       irq_set_chained_handler_and_data(kirq->irq, keystone_irq_handler, kirq);
+       ret = request_irq(kirq->irq, keystone_irq_handler,
+                         0, dev_name(dev), kirq);
+       if (ret) {
+               irq_domain_remove(kirq->irqd);
+               return ret;
+       }
 
        /* clear all source bits */
        keystone_irq_writel(kirq, ~0x0);
@@ -199,6 +207,8 @@ static int keystone_irq_remove(struct platform_device *pdev)
        struct keystone_irq_device *kirq = platform_get_drvdata(pdev);
        int hwirq;
 
+       free_irq(kirq->irq, kirq);
+
        for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++)
                irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq));
 
index 17304705f2cf9443b99690565ece5b537e3e61c4..05fa9f7af53cd78732802dfbec28c27770e6f01f 100644 (file)
@@ -131,12 +131,16 @@ static struct irq_chip mxs_icoll_chip = {
        .irq_ack = icoll_ack_irq,
        .irq_mask = icoll_mask_irq,
        .irq_unmask = icoll_unmask_irq,
+       .flags = IRQCHIP_MASK_ON_SUSPEND |
+                IRQCHIP_SKIP_SET_WAKE,
 };
 
 static struct irq_chip asm9260_icoll_chip = {
        .irq_ack = icoll_ack_irq,
        .irq_mask = asm9260_mask_irq,
        .irq_unmask = asm9260_unmask_irq,
+       .flags = IRQCHIP_MASK_ON_SUSPEND |
+                IRQCHIP_SKIP_SET_WAKE,
 };
 
 asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
index 1a1d99704fe694ad2f0c19933fdfc7df89803da9..296f1411fe84208d8c2511b8866d3f6936f8254a 100644 (file)
@@ -11297,7 +11297,8 @@ static void mixer_notify_update(PLCI *plci, byte others)
                                ((CAPI_MSG *) msg)->header.ncci = 0;
                                ((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
                                ((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
-                               PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
+                               ((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
+                               ((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
                                ((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
                                w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
                                if (w != _QUEUE_FULL)
index 7c6c57216bf29f301690d270ca5f05a55dea3d3f..8a9f742d8ed72c810d49115ff802706d2b9d7e7f 100644 (file)
@@ -1534,18 +1534,18 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
                return PTR_ERR(key);
        }
 
-       rcu_read_lock();
+       down_read(&key->sem);
 
        ukp = user_key_payload(key);
        if (!ukp) {
-               rcu_read_unlock();
+               up_read(&key->sem);
                key_put(key);
                kzfree(new_key_string);
                return -EKEYREVOKED;
        }
 
        if (cc->key_size != ukp->datalen) {
-               rcu_read_unlock();
+               up_read(&key->sem);
                key_put(key);
                kzfree(new_key_string);
                return -EINVAL;
@@ -1553,7 +1553,7 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
 
        memcpy(cc->key, ukp->data, cc->key_size);
 
-       rcu_read_unlock();
+       up_read(&key->sem);
        key_put(key);
 
        /* clear the flag since following operations may invalidate previously valid key */
index 6400cffb986df21be7289dce8d2a4d4ff228a9a2..3570bcb7a4a4e5cade63c39b9071ed610da1e4ae 100644 (file)
@@ -427,7 +427,7 @@ static struct pgpath *choose_pgpath(struct multipath *m, size_t nr_bytes)
        unsigned long flags;
        struct priority_group *pg;
        struct pgpath *pgpath;
-       bool bypassed = true;
+       unsigned bypassed = 1;
 
        if (!atomic_read(&m->nr_valid_paths)) {
                clear_bit(MPATHF_QUEUE_IO, &m->flags);
@@ -466,7 +466,7 @@ check_current_pg:
         */
        do {
                list_for_each_entry(pg, &m->priority_groups, list) {
-                       if (pg->bypassed == bypassed)
+                       if (pg->bypassed == !!bypassed)
                                continue;
                        pgpath = choose_path_in_pg(m, pg, nr_bytes);
                        if (!IS_ERR_OR_NULL(pgpath)) {
index 9d7275fb541ad422b171cbe0ee43335e3e1efc27..6e702fc69a83cb27f6bc1792d4871ad18d708f71 100644 (file)
@@ -779,6 +779,10 @@ static void dm_old_request_fn(struct request_queue *q)
                int srcu_idx;
                struct dm_table *map = dm_get_live_table(md, &srcu_idx);
 
+               if (unlikely(!map)) {
+                       dm_put_live_table(md, srcu_idx);
+                       return;
+               }
                ti = dm_table_find_target(map, pos);
                dm_put_live_table(md, srcu_idx);
        }
index 82821ee0d57fac691d26e0c3f41c2ba31bb611fc..01175dac0db6361f04cd1bcad910a59202cc276d 100644 (file)
@@ -5291,6 +5291,11 @@ int md_run(struct mddev *mddev)
        if (start_readonly && mddev->ro == 0)
                mddev->ro = 2; /* read-only, but switch on first write */
 
+       /*
+        * NOTE: some pers->run(), for example r5l_recovery_log(), wakes
+        * up mddev->thread. It is important to initialize critical
+        * resources for mddev->thread BEFORE calling pers->run().
+        */
        err = pers->run(mddev);
        if (err)
                pr_warn("md: pers->run() failed ...\n");
index e38936d05df18fa20564c0ed7e8093e3b377fd81..2a514036a83dc0da07c0966b7fe247c18356bbbf 100644 (file)
@@ -212,6 +212,7 @@ extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
                                int is_new);
 struct md_cluster_info;
 
+/* change UNSUPPORTED_MDDEV_FLAGS for each array type if new flag is added */
 enum mddev_flags {
        MD_ARRAY_FIRST_USE,     /* First use of array, needs initialization */
        MD_CLOSING,             /* If set, we are closing the array, do not open
@@ -702,4 +703,11 @@ static inline int mddev_is_clustered(struct mddev *mddev)
 {
        return mddev->cluster_info && mddev->bitmap_info.nodes > 1;
 }
+
+/* clear unsupported mddev_flags */
+static inline void mddev_clear_unsupported_flags(struct mddev *mddev,
+       unsigned long unsupported_flags)
+{
+       mddev->flags &= ~unsupported_flags;
+}
 #endif /* _MD_MD_H */
index a162fedeb51a48ce31d18fbca5a51a0fe9204bf4..848365d474f3a3bca26168ac3619f2c52edd7618 100644 (file)
 #include "raid0.h"
 #include "raid5.h"
 
+#define UNSUPPORTED_MDDEV_FLAGS                \
+       ((1L << MD_HAS_JOURNAL) |       \
+        (1L << MD_JOURNAL_CLEAN) |     \
+        (1L << MD_FAILFAST_SUPPORTED))
+
 static int raid0_congested(struct mddev *mddev, int bits)
 {
        struct r0conf *conf = mddev->private;
@@ -539,8 +544,7 @@ static void *raid0_takeover_raid45(struct mddev *mddev)
        mddev->delta_disks = -1;
        /* make sure it will be not marked as dirty */
        mddev->recovery_cp = MaxSector;
-       clear_bit(MD_HAS_JOURNAL, &mddev->flags);
-       clear_bit(MD_JOURNAL_CLEAN, &mddev->flags);
+       mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
 
        create_strip_zones(mddev, &priv_conf);
 
@@ -583,7 +587,7 @@ static void *raid0_takeover_raid10(struct mddev *mddev)
        mddev->degraded = 0;
        /* make sure it will be not marked as dirty */
        mddev->recovery_cp = MaxSector;
-       clear_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
+       mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
 
        create_strip_zones(mddev, &priv_conf);
        return priv_conf;
@@ -626,7 +630,7 @@ static void *raid0_takeover_raid1(struct mddev *mddev)
        mddev->raid_disks = 1;
        /* make sure it will be not marked as dirty */
        mddev->recovery_cp = MaxSector;
-       clear_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
+       mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
 
        create_strip_zones(mddev, &priv_conf);
        return priv_conf;
index a1f3fbed91009c5aa3253109d82db8eed38a2720..7b0f647bcccb513b6650136cddd51bc0ebec796a 100644 (file)
 #include "raid1.h"
 #include "bitmap.h"
 
+#define UNSUPPORTED_MDDEV_FLAGS                \
+       ((1L << MD_HAS_JOURNAL) |       \
+        (1L << MD_JOURNAL_CLEAN))
+
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
@@ -1066,17 +1070,107 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
        kfree(plug);
 }
 
-static void raid1_make_request(struct mddev *mddev, struct bio * bio)
+static void raid1_read_request(struct mddev *mddev, struct bio *bio,
+                                struct r1bio *r1_bio)
 {
        struct r1conf *conf = mddev->private;
        struct raid1_info *mirror;
-       struct r1bio *r1_bio;
        struct bio *read_bio;
+       struct bitmap *bitmap = mddev->bitmap;
+       const int op = bio_op(bio);
+       const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
+       int sectors_handled;
+       int max_sectors;
+       int rdisk;
+
+       wait_barrier(conf, bio);
+
+read_again:
+       rdisk = read_balance(conf, r1_bio, &max_sectors);
+
+       if (rdisk < 0) {
+               /* couldn't find anywhere to read from */
+               raid_end_bio_io(r1_bio);
+               return;
+       }
+       mirror = conf->mirrors + rdisk;
+
+       if (test_bit(WriteMostly, &mirror->rdev->flags) &&
+           bitmap) {
+               /*
+                * Reading from a write-mostly device must take care not to
+                * over-take any writes that are 'behind'
+                */
+               raid1_log(mddev, "wait behind writes");
+               wait_event(bitmap->behind_wait,
+                          atomic_read(&bitmap->behind_writes) == 0);
+       }
+       r1_bio->read_disk = rdisk;
+       r1_bio->start_next_window = 0;
+
+       read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+       bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
+                max_sectors);
+
+       r1_bio->bios[rdisk] = read_bio;
+
+       read_bio->bi_iter.bi_sector = r1_bio->sector +
+               mirror->rdev->data_offset;
+       read_bio->bi_bdev = mirror->rdev->bdev;
+       read_bio->bi_end_io = raid1_end_read_request;
+       bio_set_op_attrs(read_bio, op, do_sync);
+       if (test_bit(FailFast, &mirror->rdev->flags) &&
+           test_bit(R1BIO_FailFast, &r1_bio->state))
+               read_bio->bi_opf |= MD_FAILFAST;
+       read_bio->bi_private = r1_bio;
+
+       if (mddev->gendisk)
+               trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
+                                     read_bio, disk_devt(mddev->gendisk),
+                                     r1_bio->sector);
+
+       if (max_sectors < r1_bio->sectors) {
+               /*
+                * could not read all from this device, so we will need another
+                * r1_bio.
+                */
+               sectors_handled = (r1_bio->sector + max_sectors
+                                  - bio->bi_iter.bi_sector);
+               r1_bio->sectors = max_sectors;
+               spin_lock_irq(&conf->device_lock);
+               if (bio->bi_phys_segments == 0)
+                       bio->bi_phys_segments = 2;
+               else
+                       bio->bi_phys_segments++;
+               spin_unlock_irq(&conf->device_lock);
+
+               /*
+                * Cannot call generic_make_request directly as that will be
+                * queued in __make_request and subsequent mempool_alloc might
+                * block waiting for it.  So hand bio over to raid1d.
+                */
+               reschedule_retry(r1_bio);
+
+               r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+
+               r1_bio->master_bio = bio;
+               r1_bio->sectors = bio_sectors(bio) - sectors_handled;
+               r1_bio->state = 0;
+               r1_bio->mddev = mddev;
+               r1_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
+               goto read_again;
+       } else
+               generic_make_request(read_bio);
+}
+
+static void raid1_write_request(struct mddev *mddev, struct bio *bio,
+                               struct r1bio *r1_bio)
+{
+       struct r1conf *conf = mddev->private;
        int i, disks;
-       struct bitmap *bitmap;
+       struct bitmap *bitmap = mddev->bitmap;
        unsigned long flags;
        const int op = bio_op(bio);
-       const int rw = bio_data_dir(bio);
        const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
        const unsigned long do_flush_fua = (bio->bi_opf &
                                                (REQ_PREFLUSH | REQ_FUA));
@@ -1096,15 +1190,15 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio)
 
        md_write_start(mddev, bio); /* wait on superblock update early */
 
-       if (bio_data_dir(bio) == WRITE &&
-           ((bio_end_sector(bio) > mddev->suspend_lo &&
+       if ((bio_end_sector(bio) > mddev->suspend_lo &&
            bio->bi_iter.bi_sector < mddev->suspend_hi) ||
            (mddev_is_clustered(mddev) &&
             md_cluster_ops->area_resyncing(mddev, WRITE,
-                    bio->bi_iter.bi_sector, bio_end_sector(bio))))) {
-               /* As the suspend_* range is controlled by
-                * userspace, we want an interruptible
-                * wait.
+                    bio->bi_iter.bi_sector, bio_end_sector(bio)))) {
+
+               /*
+                * As the suspend_* range is controlled by userspace, we want
+                * an interruptible wait.
                 */
                DEFINE_WAIT(w);
                for (;;) {
@@ -1115,128 +1209,15 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio)
                            bio->bi_iter.bi_sector >= mddev->suspend_hi ||
                            (mddev_is_clustered(mddev) &&
                             !md_cluster_ops->area_resyncing(mddev, WRITE,
-                                    bio->bi_iter.bi_sector, bio_end_sector(bio))))
+                                    bio->bi_iter.bi_sector,
+                                    bio_end_sector(bio))))
                                break;
                        schedule();
                }
                finish_wait(&conf->wait_barrier, &w);
        }
-
        start_next_window = wait_barrier(conf, bio);
 
-       bitmap = mddev->bitmap;
-
-       /*
-        * make_request() can abort the operation when read-ahead is being
-        * used and no empty request is available.
-        *
-        */
-       r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
-
-       r1_bio->master_bio = bio;
-       r1_bio->sectors = bio_sectors(bio);
-       r1_bio->state = 0;
-       r1_bio->mddev = mddev;
-       r1_bio->sector = bio->bi_iter.bi_sector;
-
-       /* We might need to issue multiple reads to different
-        * devices if there are bad blocks around, so we keep
-        * track of the number of reads in bio->bi_phys_segments.
-        * If this is 0, there is only one r1_bio and no locking
-        * will be needed when requests complete.  If it is
-        * non-zero, then it is the number of not-completed requests.
-        */
-       bio->bi_phys_segments = 0;
-       bio_clear_flag(bio, BIO_SEG_VALID);
-
-       if (rw == READ) {
-               /*
-                * read balancing logic:
-                */
-               int rdisk;
-
-read_again:
-               rdisk = read_balance(conf, r1_bio, &max_sectors);
-
-               if (rdisk < 0) {
-                       /* couldn't find anywhere to read from */
-                       raid_end_bio_io(r1_bio);
-                       return;
-               }
-               mirror = conf->mirrors + rdisk;
-
-               if (test_bit(WriteMostly, &mirror->rdev->flags) &&
-                   bitmap) {
-                       /* Reading from a write-mostly device must
-                        * take care not to over-take any writes
-                        * that are 'behind'
-                        */
-                       raid1_log(mddev, "wait behind writes");
-                       wait_event(bitmap->behind_wait,
-                                  atomic_read(&bitmap->behind_writes) == 0);
-               }
-               r1_bio->read_disk = rdisk;
-               r1_bio->start_next_window = 0;
-
-               read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
-                        max_sectors);
-
-               r1_bio->bios[rdisk] = read_bio;
-
-               read_bio->bi_iter.bi_sector = r1_bio->sector +
-                       mirror->rdev->data_offset;
-               read_bio->bi_bdev = mirror->rdev->bdev;
-               read_bio->bi_end_io = raid1_end_read_request;
-               bio_set_op_attrs(read_bio, op, do_sync);
-               if (test_bit(FailFast, &mirror->rdev->flags) &&
-                   test_bit(R1BIO_FailFast, &r1_bio->state))
-                       read_bio->bi_opf |= MD_FAILFAST;
-               read_bio->bi_private = r1_bio;
-
-               if (mddev->gendisk)
-                       trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
-                                             read_bio, disk_devt(mddev->gendisk),
-                                             r1_bio->sector);
-
-               if (max_sectors < r1_bio->sectors) {
-                       /* could not read all from this device, so we will
-                        * need another r1_bio.
-                        */
-
-                       sectors_handled = (r1_bio->sector + max_sectors
-                                          - bio->bi_iter.bi_sector);
-                       r1_bio->sectors = max_sectors;
-                       spin_lock_irq(&conf->device_lock);
-                       if (bio->bi_phys_segments == 0)
-                               bio->bi_phys_segments = 2;
-                       else
-                               bio->bi_phys_segments++;
-                       spin_unlock_irq(&conf->device_lock);
-                       /* Cannot call generic_make_request directly
-                        * as that will be queued in __make_request
-                        * and subsequent mempool_alloc might block waiting
-                        * for it.  So hand bio over to raid1d.
-                        */
-                       reschedule_retry(r1_bio);
-
-                       r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
-
-                       r1_bio->master_bio = bio;
-                       r1_bio->sectors = bio_sectors(bio) - sectors_handled;
-                       r1_bio->state = 0;
-                       r1_bio->mddev = mddev;
-                       r1_bio->sector = bio->bi_iter.bi_sector +
-                               sectors_handled;
-                       goto read_again;
-               } else
-                       generic_make_request(read_bio);
-               return;
-       }
-
-       /*
-        * WRITE:
-        */
        if (conf->pending_count >= max_queued_requests) {
                md_wakeup_thread(mddev->thread);
                raid1_log(mddev, "wait queued");
@@ -1280,8 +1261,7 @@ read_again:
                        int bad_sectors;
                        int is_bad;
 
-                       is_bad = is_badblock(rdev, r1_bio->sector,
-                                            max_sectors,
+                       is_bad = is_badblock(rdev, r1_bio->sector, max_sectors,
                                             &first_bad, &bad_sectors);
                        if (is_bad < 0) {
                                /* mustn't write here until the bad block is
@@ -1370,7 +1350,8 @@ read_again:
                        continue;
 
                mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector, max_sectors);
+               bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector,
+                        max_sectors);
 
                if (first_clone) {
                        /* do behind I/O ?
@@ -1464,6 +1445,40 @@ read_again:
        wake_up(&conf->wait_barrier);
 }
 
+static void raid1_make_request(struct mddev *mddev, struct bio *bio)
+{
+       struct r1conf *conf = mddev->private;
+       struct r1bio *r1_bio;
+
+       /*
+        * make_request() can abort the operation when read-ahead is being
+        * used and no empty request is available.
+        *
+        */
+       r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+
+       r1_bio->master_bio = bio;
+       r1_bio->sectors = bio_sectors(bio);
+       r1_bio->state = 0;
+       r1_bio->mddev = mddev;
+       r1_bio->sector = bio->bi_iter.bi_sector;
+
+       /*
+        * We might need to issue multiple reads to different devices if there
+        * are bad blocks around, so we keep track of the number of reads in
+        * bio->bi_phys_segments.  If this is 0, there is only one r1_bio and
+        * no locking will be needed when requests complete.  If it is
+        * non-zero, then it is the number of not-completed requests.
+        */
+       bio->bi_phys_segments = 0;
+       bio_clear_flag(bio, BIO_SEG_VALID);
+
+       if (bio_data_dir(bio) == READ)
+               raid1_read_request(mddev, bio, r1_bio);
+       else
+               raid1_write_request(mddev, bio, r1_bio);
+}
+
 static void raid1_status(struct seq_file *seq, struct mddev *mddev)
 {
        struct r1conf *conf = mddev->private;
@@ -3246,8 +3261,8 @@ static void *raid1_takeover(struct mddev *mddev)
                if (!IS_ERR(conf)) {
                        /* Array must appear to be quiesced */
                        conf->array_frozen = 1;
-                       clear_bit(MD_HAS_JOURNAL, &mddev->flags);
-                       clear_bit(MD_JOURNAL_CLEAN, &mddev->flags);
+                       mddev_clear_unsupported_flags(mddev,
+                               UNSUPPORTED_MDDEV_FLAGS);
                }
                return conf;
        }
index ab5e86209322fc0d0ed3e2db18a468c6f5054f13..1920756828dfb3fd512e2cb5705f329f10324698 100644 (file)
@@ -1087,23 +1087,122 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
        kfree(plug);
 }
 
-static void __make_request(struct mddev *mddev, struct bio *bio)
+static void raid10_read_request(struct mddev *mddev, struct bio *bio,
+                               struct r10bio *r10_bio)
 {
        struct r10conf *conf = mddev->private;
-       struct r10bio *r10_bio;
        struct bio *read_bio;
+       const int op = bio_op(bio);
+       const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
+       int sectors_handled;
+       int max_sectors;
+       sector_t sectors;
+       struct md_rdev *rdev;
+       int slot;
+
+       /*
+        * Register the new request and wait if the reconstruction
+        * thread has put up a bar for new requests.
+        * Continue immediately if no resync is active currently.
+        */
+       wait_barrier(conf);
+
+       sectors = bio_sectors(bio);
+       while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+           bio->bi_iter.bi_sector < conf->reshape_progress &&
+           bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
+               /*
+                * IO spans the reshape position.  Need to wait for reshape to
+                * pass
+                */
+               raid10_log(conf->mddev, "wait reshape");
+               allow_barrier(conf);
+               wait_event(conf->wait_barrier,
+                          conf->reshape_progress <= bio->bi_iter.bi_sector ||
+                          conf->reshape_progress >= bio->bi_iter.bi_sector +
+                          sectors);
+               wait_barrier(conf);
+       }
+
+read_again:
+       rdev = read_balance(conf, r10_bio, &max_sectors);
+       if (!rdev) {
+               raid_end_bio_io(r10_bio);
+               return;
+       }
+       slot = r10_bio->read_slot;
+
+       read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+       bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
+                max_sectors);
+
+       r10_bio->devs[slot].bio = read_bio;
+       r10_bio->devs[slot].rdev = rdev;
+
+       read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
+               choose_data_offset(r10_bio, rdev);
+       read_bio->bi_bdev = rdev->bdev;
+       read_bio->bi_end_io = raid10_end_read_request;
+       bio_set_op_attrs(read_bio, op, do_sync);
+       if (test_bit(FailFast, &rdev->flags) &&
+           test_bit(R10BIO_FailFast, &r10_bio->state))
+               read_bio->bi_opf |= MD_FAILFAST;
+       read_bio->bi_private = r10_bio;
+
+       if (mddev->gendisk)
+               trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
+                                     read_bio, disk_devt(mddev->gendisk),
+                                     r10_bio->sector);
+       if (max_sectors < r10_bio->sectors) {
+               /*
+                * Could not read all from this device, so we will need another
+                * r10_bio.
+                */
+               sectors_handled = (r10_bio->sector + max_sectors
+                                  - bio->bi_iter.bi_sector);
+               r10_bio->sectors = max_sectors;
+               spin_lock_irq(&conf->device_lock);
+               if (bio->bi_phys_segments == 0)
+                       bio->bi_phys_segments = 2;
+               else
+                       bio->bi_phys_segments++;
+               spin_unlock_irq(&conf->device_lock);
+               /*
+                * Cannot call generic_make_request directly as that will be
+                * queued in __generic_make_request and subsequent
+                * mempool_alloc might block waiting for it.  so hand bio over
+                * to raid10d.
+                */
+               reschedule_retry(r10_bio);
+
+               r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+               r10_bio->master_bio = bio;
+               r10_bio->sectors = bio_sectors(bio) - sectors_handled;
+               r10_bio->state = 0;
+               r10_bio->mddev = mddev;
+               r10_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
+               goto read_again;
+       } else
+               generic_make_request(read_bio);
+       return;
+}
+
+static void raid10_write_request(struct mddev *mddev, struct bio *bio,
+                                struct r10bio *r10_bio)
+{
+       struct r10conf *conf = mddev->private;
        int i;
        const int op = bio_op(bio);
-       const int rw = bio_data_dir(bio);
        const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
        const unsigned long do_fua = (bio->bi_opf & REQ_FUA);
        unsigned long flags;
        struct md_rdev *blocked_rdev;
        struct blk_plug_cb *cb;
        struct raid10_plug_cb *plug = NULL;
+       sector_t sectors;
        int sectors_handled;
        int max_sectors;
-       int sectors;
 
        md_write_start(mddev, bio);
 
@@ -1118,8 +1217,9 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
        while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
            bio->bi_iter.bi_sector < conf->reshape_progress &&
            bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
-               /* IO spans the reshape position.  Need to wait for
-                * reshape to pass
+               /*
+                * IO spans the reshape position.  Need to wait for reshape to
+                * pass
                 */
                raid10_log(conf->mddev, "wait reshape");
                allow_barrier(conf);
@@ -1129,8 +1229,8 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
                           sectors);
                wait_barrier(conf);
        }
+
        if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
-           bio_data_dir(bio) == WRITE &&
            (mddev->reshape_backwards
             ? (bio->bi_iter.bi_sector < conf->reshape_safe &&
                bio->bi_iter.bi_sector + sectors > conf->reshape_progress)
@@ -1148,98 +1248,6 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
                conf->reshape_safe = mddev->reshape_position;
        }
 
-       r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
-
-       r10_bio->master_bio = bio;
-       r10_bio->sectors = sectors;
-
-       r10_bio->mddev = mddev;
-       r10_bio->sector = bio->bi_iter.bi_sector;
-       r10_bio->state = 0;
-
-       /* We might need to issue multiple reads to different
-        * devices if there are bad blocks around, so we keep
-        * track of the number of reads in bio->bi_phys_segments.
-        * If this is 0, there is only one r10_bio and no locking
-        * will be needed when the request completes.  If it is
-        * non-zero, then it is the number of not-completed requests.
-        */
-       bio->bi_phys_segments = 0;
-       bio_clear_flag(bio, BIO_SEG_VALID);
-
-       if (rw == READ) {
-               /*
-                * read balancing logic:
-                */
-               struct md_rdev *rdev;
-               int slot;
-
-read_again:
-               rdev = read_balance(conf, r10_bio, &max_sectors);
-               if (!rdev) {
-                       raid_end_bio_io(r10_bio);
-                       return;
-               }
-               slot = r10_bio->read_slot;
-
-               read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
-                        max_sectors);
-
-               r10_bio->devs[slot].bio = read_bio;
-               r10_bio->devs[slot].rdev = rdev;
-
-               read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
-                       choose_data_offset(r10_bio, rdev);
-               read_bio->bi_bdev = rdev->bdev;
-               read_bio->bi_end_io = raid10_end_read_request;
-               bio_set_op_attrs(read_bio, op, do_sync);
-               if (test_bit(FailFast, &rdev->flags) &&
-                   test_bit(R10BIO_FailFast, &r10_bio->state))
-                       read_bio->bi_opf |= MD_FAILFAST;
-               read_bio->bi_private = r10_bio;
-
-               if (mddev->gendisk)
-                       trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
-                                             read_bio, disk_devt(mddev->gendisk),
-                                             r10_bio->sector);
-               if (max_sectors < r10_bio->sectors) {
-                       /* Could not read all from this device, so we will
-                        * need another r10_bio.
-                        */
-                       sectors_handled = (r10_bio->sector + max_sectors
-                                          - bio->bi_iter.bi_sector);
-                       r10_bio->sectors = max_sectors;
-                       spin_lock_irq(&conf->device_lock);
-                       if (bio->bi_phys_segments == 0)
-                               bio->bi_phys_segments = 2;
-                       else
-                               bio->bi_phys_segments++;
-                       spin_unlock_irq(&conf->device_lock);
-                       /* Cannot call generic_make_request directly
-                        * as that will be queued in __generic_make_request
-                        * and subsequent mempool_alloc might block
-                        * waiting for it.  so hand bio over to raid10d.
-                        */
-                       reschedule_retry(r10_bio);
-
-                       r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
-
-                       r10_bio->master_bio = bio;
-                       r10_bio->sectors = bio_sectors(bio) - sectors_handled;
-                       r10_bio->state = 0;
-                       r10_bio->mddev = mddev;
-                       r10_bio->sector = bio->bi_iter.bi_sector +
-                               sectors_handled;
-                       goto read_again;
-               } else
-                       generic_make_request(read_bio);
-               return;
-       }
-
-       /*
-        * WRITE:
-        */
        if (conf->pending_count >= max_queued_requests) {
                md_wakeup_thread(mddev->thread);
                raid10_log(mddev, "wait queued");
@@ -1300,8 +1308,7 @@ retry_write:
                        int bad_sectors;
                        int is_bad;
 
-                       is_bad = is_badblock(rdev, dev_sector,
-                                            max_sectors,
+                       is_bad = is_badblock(rdev, dev_sector, max_sectors,
                                             &first_bad, &bad_sectors);
                        if (is_bad < 0) {
                                /* Mustn't write here until the bad block
@@ -1405,8 +1412,7 @@ retry_write:
                        r10_bio->devs[i].bio = mbio;
 
                        mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr+
-                                          choose_data_offset(r10_bio,
-                                                             rdev));
+                                          choose_data_offset(r10_bio, rdev));
                        mbio->bi_bdev = rdev->bdev;
                        mbio->bi_end_io = raid10_end_write_request;
                        bio_set_op_attrs(mbio, op, do_sync | do_fua);
@@ -1457,8 +1463,7 @@ retry_write:
                        r10_bio->devs[i].repl_bio = mbio;
 
                        mbio->bi_iter.bi_sector = (r10_bio->devs[i].addr +
-                                          choose_data_offset(
-                                                  r10_bio, rdev));
+                                          choose_data_offset(r10_bio, rdev));
                        mbio->bi_bdev = rdev->bdev;
                        mbio->bi_end_io = raid10_end_write_request;
                        bio_set_op_attrs(mbio, op, do_sync | do_fua);
@@ -1503,6 +1508,36 @@ retry_write:
        one_write_done(r10_bio);
 }
 
+static void __make_request(struct mddev *mddev, struct bio *bio)
+{
+       struct r10conf *conf = mddev->private;
+       struct r10bio *r10_bio;
+
+       r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+       r10_bio->master_bio = bio;
+       r10_bio->sectors = bio_sectors(bio);
+
+       r10_bio->mddev = mddev;
+       r10_bio->sector = bio->bi_iter.bi_sector;
+       r10_bio->state = 0;
+
+       /*
+        * We might need to issue multiple reads to different devices if there
+        * are bad blocks around, so we keep track of the number of reads in
+        * bio->bi_phys_segments.  If this is 0, there is only one r10_bio and
+        * no locking will be needed when the request completes.  If it is
+        * non-zero, then it is the number of not-completed requests.
+        */
+       bio->bi_phys_segments = 0;
+       bio_clear_flag(bio, BIO_SEG_VALID);
+
+       if (bio_data_dir(bio) == READ)
+               raid10_read_request(mddev, bio, r10_bio);
+       else
+               raid10_write_request(mddev, bio, r10_bio);
+}
+
 static void raid10_make_request(struct mddev *mddev, struct bio *bio)
 {
        struct r10conf *conf = mddev->private;
index d7bfb6fc8aef8808b143c024f823bab4e6bf640b..302dea3296ba5ccd07740365314f45d74df49ec2 100644 (file)
@@ -162,6 +162,8 @@ struct r5l_log {
 
        /* to submit async io_units, to fulfill ordering of flush */
        struct work_struct deferred_io_work;
+       /* to disable write back during in degraded mode */
+       struct work_struct disable_writeback_work;
 };
 
 /*
@@ -611,6 +613,21 @@ static void r5l_submit_io_async(struct work_struct *work)
                r5l_do_submit_io(log, io);
 }
 
+static void r5c_disable_writeback_async(struct work_struct *work)
+{
+       struct r5l_log *log = container_of(work, struct r5l_log,
+                                          disable_writeback_work);
+       struct mddev *mddev = log->rdev->mddev;
+
+       if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
+               return;
+       pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n",
+               mdname(mddev));
+       mddev_suspend(mddev);
+       log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
+       mddev_resume(mddev);
+}
+
 static void r5l_submit_current_io(struct r5l_log *log)
 {
        struct r5l_io_unit *io = log->current_io;
@@ -1393,8 +1410,6 @@ static void r5l_do_reclaim(struct r5l_log *log)
        next_checkpoint = r5c_calculate_new_cp(conf);
        spin_unlock_irq(&log->io_list_lock);
 
-       BUG_ON(reclaimable < 0);
-
        if (reclaimable == 0 || !write_super)
                return;
 
@@ -1682,8 +1697,7 @@ out:
 
 static struct stripe_head *
 r5c_recovery_alloc_stripe(struct r5conf *conf,
-                         sector_t stripe_sect,
-                         sector_t log_start)
+                         sector_t stripe_sect)
 {
        struct stripe_head *sh;
 
@@ -1692,7 +1706,6 @@ r5c_recovery_alloc_stripe(struct r5conf *conf,
                return NULL;  /* no more stripe available */
 
        r5l_recovery_reset_stripe(sh);
-       sh->log_start = log_start;
 
        return sh;
 }
@@ -1862,7 +1875,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                                stripe_sect);
 
                if (!sh) {
-                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect, ctx->pos);
+                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
                        /*
                         * cannot get stripe from raid5_get_active_stripe
                         * try replay some stripes
@@ -1871,7 +1884,7 @@ 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, ctx->pos);
+                                       conf, stripe_sect);
                        }
                        if (!sh) {
                                pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
@@ -1879,8 +1892,8 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                        conf->min_nr_stripes * 2);
                                raid5_set_cache_size(mddev,
                                                     conf->min_nr_stripes * 2);
-                               sh = r5c_recovery_alloc_stripe(
-                                       conf, stripe_sect, ctx->pos);
+                               sh = r5c_recovery_alloc_stripe(conf,
+                                                              stripe_sect);
                        }
                        if (!sh) {
                                pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
@@ -1894,7 +1907,6 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                        if (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
                            test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags)) {
                                r5l_recovery_replay_one_stripe(conf, sh, ctx);
-                               sh->log_start = ctx->pos;
                                list_move_tail(&sh->lru, cached_stripe_list);
                        }
                        r5l_recovery_load_data(log, sh, ctx, payload,
@@ -1933,8 +1945,6 @@ static void r5c_recovery_load_one_stripe(struct r5l_log *log,
                        set_bit(R5_UPTODATE, &dev->flags);
                }
        }
-       list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
-       atomic_inc(&log->stripe_in_journal_count);
 }
 
 /*
@@ -2067,9 +2077,10 @@ static int
 r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
                                       struct r5l_recovery_ctx *ctx)
 {
-       struct stripe_head *sh, *next;
+       struct stripe_head *sh;
        struct mddev *mddev = log->rdev->mddev;
        struct page *page;
+       sector_t next_checkpoint = MaxSector;
 
        page = alloc_page(GFP_KERNEL);
        if (!page) {
@@ -2078,7 +2089,9 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
                return -ENOMEM;
        }
 
-       list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
+       WARN_ON(list_empty(&ctx->cached_list));
+
+       list_for_each_entry(sh, &ctx->cached_list, lru) {
                struct r5l_meta_block *mb;
                int i;
                int offset;
@@ -2123,14 +2136,42 @@ r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
                sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page,
                             REQ_OP_WRITE, REQ_FUA, false);
                sh->log_start = ctx->pos;
+               list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
+               atomic_inc(&log->stripe_in_journal_count);
                ctx->pos = write_pos;
                ctx->seq += 1;
+               next_checkpoint = sh->log_start;
+       }
+       log->next_checkpoint = next_checkpoint;
+       __free_page(page);
+       return 0;
+}
+
+static void r5c_recovery_flush_data_only_stripes(struct r5l_log *log,
+                                                struct r5l_recovery_ctx *ctx)
+{
+       struct mddev *mddev = log->rdev->mddev;
+       struct r5conf *conf = mddev->private;
+       struct stripe_head *sh, *next;
+
+       if (ctx->data_only_stripes == 0)
+               return;
 
+       log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_BACK;
+
+       list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
+               r5c_make_stripe_write_out(sh);
+               set_bit(STRIPE_HANDLE, &sh->state);
                list_del_init(&sh->lru);
                raid5_release_stripe(sh);
        }
-       __free_page(page);
-       return 0;
+
+       md_wakeup_thread(conf->mddev->thread);
+       /* reuse conf->wait_for_quiescent in recovery */
+       wait_event(conf->wait_for_quiescent,
+                  atomic_read(&conf->active_stripes) == 0);
+
+       log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
 }
 
 static int r5l_recovery_log(struct r5l_log *log)
@@ -2139,7 +2180,6 @@ static int r5l_recovery_log(struct r5l_log *log)
        struct r5l_recovery_ctx ctx;
        int ret;
        sector_t pos;
-       struct stripe_head *sh;
 
        ctx.pos = log->last_checkpoint;
        ctx.seq = log->last_cp_seq;
@@ -2160,35 +2200,31 @@ static int r5l_recovery_log(struct r5l_log *log)
        pos = ctx.pos;
        ctx.seq += 10000;
 
-       if (ctx.data_only_stripes == 0) {
-               log->next_checkpoint = ctx.pos;
-               r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq++);
-               ctx.pos = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
-       } else {
-               sh = list_last_entry(&ctx.cached_list, struct stripe_head, lru);
-               log->next_checkpoint = sh->log_start;
-       }
 
        if ((ctx.data_only_stripes == 0) && (ctx.data_parity_stripes == 0))
                pr_debug("md/raid:%s: starting from clean shutdown\n",
                         mdname(mddev));
-       else {
-               pr_debug("md/raid:%s: recoverying %d data-only stripes and %d data-parity stripes\n",
+       else
+               pr_debug("md/raid:%s: recovering %d data-only stripes and %d data-parity stripes\n",
                         mdname(mddev), ctx.data_only_stripes,
                         ctx.data_parity_stripes);
 
-               if (ctx.data_only_stripes > 0)
-                       if (r5c_recovery_rewrite_data_only_stripes(log, &ctx)) {
-                               pr_err("md/raid:%s: failed to rewrite stripes to journal\n",
-                                      mdname(mddev));
-                               return -EIO;
-                       }
+       if (ctx.data_only_stripes == 0) {
+               log->next_checkpoint = ctx.pos;
+               r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq++);
+               ctx.pos = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
+       } else if (r5c_recovery_rewrite_data_only_stripes(log, &ctx)) {
+               pr_err("md/raid:%s: failed to rewrite stripes to journal\n",
+                      mdname(mddev));
+               return -EIO;
        }
 
        log->log_start = ctx.pos;
        log->seq = ctx.seq;
        log->last_checkpoint = pos;
        r5l_write_super(log, pos);
+
+       r5c_recovery_flush_data_only_stripes(log, &ctx);
        return 0;
 }
 
@@ -2250,6 +2286,10 @@ static ssize_t r5c_journal_mode_store(struct mddev *mddev,
            val > R5C_JOURNAL_MODE_WRITE_BACK)
                return -EINVAL;
 
+       if (raid5_calc_degraded(conf) > 0 &&
+           val == R5C_JOURNAL_MODE_WRITE_BACK)
+               return -EINVAL;
+
        mddev_suspend(mddev);
        conf->log->r5c_journal_mode = val;
        mddev_resume(mddev);
@@ -2304,6 +2344,16 @@ int r5c_try_caching_write(struct r5conf *conf,
                set_bit(STRIPE_R5C_CACHING, &sh->state);
        }
 
+       /*
+        * When run in degraded mode, array is set to write-through mode.
+        * This check helps drain pending write safely in the transition to
+        * write-through mode.
+        */
+       if (s->failed) {
+               r5c_make_stripe_write_out(sh);
+               return -EAGAIN;
+       }
+
        for (i = disks; i--; ) {
                dev = &sh->dev[i];
                /* if non-overwrite, use writing-out phase */
@@ -2354,6 +2404,8 @@ void r5c_release_extra_page(struct stripe_head *sh)
                        struct page *p = sh->dev[i].orig_page;
 
                        sh->dev[i].orig_page = sh->dev[i].page;
+                       clear_bit(R5_OrigPageUPTDODATE, &sh->dev[i].flags);
+
                        if (!using_disk_info_extra_page)
                                put_page(p);
                }
@@ -2418,9 +2470,6 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
        if (do_wakeup)
                wake_up(&conf->wait_for_overlap);
 
-       if (conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
-               return;
-
        spin_lock_irq(&conf->log->stripe_in_journal_lock);
        list_del_init(&sh->r5c);
        spin_unlock_irq(&conf->log->stripe_in_journal_lock);
@@ -2561,6 +2610,19 @@ ioerr:
        return ret;
 }
 
+void r5c_update_on_rdev_error(struct mddev *mddev)
+{
+       struct r5conf *conf = mddev->private;
+       struct r5l_log *log = conf->log;
+
+       if (!log)
+               return;
+
+       if (raid5_calc_degraded(conf) > 0 &&
+           conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
+               schedule_work(&log->disable_writeback_work);
+}
+
 int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
 {
        struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -2633,20 +2695,23 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
        spin_lock_init(&log->no_space_stripes_lock);
 
        INIT_WORK(&log->deferred_io_work, r5l_submit_io_async);
+       INIT_WORK(&log->disable_writeback_work, r5c_disable_writeback_async);
 
        log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
        INIT_LIST_HEAD(&log->stripe_in_journal_list);
        spin_lock_init(&log->stripe_in_journal_lock);
        atomic_set(&log->stripe_in_journal_count, 0);
 
+       rcu_assign_pointer(conf->log, log);
+
        if (r5l_load_log(log))
                goto error;
 
-       rcu_assign_pointer(conf->log, log);
        set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
        return 0;
 
 error:
+       rcu_assign_pointer(conf->log, NULL);
        md_unregister_thread(&log->reclaim_thread);
 reclaim_thread:
        mempool_destroy(log->meta_pool);
@@ -2663,6 +2728,7 @@ io_kc:
 
 void r5l_exit_log(struct r5l_log *log)
 {
+       flush_work(&log->disable_writeback_work);
        md_unregister_thread(&log->reclaim_thread);
        mempool_destroy(log->meta_pool);
        bioset_free(log->bs);
index 06d7279bdd048e66369961194bc1d21567a08446..3c7e106c12a246046abc67c479f589d10966bce3 100644 (file)
@@ -62,6 +62,8 @@
 #include "raid0.h"
 #include "bitmap.h"
 
+#define UNSUPPORTED_MDDEV_FLAGS        (1L << MD_FAILFAST_SUPPORTED)
+
 #define cpu_to_group(cpu) cpu_to_node(cpu)
 #define ANY_GROUP NUMA_NO_NODE
 
@@ -554,7 +556,7 @@ static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
  * of the two sections, and some non-in_sync devices may
  * be insync in the section most affected by failed devices.
  */
-static int calc_degraded(struct r5conf *conf)
+int raid5_calc_degraded(struct r5conf *conf)
 {
        int degraded, degraded2;
        int i;
@@ -617,7 +619,7 @@ static int has_failed(struct r5conf *conf)
        if (conf->mddev->reshape_position == MaxSector)
                return conf->mddev->degraded > conf->max_degraded;
 
-       degraded = calc_degraded(conf);
+       degraded = raid5_calc_degraded(conf);
        if (degraded > conf->max_degraded)
                return 1;
        return 0;
@@ -1013,7 +1015,17 @@ again:
 
                        if (test_bit(R5_SkipCopy, &sh->dev[i].flags))
                                WARN_ON(test_bit(R5_UPTODATE, &sh->dev[i].flags));
-                       sh->dev[i].vec.bv_page = sh->dev[i].page;
+
+                       if (!op_is_write(op) &&
+                           test_bit(R5_InJournal, &sh->dev[i].flags))
+                               /*
+                                * issuing read for a page in journal, this
+                                * must be preparing for prexor in rmw; read
+                                * the data into orig_page
+                                */
+                               sh->dev[i].vec.bv_page = sh->dev[i].orig_page;
+                       else
+                               sh->dev[i].vec.bv_page = sh->dev[i].page;
                        bi->bi_vcnt = 1;
                        bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
                        bi->bi_io_vec[0].bv_offset = 0;
@@ -2378,6 +2390,13 @@ static void raid5_end_read_request(struct bio * bi)
                } else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags))
                        clear_bit(R5_ReadNoMerge, &sh->dev[i].flags);
 
+               if (test_bit(R5_InJournal, &sh->dev[i].flags))
+                       /*
+                        * end read for a page in journal, this
+                        * must be preparing for prexor in rmw
+                        */
+                       set_bit(R5_OrigPageUPTDODATE, &sh->dev[i].flags);
+
                if (atomic_read(&rdev->read_errors))
                        atomic_set(&rdev->read_errors, 0);
        } else {
@@ -2536,7 +2555,7 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
 
        spin_lock_irqsave(&conf->device_lock, flags);
        clear_bit(In_sync, &rdev->flags);
-       mddev->degraded = calc_degraded(conf);
+       mddev->degraded = raid5_calc_degraded(conf);
        spin_unlock_irqrestore(&conf->device_lock, flags);
        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 
@@ -2550,6 +2569,7 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
                bdevname(rdev->bdev, b),
                mdname(mddev),
                conf->raid_disks - mddev->degraded);
+       r5c_update_on_rdev_error(mddev);
 }
 
 /*
@@ -2878,6 +2898,30 @@ sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous)
        return r_sector;
 }
 
+/*
+ * There are cases where we want handle_stripe_dirtying() and
+ * schedule_reconstruction() to delay towrite to some dev of a stripe.
+ *
+ * This function checks whether we want to delay the towrite. Specifically,
+ * we delay the towrite when:
+ *
+ *   1. degraded stripe has a non-overwrite to the missing dev, AND this
+ *      stripe has data in journal (for other devices).
+ *
+ *      In this case, when reading data for the non-overwrite dev, it is
+ *      necessary to handle complex rmw of write back cache (prexor with
+ *      orig_page, and xor with page). To keep read path simple, we would
+ *      like to flush data in journal to RAID disks first, so complex rmw
+ *      is handled in the write patch (handle_stripe_dirtying).
+ *
+ */
+static inline bool delay_towrite(struct r5dev *dev,
+                                  struct stripe_head_state *s)
+{
+       return !test_bit(R5_OVERWRITE, &dev->flags) &&
+               !test_bit(R5_Insync, &dev->flags) && s->injournal;
+}
+
 static void
 schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                         int rcw, int expand)
@@ -2898,7 +2942,7 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
 
-                       if (dev->towrite) {
+                       if (dev->towrite && !delay_towrite(dev, s)) {
                                set_bit(R5_LOCKED, &dev->flags);
                                set_bit(R5_Wantdrain, &dev->flags);
                                if (!expand)
@@ -3293,13 +3337,6 @@ static int want_replace(struct stripe_head *sh, int disk_idx)
        return rv;
 }
 
-/* fetch_block - checks the given member device to see if its data needs
- * to be read or computed to satisfy a request.
- *
- * Returns 1 when no more member devices need to be checked, otherwise returns
- * 0 to tell the loop in handle_stripe_fill to continue
- */
-
 static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
                           int disk_idx, int disks)
 {
@@ -3390,6 +3427,12 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
        return 0;
 }
 
+/* fetch_block - checks the given member device to see if its data needs
+ * to be read or computed to satisfy a request.
+ *
+ * Returns 1 when no more member devices need to be checked, otherwise returns
+ * 0 to tell the loop in handle_stripe_fill to continue
+ */
 static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s,
                       int disk_idx, int disks)
 {
@@ -3476,10 +3519,26 @@ static void handle_stripe_fill(struct stripe_head *sh,
         * midst of changing due to a write
         */
        if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&
-           !sh->reconstruct_state)
+           !sh->reconstruct_state) {
+
+               /*
+                * For degraded stripe with data in journal, do not handle
+                * read requests yet, instead, flush the stripe to raid
+                * disks first, this avoids handling complex rmw of write
+                * back cache (prexor with orig_page, and then xor with
+                * page) in the read path
+                */
+               if (s->injournal && s->failed) {
+                       if (test_bit(STRIPE_R5C_CACHING, &sh->state))
+                               r5c_make_stripe_write_out(sh);
+                       goto out;
+               }
+
                for (i = disks; i--; )
                        if (fetch_block(sh, s, i, disks))
                                break;
+       }
+out:
        set_bit(STRIPE_HANDLE, &sh->state);
 }
 
@@ -3592,6 +3651,21 @@ unhash:
                break_stripe_batch_list(head_sh, STRIPE_EXPAND_SYNC_FLAGS);
 }
 
+/*
+ * For RMW in write back cache, we need extra page in prexor to store the
+ * old data. This page is stored in dev->orig_page.
+ *
+ * This function checks whether we have data for prexor. The exact logic
+ * is:
+ *       R5_UPTODATE && (!R5_InJournal || R5_OrigPageUPTDODATE)
+ */
+static inline bool uptodate_for_rmw(struct r5dev *dev)
+{
+       return (test_bit(R5_UPTODATE, &dev->flags)) &&
+               (!test_bit(R5_InJournal, &dev->flags) ||
+                test_bit(R5_OrigPageUPTDODATE, &dev->flags));
+}
+
 static int handle_stripe_dirtying(struct r5conf *conf,
                                  struct stripe_head *sh,
                                  struct stripe_head_state *s,
@@ -3620,12 +3694,11 @@ static int handle_stripe_dirtying(struct r5conf *conf,
        } else for (i = disks; i--; ) {
                /* would I have to read this buffer for read_modify_write */
                struct r5dev *dev = &sh->dev[i];
-               if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx ||
+               if (((dev->towrite && !delay_towrite(dev, s)) ||
+                    i == sh->pd_idx || i == sh->qd_idx ||
                     test_bit(R5_InJournal, &dev->flags)) &&
                    !test_bit(R5_LOCKED, &dev->flags) &&
-                   !((test_bit(R5_UPTODATE, &dev->flags) &&
-                      (!test_bit(R5_InJournal, &dev->flags) ||
-                       dev->page != dev->orig_page)) ||
+                   !(uptodate_for_rmw(dev) ||
                      test_bit(R5_Wantcompute, &dev->flags))) {
                        if (test_bit(R5_Insync, &dev->flags))
                                rmw++;
@@ -3637,7 +3710,6 @@ static int handle_stripe_dirtying(struct r5conf *conf,
                    i != sh->pd_idx && i != sh->qd_idx &&
                    !test_bit(R5_LOCKED, &dev->flags) &&
                    !(test_bit(R5_UPTODATE, &dev->flags) ||
-                     test_bit(R5_InJournal, &dev->flags) ||
                      test_bit(R5_Wantcompute, &dev->flags))) {
                        if (test_bit(R5_Insync, &dev->flags))
                                rcw++;
@@ -3687,13 +3759,11 @@ static int handle_stripe_dirtying(struct r5conf *conf,
 
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
-                       if ((dev->towrite ||
+                       if (((dev->towrite && !delay_towrite(dev, s)) ||
                             i == sh->pd_idx || i == sh->qd_idx ||
                             test_bit(R5_InJournal, &dev->flags)) &&
                            !test_bit(R5_LOCKED, &dev->flags) &&
-                           !((test_bit(R5_UPTODATE, &dev->flags) &&
-                              (!test_bit(R5_InJournal, &dev->flags) ||
-                               dev->page != dev->orig_page)) ||
+                           !(uptodate_for_rmw(dev) ||
                              test_bit(R5_Wantcompute, &dev->flags)) &&
                            test_bit(R5_Insync, &dev->flags)) {
                                if (test_bit(STRIPE_PREREAD_ACTIVE,
@@ -3720,7 +3790,6 @@ static int handle_stripe_dirtying(struct r5conf *conf,
                            i != sh->pd_idx && i != sh->qd_idx &&
                            !test_bit(R5_LOCKED, &dev->flags) &&
                            !(test_bit(R5_UPTODATE, &dev->flags) ||
-                             test_bit(R5_InJournal, &dev->flags) ||
                              test_bit(R5_Wantcompute, &dev->flags))) {
                                rcw++;
                                if (test_bit(R5_Insync, &dev->flags) &&
@@ -7023,7 +7092,7 @@ static int raid5_run(struct mddev *mddev)
        /*
         * 0 for a fully functional array, 1 or 2 for a degraded array.
         */
-       mddev->degraded = calc_degraded(conf);
+       mddev->degraded = raid5_calc_degraded(conf);
 
        if (has_failed(conf)) {
                pr_crit("md/raid:%s: not enough operational devices (%d/%d failed)\n",
@@ -7270,7 +7339,7 @@ static int raid5_spare_active(struct mddev *mddev)
                }
        }
        spin_lock_irqsave(&conf->device_lock, flags);
-       mddev->degraded = calc_degraded(conf);
+       mddev->degraded = raid5_calc_degraded(conf);
        spin_unlock_irqrestore(&conf->device_lock, flags);
        print_raid5_conf(conf);
        return count;
@@ -7630,7 +7699,7 @@ static int raid5_start_reshape(struct mddev *mddev)
                 * pre and post number of devices.
                 */
                spin_lock_irqsave(&conf->device_lock, flags);
-               mddev->degraded = calc_degraded(conf);
+               mddev->degraded = raid5_calc_degraded(conf);
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
        mddev->raid_disks = conf->raid_disks;
@@ -7718,7 +7787,7 @@ static void raid5_finish_reshape(struct mddev *mddev)
                } else {
                        int d;
                        spin_lock_irq(&conf->device_lock);
-                       mddev->degraded = calc_degraded(conf);
+                       mddev->degraded = raid5_calc_degraded(conf);
                        spin_unlock_irq(&conf->device_lock);
                        for (d = conf->raid_disks ;
                             d < conf->raid_disks - mddev->delta_disks;
@@ -7829,8 +7898,9 @@ static void *raid5_takeover_raid1(struct mddev *mddev)
        mddev->new_chunk_sectors = chunksect;
 
        ret = setup_conf(mddev);
-       if (!IS_ERR_VALUE(ret))
-               clear_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
+       if (!IS_ERR(ret))
+               mddev_clear_unsupported_flags(mddev,
+                       UNSUPPORTED_MDDEV_FLAGS);
        return ret;
 }
 
index ed8e1362ab3698e6608aceee90614501bb1a69b2..1440fa26e29629c4f9acc098f0fa9035f5ff1d1a 100644 (file)
@@ -322,6 +322,11 @@ enum r5dev_flags {
                         * data and parity being written are in the journal
                         * device
                         */
+       R5_OrigPageUPTDODATE,   /* with write back cache, we read old data into
+                                * dev->orig_page for prexor. When this flag is
+                                * set, orig_page contains latest data in the
+                                * raid disk.
+                                */
 };
 
 /*
@@ -753,6 +758,7 @@ extern sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector,
 extern struct stripe_head *
 raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
                        int previous, int noblock, int noquiesce);
+extern int raid5_calc_degraded(struct r5conf *conf);
 extern int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev);
 extern void r5l_exit_log(struct r5l_log *log);
 extern int r5l_write_stripe(struct r5l_log *log, struct stripe_head *head_sh);
@@ -781,4 +787,5 @@ extern void r5c_flush_cache(struct r5conf *conf, int num);
 extern void r5c_check_stripe_cache_usage(struct r5conf *conf);
 extern void r5c_check_cached_full_stripe(struct r5conf *conf);
 extern struct md_sysfs_entry r5c_journal_mode;
+extern void r5c_update_on_rdev_error(struct mddev *mddev);
 #endif
index 0ea4efb3de6683ee2dca71b3b7e20bc7f5f1e761..ccda41c2c9e41ed37969280420b7d98609c6641b 100644 (file)
@@ -30,8 +30,9 @@
 
 #include "cec-priv.h"
 
-static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx);
-static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx);
+static void cec_fill_msg_report_features(struct cec_adapter *adap,
+                                        struct cec_msg *msg,
+                                        unsigned int la_idx);
 
 /*
  * 400 ms is the time it takes for one 16 byte message to be
@@ -288,10 +289,10 @@ static void cec_data_cancel(struct cec_data *data)
 
        /* Mark it as an error */
        data->msg.tx_ts = ktime_get_ns();
-       data->msg.tx_status = CEC_TX_STATUS_ERROR |
-                             CEC_TX_STATUS_MAX_RETRIES;
+       data->msg.tx_status |= CEC_TX_STATUS_ERROR |
+                              CEC_TX_STATUS_MAX_RETRIES;
+       data->msg.tx_error_cnt++;
        data->attempts = 0;
-       data->msg.tx_error_cnt = 1;
        /* Queue transmitted message for monitoring purposes */
        cec_queue_msg_monitor(data->adap, &data->msg, 1);
 
@@ -611,8 +612,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
        }
        memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len);
        if (msg->len == 1) {
-               if (cec_msg_initiator(msg) != 0xf ||
-                   cec_msg_destination(msg) == 0xf) {
+               if (cec_msg_destination(msg) == 0xf) {
                        dprintk(1, "cec_transmit_msg: invalid poll message\n");
                        return -EINVAL;
                }
@@ -637,7 +637,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
                dprintk(1, "cec_transmit_msg: destination is the adapter itself\n");
                return -EINVAL;
        }
-       if (cec_msg_initiator(msg) != 0xf &&
+       if (msg->len > 1 && adap->is_configured &&
            !cec_has_log_addr(adap, cec_msg_initiator(msg))) {
                dprintk(1, "cec_transmit_msg: initiator has unknown logical address %d\n",
                        cec_msg_initiator(msg));
@@ -851,7 +851,7 @@ static const u8 cec_msg_size[256] = {
        [CEC_MSG_REQUEST_ARC_TERMINATION] = 2 | DIRECTED,
        [CEC_MSG_TERMINATE_ARC] = 2 | DIRECTED,
        [CEC_MSG_REQUEST_CURRENT_LATENCY] = 4 | BCAST,
-       [CEC_MSG_REPORT_CURRENT_LATENCY] = 7 | BCAST,
+       [CEC_MSG_REPORT_CURRENT_LATENCY] = 6 | BCAST,
        [CEC_MSG_CDC_MESSAGE] = 2 | BCAST,
 };
 
@@ -1071,7 +1071,7 @@ static int cec_config_log_addr(struct cec_adapter *adap,
 
        /* Send poll message */
        msg.len = 1;
-       msg.msg[0] = 0xf0 | log_addr;
+       msg.msg[0] = (log_addr << 4) | log_addr;
        err = cec_transmit_msg_fh(adap, &msg, NULL, true);
 
        /*
@@ -1205,7 +1205,7 @@ static int cec_config_thread_func(void *arg)
                las->log_addr[i] = CEC_LOG_ADDR_INVALID;
                if (last_la == CEC_LOG_ADDR_INVALID ||
                    last_la == CEC_LOG_ADDR_UNREGISTERED ||
-                   !(last_la & type2mask[type]))
+                   !((1 << last_la) & type2mask[type]))
                        last_la = la_list[0];
 
                err = cec_config_log_addr(adap, i, last_la);
@@ -1250,30 +1250,49 @@ configured:
                for (i = 1; i < las->num_log_addrs; i++)
                        las->log_addr[i] = CEC_LOG_ADDR_INVALID;
        }
+       for (i = las->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++)
+               las->log_addr[i] = CEC_LOG_ADDR_INVALID;
        adap->is_configured = true;
        adap->is_configuring = false;
        cec_post_state_event(adap);
-       mutex_unlock(&adap->lock);
 
+       /*
+        * Now post the Report Features and Report Physical Address broadcast
+        * messages. Note that these are non-blocking transmits, meaning that
+        * they are just queued up and once adap->lock is unlocked the main
+        * thread will kick in and start transmitting these.
+        *
+        * If after this function is done (but before one or more of these
+        * messages are actually transmitted) the CEC adapter is unconfigured,
+        * then any remaining messages will be dropped by the main thread.
+        */
        for (i = 0; i < las->num_log_addrs; i++) {
+               struct cec_msg msg = {};
+
                if (las->log_addr[i] == CEC_LOG_ADDR_INVALID ||
                    (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY))
                        continue;
 
-               /*
-                * Report Features must come first according
-                * to CEC 2.0
-                */
-               if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED)
-                       cec_report_features(adap, i);
-               cec_report_phys_addr(adap, i);
+               msg.msg[0] = (las->log_addr[i] << 4) | 0x0f;
+
+               /* Report Features must come first according to CEC 2.0 */
+               if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED &&
+                   adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0) {
+                       cec_fill_msg_report_features(adap, &msg, i);
+                       cec_transmit_msg_fh(adap, &msg, NULL, false);
+               }
+
+               /* Report Physical Address */
+               cec_msg_report_physical_addr(&msg, adap->phys_addr,
+                                            las->primary_device_type[i]);
+               dprintk(2, "config: la %d pa %x.%x.%x.%x\n",
+                       las->log_addr[i],
+                       cec_phys_addr_exp(adap->phys_addr));
+               cec_transmit_msg_fh(adap, &msg, NULL, false);
        }
-       for (i = las->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++)
-               las->log_addr[i] = CEC_LOG_ADDR_INVALID;
-       mutex_lock(&adap->lock);
        adap->kthread_config = NULL;
-       mutex_unlock(&adap->lock);
        complete(&adap->config_completion);
+       mutex_unlock(&adap->lock);
        return 0;
 
 unconfigure:
@@ -1526,52 +1545,32 @@ EXPORT_SYMBOL_GPL(cec_s_log_addrs);
 
 /* High-level core CEC message handling */
 
-/* Transmit the Report Features message */
-static int cec_report_features(struct cec_adapter *adap, unsigned int la_idx)
+/* Fill in the Report Features message */
+static void cec_fill_msg_report_features(struct cec_adapter *adap,
+                                        struct cec_msg *msg,
+                                        unsigned int la_idx)
 {
-       struct cec_msg msg = { };
        const struct cec_log_addrs *las = &adap->log_addrs;
        const u8 *features = las->features[la_idx];
        bool op_is_dev_features = false;
        unsigned int idx;
 
-       /* This is 2.0 and up only */
-       if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0)
-               return 0;
-
        /* Report Features */
-       msg.msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
-       msg.len = 4;
-       msg.msg[1] = CEC_MSG_REPORT_FEATURES;
-       msg.msg[2] = adap->log_addrs.cec_version;
-       msg.msg[3] = las->all_device_types[la_idx];
+       msg->msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
+       msg->len = 4;
+       msg->msg[1] = CEC_MSG_REPORT_FEATURES;
+       msg->msg[2] = adap->log_addrs.cec_version;
+       msg->msg[3] = las->all_device_types[la_idx];
 
        /* Write RC Profiles first, then Device Features */
        for (idx = 0; idx < ARRAY_SIZE(las->features[0]); idx++) {
-               msg.msg[msg.len++] = features[idx];
+               msg->msg[msg->len++] = features[idx];
                if ((features[idx] & CEC_OP_FEAT_EXT) == 0) {
                        if (op_is_dev_features)
                                break;
                        op_is_dev_features = true;
                }
        }
-       return cec_transmit_msg(adap, &msg, false);
-}
-
-/* Transmit the Report Physical Address message */
-static int cec_report_phys_addr(struct cec_adapter *adap, unsigned int la_idx)
-{
-       const struct cec_log_addrs *las = &adap->log_addrs;
-       struct cec_msg msg = { };
-
-       /* Report Physical Address */
-       msg.msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
-       cec_msg_report_physical_addr(&msg, adap->phys_addr,
-                                    las->primary_device_type[la_idx]);
-       dprintk(2, "config: la %d pa %x.%x.%x.%x\n",
-               las->log_addr[la_idx],
-                       cec_phys_addr_exp(adap->phys_addr));
-       return cec_transmit_msg(adap, &msg, false);
 }
 
 /* Transmit the Feature Abort message */
@@ -1777,9 +1776,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
        }
 
        case CEC_MSG_GIVE_FEATURES:
-               if (adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0)
-                       return cec_report_features(adap, la_idx);
-               return 0;
+               if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0)
+                       return cec_feature_abort(adap, msg);
+               cec_fill_msg_report_features(adap, &tx_cec_msg, la_idx);
+               return cec_transmit_msg(adap, &tx_cec_msg, false);
 
        default:
                /*
index bc5e8cfe7ca235134cfcaa5723f27fa146d5d0c5..8f11d7e459931bb5a8ed74569781dc83d4bd6422 100644 (file)
@@ -719,6 +719,9 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
                skb_copy_from_linear_data(h->priv->ule_skb, dest_addr,
                                          ETH_ALEN);
                skb_pull(h->priv->ule_skb, ETH_ALEN);
+       } else {
+               /* dest_addr buffer is only valid if h->priv->ule_dbit == 0 */
+               eth_zero_addr(dest_addr);
        }
 
        /* Handle ULE Extension Headers. */
@@ -750,16 +753,8 @@ static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
        if (!h->priv->ule_bridged) {
                skb_push(h->priv->ule_skb, ETH_HLEN);
                h->ethh = (struct ethhdr *)h->priv->ule_skb->data;
-               if (!h->priv->ule_dbit) {
-                       /*
-                        * dest_addr buffer is only valid if
-                        * h->priv->ule_dbit == 0
-                        */
-                       memcpy(h->ethh->h_dest, dest_addr, ETH_ALEN);
-                       eth_zero_addr(h->ethh->h_source);
-               } else /* zeroize source and dest */
-                       memset(h->ethh, 0, ETH_ALEN * 2);
-
+               memcpy(h->ethh->h_dest, dest_addr, ETH_ALEN);
+               eth_zero_addr(h->ethh->h_source);
                h->ethh->h_proto = htons(h->priv->ule_sndu_type);
        }
        /* else:  skb is in correct state; nothing to do. */
index b31fa6fae009171a8edda132b224a52631a24b39..b979ea148251deab48fbfca7a0141aa408010f5e 100644 (file)
@@ -655,6 +655,7 @@ config VIDEO_S5K6A3
 config VIDEO_S5K4ECGX
         tristate "Samsung S5K4ECGX sensor support"
         depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       select CRC32
         ---help---
           This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M
           camera sensor with an embedded SoC image signal processor.
index 59872b31f832cb7983337e1ce1290a5eea1aa36a..f4e92bdfe1926cb71be5a9dc29de7b7608903950 100644 (file)
@@ -2741,9 +2741,7 @@ static const struct v4l2_subdev_internal_ops smiapp_internal_ops = {
  * I2C Driver
  */
 
-#ifdef CONFIG_PM
-
-static int smiapp_suspend(struct device *dev)
+static int __maybe_unused smiapp_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
@@ -2768,7 +2766,7 @@ static int smiapp_suspend(struct device *dev)
        return 0;
 }
 
-static int smiapp_resume(struct device *dev)
+static int __maybe_unused smiapp_resume(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct v4l2_subdev *subdev = i2c_get_clientdata(client);
@@ -2783,13 +2781,6 @@ static int smiapp_resume(struct device *dev)
        return rval;
 }
 
-#else
-
-#define smiapp_suspend NULL
-#define smiapp_resume  NULL
-
-#endif /* CONFIG_PM */
-
 static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
 {
        struct smiapp_hwconfig *hwcfg;
@@ -2913,13 +2904,9 @@ static int smiapp_probe(struct i2c_client *client,
        if (IS_ERR(sensor->xshutdown))
                return PTR_ERR(sensor->xshutdown);
 
-       pm_runtime_enable(&client->dev);
-
-       rval = pm_runtime_get_sync(&client->dev);
-       if (rval < 0) {
-               rval = -ENODEV;
-               goto out_power_off;
-       }
+       rval = smiapp_power_on(&client->dev);
+       if (rval < 0)
+               return rval;
 
        rval = smiapp_identify_module(sensor);
        if (rval) {
@@ -3100,6 +3087,9 @@ static int smiapp_probe(struct i2c_client *client,
        if (rval < 0)
                goto out_media_entity_cleanup;
 
+       pm_runtime_set_active(&client->dev);
+       pm_runtime_get_noresume(&client->dev);
+       pm_runtime_enable(&client->dev);
        pm_runtime_set_autosuspend_delay(&client->dev, 1000);
        pm_runtime_use_autosuspend(&client->dev);
        pm_runtime_put_autosuspend(&client->dev);
@@ -3113,8 +3103,7 @@ out_cleanup:
        smiapp_cleanup(sensor);
 
 out_power_off:
-       pm_runtime_put(&client->dev);
-       pm_runtime_disable(&client->dev);
+       smiapp_power_off(&client->dev);
 
        return rval;
 }
@@ -3127,8 +3116,10 @@ static int smiapp_remove(struct i2c_client *client)
 
        v4l2_async_unregister_subdev(subdev);
 
-       pm_runtime_suspend(&client->dev);
        pm_runtime_disable(&client->dev);
+       if (!pm_runtime_status_suspended(&client->dev))
+               smiapp_power_off(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
 
        for (i = 0; i < sensor->ssds_used; i++) {
                v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
index 3a0fe8cc64e94c5199730e00a6ce0e6fcb41ffb2..48646a7f3fb00c2e35944e656089a9031b2eaf01 100644 (file)
@@ -291,8 +291,12 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
        tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
        tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
 
-       /* Svideo should enable YCrCb output and disable GPCL output
-        * For Composite and TV, it should be the reverse
+       /*
+        * Setup the FID/GLCO/VLK/HVLK and INTREQ/GPCL/VBLK output signals. For
+        * S-Video we output the vertical lock (VLK) signal on FID/GLCO/VLK/HVLK
+        * and set INTREQ/GPCL/VBLK to logic 0. For composite we output the
+        * field indicator (FID) signal on FID/GLCO/VLK/HVLK and set
+        * INTREQ/GPCL/VBLK to logic 1.
         */
        val = tvp5150_read(sd, TVP5150_MISC_CTL);
        if (val < 0) {
@@ -301,9 +305,9 @@ static void tvp5150_selmux(struct v4l2_subdev *sd)
        }
 
        if (decoder->input == TVP5150_SVIDEO)
-               val = (val & ~0x40) | 0x10;
+               val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK;
        else
-               val = (val & ~0x10) | 0x40;
+               val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL;
        tvp5150_write(sd, TVP5150_MISC_CTL, val);
 };
 
@@ -455,7 +459,12 @@ static const struct i2c_reg_value tvp5150_init_enable[] = {
        },{     /* Automatic offset and AGC enabled */
                TVP5150_ANAL_CHL_CTL, 0x15
        },{     /* Activate YCrCb output 0x9 or 0xd ? */
-               TVP5150_MISC_CTL, 0x6f
+               TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
+                                 TVP5150_MISC_CTL_INTREQ_OE |
+                                 TVP5150_MISC_CTL_YCBCR_OE |
+                                 TVP5150_MISC_CTL_SYNC_OE |
+                                 TVP5150_MISC_CTL_VBLANK |
+                                 TVP5150_MISC_CTL_CLOCK_OE,
        },{     /* Activates video std autodetection for all standards */
                TVP5150_AUTOSW_MSK, 0x0
        },{     /* Default format: 0x47. For 4:2:2: 0x40 */
@@ -861,8 +870,6 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
 
        f = &format->format;
 
-       tvp5150_reset(sd, 0);
-
        f->width = decoder->rect.width;
        f->height = decoder->rect.height / 2;
 
@@ -1051,21 +1058,27 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
 static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct tvp5150 *decoder = to_tvp5150(sd);
-       /* Output format: 8-bit ITU-R BT.656 with embedded syncs */
-       int val = 0x09;
-
-       /* Output format: 8-bit 4:2:2 YUV with discrete sync */
-       if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
-               val = 0x0d;
+       int val;
 
-       /* Initializes TVP5150 to its default values */
-       /* # set PCLK (27MHz) */
-       tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00);
+       /* Enable or disable the video output signals. */
+       val = tvp5150_read(sd, TVP5150_MISC_CTL);
+       if (val < 0)
+               return val;
+
+       val &= ~(TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
+                TVP5150_MISC_CTL_CLOCK_OE);
+
+       if (enable) {
+               /*
+                * Enable the YCbCr and clock outputs. In discrete sync mode
+                * (non-BT.656) additionally enable the the sync outputs.
+                */
+               val |= TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
+               if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
+                       val |= TVP5150_MISC_CTL_SYNC_OE;
+       }
 
-       if (enable)
-               tvp5150_write(sd, TVP5150_MISC_CTL, val);
-       else
-               tvp5150_write(sd, TVP5150_MISC_CTL, 0x00);
+       tvp5150_write(sd, TVP5150_MISC_CTL, val);
 
        return 0;
 }
@@ -1524,7 +1537,6 @@ static int tvp5150_probe(struct i2c_client *c,
                res = core->hdl.error;
                goto err;
        }
-       v4l2_ctrl_handler_setup(&core->hdl);
 
        /* Default is no cropping */
        core->rect.top = 0;
@@ -1535,6 +1547,8 @@ static int tvp5150_probe(struct i2c_client *c,
        core->rect.left = 0;
        core->rect.width = TVP5150_H_MAX;
 
+       tvp5150_reset(sd, 0);   /* Calls v4l2_ctrl_handler_setup() */
+
        res = v4l2_async_register_subdev(sd);
        if (res < 0)
                goto err;
index 25a994944918703f064eee85a6017ca7010dca4b..30a48c28d05ab5d46d9eff505005ebf3f90e6409 100644 (file)
@@ -9,6 +9,15 @@
 #define TVP5150_ANAL_CHL_CTL         0x01 /* Analog channel controls */
 #define TVP5150_OP_MODE_CTL          0x02 /* Operation mode controls */
 #define TVP5150_MISC_CTL             0x03 /* Miscellaneous controls */
+#define TVP5150_MISC_CTL_VBLK_GPCL     BIT(7)
+#define TVP5150_MISC_CTL_GPCL          BIT(6)
+#define TVP5150_MISC_CTL_INTREQ_OE     BIT(5)
+#define TVP5150_MISC_CTL_HVLK          BIT(4)
+#define TVP5150_MISC_CTL_YCBCR_OE      BIT(3)
+#define TVP5150_MISC_CTL_SYNC_OE       BIT(2)
+#define TVP5150_MISC_CTL_VBLANK                BIT(1)
+#define TVP5150_MISC_CTL_CLOCK_OE      BIT(0)
+
 #define TVP5150_AUTOSW_MSK           0x04 /* Autoswitch mask: TVP5150A / TVP5150AM */
 
 /* Reserved 05h */
index 979634000597f79124befabb48af909d4b8f6a6e..d5c911c09e2b792e767970f32c463862617cec19 100644 (file)
@@ -308,9 +308,7 @@ static void cobalt_pci_iounmap(struct cobalt *cobalt, struct pci_dev *pci_dev)
 static void cobalt_free_msi(struct cobalt *cobalt, struct pci_dev *pci_dev)
 {
        free_irq(pci_dev->irq, (void *)cobalt);
-
-       if (cobalt->msi_enabled)
-               pci_disable_msi(pci_dev);
+       pci_free_irq_vectors(pci_dev);
 }
 
 static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
@@ -387,14 +385,12 @@ static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
           from being generated. */
        cobalt_set_interrupt(cobalt, false);
 
-       if (pci_enable_msi_range(pci_dev, 1, 1) < 1) {
+       if (pci_alloc_irq_vectors(pci_dev, 1, 1, PCI_IRQ_MSI) < 1) {
                cobalt_err("Could not enable MSI\n");
-               cobalt->msi_enabled = false;
                ret = -EIO;
                goto err_release;
        }
        msi_config_show(cobalt, pci_dev);
-       cobalt->msi_enabled = true;
 
        /* Register IRQ */
        if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED,
index ed00dc9d93995e03ddf128dfb476dbc73ae086a3..00f773ec359ad954a15859329fb541fd5ab2a848 100644 (file)
@@ -287,8 +287,6 @@ struct cobalt {
        u32 irq_none;
        u32 irq_full_fifo;
 
-       bool msi_enabled;
-
        /* omnitek dma */
        int dma_channels;
        int first_fifo_channel;
index 07fa08be9e994a3f7d5952251b73f871fe4ecdca..d54ebe7e02150f7240f58da51a32d025026bdf34 100644 (file)
@@ -97,14 +97,13 @@ struct pctv452e_state {
        u8 c;      /* transaction counter, wraps around...  */
        u8 initialized; /* set to 1 if 0x15 has been sent */
        u16 last_rc_key;
-
-       unsigned char data[80];
 };
 
 static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
                         unsigned int write_len, unsigned int read_len)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+       u8 *buf;
        u8 id;
        unsigned int rlen;
        int ret;
@@ -114,36 +113,39 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
                return -EIO;
        }
 
-       mutex_lock(&state->ca_mutex);
+       buf = kmalloc(64, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        id = state->c++;
 
-       state->data[0] = SYNC_BYTE_OUT;
-       state->data[1] = id;
-       state->data[2] = cmd;
-       state->data[3] = write_len;
+       buf[0] = SYNC_BYTE_OUT;
+       buf[1] = id;
+       buf[2] = cmd;
+       buf[3] = write_len;
 
-       memcpy(state->data + 4, data, write_len);
+       memcpy(buf + 4, data, write_len);
 
        rlen = (read_len > 0) ? 64 : 0;
-       ret = dvb_usb_generic_rw(d, state->data, 4 + write_len,
-                                 state->data, rlen, /* delay_ms */ 0);
+       ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
+                                 buf, rlen, /* delay_ms */ 0);
        if (0 != ret)
                goto failed;
 
        ret = -EIO;
-       if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
+       if (SYNC_BYTE_IN != buf[0] || id != buf[1])
                goto failed;
 
-       memcpy(data, state->data + 4, read_len);
+       memcpy(data, buf + 4, read_len);
 
-       mutex_unlock(&state->ca_mutex);
+       kfree(buf);
        return 0;
 
 failed:
        err("CI error %d; %02X %02X %02X -> %*ph.",
-            ret, SYNC_BYTE_OUT, id, cmd, 3, state->data);
+            ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
 
-       mutex_unlock(&state->ca_mutex);
+       kfree(buf);
        return ret;
 }
 
@@ -410,53 +412,57 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
                                u8 *rcv_buf, u8 rcv_len)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+       u8 *buf;
        u8 id;
        int ret;
 
-       mutex_lock(&state->ca_mutex);
+       buf = kmalloc(64, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        id = state->c++;
 
        ret = -EINVAL;
        if (snd_len > 64 - 7 || rcv_len > 64 - 7)
                goto failed;
 
-       state->data[0] = SYNC_BYTE_OUT;
-       state->data[1] = id;
-       state->data[2] = PCTV_CMD_I2C;
-       state->data[3] = snd_len + 3;
-       state->data[4] = addr << 1;
-       state->data[5] = snd_len;
-       state->data[6] = rcv_len;
+       buf[0] = SYNC_BYTE_OUT;
+       buf[1] = id;
+       buf[2] = PCTV_CMD_I2C;
+       buf[3] = snd_len + 3;
+       buf[4] = addr << 1;
+       buf[5] = snd_len;
+       buf[6] = rcv_len;
 
-       memcpy(state->data + 7, snd_buf, snd_len);
+       memcpy(buf + 7, snd_buf, snd_len);
 
-       ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len,
-                                 state->data, /* rcv_len */ 64,
+       ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
+                                 buf, /* rcv_len */ 64,
                                  /* delay_ms */ 0);
        if (ret < 0)
                goto failed;
 
        /* TT USB protocol error. */
        ret = -EIO;
-       if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
+       if (SYNC_BYTE_IN != buf[0] || id != buf[1])
                goto failed;
 
        /* I2C device didn't respond as expected. */
        ret = -EREMOTEIO;
-       if (state->data[5] < snd_len || state->data[6] < rcv_len)
+       if (buf[5] < snd_len || buf[6] < rcv_len)
                goto failed;
 
-       memcpy(rcv_buf, state->data + 7, rcv_len);
-       mutex_unlock(&state->ca_mutex);
+       memcpy(rcv_buf, buf + 7, rcv_len);
 
+       kfree(buf);
        return rcv_len;
 
 failed:
        err("I2C error %d; %02X %02X  %02X %02X %02X -> %*ph",
             ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
-            7, state->data);
+            7, buf);
 
-       mutex_unlock(&state->ca_mutex);
+       kfree(buf);
        return ret;
 }
 
@@ -505,7 +511,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
 static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-       u8 *rx;
+       u8 *b0, *rx;
        int ret;
 
        info("%s: %d\n", __func__, i);
@@ -516,11 +522,12 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
        if (state->initialized)
                return 0;
 
-       rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL);
-       if (!rx)
+       b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL);
+       if (!b0)
                return -ENOMEM;
 
-       mutex_lock(&state->ca_mutex);
+       rx = b0 + 5;
+
        /* hmm where shoud this should go? */
        ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
        if (ret != 0)
@@ -528,66 +535,70 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
                        __func__, ret);
 
        /* this is a one-time initialization, dont know where to put */
-       state->data[0] = 0xaa;
-       state->data[1] = state->c++;
-       state->data[2] = PCTV_CMD_RESET;
-       state->data[3] = 1;
-       state->data[4] = 0;
+       b0[0] = 0xaa;
+       b0[1] = state->c++;
+       b0[2] = PCTV_CMD_RESET;
+       b0[3] = 1;
+       b0[4] = 0;
        /* reset board */
-       ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
+       ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
        if (ret)
                goto ret;
 
-       state->data[1] = state->c++;
-       state->data[4] = 1;
+       b0[1] = state->c++;
+       b0[4] = 1;
        /* reset board (again?) */
-       ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
+       ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
        if (ret)
                goto ret;
 
        state->initialized = 1;
 
 ret:
-       mutex_unlock(&state->ca_mutex);
-       kfree(rx);
+       kfree(b0);
        return ret;
 }
 
 static int pctv452e_rc_query(struct dvb_usb_device *d)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+       u8 *b, *rx;
        int ret, i;
        u8 id;
 
-       mutex_lock(&state->ca_mutex);
+       b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL);
+       if (!b)
+               return -ENOMEM;
+
+       rx = b + CMD_BUFFER_SIZE;
+
        id = state->c++;
 
        /* prepare command header  */
-       state->data[0] = SYNC_BYTE_OUT;
-       state->data[1] = id;
-       state->data[2] = PCTV_CMD_IR;
-       state->data[3] = 0;
+       b[0] = SYNC_BYTE_OUT;
+       b[1] = id;
+       b[2] = PCTV_CMD_IR;
+       b[3] = 0;
 
        /* send ir request */
-       ret = dvb_usb_generic_rw(d, state->data, 4,
-                                state->data, PCTV_ANSWER_LEN, 0);
+       ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
        if (ret != 0)
                goto ret;
 
        if (debug > 3) {
-               info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data);
-               for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++)
-                       info(" %02x", state->data[i + 3]);
+               info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
+               for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
+                       info(" %02x", rx[i+3]);
 
                info("\n");
        }
 
-       if ((state->data[3] == 9) &&  (state->data[12] & 0x01)) {
+       if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
                /* got a "press" event */
-               state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]);
+               state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
                if (debug > 2)
                        info("%s: cmd=0x%02x sys=0x%02x\n",
-                               __func__, state->data[6], state->data[7]);
+                               __func__, rx[6], rx[7]);
 
                rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
        } else if (state->last_rc_key) {
@@ -595,7 +606,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d)
                state->last_rc_key = 0;
        }
 ret:
-       mutex_unlock(&state->ca_mutex);
+       kfree(b);
        return ret;
 }
 
index a4dcaec31d02c06d82cddd81b0a47a4eb895608a..8c1f926567ec04425f36fd9fd68d80cf37df98a4 100644 (file)
@@ -218,22 +218,30 @@ static int smsusb_start_streaming(struct smsusb_device_t *dev)
 static int smsusb_sendrequest(void *context, void *buffer, size_t size)
 {
        struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
-       struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
-       int dummy;
+       struct sms_msg_hdr *phdr;
+       int dummy, ret;
 
        if (dev->state != SMSUSB_ACTIVE) {
                pr_debug("Device not active yet\n");
                return -ENOENT;
        }
 
+       phdr = kmalloc(size, GFP_KERNEL);
+       if (!phdr)
+               return -ENOMEM;
+       memcpy(phdr, buffer, size);
+
        pr_debug("sending %s(%d) size: %d\n",
                  smscore_translate_msg(phdr->msg_type), phdr->msg_type,
                  phdr->msg_length);
 
        smsendian_handle_tx_message((struct sms_msg_data *) phdr);
-       smsendian_handle_message_header((struct sms_msg_hdr *)buffer);
-       return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
-                           buffer, size, &dummy, 1000);
+       smsendian_handle_message_header((struct sms_msg_hdr *)phdr);
+       ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
+                           phdr, size, &dummy, 1000);
+
+       kfree(phdr);
+       return ret;
 }
 
 static char *smsusb1_fw_lkup[] = {
index a0547dbf980645104d862fdc39e2ad740107ad15..76382c858c35435b98e061a7dda49d5dacad9585 100644 (file)
@@ -330,7 +330,7 @@ static int h_memstick_read_dev_id(struct memstick_dev *card,
        struct ms_id_register id_reg;
 
        if (!(*mrq)) {
-               memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,
+               memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, &id_reg,
                                  sizeof(struct ms_id_register));
                *mrq = &card->current_mrq;
                return 0;
index 18e05ca7584f9723ba12bf26a0aaf145b5903896..3600c9993a9830504d0cc5bcd61c4b8f19376762 100644 (file)
@@ -152,6 +152,9 @@ static void mei_mkhi_fix(struct mei_cl_device *cldev)
 {
        int ret;
 
+       if (!cldev->bus->hbm_f_os_supported)
+               return;
+
        ret = mei_cldev_enable(cldev);
        if (ret)
                return;
index 0037153c80a6ad27a7949be67d0f643e52b23edd..2d9c5dd06e423266680294e4d806e2e736d32156 100644 (file)
@@ -450,7 +450,7 @@ bool mei_cldev_enabled(struct mei_cl_device *cldev)
 EXPORT_SYMBOL_GPL(mei_cldev_enabled);
 
 /**
- * mei_cldev_enable_device - enable me client device
+ * mei_cldev_enable - enable me client device
  *     create connection with me client
  *
  * @cldev: me client device
index 391936c1aa041c5bd925d284aa593e65b5ce1065..b0395601c6ae83340f62cd801531632134b85a7a 100644 (file)
@@ -1541,7 +1541,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1;
        if (rets < 0)
-               return rets;
+               goto err;
 
        if (rets == 0) {
                cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
@@ -1575,11 +1575,8 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
                        cb->buf.size, cb->buf_idx);
 
        rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
-       if (rets) {
-               cl->status = rets;
-               list_move_tail(&cb->list, &cmpl_list->list);
-               return rets;
-       }
+       if (rets)
+               goto err;
 
        cl->status = 0;
        cl->writing_state = MEI_WRITING;
@@ -1587,14 +1584,21 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
        cb->completed = mei_hdr.msg_complete == 1;
 
        if (first_chunk) {
-               if (mei_cl_tx_flow_ctrl_creds_reduce(cl))
-                       return -EIO;
+               if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {
+                       rets = -EIO;
+                       goto err;
+               }
        }
 
        if (mei_hdr.msg_complete)
                list_move_tail(&cb->list, &dev->write_waiting_list.list);
 
        return 0;
+
+err:
+       cl->status = rets;
+       list_move_tail(&cb->list, &cmpl_list->list);
+       return rets;
 }
 
 /**
index c6c051b52f55faf1b5896164a4e5e3e251f86899..c6217a4993ad4da05094978e50cc3f1acb1b1fd5 100644 (file)
@@ -180,6 +180,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf,
                                 dev->hbm_f_ev_supported);
                pos += scnprintf(buf + pos, bufsz - pos, "\tFA: %01d\n",
                                 dev->hbm_f_fa_supported);
+               pos += scnprintf(buf + pos, bufsz - pos, "\tOS: %01d\n",
+                                dev->hbm_f_os_supported);
        }
 
        pos += scnprintf(buf + pos, bufsz - pos, "pg:  %s, %s\n",
index dd7f15a65eeddbdf53bd2b6c094bfa98be969caf..25b4a1ba522df87fa60f0c8a9555607aa76df6d6 100644 (file)
@@ -989,6 +989,10 @@ static void mei_hbm_config_features(struct mei_device *dev)
        /* Fixed Address Client Support */
        if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
                dev->hbm_f_fa_supported = 1;
+
+       /* OS ver message Support */
+       if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
+               dev->hbm_f_os_supported = 1;
 }
 
 /**
index 9daf3f9aed2508e08070cb3ef96a53fc43f8d5f9..e1e4d47d4d7d21f5d62a7b514b2886277f9ae9bb 100644 (file)
 #define HBM_MINOR_VERSION_FA               0
 #define HBM_MAJOR_VERSION_FA               2
 
+/*
+ * MEI version with OS ver message support
+ */
+#define HBM_MINOR_VERSION_OS               0
+#define HBM_MAJOR_VERSION_OS               2
+
 /* Host bus message command opcode */
 #define MEI_HBM_CMD_OP_MSK                  0x7f
 /* Host bus message command RESPONSE */
index 699693cd8c59ddde7cd109c550d92f955b0f4c0e..8dadb98662a9e61da14ed8d95268bc9b4ec23d2b 100644 (file)
@@ -406,6 +406,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @hbm_f_ev_supported  : hbm feature event notification
  * @hbm_f_fa_supported  : hbm feature fixed address client
  * @hbm_f_ie_supported  : hbm feature immediate reply to enum request
+ * @hbm_f_os_supported  : hbm feature support OS ver message
  *
  * @me_clients_rwsem: rw lock over me_clients list
  * @me_clients  : list of FW clients
@@ -487,6 +488,7 @@ struct mei_device {
        unsigned int hbm_f_ev_supported:1;
        unsigned int hbm_f_fa_supported:1;
        unsigned int hbm_f_ie_supported:1;
+       unsigned int hbm_f_os_supported:1;
 
        struct rw_semaphore me_clients_rwsem;
        struct list_head me_clients;
index b61b52f9da3d88bc1903e14ffc56dd276700c814..0fccca075e2947337cc999e04438b1c1e2cc056d 100644 (file)
@@ -1706,10 +1706,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                err = mmc_select_hs400(card);
                if (err)
                        goto free_card;
-       } else if (mmc_card_hs(card)) {
+       } else {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
-               if (err > 0) {
+               if (err > 0 && mmc_card_hs(card)) {
                        err = mmc_select_hs_ddr(card);
                        if (err)
                                goto free_card;
index b11c3455b040c5b03e8083e9b8e4f234b0752537..e6ea8503f40c8466643db34f6ee36ff19345aa89 100644 (file)
@@ -506,9 +506,6 @@ static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
                }
        } while (busy);
 
-       if (host->ops->card_busy && send_status)
-               return mmc_switch_status(card);
-
        return 0;
 }
 
@@ -577,24 +574,26 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
        if (!use_busy_signal)
                goto out;
 
-       /* Switch to new timing before poll and check switch status. */
-       if (timing)
-               mmc_set_timing(host, timing);
-
        /*If SPI or used HW busy detection above, then we don't need to poll. */
        if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ||
-               mmc_host_is_spi(host)) {
-               if (send_status)
-                       err = mmc_switch_status(card);
+               mmc_host_is_spi(host))
                goto out_tim;
-       }
 
        /* Let's try to poll to find out when the command is completed. */
        err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err);
+       if (err)
+               goto out;
 
 out_tim:
-       if (err && timing)
-               mmc_set_timing(host, old_timing);
+       /* Switch to new timing before check switch status. */
+       if (timing)
+               mmc_set_timing(host, timing);
+
+       if (send_status) {
+               err = mmc_switch_status(card);
+               if (err && timing)
+                       mmc_set_timing(host, old_timing);
+       }
 out:
        mmc_retune_release(host);
 
index b44306b886cb6d7a383abae4d985cd18ea1d48e3..73db08558e4dd6d100d44e04cd58649e63ee94e8 100644 (file)
@@ -3354,10 +3354,11 @@ int dw_mci_runtime_resume(struct device *dev)
 
                if (!slot)
                        continue;
-               if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+               if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER)
                        dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
-                       dw_mci_setup_bus(slot, true);
-               }
+
+               /* Force setup bus to guarantee available clock output */
+               dw_mci_setup_bus(slot, true);
        }
 
        /* Now that slots are all setup, we can enable card detect */
index b352760c041ee5332be4eddc61a6f0cf0816bba6..09739352834c8253eedac3000b703e42c37eacfc 100644 (file)
@@ -578,13 +578,15 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
 {
        struct meson_host *host = dev_id;
        struct mmc_request *mrq;
-       struct mmc_command *cmd = host->cmd;
+       struct mmc_command *cmd;
        u32 irq_en, status, raw_status;
        irqreturn_t ret = IRQ_HANDLED;
 
        if (WARN_ON(!host))
                return IRQ_NONE;
 
+       cmd = host->cmd;
+
        mrq = host->mrq;
 
        if (WARN_ON(!mrq))
@@ -670,10 +672,10 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
        int ret = IRQ_HANDLED;
 
        if (WARN_ON(!mrq))
-               ret = IRQ_NONE;
+               return IRQ_NONE;
 
        if (WARN_ON(!cmd))
-               ret = IRQ_NONE;
+               return IRQ_NONE;
 
        data = cmd->data;
        if (data) {
index 01a804792f3007c1b8512b0cbdf4aea1a000cb82..b5972440c1bf606e677ad312a9a391576f859f70 100644 (file)
@@ -1023,7 +1023,12 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
                if (!host->busy_status && busy_resp &&
                    !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
                    (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
-                       /* Unmask the busy IRQ */
+
+                       /* Clear the busy start IRQ */
+                       writel(host->variant->busy_detect_mask,
+                              host->base + MMCICLEAR);
+
+                       /* Unmask the busy end IRQ */
                        writel(readl(base + MMCIMASK0) |
                               host->variant->busy_detect_mask,
                               base + MMCIMASK0);
@@ -1038,10 +1043,14 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
 
                /*
                 * At this point we are not busy with a command, we have
-                * not received a new busy request, mask the busy IRQ and
-                * fall through to process the IRQ.
+                * not received a new busy request, clear and mask the busy
+                * end IRQ and fall through to process the IRQ.
                 */
                if (host->busy_status) {
+
+                       writel(host->variant->busy_detect_mask,
+                              host->base + MMCICLEAR);
+
                        writel(readl(base + MMCIMASK0) &
                               ~host->variant->busy_detect_mask,
                               base + MMCIMASK0);
@@ -1283,12 +1292,21 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
                }
 
                /*
-                * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
-                * enabled) since the HW seems to be triggering the IRQ on both
-                * edges while monitoring DAT0 for busy completion.
+                * We intentionally clear the MCI_ST_CARDBUSY IRQ (if it's
+                * enabled) in mmci_cmd_irq() function where ST Micro busy
+                * detection variant is handled. Considering the HW seems to be
+                * triggering the IRQ on both edges while monitoring DAT0 for
+                * busy completion and that same status bit is used to monitor
+                * start and end of busy detection, special care must be taken
+                * to make sure that both start and end interrupts are always
+                * cleared one after the other.
                 */
                status &= readl(host->base + MMCIMASK0);
-               writel(status, host->base + MMCICLEAR);
+               if (host->variant->busy_detect)
+                       writel(status & ~host->variant->busy_detect_mask,
+                              host->base + MMCICLEAR);
+               else
+                       writel(status, host->base + MMCICLEAR);
 
                dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
 
index 44ecebd1ea8c1834a5d311fbe36ddfc8383e3ecd..c8b8ac66ff7e3a4839ba4943c9069e540846c87e 100644 (file)
@@ -309,6 +309,9 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
        cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
        cmd1 = cmd->arg;
 
+       if (cmd->opcode == MMC_STOP_TRANSMISSION)
+               cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
        if (host->sdio_irq_en) {
                ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
                cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
@@ -417,8 +420,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
                       ssp->base + HW_SSP_BLOCK_SIZE);
        }
 
-       if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
-           (cmd->opcode == SD_IO_RW_EXTENDED))
+       if (cmd->opcode == SD_IO_RW_EXTENDED)
                cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
 
        cmd1 = cmd->arg;
index 160f695cc09c611cf4aabdeeff236d672c66b639..278a5a435ab76bc422dd748617c96611fe09b105 100644 (file)
@@ -395,7 +395,8 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
        /* Power on the SDHCI controller and its children */
        acpi_device_fix_up_power(device);
        list_for_each_entry(child, &device->children, node)
-               acpi_device_fix_up_power(child);
+               if (child->status.present && child->status.enabled)
+                       acpi_device_fix_up_power(child);
 
        if (acpi_bus_get_status(device) || !device->status.present)
                return -ENODEV;
index 23909804ffb840d3187f21f67180a634a769425e..0def99590d162ebcfb86a16a6b9d5adf96f19cb6 100644 (file)
@@ -2733,7 +2733,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                if (intmask & SDHCI_INT_RETUNE)
                        mmc_retune_needed(host->mmc);
 
-               if (intmask & SDHCI_INT_CARD_INT) {
+               if ((intmask & SDHCI_INT_CARD_INT) &&
+                   (host->ier & SDHCI_INT_CARD_INT)) {
                        sdhci_enable_sdio_irq_nolock(host, false);
                        host->thread_isr |= SDHCI_INT_CARD_INT;
                        result = IRQ_WAKE_THREAD;
index 353a9ddf6b975d48d522da646761660b35b44d4c..9ce5dcb4abd0f5026384ed4e0466d1ddfa44c617 100644 (file)
@@ -426,6 +426,7 @@ config MTD_NAND_ORION
 
 config MTD_NAND_OXNAS
        tristate "NAND Flash support for Oxford Semiconductor SoC"
+       depends on HAS_IOMEM
        help
          This enables the NAND flash controller on Oxford Semiconductor SoCs.
 
@@ -540,7 +541,7 @@ config MTD_NAND_FSMC
          Flexible Static Memory Controller (FSMC)
 
 config MTD_NAND_XWAY
-       tristate "Support for NAND on Lantiq XWAY SoC"
+       bool "Support for NAND on Lantiq XWAY SoC"
        depends on LANTIQ && SOC_TYPE_XWAY
        help
          Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
index 5553a5d9efd1144b276a20290f5cb2be9fc302f0..846a66c1b1338f92e65a9548c6fa32e63d834294 100644 (file)
@@ -775,7 +775,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
        init_completion(&host->comp_controller);
 
        host->irq = platform_get_irq(pdev, 0);
-       if ((host->irq < 0) || (host->irq >= NR_IRQS)) {
+       if (host->irq < 0) {
                dev_err(&pdev->dev, "failed to get platform irq\n");
                res = -EINVAL;
                goto err_exit3;
index 28c7f474be77b8b7ccab3379d81bdaa6006594ae..4a5e948c62df1b7d29ff9fe78b50e7d0858b01d5 100644 (file)
@@ -632,11 +632,13 @@ static int tango_nand_probe(struct platform_device *pdev)
        if (IS_ERR(nfc->pbus_base))
                return PTR_ERR(nfc->pbus_base);
 
+       writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE);
+
        clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
-       nfc->chan = dma_request_chan(&pdev->dev, "nfc_sbox");
+       nfc->chan = dma_request_chan(&pdev->dev, "rxtx");
        if (IS_ERR(nfc->chan))
                return PTR_ERR(nfc->chan);
 
index 1f2948c0c458d60ec60e898bb1b4893ddba33ecf..895101a5e686457c0dc63237efcb33a79c43a559 100644 (file)
@@ -232,7 +232,6 @@ static const struct of_device_id xway_nand_match[] = {
        { .compatible = "lantiq,nand-xway" },
        {},
 };
-MODULE_DEVICE_TABLE(of, xway_nand_match);
 
 static struct platform_driver xway_nand_driver = {
        .probe  = xway_nand_probe,
@@ -243,6 +242,4 @@ static struct platform_driver xway_nand_driver = {
        },
 };
 
-module_platform_driver(xway_nand_driver);
-
-MODULE_LICENSE("GPL");
+builtin_platform_driver(xway_nand_driver);
index b8c293373eccd8293ab50fea6a4ce25b1745076b..a306de4318d7d2301fdcb8f34c7045e884278ad4 100644 (file)
@@ -190,7 +190,7 @@ static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
  */
 static int ipddp_create(struct ipddp_route *new_rt)
 {
-        struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+        struct ipddp_route *rt = kzalloc(sizeof(*rt), GFP_KERNEL);
 
         if (rt == NULL)
                 return -ENOMEM;
index 7be393c96b1a0481c1f181443a7b521b647378f5..cf7c18947189a1f5c2834ad5b0d14ac615686294 100644 (file)
@@ -161,6 +161,7 @@ static int c_can_pci_probe(struct pci_dev *pdev,
 
        dev->irq = pdev->irq;
        priv->base = addr;
+       priv->device = &pdev->dev;
 
        if (!c_can_pci_data->freq) {
                dev_err(&pdev->dev, "no clock frequency defined\n");
index 680d1ff07a55ddd60ceb09eb42bb98faaa42ad9f..6749b1829469411315dedac1634b7be974cf21d8 100644 (file)
@@ -948,7 +948,12 @@ static int ti_hecc_probe(struct platform_device *pdev)
        netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll,
                HECC_DEF_NAPI_WEIGHT);
 
-       clk_enable(priv->clk);
+       err = clk_prepare_enable(priv->clk);
+       if (err) {
+               dev_err(&pdev->dev, "clk_prepare_enable() failed\n");
+               goto probe_exit_clk;
+       }
+
        err = register_candev(ndev);
        if (err) {
                dev_err(&pdev->dev, "register_candev() failed\n");
@@ -981,7 +986,7 @@ static int ti_hecc_remove(struct platform_device *pdev)
        struct ti_hecc_priv *priv = netdev_priv(ndev);
 
        unregister_candev(ndev);
-       clk_disable(priv->clk);
+       clk_disable_unprepare(priv->clk);
        clk_put(priv->clk);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        iounmap(priv->base);
@@ -1006,7 +1011,7 @@ static int ti_hecc_suspend(struct platform_device *pdev, pm_message_t state)
        hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
        priv->can.state = CAN_STATE_SLEEPING;
 
-       clk_disable(priv->clk);
+       clk_disable_unprepare(priv->clk);
 
        return 0;
 }
@@ -1015,8 +1020,11 @@ static int ti_hecc_resume(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct ti_hecc_priv *priv = netdev_priv(dev);
+       int err;
 
-       clk_enable(priv->clk);
+       err = clk_prepare_enable(priv->clk);
+       if (err)
+               return err;
 
        hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
        priv->can.state = CAN_STATE_ERROR_ACTIVE;
index 9ec33b51a0edad879701bef79d6c8f250d778b91..2ce7ae97ac9148d39137eff66954dfc3b4cf239b 100644 (file)
@@ -393,7 +393,7 @@ static int bcm_sf2_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
        if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
                return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
        else
-               return mdiobus_read(priv->master_mii_bus, addr, regnum);
+               return mdiobus_read_nested(priv->master_mii_bus, addr, regnum);
 }
 
 static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
@@ -407,7 +407,7 @@ static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
        if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
                bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
        else
-               mdiobus_write(priv->master_mii_bus, addr, regnum, val);
+               mdiobus_write_nested(priv->master_mii_bus, addr, regnum, val);
 
        return 0;
 }
@@ -982,6 +982,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
        const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
        struct device_node *dn = pdev->dev.of_node;
        struct b53_platform_data *pdata;
+       struct dsa_switch_ops *ops;
        struct bcm_sf2_priv *priv;
        struct b53_device *dev;
        struct dsa_switch *ds;
@@ -995,6 +996,10 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       ops = devm_kzalloc(&pdev->dev, sizeof(*ops), GFP_KERNEL);
+       if (!ops)
+               return -ENOMEM;
+
        dev = b53_switch_alloc(&pdev->dev, &bcm_sf2_io_ops, priv);
        if (!dev)
                return -ENOMEM;
@@ -1014,6 +1019,8 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
        ds = dev->ds;
 
        /* Override the parts that are non-standard wrt. normal b53 devices */
+       memcpy(ops, ds->ops, sizeof(*ops));
+       ds->ops = ops;
        ds->ops->get_tag_protocol = bcm_sf2_sw_get_tag_protocol;
        ds->ops->setup = bcm_sf2_sw_setup;
        ds->ops->get_phy_flags = bcm_sf2_sw_get_phy_flags;
index c12d2618eebf76397b2e71eaeb6f2fafa938fea6..3872ab96b80a39eecbb1d0b8150a2e8288915e46 100644 (file)
@@ -1152,6 +1152,12 @@ static void init_ring(struct net_device *dev)
                if (skb == NULL)
                        break;
                np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+               if (pci_dma_mapping_error(np->pci_dev,
+                                         np->rx_info[i].mapping)) {
+                       dev_kfree_skb(skb);
+                       np->rx_info[i].skb = NULL;
+                       break;
+               }
                /* Grrr, we cannot offset to correctly align the IP header. */
                np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
        }
@@ -1182,8 +1188,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
        unsigned int entry;
+       unsigned int prev_tx;
        u32 status;
-       int i;
+       int i, j;
 
        /*
         * be cautious here, wrapping the queue has weird semantics
@@ -1201,6 +1208,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
        }
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
+       prev_tx = np->cur_tx;
        entry = np->cur_tx % TX_RING_SIZE;
        for (i = 0; i < skb_num_frags(skb); i++) {
                int wrap_ring = 0;
@@ -1234,6 +1242,11 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
                                               skb_frag_size(this_frag),
                                               PCI_DMA_TODEVICE);
                }
+               if (pci_dma_mapping_error(np->pci_dev,
+                                         np->tx_info[entry].mapping)) {
+                       dev->stats.tx_dropped++;
+                       goto err_out;
+               }
 
                np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
                np->tx_ring[entry].status = cpu_to_le32(status);
@@ -1268,8 +1281,30 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
                netif_stop_queue(dev);
 
        return NETDEV_TX_OK;
-}
 
+err_out:
+       entry = prev_tx % TX_RING_SIZE;
+       np->tx_info[entry].skb = NULL;
+       if (i > 0) {
+               pci_unmap_single(np->pci_dev,
+                                np->tx_info[entry].mapping,
+                                skb_first_frag_len(skb),
+                                PCI_DMA_TODEVICE);
+               np->tx_info[entry].mapping = 0;
+               entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
+               for (j = 1; j < i; j++) {
+                       pci_unmap_single(np->pci_dev,
+                                        np->tx_info[entry].mapping,
+                                        skb_frag_size(
+                                               &skb_shinfo(skb)->frags[j-1]),
+                                        PCI_DMA_TODEVICE);
+                       entry++;
+               }
+       }
+       dev_kfree_skb_any(skb);
+       np->cur_tx = prev_tx;
+       return NETDEV_TX_OK;
+}
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
@@ -1569,6 +1604,12 @@ static void refill_rx_ring(struct net_device *dev)
                                break;  /* Better luck next round. */
                        np->rx_info[entry].mapping =
                                pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+                       if (pci_dma_mapping_error(np->pci_dev,
+                                               np->rx_info[entry].mapping)) {
+                               dev_kfree_skb(skb);
+                               np->rx_info[entry].skb = NULL;
+                               break;
+                       }
                        np->rx_ring[entry].rxaddr =
                                cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
                }
index 5b7ba25e006522a6143d6c73a9b8141a7ac76f85..8a280e7d66bddc998763288a5756b2ae6a7f70bc 100644 (file)
 #define PCS_V1_WINDOW_SELECT           0x03fc
 #define PCS_V2_WINDOW_DEF              0x9060
 #define PCS_V2_WINDOW_SELECT           0x9064
+#define PCS_V2_RV_WINDOW_DEF           0x1060
+#define PCS_V2_RV_WINDOW_SELECT                0x1064
 
 /* PCS register entry bit positions and sizes */
 #define PCS_V2_WINDOW_DEF_OFFSET_INDEX 6
index aaf0350076a90a1dcd91502b9ce8e4a81cff7174..a7d16db5c4b21d8f9d80d9801259419da8def379 100644 (file)
@@ -1151,7 +1151,7 @@ static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
        offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
        spin_lock_irqsave(&pdata->xpcs_lock, flags);
-       XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
+       XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
        mmd_data = XPCS16_IOREAD(pdata, offset);
        spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
 
@@ -1183,7 +1183,7 @@ static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
        offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
 
        spin_lock_irqsave(&pdata->xpcs_lock, flags);
-       XPCS32_IOWRITE(pdata, PCS_V2_WINDOW_SELECT, index);
+       XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
        XPCS16_IOWRITE(pdata, offset, mmd_data);
        spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
 }
@@ -3407,8 +3407,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata)
 
        /* Flush Tx queues */
        ret = xgbe_flush_tx_queues(pdata);
-       if (ret)
+       if (ret) {
+               netdev_err(pdata->netdev, "error flushing TX queues\n");
                return ret;
+       }
 
        /*
         * Initialize DMA related features
index 155190db682d29a6a97b2267550954fb4eba639d..1c87cc20407590fc84710c9ecb4f8047cf811797 100644 (file)
@@ -539,6 +539,7 @@ static irqreturn_t xgbe_isr(int irq, void *data)
                }
        }
 
+isr_done:
        /* If there is not a separate AN irq, handle it here */
        if (pdata->dev_irq == pdata->an_irq)
                pdata->phy_if.an_isr(irq, pdata);
@@ -551,7 +552,6 @@ static irqreturn_t xgbe_isr(int irq, void *data)
        if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq))
                pdata->i2c_if.i2c_isr(irq, pdata);
 
-isr_done:
        return IRQ_HANDLED;
 }
 
@@ -1070,7 +1070,9 @@ static int xgbe_start(struct xgbe_prv_data *pdata)
 
        DBGPR("-->xgbe_start\n");
 
-       hw_if->init(pdata);
+       ret = hw_if->init(pdata);
+       if (ret)
+               return ret;
 
        xgbe_napi_enable(pdata, 1);
 
index e76b7f65b805171ca81945efb75a44c3c1d7242d..c2730f15bd8b62d2e0487e4eef11f6518a476c39 100644 (file)
@@ -265,6 +265,7 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct xgbe_prv_data *pdata;
        struct device *dev = &pdev->dev;
        void __iomem * const *iomap_table;
+       struct pci_dev *rdev;
        unsigned int ma_lo, ma_hi;
        unsigned int reg;
        int bar_mask;
@@ -326,8 +327,20 @@ static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (netif_msg_probe(pdata))
                dev_dbg(dev, "xpcs_regs  = %p\n", pdata->xpcs_regs);
 
+       /* Set the PCS indirect addressing definition registers */
+       rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+       if (rdev &&
+           (rdev->vendor == PCI_VENDOR_ID_AMD) && (rdev->device == 0x15d0)) {
+               pdata->xpcs_window_def_reg = PCS_V2_RV_WINDOW_DEF;
+               pdata->xpcs_window_sel_reg = PCS_V2_RV_WINDOW_SELECT;
+       } else {
+               pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF;
+               pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT;
+       }
+       pci_dev_put(rdev);
+
        /* Configure the PCS indirect addressing support */
-       reg = XPCS32_IOREAD(pdata, PCS_V2_WINDOW_DEF);
+       reg = XPCS32_IOREAD(pdata, pdata->xpcs_window_def_reg);
        pdata->xpcs_window = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, OFFSET);
        pdata->xpcs_window <<= 6;
        pdata->xpcs_window_size = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, SIZE);
index f52a9bd05baca559d7afd6e1184010d103e1c08a..00108815b55eeb1417bd83bea4c9fbb7aa101fe1 100644 (file)
@@ -955,6 +955,8 @@ struct xgbe_prv_data {
 
        /* XPCS indirect addressing lock */
        spinlock_t xpcs_lock;
+       unsigned int xpcs_window_def_reg;
+       unsigned int xpcs_window_sel_reg;
        unsigned int xpcs_window;
        unsigned int xpcs_window_size;
        unsigned int xpcs_window_mask;
index c8f525574d68c67cbed2899c8461ace4606a7515..7dcc907a449d60adcbeb27cf58434edb0442792b 100644 (file)
@@ -685,8 +685,6 @@ static int alx_alloc_rings(struct alx_priv *alx)
                return -ENOMEM;
        }
 
-       alx_reinit_rings(alx);
-
        return 0;
 }
 
@@ -703,7 +701,7 @@ static void alx_free_rings(struct alx_priv *alx)
        if (alx->qnapi[0] && alx->qnapi[0]->rxq)
                kfree(alx->qnapi[0]->rxq->bufs);
 
-       if (!alx->descmem.virt)
+       if (alx->descmem.virt)
                dma_free_coherent(&alx->hw.pdev->dev,
                                  alx->descmem.size,
                                  alx->descmem.virt,
@@ -984,6 +982,7 @@ static int alx_realloc_resources(struct alx_priv *alx)
        alx_free_rings(alx);
        alx_free_napis(alx);
        alx_disable_advanced_intr(alx);
+       alx_init_intr(alx, false);
 
        err = alx_alloc_napis(alx);
        if (err)
@@ -1241,6 +1240,12 @@ static int __alx_open(struct alx_priv *alx, bool resume)
        if (err)
                goto out_free_rings;
 
+       /* must be called after alx_request_irq because the chip stops working
+        * if we copy the dma addresses in alx_init_ring_ptrs twice when
+        * requesting msi-x interrupts failed
+        */
+       alx_reinit_rings(alx);
+
        netif_set_real_num_tx_queues(alx->dev, alx->num_txq);
        netif_set_real_num_rx_queues(alx->dev, alx->num_rxq);
 
index 3b14d51442280b8a399b0d9b7145bebfc1560597..c483618b57bd7ef93f8522a91814a5dd9d9b0eed 100644 (file)
@@ -913,6 +913,8 @@ static int bcm_enet_open(struct net_device *dev)
                priv->old_link = 0;
                priv->old_duplex = -1;
                priv->old_pause = -1;
+       } else {
+               phydev = NULL;
        }
 
        /* mask all interrupts and request them */
@@ -1083,7 +1085,7 @@ static int bcm_enet_open(struct net_device *dev)
        enet_dmac_writel(priv, priv->dma_chan_int_mask,
                         ENETDMAC_IRMASK, priv->tx_chan);
 
-       if (priv->has_phy)
+       if (phydev)
                phy_start(phydev);
        else
                bcm_enet_adjust_link(dev);
@@ -1126,7 +1128,7 @@ out_freeirq:
        free_irq(dev->irq, dev);
 
 out_phy_disconnect:
-       if (priv->has_phy)
+       if (phydev)
                phy_disconnect(phydev);
 
        return ret;
index 7e8cf213fd813d8530f65c8439a77fd16ffeff9b..744ed6ddaf373964a2b3526a2b73613932c73c87 100644 (file)
@@ -710,11 +710,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
        unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
        unsigned int pkts_compl = 0, bytes_compl = 0;
        struct bcm_sysport_cb *cb;
-       struct netdev_queue *txq;
        u32 hw_ind;
 
-       txq = netdev_get_tx_queue(ndev, ring->index);
-
        /* Compute how many descriptors have been processed since last call */
        hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
        c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
@@ -745,9 +742,6 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
 
        ring->c_index = c_index;
 
-       if (netif_tx_queue_stopped(txq) && pkts_compl)
-               netif_tx_wake_queue(txq);
-
        netif_dbg(priv, tx_done, ndev,
                  "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
                  ring->index, ring->c_index, pkts_compl, bytes_compl);
@@ -759,16 +753,33 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
 static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
                                           struct bcm_sysport_tx_ring *ring)
 {
+       struct netdev_queue *txq;
        unsigned int released;
        unsigned long flags;
 
+       txq = netdev_get_tx_queue(priv->netdev, ring->index);
+
        spin_lock_irqsave(&ring->lock, flags);
        released = __bcm_sysport_tx_reclaim(priv, ring);
+       if (released)
+               netif_tx_wake_queue(txq);
+
        spin_unlock_irqrestore(&ring->lock, flags);
 
        return released;
 }
 
+/* Locked version of the per-ring TX reclaim, but does not wake the queue */
+static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv,
+                                struct bcm_sysport_tx_ring *ring)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ring->lock, flags);
+       __bcm_sysport_tx_reclaim(priv, ring);
+       spin_unlock_irqrestore(&ring->lock, flags);
+}
+
 static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
 {
        struct bcm_sysport_tx_ring *ring =
@@ -1252,7 +1263,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
        napi_disable(&ring->napi);
        netif_napi_del(&ring->napi);
 
-       bcm_sysport_tx_reclaim(priv, ring);
+       bcm_sysport_tx_clean(priv, ring);
 
        kfree(ring->cbs);
        ring->cbs = NULL;
index 9608cb49a11ca3d40c9d497bad10bf94d42433ad..4fcc6a84a087974e5d73042ce1af98268f59bcde 100644 (file)
@@ -1099,7 +1099,7 @@ static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info,
 {
 #ifdef CONFIG_INET
        struct tcphdr *th;
-       int len, nw_off, tcp_opt_len;
+       int len, nw_off, tcp_opt_len = 0;
 
        if (tcp_ts)
                tcp_opt_len = 12;
@@ -5314,17 +5314,12 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
        if ((link_info->support_auto_speeds | diff) !=
            link_info->support_auto_speeds) {
                /* An advertised speed is no longer supported, so we need to
-                * update the advertisement settings.  See bnxt_reset() for
-                * comments about the rtnl_lock() sequence below.
+                * update the advertisement settings.  Caller holds RTNL
+                * so we can modify link settings.
                 */
-               clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
-               rtnl_lock();
                link_info->advertising = link_info->support_auto_speeds;
-               if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
-                   (link_info->autoneg & BNXT_AUTONEG_SPEED))
+               if (link_info->autoneg & BNXT_AUTONEG_SPEED)
                        bnxt_hwrm_set_link_setting(bp, true, false);
-               set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
-               rtnl_unlock();
        }
        return 0;
 }
@@ -6200,29 +6195,37 @@ bnxt_restart_timer:
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
-/* Only called from bnxt_sp_task() */
-static void bnxt_reset(struct bnxt *bp, bool silent)
+static void bnxt_rtnl_lock_sp(struct bnxt *bp)
 {
-       /* bnxt_reset_task() calls bnxt_close_nic() which waits
-        * for BNXT_STATE_IN_SP_TASK to clear.
-        * If there is a parallel dev_close(), bnxt_close() may be holding
+       /* We are called from bnxt_sp_task which has BNXT_STATE_IN_SP_TASK
+        * set.  If the device is being closed, bnxt_close() may be holding
         * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear.  So we
         * must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
         */
        clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
        rtnl_lock();
-       if (test_bit(BNXT_STATE_OPEN, &bp->state))
-               bnxt_reset_task(bp, silent);
+}
+
+static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
+{
        set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
        rtnl_unlock();
 }
 
+/* Only called from bnxt_sp_task() */
+static void bnxt_reset(struct bnxt *bp, bool silent)
+{
+       bnxt_rtnl_lock_sp(bp);
+       if (test_bit(BNXT_STATE_OPEN, &bp->state))
+               bnxt_reset_task(bp, silent);
+       bnxt_rtnl_unlock_sp(bp);
+}
+
 static void bnxt_cfg_ntp_filters(struct bnxt *);
 
 static void bnxt_sp_task(struct work_struct *work)
 {
        struct bnxt *bp = container_of(work, struct bnxt, sp_task);
-       int rc;
 
        set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
        smp_mb__after_atomic();
@@ -6236,16 +6239,6 @@ static void bnxt_sp_task(struct work_struct *work)
 
        if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
                bnxt_cfg_ntp_filters(bp);
-       if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
-               if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
-                                      &bp->sp_event))
-                       bnxt_hwrm_phy_qcaps(bp);
-
-               rc = bnxt_update_link(bp, true);
-               if (rc)
-                       netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
-                                  rc);
-       }
        if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
                bnxt_hwrm_exec_fwd_req(bp);
        if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
@@ -6266,18 +6259,39 @@ static void bnxt_sp_task(struct work_struct *work)
                bnxt_hwrm_tunnel_dst_port_free(
                        bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
        }
+       if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
+               bnxt_hwrm_port_qstats(bp);
+
+       /* These functions below will clear BNXT_STATE_IN_SP_TASK.  They
+        * must be the last functions to be called before exiting.
+        */
+       if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
+               int rc = 0;
+
+               if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
+                                      &bp->sp_event))
+                       bnxt_hwrm_phy_qcaps(bp);
+
+               bnxt_rtnl_lock_sp(bp);
+               if (test_bit(BNXT_STATE_OPEN, &bp->state))
+                       rc = bnxt_update_link(bp, true);
+               bnxt_rtnl_unlock_sp(bp);
+               if (rc)
+                       netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
+                                  rc);
+       }
+       if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) {
+               bnxt_rtnl_lock_sp(bp);
+               if (test_bit(BNXT_STATE_OPEN, &bp->state))
+                       bnxt_get_port_module_status(bp);
+               bnxt_rtnl_unlock_sp(bp);
+       }
        if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
                bnxt_reset(bp, false);
 
        if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
                bnxt_reset(bp, true);
 
-       if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
-               bnxt_get_port_module_status(bp);
-
-       if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
-               bnxt_hwrm_port_qstats(bp);
-
        smp_mb__before_atomic();
        clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 }
index 185e9e047aa9adda61ac602caea5f59c3efe2d7e..ae42de4fdddf6b77d2c2cf1606795e139d4b472b 100644 (file)
@@ -8720,11 +8720,14 @@ static void tg3_free_consistent(struct tg3 *tp)
        tg3_mem_rx_release(tp);
        tg3_mem_tx_release(tp);
 
+       /* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
+       tg3_full_lock(tp, 0);
        if (tp->hw_stats) {
                dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
                                  tp->hw_stats, tp->stats_mapping);
                tp->hw_stats = NULL;
        }
+       tg3_full_unlock(tp);
 }
 
 /*
index c0fb80acc2dad4b91d3b3cb8198be50dc9597fbd..baba2db9d9c25988da94cb323e5d1a6832a12b51 100644 (file)
 #define DEFAULT_RX_RING_SIZE   512 /* must be power of 2 */
 #define MIN_RX_RING_SIZE       64
 #define MAX_RX_RING_SIZE       8192
-#define RX_RING_BYTES(bp)      (sizeof(struct macb_dma_desc)   \
+#define RX_RING_BYTES(bp)      (macb_dma_desc_get_size(bp)     \
                                 * (bp)->rx_ring_size)
 
 #define DEFAULT_TX_RING_SIZE   512 /* must be power of 2 */
 #define MIN_TX_RING_SIZE       64
 #define MAX_TX_RING_SIZE       4096
-#define TX_RING_BYTES(bp)      (sizeof(struct macb_dma_desc)   \
+#define TX_RING_BYTES(bp)      (macb_dma_desc_get_size(bp)     \
                                 * (bp)->tx_ring_size)
 
 /* level of occupied TX descriptors under which we wake up TX process */
  */
 #define MACB_HALT_TIMEOUT      1230
 
+/* DMA buffer descriptor might be different size
+ * depends on hardware configuration.
+ */
+static unsigned int macb_dma_desc_get_size(struct macb *bp)
+{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+               return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
+#endif
+       return sizeof(struct macb_dma_desc);
+}
+
+static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int idx)
+{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+       /* Dma buffer descriptor is 4 words length (instead of 2 words)
+        * for 64b GEM.
+        */
+       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+               idx <<= 1;
+#endif
+       return idx;
+}
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
+{
+       return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+}
+#endif
+
 /* Ring buffer accessors */
 static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
 {
@@ -87,7 +118,9 @@ static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
 static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
                                          unsigned int index)
 {
-       return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)];
+       index = macb_tx_ring_wrap(queue->bp, index);
+       index = macb_adj_dma_desc_idx(queue->bp, index);
+       return &queue->tx_ring[index];
 }
 
 static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
@@ -101,7 +134,7 @@ static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
        dma_addr_t offset;
 
        offset = macb_tx_ring_wrap(queue->bp, index) *
-                sizeof(struct macb_dma_desc);
+                       macb_dma_desc_get_size(queue->bp);
 
        return queue->tx_ring_dma + offset;
 }
@@ -113,7 +146,9 @@ static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
 
 static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
 {
-       return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
+       index = macb_rx_ring_wrap(bp, index);
+       index = macb_adj_dma_desc_idx(bp, index);
+       return &bp->rx_ring[index];
 }
 
 static void *macb_rx_buffer(struct macb *bp, unsigned int index)
@@ -560,12 +595,32 @@ static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb)
        }
 }
 
-static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t addr)
+static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_t addr)
 {
-       desc->addr = (u32)addr;
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       desc->addrh = (u32)(addr >> 32);
+       struct macb_dma_desc_64 *desc_64;
+
+       if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+               desc_64 = macb_64b_desc(bp, desc);
+               desc_64->addrh = upper_32_bits(addr);
+       }
 #endif
+       desc->addr = lower_32_bits(addr);
+}
+
+static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
+{
+       dma_addr_t addr = 0;
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+       struct macb_dma_desc_64 *desc_64;
+
+       if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+               desc_64 = macb_64b_desc(bp, desc);
+               addr = ((u64)(desc_64->addrh) << 32);
+       }
+#endif
+       addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
+       return addr;
 }
 
 static void macb_tx_error_task(struct work_struct *work)
@@ -649,16 +704,17 @@ static void macb_tx_error_task(struct work_struct *work)
 
        /* Set end of TX queue */
        desc = macb_tx_desc(queue, 0);
-       macb_set_addr(desc, 0);
+       macb_set_addr(bp, desc, 0);
        desc->ctrl = MACB_BIT(TX_USED);
 
        /* Make descriptor updates visible to hardware */
        wmb();
 
        /* Reinitialize the TX desc queue */
-       queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
+       queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
+       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+               queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
        /* Make TX ring reflect state of hardware */
        queue->tx_head = 0;
@@ -750,6 +806,7 @@ static void gem_rx_refill(struct macb *bp)
        unsigned int            entry;
        struct sk_buff          *skb;
        dma_addr_t              paddr;
+       struct macb_dma_desc *desc;
 
        while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
                          bp->rx_ring_size) > 0) {
@@ -759,6 +816,7 @@ static void gem_rx_refill(struct macb *bp)
                rmb();
 
                bp->rx_prepared_head++;
+               desc = macb_rx_desc(bp, entry);
 
                if (!bp->rx_skbuff[entry]) {
                        /* allocate sk_buff for this free entry in ring */
@@ -782,14 +840,14 @@ static void gem_rx_refill(struct macb *bp)
 
                        if (entry == bp->rx_ring_size - 1)
                                paddr |= MACB_BIT(RX_WRAP);
-                       macb_set_addr(&(bp->rx_ring[entry]), paddr);
-                       bp->rx_ring[entry].ctrl = 0;
+                       macb_set_addr(bp, desc, paddr);
+                       desc->ctrl = 0;
 
                        /* properly align Ethernet header */
                        skb_reserve(skb, NET_IP_ALIGN);
                } else {
-                       bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED);
-                       bp->rx_ring[entry].ctrl = 0;
+                       desc->addr &= ~MACB_BIT(RX_USED);
+                       desc->ctrl = 0;
                }
        }
 
@@ -835,16 +893,13 @@ static int gem_rx(struct macb *bp, int budget)
                bool rxused;
 
                entry = macb_rx_ring_wrap(bp, bp->rx_tail);
-               desc = &bp->rx_ring[entry];
+               desc = macb_rx_desc(bp, entry);
 
                /* Make hw descriptor updates visible to CPU */
                rmb();
 
                rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
-               addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               addr |= ((u64)(desc->addrh) << 32);
-#endif
+               addr = macb_get_addr(bp, desc);
                ctrl = desc->ctrl;
 
                if (!rxused)
@@ -987,15 +1042,17 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
 static inline void macb_init_rx_ring(struct macb *bp)
 {
        dma_addr_t addr;
+       struct macb_dma_desc *desc = NULL;
        int i;
 
        addr = bp->rx_buffers_dma;
        for (i = 0; i < bp->rx_ring_size; i++) {
-               bp->rx_ring[i].addr = addr;
-               bp->rx_ring[i].ctrl = 0;
+               desc = macb_rx_desc(bp, i);
+               macb_set_addr(bp, desc, addr);
+               desc->ctrl = 0;
                addr += bp->rx_buffer_size;
        }
-       bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
+       desc->addr |= MACB_BIT(RX_WRAP);
        bp->rx_tail = 0;
 }
 
@@ -1008,15 +1065,14 @@ static int macb_rx(struct macb *bp, int budget)
 
        for (tail = bp->rx_tail; budget > 0; tail++) {
                struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
-               u32 addr, ctrl;
+               u32 ctrl;
 
                /* Make hw descriptor updates visible to CPU */
                rmb();
 
-               addr = desc->addr;
                ctrl = desc->ctrl;
 
-               if (!(addr & MACB_BIT(RX_USED)))
+               if (!(desc->addr & MACB_BIT(RX_USED)))
                        break;
 
                if (ctrl & MACB_BIT(RX_SOF)) {
@@ -1336,7 +1392,7 @@ static unsigned int macb_tx_map(struct macb *bp,
        i = tx_head;
        entry = macb_tx_ring_wrap(bp, i);
        ctrl = MACB_BIT(TX_USED);
-       desc = &queue->tx_ring[entry];
+       desc = macb_tx_desc(queue, entry);
        desc->ctrl = ctrl;
 
        if (lso_ctrl) {
@@ -1358,7 +1414,7 @@ static unsigned int macb_tx_map(struct macb *bp,
                i--;
                entry = macb_tx_ring_wrap(bp, i);
                tx_skb = &queue->tx_skb[entry];
-               desc = &queue->tx_ring[entry];
+               desc = macb_tx_desc(queue, entry);
 
                ctrl = (u32)tx_skb->size;
                if (eof) {
@@ -1379,7 +1435,7 @@ static unsigned int macb_tx_map(struct macb *bp,
                        ctrl |= MACB_BF(MSS_MFS, mss_mfs);
 
                /* Set TX buffer descriptor */
-               macb_set_addr(desc, tx_skb->mapping);
+               macb_set_addr(bp, desc, tx_skb->mapping);
                /* desc->addr must be visible to hardware before clearing
                 * 'TX_USED' bit in desc->ctrl.
                 */
@@ -1586,11 +1642,9 @@ static void gem_free_rx_buffers(struct macb *bp)
                if (!skb)
                        continue;
 
-               desc = &bp->rx_ring[i];
-               addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               addr |= ((u64)(desc->addrh) << 32);
-#endif
+               desc = macb_rx_desc(bp, i);
+               addr = macb_get_addr(bp, desc);
+
                dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
                                 DMA_FROM_DEVICE);
                dev_kfree_skb_any(skb);
@@ -1711,15 +1765,17 @@ out_err:
 static void gem_init_rings(struct macb *bp)
 {
        struct macb_queue *queue;
+       struct macb_dma_desc *desc = NULL;
        unsigned int q;
        int i;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
                for (i = 0; i < bp->tx_ring_size; i++) {
-                       queue->tx_ring[i].addr = 0;
-                       queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+                       desc = macb_tx_desc(queue, i);
+                       macb_set_addr(bp, desc, 0);
+                       desc->ctrl = MACB_BIT(TX_USED);
                }
-               queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
+               desc->ctrl |= MACB_BIT(TX_WRAP);
                queue->tx_head = 0;
                queue->tx_tail = 0;
        }
@@ -1733,16 +1789,18 @@ static void gem_init_rings(struct macb *bp)
 static void macb_init_rings(struct macb *bp)
 {
        int i;
+       struct macb_dma_desc *desc = NULL;
 
        macb_init_rx_ring(bp);
 
        for (i = 0; i < bp->tx_ring_size; i++) {
-               bp->queues[0].tx_ring[i].addr = 0;
-               bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
+               desc = macb_tx_desc(&bp->queues[0], i);
+               macb_set_addr(bp, desc, 0);
+               desc->ctrl = MACB_BIT(TX_USED);
        }
        bp->queues[0].tx_head = 0;
        bp->queues[0].tx_tail = 0;
-       bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
+       desc->ctrl |= MACB_BIT(TX_WRAP);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -1863,7 +1921,8 @@ static void macb_configure_dma(struct macb *bp)
                        dmacfg &= ~GEM_BIT(TXCOEN);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               dmacfg |= GEM_BIT(ADDR64);
+               if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+                       dmacfg |= GEM_BIT(ADDR64);
 #endif
                netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
                           dmacfg);
@@ -1910,14 +1969,16 @@ static void macb_init_hw(struct macb *bp)
        macb_configure_dma(bp);
 
        /* Initialize TX and RX buffers */
-       macb_writel(bp, RBQP, (u32)(bp->rx_ring_dma));
+       macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       macb_writel(bp, RBQPH, (u32)(bp->rx_ring_dma >> 32));
+       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+               macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
 #endif
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
+               queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-               queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
+               if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+                       queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
 
                /* Enable interrupts */
@@ -2627,7 +2688,8 @@ static int macb_init(struct platform_device *pdev)
                        queue->IMR  = GEM_IMR(hw_q - 1);
                        queue->TBQP = GEM_TBQP(hw_q - 1);
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-                       queue->TBQPH = GEM_TBQPH(hw_q -1);
+                       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+                               queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
                } else {
                        /* queue0 uses legacy registers */
@@ -2637,7 +2699,8 @@ static int macb_init(struct platform_device *pdev)
                        queue->IMR  = MACB_IMR;
                        queue->TBQP = MACB_TBQP;
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-                       queue->TBQPH = MACB_TBQPH;
+                       if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+                               queue->TBQPH = MACB_TBQPH;
 #endif
                }
 
@@ -2730,13 +2793,14 @@ static int macb_init(struct platform_device *pdev)
 static int at91ether_start(struct net_device *dev)
 {
        struct macb *lp = netdev_priv(dev);
+       struct macb_dma_desc *desc;
        dma_addr_t addr;
        u32 ctl;
        int i;
 
        lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
                                         (AT91ETHER_MAX_RX_DESCR *
-                                         sizeof(struct macb_dma_desc)),
+                                         macb_dma_desc_get_size(lp)),
                                         &lp->rx_ring_dma, GFP_KERNEL);
        if (!lp->rx_ring)
                return -ENOMEM;
@@ -2748,7 +2812,7 @@ static int at91ether_start(struct net_device *dev)
        if (!lp->rx_buffers) {
                dma_free_coherent(&lp->pdev->dev,
                                  AT91ETHER_MAX_RX_DESCR *
-                                 sizeof(struct macb_dma_desc),
+                                 macb_dma_desc_get_size(lp),
                                  lp->rx_ring, lp->rx_ring_dma);
                lp->rx_ring = NULL;
                return -ENOMEM;
@@ -2756,13 +2820,14 @@ static int at91ether_start(struct net_device *dev)
 
        addr = lp->rx_buffers_dma;
        for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
-               lp->rx_ring[i].addr = addr;
-               lp->rx_ring[i].ctrl = 0;
+               desc = macb_rx_desc(lp, i);
+               macb_set_addr(lp, desc, addr);
+               desc->ctrl = 0;
                addr += AT91ETHER_MAX_RBUFF_SZ;
        }
 
        /* Set the Wrap bit on the last descriptor */
-       lp->rx_ring[AT91ETHER_MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
+       desc->addr |= MACB_BIT(RX_WRAP);
 
        /* Reset buffer index */
        lp->rx_tail = 0;
@@ -2834,7 +2899,7 @@ static int at91ether_close(struct net_device *dev)
 
        dma_free_coherent(&lp->pdev->dev,
                          AT91ETHER_MAX_RX_DESCR *
-                         sizeof(struct macb_dma_desc),
+                         macb_dma_desc_get_size(lp),
                          lp->rx_ring, lp->rx_ring_dma);
        lp->rx_ring = NULL;
 
@@ -2885,13 +2950,15 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static void at91ether_rx(struct net_device *dev)
 {
        struct macb *lp = netdev_priv(dev);
+       struct macb_dma_desc *desc;
        unsigned char *p_recv;
        struct sk_buff *skb;
        unsigned int pktlen;
 
-       while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+       desc = macb_rx_desc(lp, lp->rx_tail);
+       while (desc->addr & MACB_BIT(RX_USED)) {
                p_recv = lp->rx_buffers + lp->rx_tail * AT91ETHER_MAX_RBUFF_SZ;
-               pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
+               pktlen = MACB_BF(RX_FRMLEN, desc->ctrl);
                skb = netdev_alloc_skb(dev, pktlen + 2);
                if (skb) {
                        skb_reserve(skb, 2);
@@ -2905,17 +2972,19 @@ static void at91ether_rx(struct net_device *dev)
                        lp->stats.rx_dropped++;
                }
 
-               if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+               if (desc->ctrl & MACB_BIT(RX_MHASH_MATCH))
                        lp->stats.multicast++;
 
                /* reset ownership bit */
-               lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
+               desc->addr &= ~MACB_BIT(RX_USED);
 
                /* wrap after last buffer */
                if (lp->rx_tail == AT91ETHER_MAX_RX_DESCR - 1)
                        lp->rx_tail = 0;
                else
                        lp->rx_tail++;
+
+               desc = macb_rx_desc(lp, lp->rx_tail);
        }
 }
 
@@ -3211,8 +3280,11 @@ static int macb_probe(struct platform_device *pdev)
        device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       if (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1)) > GEM_DBW32)
+       if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
                dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+               bp->hw_dma_cap = HW_DMA_CAP_64B;
+       } else
+               bp->hw_dma_cap = HW_DMA_CAP_32B;
 #endif
 
        spin_lock_init(&bp->lock);
index d67adad67be1c097a339d993a866597b4d202f4d..fc8550a5d47f75df540521c27f07f5c2d03995f9 100644 (file)
 /* Bitfields in DCFG6. */
 #define GEM_PBUF_LSO_OFFSET                    27
 #define GEM_PBUF_LSO_SIZE                      1
+#define GEM_DAW64_OFFSET                       23
+#define GEM_DAW64_SIZE                         1
 
 /* Constants for CLK */
 #define MACB_CLK_DIV8                          0
 struct macb_dma_desc {
        u32     addr;
        u32     ctrl;
+};
+
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-       u32     addrh;
-       u32     resvd;
-#endif
+enum macb_hw_dma_cap {
+       HW_DMA_CAP_32B,
+       HW_DMA_CAP_64B,
 };
 
+struct macb_dma_desc_64 {
+       u32 addrh;
+       u32 resvd;
+};
+#endif
+
 /* DMA descriptor bitfields */
 #define MACB_RX_USED_OFFSET                    0
 #define MACB_RX_USED_SIZE                      1
@@ -874,6 +884,10 @@ struct macb {
        unsigned int            jumbo_max_len;
 
        u32                     wol;
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+       enum macb_hw_dma_cap hw_dma_cap;
+#endif
 };
 
 static inline bool macb_is_gem(struct macb *bp)
index 9211c750e0642660bfdd79bb023f9058a89c18af..1e4695270da6cc422c441542783a0ae24dd943a6 100644 (file)
@@ -31,6 +31,7 @@ struct lmac {
        u8                      lmac_type;
        u8                      lane_to_sds;
        bool                    use_training;
+       bool                    autoneg;
        bool                    link_up;
        int                     lmacid; /* ID within BGX */
        int                     lmacid_bd; /* ID on board */
@@ -47,8 +48,9 @@ struct lmac {
 struct bgx {
        u8                      bgx_id;
        struct  lmac            lmac[MAX_LMAC_PER_BGX];
-       int                     lmac_count;
+       u8                      lmac_count;
        u8                      max_lmac;
+       u8                      acpi_lmac_idx;
        void __iomem            *reg_base;
        struct pci_dev          *pdev;
        bool                    is_dlm;
@@ -460,7 +462,17 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
        /* power down, reset autoneg, autoneg enable */
        cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL);
        cfg &= ~PCS_MRX_CTL_PWR_DN;
-       cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN);
+       cfg |= PCS_MRX_CTL_RST_AN;
+       if (lmac->phydev) {
+               cfg |= PCS_MRX_CTL_AN_EN;
+       } else {
+               /* In scenarios where PHY driver is not present or it's a
+                * non-standard PHY, FW sets AN_EN to inform Linux driver
+                * to do auto-neg and link polling or not.
+                */
+               if (cfg & PCS_MRX_CTL_AN_EN)
+                       lmac->autoneg = true;
+       }
        bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);
 
        if (lmac->lmac_type == BGX_MODE_QSGMII) {
@@ -471,7 +483,7 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
                return 0;
        }
 
-       if (lmac->lmac_type == BGX_MODE_SGMII) {
+       if ((lmac->lmac_type == BGX_MODE_SGMII) && lmac->phydev) {
                if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
                                 PCS_MRX_STATUS_AN_CPT, false)) {
                        dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
@@ -677,12 +689,71 @@ static int bgx_xaui_check_link(struct lmac *lmac)
        return -1;
 }
 
+static void bgx_poll_for_sgmii_link(struct lmac *lmac)
+{
+       u64 pcs_link, an_result;
+       u8 speed;
+
+       pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
+                               BGX_GMP_PCS_MRX_STATUS);
+
+       /*Link state bit is sticky, read it again*/
+       if (!(pcs_link & PCS_MRX_STATUS_LINK))
+               pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
+                                       BGX_GMP_PCS_MRX_STATUS);
+
+       if (bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_GMP_PCS_MRX_STATUS,
+                        PCS_MRX_STATUS_AN_CPT, false)) {
+               lmac->link_up = false;
+               lmac->last_speed = SPEED_UNKNOWN;
+               lmac->last_duplex = DUPLEX_UNKNOWN;
+               goto next_poll;
+       }
+
+       lmac->link_up = ((pcs_link & PCS_MRX_STATUS_LINK) != 0) ? true : false;
+       an_result = bgx_reg_read(lmac->bgx, lmac->lmacid,
+                                BGX_GMP_PCS_ANX_AN_RESULTS);
+
+       speed = (an_result >> 3) & 0x3;
+       lmac->last_duplex = (an_result >> 1) & 0x1;
+       switch (speed) {
+       case 0:
+               lmac->last_speed = 10;
+               break;
+       case 1:
+               lmac->last_speed = 100;
+               break;
+       case 2:
+               lmac->last_speed = 1000;
+               break;
+       default:
+               lmac->link_up = false;
+               lmac->last_speed = SPEED_UNKNOWN;
+               lmac->last_duplex = DUPLEX_UNKNOWN;
+               break;
+       }
+
+next_poll:
+
+       if (lmac->last_link != lmac->link_up) {
+               if (lmac->link_up)
+                       bgx_sgmii_change_link_state(lmac);
+               lmac->last_link = lmac->link_up;
+       }
+
+       queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 3);
+}
+
 static void bgx_poll_for_link(struct work_struct *work)
 {
        struct lmac *lmac;
        u64 spu_link, smu_link;
 
        lmac = container_of(work, struct lmac, dwork.work);
+       if (lmac->is_sgmii) {
+               bgx_poll_for_sgmii_link(lmac);
+               return;
+       }
 
        /* Receive link is latching low. Force it high and verify it */
        bgx_reg_modify(lmac->bgx, lmac->lmacid,
@@ -774,9 +845,21 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
            (lmac->lmac_type != BGX_MODE_XLAUI) &&
            (lmac->lmac_type != BGX_MODE_40G_KR) &&
            (lmac->lmac_type != BGX_MODE_10G_KR)) {
-               if (!lmac->phydev)
-                       return -ENODEV;
-
+               if (!lmac->phydev) {
+                       if (lmac->autoneg) {
+                               bgx_reg_write(bgx, lmacid,
+                                             BGX_GMP_PCS_LINKX_TIMER,
+                                             PCS_LINKX_TIMER_COUNT);
+                               goto poll;
+                       } else {
+                               /* Default to below link speed and duplex */
+                               lmac->link_up = true;
+                               lmac->last_speed = 1000;
+                               lmac->last_duplex = 1;
+                               bgx_sgmii_change_link_state(lmac);
+                               return 0;
+                       }
+               }
                lmac->phydev->dev_flags = 0;
 
                if (phy_connect_direct(&lmac->netdev, lmac->phydev,
@@ -785,15 +868,17 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
                        return -ENODEV;
 
                phy_start_aneg(lmac->phydev);
-       } else {
-               lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
-                                                  WQ_MEM_RECLAIM, 1);
-               if (!lmac->check_link)
-                       return -ENOMEM;
-               INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
-               queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
+               return 0;
        }
 
+poll:
+       lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
+                                          WQ_MEM_RECLAIM, 1);
+       if (!lmac->check_link)
+               return -ENOMEM;
+       INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
+       queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
+
        return 0;
 }
 
@@ -1143,13 +1228,13 @@ static acpi_status bgx_acpi_register_phy(acpi_handle handle,
        if (acpi_bus_get_device(handle, &adev))
                goto out;
 
-       acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac);
+       acpi_get_mac_address(dev, adev, bgx->lmac[bgx->acpi_lmac_idx].mac);
 
-       SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev);
+       SET_NETDEV_DEV(&bgx->lmac[bgx->acpi_lmac_idx].netdev, dev);
 
-       bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count;
+       bgx->lmac[bgx->acpi_lmac_idx].lmacid = bgx->acpi_lmac_idx;
+       bgx->acpi_lmac_idx++; /* move to next LMAC */
 out:
-       bgx->lmac_count++;
        return AE_OK;
 }
 
index c18ebfeb203919ea9b16e406bb678bd05a98a656..a60f189429bb658cb5ab8383982f86ddd9090fc3 100644 (file)
 #define         PCS_MRX_CTL_LOOPBACK1                  BIT_ULL(14)
 #define         PCS_MRX_CTL_RESET                      BIT_ULL(15)
 #define BGX_GMP_PCS_MRX_STATUS         0x30008
+#define         PCS_MRX_STATUS_LINK                    BIT_ULL(2)
 #define         PCS_MRX_STATUS_AN_CPT                  BIT_ULL(5)
+#define BGX_GMP_PCS_ANX_ADV            0x30010
 #define BGX_GMP_PCS_ANX_AN_RESULTS     0x30020
+#define BGX_GMP_PCS_LINKX_TIMER                0x30040
+#define PCS_LINKX_TIMER_COUNT                  0x1E84
 #define BGX_GMP_PCS_SGM_AN_ADV         0x30068
 #define BGX_GMP_PCS_MISCX_CTL          0x30078
+#define  PCS_MISC_CTL_MODE                     BIT_ULL(8)
 #define  PCS_MISC_CTL_DISP_EN                  BIT_ULL(13)
 #define  PCS_MISC_CTL_GMX_ENO                  BIT_ULL(11)
 #define  PCS_MISC_CTL_SAMP_PT_MASK     0x7Full
index 67befedef7098ddbde763738eb7940116efa283e..578c7f8f11bf23add2ac4d3c2263e371b4509136 100644 (file)
@@ -116,8 +116,7 @@ void xcv_setup_link(bool link_up, int link_speed)
        int speed = 2;
 
        if (!xcv) {
-               dev_err(&xcv->pdev->dev,
-                       "XCV init not done, probe may have failed\n");
+               pr_err("XCV init not done, probe may have failed\n");
                return;
        }
 
index 0e74529a42095b311c97dc367c2ba3b20bdfc27c..30e855004c57592f9ab6c0cea2eb73f63b59b7ca 100644 (file)
@@ -1118,7 +1118,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
 err:
        mutex_unlock(&adapter->mcc_lock);
 
-        if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
+        if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
                status = -EPERM;
 
        return status;
index 225e9a4877d7b16e058cfa7c0dac9ccb5434bb5b..cd49a54c538d5202f1bb0cb632b8fdb306a66989 100644 (file)
@@ -275,8 +275,7 @@ static int be_dev_mac_add(struct be_adapter *adapter, u8 *mac)
 
        /* Check if mac has already been added as part of uc-list */
        for (i = 0; i < adapter->uc_macs; i++) {
-               if (ether_addr_equal((u8 *)&adapter->uc_list[i * ETH_ALEN],
-                                    mac)) {
+               if (ether_addr_equal(adapter->uc_list[i].mac, mac)) {
                        /* mac already added, skip addition */
                        adapter->pmac_id[0] = adapter->pmac_id[i + 1];
                        return 0;
@@ -319,6 +318,13 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
        if (ether_addr_equal(addr->sa_data, adapter->dev_mac))
                return 0;
 
+       /* BE3 VFs without FILTMGMT privilege are not allowed to set its MAC
+        * address
+        */
+       if (BEx_chip(adapter) && be_virtfn(adapter) &&
+           !check_privilege(adapter, BE_PRIV_FILTMGMT))
+               return -EPERM;
+
        /* if device is not running, copy MAC to netdev->dev_addr */
        if (!netif_running(netdev))
                goto done;
@@ -356,8 +362,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
                status = -EPERM;
                goto err;
        }
-done:
+
+       /* Remember currently programmed MAC */
        ether_addr_copy(adapter->dev_mac, addr->sa_data);
+done:
        ether_addr_copy(netdev->dev_addr, addr->sa_data);
        dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
        return 0;
@@ -1655,14 +1663,12 @@ static void be_clear_mc_list(struct be_adapter *adapter)
 
 static int be_uc_mac_add(struct be_adapter *adapter, int uc_idx)
 {
-       if (ether_addr_equal((u8 *)&adapter->uc_list[uc_idx * ETH_ALEN],
-                            adapter->dev_mac)) {
+       if (ether_addr_equal(adapter->uc_list[uc_idx].mac, adapter->dev_mac)) {
                adapter->pmac_id[uc_idx + 1] = adapter->pmac_id[0];
                return 0;
        }
 
-       return be_cmd_pmac_add(adapter,
-                              (u8 *)&adapter->uc_list[uc_idx * ETH_ALEN],
+       return be_cmd_pmac_add(adapter, adapter->uc_list[uc_idx].mac,
                               adapter->if_handle,
                               &adapter->pmac_id[uc_idx + 1], 0);
 }
@@ -1698,9 +1704,8 @@ static void be_set_uc_list(struct be_adapter *adapter)
        }
 
        if (adapter->update_uc_list) {
-               i = 1; /* First slot is claimed by the Primary MAC */
-
                /* cache the uc-list in adapter array */
+               i = 0;
                netdev_for_each_uc_addr(ha, netdev) {
                        ether_addr_copy(adapter->uc_list[i].mac, ha->addr);
                        i++;
@@ -3613,7 +3618,13 @@ static void be_rx_qs_destroy(struct be_adapter *adapter)
 
 static void be_disable_if_filters(struct be_adapter *adapter)
 {
-       be_dev_mac_del(adapter, adapter->pmac_id[0]);
+       /* Don't delete MAC on BE3 VFs without FILTMGMT privilege  */
+       if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
+           check_privilege(adapter, BE_PRIV_FILTMGMT)) {
+               be_dev_mac_del(adapter, adapter->pmac_id[0]);
+               eth_zero_addr(adapter->dev_mac);
+       }
+
        be_clear_uc_list(adapter);
        be_clear_mc_list(adapter);
 
@@ -3766,11 +3777,27 @@ static int be_enable_if_filters(struct be_adapter *adapter)
        if (status)
                return status;
 
-       /* For BE3 VFs, the PF programs the initial MAC address */
-       if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
+       /* Normally this condition usually true as the ->dev_mac is zeroed.
+        * But on BE3 VFs the initial MAC is pre-programmed by PF and
+        * subsequent be_dev_mac_add() can fail (after fresh boot)
+        */
+       if (!ether_addr_equal(adapter->dev_mac, adapter->netdev->dev_addr)) {
+               int old_pmac_id = -1;
+
+               /* Remember old programmed MAC if any - can happen on BE3 VF */
+               if (!is_zero_ether_addr(adapter->dev_mac))
+                       old_pmac_id = adapter->pmac_id[0];
+
                status = be_dev_mac_add(adapter, adapter->netdev->dev_addr);
                if (status)
                        return status;
+
+               /* Delete the old programmed MAC as we successfully programmed
+                * a new MAC
+                */
+               if (old_pmac_id >= 0 && old_pmac_id != adapter->pmac_id[0])
+                       be_dev_mac_del(adapter, old_pmac_id);
+
                ether_addr_copy(adapter->dev_mac, adapter->netdev->dev_addr);
        }
 
@@ -4544,6 +4571,10 @@ static int be_mac_setup(struct be_adapter *adapter)
 
                memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
                memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
+
+               /* Initial MAC for BE3 VFs is already programmed by PF */
+               if (BEx_chip(adapter) && be_virtfn(adapter))
+                       memcpy(adapter->dev_mac, mac, ETH_ALEN);
        }
 
        return 0;
index c9b7ad65e5633bc2a5147706f5c728f4d1cffa3c..726b5693ae8a5a3a9364e5de13195d36c5b1d06f 100644 (file)
@@ -1668,7 +1668,7 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
 
 free_buffers:
        /* compensate sw bpool counter changes */
-       for (i--; i > 0; i--) {
+       for (i--; i >= 0; i--) {
                dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
                if (dpaa_bp) {
                        count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
index 38160c2bebcb33a0214c5add50a2c71fc439ef5f..8be7034b2e7ba4168ab962b951419a498ca9cc7d 100644 (file)
@@ -2910,6 +2910,7 @@ static void set_multicast_list(struct net_device *ndev)
        struct netdev_hw_addr *ha;
        unsigned int i, bit, data, crc, tmp;
        unsigned char hash;
+       unsigned int hash_high = 0, hash_low = 0;
 
        if (ndev->flags & IFF_PROMISC) {
                tmp = readl(fep->hwp + FEC_R_CNTRL);
@@ -2932,11 +2933,7 @@ static void set_multicast_list(struct net_device *ndev)
                return;
        }
 
-       /* Clear filter and add the addresses in hash register
-        */
-       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-       writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-
+       /* Add the addresses in hash register */
        netdev_for_each_mc_addr(ha, ndev) {
                /* calculate crc32 value of mac address */
                crc = 0xffffffff;
@@ -2954,16 +2951,14 @@ static void set_multicast_list(struct net_device *ndev)
                 */
                hash = (crc >> (32 - FEC_HASH_BITS)) & 0x3f;
 
-               if (hash > 31) {
-                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-                       tmp |= 1 << (hash - 32);
-                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
-               } else {
-                       tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-                       tmp |= 1 << hash;
-                       writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
-               }
+               if (hash > 31)
+                       hash_high |= 1 << (hash - 32);
+               else
+                       hash_low |= 1 << hash;
        }
+
+       writel(hash_high, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
+       writel(hash_low, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 }
 
 /* Set a MAC change in hardware. */
index a6e7afa878befd1abe00404b2cd4becfa174d103..957bfc220978479a5ccee32b58ae26d4236fe939 100644 (file)
@@ -2010,8 +2010,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
                if (!rxb->page)
                        continue;
 
-               dma_unmap_single(rx_queue->dev, rxb->dma,
-                                PAGE_SIZE, DMA_FROM_DEVICE);
+               dma_unmap_page(rx_queue->dev, rxb->dma,
+                              PAGE_SIZE, DMA_FROM_DEVICE);
                __free_page(rxb->page);
 
                rxb->page = NULL;
@@ -2948,7 +2948,7 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus,
        }
 
        /* try reuse page */
-       if (unlikely(page_count(page) != 1))
+       if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page)))
                return false;
 
        /* change offset to the other half */
index 87226685f74215a2093e59a99bd8042a2e2585c5..8fa18fc17cd2e25f2e3458e608abe6f5a96b60d9 100644 (file)
 
 static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
 {
-       u8 __iomem *reg_addr = ACCESS_ONCE(base);
-
-       writel(value, reg_addr + reg);
+       writel(value, base + reg);
 }
 
 #define dsaf_write_dev(a, reg, value) \
@@ -1024,9 +1022,7 @@ static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
 
 static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg)
 {
-       u8 __iomem *reg_addr = ACCESS_ONCE(base);
-
-       return readl(reg_addr + reg);
+       return readl(base + reg);
 }
 
 static inline void dsaf_write_syscon(struct regmap *base, u32 reg, u32 value)
index 672b64606321c3a1e2ab8eb9be8666ad04713d5f..8aed72860e7c0eece690c97ae38b1fbedfa58557 100644 (file)
@@ -305,8 +305,8 @@ int hns_nic_net_xmit_hw(struct net_device *ndev,
                        struct hns_nic_ring_data *ring_data)
 {
        struct hns_nic_priv *priv = netdev_priv(ndev);
-       struct device *dev = priv->dev;
        struct hnae_ring *ring = ring_data->ring;
+       struct device *dev = ring_to_dev(ring);
        struct netdev_queue *dev_queue;
        struct skb_frag_struct *frag;
        int buf_num;
index a831f947ca8c1157737a18b69c611105442f9276..309f5c66083cf504e8beaeff9f4575e40c646063 100644 (file)
@@ -1601,8 +1601,11 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
        netdev->netdev_ops = &ibmveth_netdev_ops;
        netdev->ethtool_ops = &netdev_ethtool_ops;
        SET_NETDEV_DEV(netdev, &dev->dev);
-       netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+       netdev->hw_features = NETIF_F_SG;
+       if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) {
+               netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+                                      NETIF_F_RXCSUM;
+       }
 
        netdev->features |= netdev->hw_features;
 
index c12596676bbbba5ef426b1e8463e7080bdd2539b..a07b8d79174cd0aa4f338df7214ea4e9601076dc 100644 (file)
@@ -189,9 +189,10 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
        }
        ltb->map_id = adapter->map_id;
        adapter->map_id++;
+
+       init_completion(&adapter->fw_done);
        send_request_map(adapter, ltb->addr,
                         ltb->size, ltb->map_id);
-       init_completion(&adapter->fw_done);
        wait_for_completion(&adapter->fw_done);
        return 0;
 }
@@ -505,7 +506,7 @@ rx_pool_alloc_failed:
        adapter->rx_pool = NULL;
 rx_pool_arr_alloc_failed:
        for (i = 0; i < adapter->req_rx_queues; i++)
-               napi_enable(&adapter->napi[i]);
+               napi_disable(&adapter->napi[i]);
 alloc_napi_failed:
        return -ENOMEM;
 }
@@ -1121,10 +1122,10 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
        crq.request_statistics.ioba = cpu_to_be32(adapter->stats_token);
        crq.request_statistics.len =
            cpu_to_be32(sizeof(struct ibmvnic_statistics));
-       ibmvnic_send_crq(adapter, &crq);
 
        /* Wait for data to be written */
        init_completion(&adapter->stats_done);
+       ibmvnic_send_crq(adapter, &crq);
        wait_for_completion(&adapter->stats_done);
 
        for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
@@ -1496,7 +1497,7 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry)
                adapter->req_rx_queues = adapter->opt_rx_comp_queues;
                adapter->req_rx_add_queues = adapter->max_rx_add_queues;
 
-               adapter->req_mtu = adapter->max_mtu;
+               adapter->req_mtu = adapter->netdev->mtu + ETH_HLEN;
        }
 
        total_queues = adapter->req_tx_queues + adapter->req_rx_queues;
@@ -2185,12 +2186,12 @@ static void handle_error_info_rsp(union ibmvnic_crq *crq,
 
        if (!found) {
                dev_err(dev, "Couldn't find error id %x\n",
-                       crq->request_error_rsp.error_id);
+                       be32_to_cpu(crq->request_error_rsp.error_id));
                return;
        }
 
        dev_err(dev, "Detailed info for error id %x:",
-               crq->request_error_rsp.error_id);
+               be32_to_cpu(crq->request_error_rsp.error_id));
 
        for (i = 0; i < error_buff->len; i++) {
                pr_cont("%02x", (int)error_buff->buff[i]);
@@ -2269,8 +2270,8 @@ static void handle_error_indication(union ibmvnic_crq *crq,
        dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
                crq->error_indication.
                    flags & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
-               crq->error_indication.error_id,
-               crq->error_indication.error_cause);
+               be32_to_cpu(crq->error_indication.error_id),
+               be16_to_cpu(crq->error_indication.error_cause));
 
        error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC);
        if (!error_buff)
@@ -2388,10 +2389,10 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
        case PARTIALSUCCESS:
                dev_info(dev, "req=%lld, rsp=%ld in %s queue, retrying.\n",
                         *req_value,
-                        (long int)be32_to_cpu(crq->request_capability_rsp.
+                        (long int)be64_to_cpu(crq->request_capability_rsp.
                                               number), name);
                release_sub_crqs_no_irqs(adapter);
-               *req_value = be32_to_cpu(crq->request_capability_rsp.number);
+               *req_value = be64_to_cpu(crq->request_capability_rsp.number);
                init_sub_crqs(adapter, 1);
                return;
        default:
@@ -2626,12 +2627,12 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
                break;
        case MIN_MTU:
                adapter->min_mtu = be64_to_cpu(crq->query_capability.number);
-               netdev->min_mtu = adapter->min_mtu;
+               netdev->min_mtu = adapter->min_mtu - ETH_HLEN;
                netdev_dbg(netdev, "min_mtu = %lld\n", adapter->min_mtu);
                break;
        case MAX_MTU:
                adapter->max_mtu = be64_to_cpu(crq->query_capability.number);
-               netdev->max_mtu = adapter->max_mtu;
+               netdev->max_mtu = adapter->max_mtu - ETH_HLEN;
                netdev_dbg(netdev, "max_mtu = %lld\n", adapter->max_mtu);
                break;
        case MAX_MULTICAST_FILTERS:
@@ -2799,9 +2800,9 @@ static ssize_t trace_read(struct file *file, char __user *user_buf, size_t len,
        crq.collect_fw_trace.correlator = adapter->ras_comps[num].correlator;
        crq.collect_fw_trace.ioba = cpu_to_be32(trace_tok);
        crq.collect_fw_trace.len = adapter->ras_comps[num].trace_buff_size;
-       ibmvnic_send_crq(adapter, &crq);
 
        init_completion(&adapter->fw_done);
+       ibmvnic_send_crq(adapter, &crq);
        wait_for_completion(&adapter->fw_done);
 
        if (*ppos + len > be32_to_cpu(adapter->ras_comps[num].trace_buff_size))
@@ -3581,9 +3582,9 @@ static int ibmvnic_dump_show(struct seq_file *seq, void *v)
        memset(&crq, 0, sizeof(crq));
        crq.request_dump_size.first = IBMVNIC_CRQ_CMD;
        crq.request_dump_size.cmd = REQUEST_DUMP_SIZE;
-       ibmvnic_send_crq(adapter, &crq);
 
        init_completion(&adapter->fw_done);
+       ibmvnic_send_crq(adapter, &crq);
        wait_for_completion(&adapter->fw_done);
 
        seq_write(seq, adapter->dump_data, adapter->dump_data_size);
@@ -3629,8 +3630,8 @@ static void handle_crq_init_rsp(struct work_struct *work)
                }
        }
 
-       send_version_xchg(adapter);
        reinit_completion(&adapter->init_done);
+       send_version_xchg(adapter);
        if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
                dev_err(dev, "Passive init timeout\n");
                goto task_failed;
@@ -3640,9 +3641,9 @@ static void handle_crq_init_rsp(struct work_struct *work)
                if (adapter->renegotiate) {
                        adapter->renegotiate = false;
                        release_sub_crqs_no_irqs(adapter);
-                       send_cap_queries(adapter);
 
                        reinit_completion(&adapter->init_done);
+                       send_cap_queries(adapter);
                        if (!wait_for_completion_timeout(&adapter->init_done,
                                                         timeout)) {
                                dev_err(dev, "Passive init timeout\n");
@@ -3656,9 +3657,7 @@ static void handle_crq_init_rsp(struct work_struct *work)
                goto task_failed;
 
        netdev->real_num_tx_queues = adapter->req_tx_queues;
-       netdev->mtu = adapter->req_mtu;
-       netdev->min_mtu = adapter->min_mtu;
-       netdev->max_mtu = adapter->max_mtu;
+       netdev->mtu = adapter->req_mtu - ETH_HLEN;
 
        if (adapter->failover) {
                adapter->failover = false;
@@ -3772,9 +3771,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
                        adapter->debugfs_dump = ent;
                }
        }
-       ibmvnic_send_crq_init(adapter);
 
        init_completion(&adapter->init_done);
+       ibmvnic_send_crq_init(adapter);
        if (!wait_for_completion_timeout(&adapter->init_done, timeout))
                return 0;
 
@@ -3782,9 +3781,9 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
                if (adapter->renegotiate) {
                        adapter->renegotiate = false;
                        release_sub_crqs_no_irqs(adapter);
-                       send_cap_queries(adapter);
 
                        reinit_completion(&adapter->init_done);
+                       send_cap_queries(adapter);
                        if (!wait_for_completion_timeout(&adapter->init_done,
                                                         timeout))
                                return 0;
@@ -3798,7 +3797,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
        }
 
        netdev->real_num_tx_queues = adapter->req_tx_queues;
-       netdev->mtu = adapter->req_mtu;
+       netdev->mtu = adapter->req_mtu - ETH_HLEN;
 
        rc = register_netdev(netdev);
        if (rc) {
index a761001308dcc190d8c9bad57dad40f09dc49caa..1515abaa5ac9cab53ef4aab0ee05104c5bd2a61f 100644 (file)
@@ -3962,8 +3962,8 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
                                     PAGE_SIZE,
                                     DMA_FROM_DEVICE,
                                     DMA_ATTR_SKIP_CPU_SYNC);
-               __page_frag_drain(buffer_info->page, 0,
-                                 buffer_info->pagecnt_bias);
+               __page_frag_cache_drain(buffer_info->page,
+                                       buffer_info->pagecnt_bias);
 
                buffer_info->page = NULL;
        }
@@ -6991,7 +6991,7 @@ static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
                dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
                                     PAGE_SIZE, DMA_FROM_DEVICE,
                                     DMA_ATTR_SKIP_CPU_SYNC);
-               __page_frag_drain(page, 0, rx_buffer->pagecnt_bias);
+               __page_frag_cache_drain(page, rx_buffer->pagecnt_bias);
        }
 
        /* clear contents of rx_buffer */
index 3dd87889e67e1a69189035631c364b95d85dabf1..1c29c86f8709f16bc75087d023858185b37c2faf 100644 (file)
@@ -2517,7 +2517,7 @@ static int mtk_remove(struct platform_device *pdev)
 }
 
 const struct of_device_id of_mtk_match[] = {
-       { .compatible = "mediatek,mt7623-eth" },
+       { .compatible = "mediatek,mt2701-eth" },
        {},
 };
 MODULE_DEVICE_TABLE(of, of_mtk_match);
index c7e939945259dc876b66cfedd0d85f9d7e90a914..53daa6ca5d83b60f7ad8632694658922921f82f5 100644 (file)
@@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev)
        return -ETIMEDOUT;
 }
 
-static int mlx4_comm_internal_err(u32 slave_read)
+int mlx4_comm_internal_err(u32 slave_read)
 {
        return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
                (slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
index a849da92f857e5c22cd1ec93158cecbff9c75d90..6b8635378f1fcb2aae4e8ac390bcd09d552c2256 100644 (file)
@@ -101,13 +101,19 @@ void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn)
 {
        struct mlx4_cq *cq;
 
+       rcu_read_lock();
        cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
                               cqn & (dev->caps.num_cqs - 1));
+       rcu_read_unlock();
+
        if (!cq) {
                mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
                return;
        }
 
+       /* Acessing the CQ outside of rcu_read_lock is safe, because
+        * the CQ is freed only after interrupt handling is completed.
+        */
        ++cq->arm_sn;
 
        cq->comp(cq);
@@ -118,23 +124,19 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
        struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
        struct mlx4_cq *cq;
 
-       spin_lock(&cq_table->lock);
-
+       rcu_read_lock();
        cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
-       if (cq)
-               atomic_inc(&cq->refcount);
-
-       spin_unlock(&cq_table->lock);
+       rcu_read_unlock();
 
        if (!cq) {
-               mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+               mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn);
                return;
        }
 
+       /* Acessing the CQ outside of rcu_read_lock is safe, because
+        * the CQ is freed only after interrupt handling is completed.
+        */
        cq->event(cq, event_type);
-
-       if (atomic_dec_and_test(&cq->refcount))
-               complete(&cq->free);
 }
 
 static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
@@ -301,9 +303,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
        if (err)
                return err;
 
-       spin_lock_irq(&cq_table->lock);
+       spin_lock(&cq_table->lock);
        err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
-       spin_unlock_irq(&cq_table->lock);
+       spin_unlock(&cq_table->lock);
        if (err)
                goto err_icm;
 
@@ -349,9 +351,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
        return 0;
 
 err_radix:
-       spin_lock_irq(&cq_table->lock);
+       spin_lock(&cq_table->lock);
        radix_tree_delete(&cq_table->tree, cq->cqn);
-       spin_unlock_irq(&cq_table->lock);
+       spin_unlock(&cq_table->lock);
 
 err_icm:
        mlx4_cq_free_icm(dev, cq->cqn);
@@ -370,15 +372,15 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
        if (err)
                mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
 
+       spin_lock(&cq_table->lock);
+       radix_tree_delete(&cq_table->tree, cq->cqn);
+       spin_unlock(&cq_table->lock);
+
        synchronize_irq(priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq);
        if (priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq !=
            priv->eq_table.eq[MLX4_EQ_ASYNC].irq)
                synchronize_irq(priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
 
-       spin_lock_irq(&cq_table->lock);
-       radix_tree_delete(&cq_table->tree, cq->cqn);
-       spin_unlock_irq(&cq_table->lock);
-
        if (atomic_dec_and_test(&cq->refcount))
                complete(&cq->free);
        wait_for_completion(&cq->free);
index d9c9f86a30df953fa555934c5406057dcaf28960..9aa4226919542f6496fedce45a09e09685433efe 100644 (file)
@@ -1099,7 +1099,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
        memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
        new_prof.tx_ring_size = tx_size;
        new_prof.rx_ring_size = rx_size;
-       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
        if (err)
                goto out;
 
@@ -1732,8 +1732,6 @@ static void mlx4_en_get_channels(struct net_device *dev,
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
 
-       memset(channel, 0, sizeof(*channel));
-
        channel->max_rx = MAX_RX_RINGS;
        channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
 
@@ -1752,10 +1750,7 @@ static int mlx4_en_set_channels(struct net_device *dev,
        int xdp_count;
        int err = 0;
 
-       if (channel->other_count || channel->combined_count ||
-           channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP ||
-           channel->rx_count > MAX_RX_RINGS ||
-           !channel->tx_count || !channel->rx_count)
+       if (!channel->tx_count || !channel->rx_count)
                return -EINVAL;
 
        tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
@@ -1779,7 +1774,7 @@ static int mlx4_en_set_channels(struct net_device *dev,
        new_prof.tx_ring_num[TX_XDP] = xdp_count;
        new_prof.rx_ring_num = channel->rx_count;
 
-       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
        if (err)
                goto out;
 
index edbe200ac2fa4a11ad30bb8f08d8f7e3cb910708..3b4961a8e8e44d6987ebd23f9239e747c7fc6cd5 100644 (file)
@@ -1748,8 +1748,11 @@ int mlx4_en_start_port(struct net_device *dev)
        /* Process all completions if exist to prevent
         * the queues freezing if they are full
         */
-       for (i = 0; i < priv->rx_ring_num; i++)
+       for (i = 0; i < priv->rx_ring_num; i++) {
+               local_bh_disable();
                napi_schedule(&priv->rx_cq[i]->napi);
+               local_bh_enable();
+       }
 
        netif_tx_start_all_queues(dev);
        netif_device_attach(dev);
@@ -2039,6 +2042,8 @@ static void mlx4_en_free_resources(struct mlx4_en_priv *priv)
                        if (priv->tx_cq[t] && priv->tx_cq[t][i])
                                mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]);
                }
+               kfree(priv->tx_ring[t]);
+               kfree(priv->tx_cq[t]);
        }
 
        for (i = 0; i < priv->rx_ring_num; i++) {
@@ -2181,9 +2186,11 @@ static void mlx4_en_update_priv(struct mlx4_en_priv *dst,
 
 int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
                                struct mlx4_en_priv *tmp,
-                               struct mlx4_en_port_profile *prof)
+                               struct mlx4_en_port_profile *prof,
+                               bool carry_xdp_prog)
 {
-       int t;
+       struct bpf_prog *xdp_prog;
+       int i, t;
 
        mlx4_en_copy_priv(tmp, priv, prof);
 
@@ -2197,6 +2204,23 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
                }
                return -ENOMEM;
        }
+
+       /* All rx_rings has the same xdp_prog.  Pick the first one. */
+       xdp_prog = rcu_dereference_protected(
+               priv->rx_ring[0]->xdp_prog,
+               lockdep_is_held(&priv->mdev->state_lock));
+
+       if (xdp_prog && carry_xdp_prog) {
+               xdp_prog = bpf_prog_add(xdp_prog, tmp->rx_ring_num);
+               if (IS_ERR(xdp_prog)) {
+                       mlx4_en_free_resources(tmp);
+                       return PTR_ERR(xdp_prog);
+               }
+               for (i = 0; i < tmp->rx_ring_num; i++)
+                       rcu_assign_pointer(tmp->rx_ring[i]->xdp_prog,
+                                          xdp_prog);
+       }
+
        return 0;
 }
 
@@ -2211,7 +2235,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
-       int t;
 
        en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
 
@@ -2245,11 +2268,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
        mlx4_en_free_resources(priv);
        mutex_unlock(&mdev->state_lock);
 
-       for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
-               kfree(priv->tx_ring[t]);
-               kfree(priv->tx_cq[t]);
-       }
-
        free_netdev(dev);
 }
 
@@ -2277,7 +2295,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
 
        if (priv->tx_ring_num[TX_XDP] &&
            !mlx4_en_check_xdp_mtu(dev, new_mtu))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        dev->mtu = new_mtu;
 
@@ -2752,7 +2770,7 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog)
                en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n");
        }
 
-       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, false);
        if (err) {
                if (prog)
                        bpf_prog_sub(prog, priv->rx_ring_num - 1);
@@ -3496,7 +3514,7 @@ int mlx4_en_reset_config(struct net_device *dev,
        memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
        memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config));
 
-       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+       err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
        if (err)
                goto out;
 
index eac527e25ec902c2a586e9952272b9e8e599e2c8..cc003fdf0ed929a981b1403f6a7d0099825fec4b 100644 (file)
@@ -514,8 +514,11 @@ void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv)
                return;
 
        for (ring = 0; ring < priv->rx_ring_num; ring++) {
-               if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
+               if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) {
+                       local_bh_disable();
                        napi_reschedule(&priv->rx_cq[ring]->napi);
+                       local_bh_enable();
+               }
        }
 }
 
index cd3638e6fe25b2f8db4ea5e771535df51652faae..0509996957d9664b612358dd805359f4bc67b8dc 100644 (file)
@@ -554,8 +554,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
                        break;
 
                case MLX4_EVENT_TYPE_SRQ_LIMIT:
-                       mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
-                                __func__);
+                       mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n",
+                                __func__, be32_to_cpu(eqe->event.srq.srqn),
+                                eq->eqn);
                case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
                        if (mlx4_is_master(dev)) {
                                /* forward only to slave owning the SRQ */
@@ -570,15 +571,19 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
                                                  eq->eqn, eq->cons_index, ret);
                                        break;
                                }
-                               mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
-                                         __func__, slave,
-                                         be32_to_cpu(eqe->event.srq.srqn),
-                                         eqe->type, eqe->subtype);
+                               if (eqe->type ==
+                                   MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+                                       mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
+                                                 __func__, slave,
+                                                 be32_to_cpu(eqe->event.srq.srqn),
+                                                 eqe->type, eqe->subtype);
 
                                if (!ret && slave != dev->caps.function) {
-                                       mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
-                                                 __func__, eqe->type,
-                                                 eqe->subtype, slave);
+                                       if (eqe->type ==
+                                           MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+                                               mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
+                                                         __func__, eqe->type,
+                                                         eqe->subtype, slave);
                                        mlx4_slave_event(dev, slave, eqe);
                                        break;
                                }
index 0e8b7c44931f907ed881d093077e93b92ae0305d..8258d08acd8c2029a8bcb812dd5efd85d8c7b0f2 100644 (file)
@@ -222,6 +222,18 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
                return;
 
        mlx4_stop_catas_poll(dev);
+       if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
+           mlx4_is_slave(dev)) {
+               /* In mlx4_remove_one on a VF */
+               u32 slave_read =
+                       swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
+
+               if (mlx4_comm_internal_err(slave_read)) {
+                       mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
+                                __func__);
+                       mlx4_enter_error_state(dev->persist);
+               }
+       }
        mutex_lock(&intf_mutex);
 
        list_for_each_entry(intf, &intf_list, list)
index 88ee7d8a59231a47d6b7aca2006f9780dbefa578..086920b615af7180e891893ffd00928c0bd0238f 100644 (file)
@@ -1220,6 +1220,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type);
 void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
 
 void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
+int mlx4_comm_internal_err(u32 slave_read);
 
 int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
                    enum mlx4_port_type *type);
index ba1c6cd0cc79590075f4420a930b613c9fdedc62..cec59bc264c9ac197048fd7c98bcd5cf25de0efd 100644 (file)
@@ -679,7 +679,8 @@ void mlx4_en_set_stats_bitmap(struct mlx4_dev *dev,
 
 int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
                                struct mlx4_en_priv *tmp,
-                               struct mlx4_en_port_profile *prof);
+                               struct mlx4_en_port_profile *prof,
+                               bool carry_xdp_prog);
 void mlx4_en_safe_replace_resources(struct mlx4_en_priv *priv,
                                    struct mlx4_en_priv *tmp);
 
index 56185a0b827df6394a1edba70cf6925683ffb403..1822382212eed5d77fb290598fbe2d0834480aa9 100644 (file)
@@ -2980,6 +2980,9 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
                put_res(dev, slave, srqn, RES_SRQ);
                qp->srq = srq;
        }
+
+       /* Save param3 for dynamic changes from VST back to VGT */
+       qp->param3 = qpc->param3;
        put_res(dev, slave, rcqn, RES_CQ);
        put_res(dev, slave, mtt_base, RES_MTT);
        res_end_move(dev, slave, RES_QP, qpn);
@@ -3772,7 +3775,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
        int qpn = vhcr->in_modifier & 0x7fffff;
        struct res_qp *qp;
        u8 orig_sched_queue;
-       __be32  orig_param3 = qpc->param3;
        u8 orig_vlan_control = qpc->pri_path.vlan_control;
        u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
        u8 orig_pri_path_fl = qpc->pri_path.fl;
@@ -3814,7 +3816,6 @@ out:
         */
        if (!err) {
                qp->sched_queue = orig_sched_queue;
-               qp->param3      = orig_param3;
                qp->vlan_control = orig_vlan_control;
                qp->fvl_rx      =  orig_fvl_rx;
                qp->pri_path_fl = orig_pri_path_fl;
index 3797cc7c1288078298ec655921f9fc9f804df97e..caa837e5e2b991fc3666776d2050fe20b1c6c7f6 100644 (file)
@@ -1728,7 +1728,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
        if (cmd->cmdif_rev > CMD_IF_REV) {
                dev_err(&dev->pdev->dev, "driver does not support command interface version. driver %d, firmware %d\n",
                        CMD_IF_REV, cmd->cmdif_rev);
-               err = -ENOTSUPP;
+               err = -EOPNOTSUPP;
                goto err_free_page;
        }
 
index 951dbd58594dcd3b32b680f752c1105132d85ba8..d5ecb8f53fd43684f185d590c8dc5553a4f25ab4 100644 (file)
@@ -791,7 +791,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
 int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd);
 
 int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz, int ix);
-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv);
+void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
+                                   enum mlx5e_traffic_types tt);
 
 int mlx5e_open_locked(struct net_device *netdev);
 int mlx5e_close_locked(struct net_device *netdev);
@@ -863,12 +864,12 @@ static inline void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) {}
 
 static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv)
 {
-       return -ENOTSUPP;
+       return -EOPNOTSUPP;
 }
 
 static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv)
 {
-       return -ENOTSUPP;
+       return -EOPNOTSUPP;
 }
 #else
 int mlx5e_arfs_create_tables(struct mlx5e_priv *priv);
index f0b460f47f2992caad4eec7ea0d655296a46e99c..0523ed47f597c715296c5ea843245625bf3dac62 100644 (file)
@@ -89,7 +89,7 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
        int i;
 
        if (!MLX5_CAP_GEN(priv->mdev, ets))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
        for (i = 0; i < ets->ets_cap; i++) {
@@ -236,7 +236,7 @@ static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
        int err;
 
        if (!MLX5_CAP_GEN(priv->mdev, ets))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        err = mlx5e_dbcnl_validate_ets(netdev, ets);
        if (err)
@@ -402,7 +402,7 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
        struct mlx5_core_dev *mdev = priv->mdev;
        struct ieee_ets ets;
        struct ieee_pfc pfc;
-       int err = -ENOTSUPP;
+       int err = -EOPNOTSUPP;
        int i;
 
        if (!MLX5_CAP_GEN(mdev, ets))
@@ -511,6 +511,11 @@ static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
 
+       if (!MLX5_CAP_GEN(priv->mdev, ets)) {
+               netdev_err(netdev, "%s, ets is not supported\n", __func__);
+               return;
+       }
+
        if (priority >= CEE_DCBX_MAX_PRIO) {
                netdev_err(netdev,
                           "%s, priority is out of range\n", __func__);
index 33a399a8b5d52297379ade73f37e61df266905fa..bb67863aa361168a8566349ef356d9a991d411be 100644 (file)
@@ -543,7 +543,6 @@ static int mlx5e_set_channels(struct net_device *dev,
                              struct ethtool_channels *ch)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
-       int ncv = mlx5e_get_max_num_channels(priv->mdev);
        unsigned int count = ch->combined_count;
        bool arfs_enabled;
        bool was_opened;
@@ -554,16 +553,6 @@ static int mlx5e_set_channels(struct net_device *dev,
                            __func__);
                return -EINVAL;
        }
-       if (ch->rx_count || ch->tx_count) {
-               netdev_info(dev, "%s: separate rx/tx count not supported\n",
-                           __func__);
-               return -EINVAL;
-       }
-       if (count > ncv) {
-               netdev_info(dev, "%s: count (%d) > max (%d)\n",
-                           __func__, count, ncv);
-               return -EINVAL;
-       }
 
        if (priv->params.num_channels == count)
                return 0;
@@ -606,7 +595,7 @@ static int mlx5e_get_coalesce(struct net_device *netdev,
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
        if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        coal->rx_coalesce_usecs       = priv->params.rx_cq_moderation.usec;
        coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation.pkts;
@@ -631,7 +620,7 @@ static int mlx5e_set_coalesce(struct net_device *netdev,
        int i;
 
        if (!MLX5_CAP_GEN(mdev, cq_moderation))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        mutex_lock(&priv->state_lock);
 
@@ -991,15 +980,18 @@ static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
 
 static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
        void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
-       int i;
+       struct mlx5_core_dev *mdev = priv->mdev;
+       int ctxlen = MLX5_ST_SZ_BYTES(tirc);
+       int tt;
 
        MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
-       mlx5e_build_tir_ctx_hash(tirc, priv);
 
-       for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
-               mlx5_core_modify_tir(mdev, priv->indir_tir[i].tirn, in, inlen);
+       for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
+               memset(tirc, 0, ctxlen);
+               mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
+               mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
+       }
 }
 
 static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
@@ -1007,6 +999,7 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
        int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
+       bool hash_changed = false;
        void *in;
 
        if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
@@ -1028,14 +1021,21 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
                mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, 0);
        }
 
-       if (key)
+       if (hfunc != ETH_RSS_HASH_NO_CHANGE &&
+           hfunc != priv->params.rss_hfunc) {
+               priv->params.rss_hfunc = hfunc;
+               hash_changed = true;
+       }
+
+       if (key) {
                memcpy(priv->params.toeplitz_hash_key, key,
                       sizeof(priv->params.toeplitz_hash_key));
+               hash_changed = hash_changed ||
+                              priv->params.rss_hfunc == ETH_RSS_HASH_TOP;
+       }
 
-       if (hfunc != ETH_RSS_HASH_NO_CHANGE)
-               priv->params.rss_hfunc = hfunc;
-
-       mlx5e_modify_tirs_hash(priv, in, inlen);
+       if (hash_changed)
+               mlx5e_modify_tirs_hash(priv, in, inlen);
 
        mutex_unlock(&priv->state_lock);
 
@@ -1307,7 +1307,7 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        u32 mlx5_wol_mode;
 
        if (!wol_supported)
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        if (wol->wolopts & ~wol_supported)
                return -EINVAL;
@@ -1437,7 +1437,7 @@ static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
 
        if (rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE &&
            !MLX5_CAP_GEN(mdev, cq_period_start_from_cqe))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        if (!rx_mode_changed)
                return 0;
@@ -1463,7 +1463,7 @@ static int set_pflag_rx_cqe_compress(struct net_device *netdev,
        bool reset;
 
        if (!MLX5_CAP_GEN(mdev, cqe_compression))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        if (enable && priv->tstamp.hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
                netdev_err(netdev, "Can't enable cqe compression while timestamping is enabled.\n");
index 1fe80de5d68f1f3cf09c6e32530cd32114580051..a0e5a69402b30a349b196eaa72ce1a413b5479b2 100644 (file)
@@ -1089,7 +1089,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
                                               MLX5_FLOW_NAMESPACE_KERNEL);
 
        if (!priv->fs.ns)
-               return -EINVAL;
+               return -EOPNOTSUPP;
 
        err = mlx5e_arfs_create_tables(priv);
        if (err) {
index d088effd7160355849faacead1326f2198d12e8d..f33f72d0237c1bafc702f4066dab31ab22963a47 100644 (file)
@@ -92,7 +92,7 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
        ns = mlx5_get_flow_namespace(priv->mdev,
                                     MLX5_FLOW_NAMESPACE_ETHTOOL);
        if (!ns)
-               return ERR_PTR(-ENOTSUPP);
+               return ERR_PTR(-EOPNOTSUPP);
 
        table_size = min_t(u32, BIT(MLX5_CAP_FLOWTABLE(priv->mdev,
                                                       flow_table_properties_nic_receive.log_max_ft_size)),
index 1236b27b149386ab61f1c25ab26c84d43d561ab9..f14ca3385fdd683b12f434e289cc8e264040c1ed 100644 (file)
@@ -2022,8 +2022,23 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
        MLX5_SET(tirc, tirc, lro_timeout_period_usecs, priv->params.lro_timeout);
 }
 
-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
+void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
+                                   enum mlx5e_traffic_types tt)
 {
+       void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
+
+#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+                                MLX5_HASH_FIELD_SEL_DST_IP)
+
+#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+                                MLX5_HASH_FIELD_SEL_DST_IP   |\
+                                MLX5_HASH_FIELD_SEL_L4_SPORT |\
+                                MLX5_HASH_FIELD_SEL_L4_DPORT)
+
+#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+                                MLX5_HASH_FIELD_SEL_DST_IP   |\
+                                MLX5_HASH_FIELD_SEL_IPSEC_SPI)
+
        MLX5_SET(tirc, tirc, rx_hash_fn,
                 mlx5e_rx_hash_fn(priv->params.rss_hfunc));
        if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
@@ -2035,6 +2050,88 @@ void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
                MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
                memcpy(rss_key, priv->params.toeplitz_hash_key, len);
        }
+
+       switch (tt) {
+       case MLX5E_TT_IPV4_TCP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_TCP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV6_TCP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_TCP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV4_UDP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_UDP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV6_UDP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_UDP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV4_IPSEC_AH:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV6_IPSEC_AH:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV4_IPSEC_ESP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV6_IPSEC_ESP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV4:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP);
+               break;
+
+       case MLX5E_TT_IPV6:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP);
+               break;
+       default:
+               WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
+       }
 }
 
 static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
@@ -2404,110 +2501,13 @@ void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
 static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
                                      enum mlx5e_traffic_types tt)
 {
-       void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
-
        MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
 
-#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-                                MLX5_HASH_FIELD_SEL_DST_IP)
-
-#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-                                MLX5_HASH_FIELD_SEL_DST_IP   |\
-                                MLX5_HASH_FIELD_SEL_L4_SPORT |\
-                                MLX5_HASH_FIELD_SEL_L4_DPORT)
-
-#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-                                MLX5_HASH_FIELD_SEL_DST_IP   |\
-                                MLX5_HASH_FIELD_SEL_IPSEC_SPI)
-
        mlx5e_build_tir_ctx_lro(tirc, priv);
 
        MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
        MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
-       mlx5e_build_tir_ctx_hash(tirc, priv);
-
-       switch (tt) {
-       case MLX5E_TT_IPV4_TCP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_TCP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV6_TCP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_TCP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV4_UDP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_UDP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV6_UDP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_UDP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV4_IPSEC_AH:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV6_IPSEC_AH:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV4_IPSEC_ESP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV6_IPSEC_ESP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV4:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP);
-               break;
-
-       case MLX5E_TT_IPV6:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP);
-               break;
-       default:
-               WARN_ONCE(true,
-                         "mlx5e_build_indir_tir_ctx: bad traffic type!\n");
-       }
+       mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
 }
 
 static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
@@ -3331,7 +3331,7 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
 {
        if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
            !MLX5_CAP_GEN(mdev, nic_flow_table) ||
            !MLX5_CAP_ETH(mdev, csum_cap) ||
@@ -3343,7 +3343,7 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
                               < 3) {
                mlx5_core_warn(mdev,
                               "Not creating net device, some required device capabilities are missing\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
        if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
                mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
@@ -3675,14 +3675,8 @@ static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
 
 static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
-       struct mlx5_eswitch *esw = mdev->priv.eswitch;
-
        mlx5e_vxlan_cleanup(priv);
 
-       if (MLX5_CAP_GEN(mdev, vport_group_manager))
-               mlx5_eswitch_unregister_vport_rep(esw, 0);
-
        if (priv->xdp_prog)
                bpf_prog_put(priv->xdp_prog);
 }
@@ -3807,9 +3801,14 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct mlx5_eswitch *esw = mdev->priv.eswitch;
+
        queue_work(priv->wq, &priv->set_rx_mode_work);
+       if (MLX5_CAP_GEN(mdev, vport_group_manager))
+               mlx5_eswitch_unregister_vport_rep(esw, 0);
        mlx5e_disable_async_events(priv);
-       mlx5_lag_remove(priv->mdev);
+       mlx5_lag_remove(mdev);
 }
 
 static const struct mlx5e_profile mlx5e_nic_profile = {
index 0e2fb3ed1790900ccdc0bbbef8bc5c33267df092..06d5e6fecb0a5ecf255c9d6319ffb285e1a660df 100644 (file)
@@ -193,6 +193,9 @@ static inline bool mlx5e_rx_cache_put(struct mlx5e_rq *rq,
                return false;
        }
 
+       if (unlikely(page_is_pfmemalloc(dma_info->page)))
+               return false;
+
        cache->page_cache[cache->tail] = *dma_info;
        cache->tail = tail_next;
        return true;
index 1fffe48a93cc35d55d03eba9ba352590924548d2..cbfac06b7ffd1d5140226ccb87331db57d4880d8 100644 (file)
@@ -109,7 +109,6 @@ static bool mlx5e_am_on_top(struct mlx5e_rx_am *am)
        switch (am->tune_state) {
        case MLX5E_AM_PARKING_ON_TOP:
        case MLX5E_AM_PARKING_TIRED:
-               WARN_ONCE(true, "mlx5e_am_on_top: PARKING\n");
                return true;
        case MLX5E_AM_GOING_RIGHT:
                return (am->steps_left > 1) && (am->steps_right == 1);
@@ -123,7 +122,6 @@ static void mlx5e_am_turn(struct mlx5e_rx_am *am)
        switch (am->tune_state) {
        case MLX5E_AM_PARKING_ON_TOP:
        case MLX5E_AM_PARKING_TIRED:
-               WARN_ONCE(true, "mlx5e_am_turn: PARKING\n");
                break;
        case MLX5E_AM_GOING_RIGHT:
                am->tune_state = MLX5E_AM_GOING_LEFT;
@@ -144,7 +142,6 @@ static int mlx5e_am_step(struct mlx5e_rx_am *am)
        switch (am->tune_state) {
        case MLX5E_AM_PARKING_ON_TOP:
        case MLX5E_AM_PARKING_TIRED:
-               WARN_ONCE(true, "mlx5e_am_step: PARKING\n");
                break;
        case MLX5E_AM_GOING_RIGHT:
                if (am->profile_ix == (MLX5E_PARAMS_AM_NUM_PROFILES - 1))
@@ -282,10 +279,8 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
        u32 delta_us = ktime_us_delta(end->time, start->time);
        unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
 
-       if (!delta_us) {
-               WARN_ONCE(true, "mlx5e_am_calc_stats: delta_us=0\n");
+       if (!delta_us)
                return;
-       }
 
        curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us;
        curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
index f8829b5171560ed2f51cd05b8c82d2a076ce8cbb..2ebbe80d8126521cd324090344ecc3865a16657b 100644 (file)
@@ -161,15 +161,21 @@ static void mlx5e_detach_encap(struct mlx5e_priv *priv,
        }
 }
 
+/* we get here also when setting rule to the FW failed, etc. It means that the
+ * flow rule itself might not exist, but some offloading related to the actions
+ * should be cleaned.
+ */
 static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_fc *counter = NULL;
 
-       counter = mlx5_flow_rule_counter(flow->rule);
-
-       mlx5_del_flow_rules(flow->rule);
+       if (!IS_ERR(flow->rule)) {
+               counter = mlx5_flow_rule_counter(flow->rule);
+               mlx5_del_flow_rules(flow->rule);
+               mlx5_fc_destroy(priv->mdev, counter);
+       }
 
        if (esw && esw->mode == SRIOV_OFFLOADS) {
                mlx5_eswitch_del_vlan_action(esw, flow->attr);
@@ -177,8 +183,6 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
                        mlx5e_detach_encap(priv, flow);
        }
 
-       mlx5_fc_destroy(priv->mdev, counter);
-
        if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
                mlx5_destroy_flow_table(priv->fs.tc.t);
                priv->fs.tc.t = NULL;
@@ -225,6 +229,11 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
        void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
                                       outer_headers);
 
+       struct flow_dissector_key_control *enc_control =
+               skb_flow_dissector_target(f->dissector,
+                                         FLOW_DISSECTOR_KEY_ENC_CONTROL,
+                                         f->key);
+
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
                struct flow_dissector_key_ports *key =
                        skb_flow_dissector_target(f->dissector,
@@ -237,28 +246,34 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
 
                /* Full udp dst port must be given */
                if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst)))
-                       return -EOPNOTSUPP;
-
-               /* udp src port isn't supported */
-               if (memchr_inv(&mask->src, 0, sizeof(mask->src)))
-                       return -EOPNOTSUPP;
+                       goto vxlan_match_offload_err;
 
                if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->dst)) &&
                    MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap))
                        parse_vxlan_attr(spec, f);
-               else
+               else {
+                       netdev_warn(priv->netdev,
+                                   "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->dst));
                        return -EOPNOTSUPP;
+               }
 
                MLX5_SET(fte_match_set_lyr_2_4, headers_c,
                         udp_dport, ntohs(mask->dst));
                MLX5_SET(fte_match_set_lyr_2_4, headers_v,
                         udp_dport, ntohs(key->dst));
 
+               MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+                        udp_sport, ntohs(mask->src));
+               MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+                        udp_sport, ntohs(key->src));
        } else { /* udp dst port must be given */
-                       return -EOPNOTSUPP;
+vxlan_match_offload_err:
+               netdev_warn(priv->netdev,
+                           "IP tunnel decap offload supported only for vxlan, must set UDP dport\n");
+               return -EOPNOTSUPP;
        }
 
-       if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
+       if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
                struct flow_dissector_key_ipv4_addrs *key =
                        skb_flow_dissector_target(f->dissector,
                                                  FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
@@ -280,10 +295,10 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
                MLX5_SET(fte_match_set_lyr_2_4, headers_v,
                         dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
                         ntohl(key->dst));
-       }
 
-       MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
-       MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
+               MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
+               MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
+       }
 
        /* Enforce DMAC when offloading incoming tunneled flows.
         * Flow counters require a match on the DMAC.
@@ -346,6 +361,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                        if (parse_tunnel_attr(priv, spec, f))
                                return -EOPNOTSUPP;
                        break;
+               case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
+                       netdev_warn(priv->netdev,
+                                   "IPv6 tunnel decap offload isn't supported\n");
                default:
                        return -EOPNOTSUPP;
                }
@@ -375,6 +393,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                        MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
                        MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
                                 key->flags & FLOW_DIS_IS_FRAGMENT);
+
+                       /* the HW doesn't need L3 inline to match on frag=no */
+                       if (key->flags & FLOW_DIS_IS_FRAGMENT)
+                               *min_inline = MLX5_INLINE_MODE_IP;
                }
        }
 
@@ -641,26 +663,26 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
                                   __be32 *saddr,
                                   int *out_ttl)
 {
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct rtable *rt;
        struct neighbour *n = NULL;
        int ttl;
 
 #if IS_ENABLED(CONFIG_INET)
+       int ret;
+
        rt = ip_route_output_key(dev_net(mirred_dev), fl4);
-       if (IS_ERR(rt)) {
-               pr_warn("%s: no route to %pI4\n", __func__, &fl4->daddr);
-               return -EOPNOTSUPP;
-       }
+       ret = PTR_ERR_OR_ZERO(rt);
+       if (ret)
+               return ret;
 #else
        return -EOPNOTSUPP;
 #endif
-
-       if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev)) {
-               pr_warn("%s: Can't offload the flow, netdevices aren't on the same HW e-switch\n",
-                       __func__);
-               ip_rt_put(rt);
-               return -EOPNOTSUPP;
-       }
+       /* if the egress device isn't on the same HW e-switch, we use the uplink */
+       if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev))
+               *out_dev = mlx5_eswitch_get_uplink_netdev(esw);
+       else
+               *out_dev = rt->dst.dev;
 
        ttl = ip4_dst_hoplimit(&rt->dst);
        n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
@@ -671,7 +693,6 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
        *out_n = n;
        *saddr = fl4->saddr;
        *out_ttl = ttl;
-       *out_dev = rt->dst.dev;
 
        return 0;
 }
@@ -718,8 +739,8 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
                                          struct net_device **out_dev)
 {
        int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
+       struct neighbour *n = NULL;
        struct flowi4 fl4 = {};
-       struct neighbour *n;
        char *encap_header;
        int encap_size;
        __be32 saddr;
@@ -750,7 +771,8 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
        e->out_dev = *out_dev;
 
        if (!(n->nud_state & NUD_VALID)) {
-               err = -ENOTSUPP;
+               pr_warn("%s: can't offload, neighbour to %pI4 invalid\n", __func__, &fl4.daddr);
+               err = -EOPNOTSUPP;
                goto out;
        }
 
@@ -772,6 +794,8 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
        err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
                               encap_size, encap_header, &e->encap_id);
 out:
+       if (err && n)
+               neigh_release(n);
        kfree(encap_header);
        return err;
 }
@@ -792,9 +816,17 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
        int tunnel_type;
        int err;
 
-       /* udp dst port must be given */
+       /* udp dst port must be set */
        if (!memchr_inv(&key->tp_dst, 0, sizeof(key->tp_dst)))
+               goto vxlan_encap_offload_err;
+
+       /* setting udp src port isn't supported */
+       if (memchr_inv(&key->tp_src, 0, sizeof(key->tp_src))) {
+vxlan_encap_offload_err:
+               netdev_warn(priv->netdev,
+                           "must set udp dst port and not set udp src port\n");
                return -EOPNOTSUPP;
+       }
 
        if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->tp_dst)) &&
            MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) {
@@ -802,6 +834,8 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                info.tun_id = tunnel_id_to_key32(key->tun_id);
                tunnel_type = MLX5_HEADER_TYPE_VXLAN;
        } else {
+               netdev_warn(priv->netdev,
+                           "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->tp_dst));
                return -EOPNOTSUPP;
        }
 
@@ -809,6 +843,9 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
        case AF_INET:
                info.daddr = key->u.ipv4.dst;
                break;
+       case AF_INET6:
+               netdev_warn(priv->netdev,
+                           "IPv6 tunnel encap offload isn't supported\n");
        default:
                return -EOPNOTSUPP;
        }
@@ -986,7 +1023,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
 
        if (IS_ERR(flow->rule)) {
                err = PTR_ERR(flow->rule);
-               goto err_free;
+               goto err_del_rule;
        }
 
        err = rhashtable_insert_fast(&tc->ht, &flow->node,
@@ -997,7 +1034,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
        goto out;
 
 err_del_rule:
-       mlx5_del_flow_rules(flow->rule);
+       mlx5e_tc_del_flow(priv, flow);
 
 err_free:
        kfree(flow);
@@ -1050,10 +1087,14 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
 
        mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
 
+       preempt_disable();
+
        tcf_exts_to_list(f->exts, &actions);
        list_for_each_entry(a, &actions, list)
                tcf_action_stats_update(a, bytes, packets, lastuse);
 
+       preempt_enable();
+
        return 0;
 }
 
index f14d9c9ba77394b83aea50564afd3c762613467a..d0c8bf014453ea38736182c03ba7b2d9c5bcd4d7 100644 (file)
@@ -133,7 +133,7 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport,
 
        if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
            !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
                  vport, vlan, qos, set_flags);
@@ -353,7 +353,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw, int nvports)
        root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
        if (!root_ns) {
                esw_warn(dev, "Failed to get FDB flow namespace\n");
-               return -ENOMEM;
+               return -EOPNOTSUPP;
        }
 
        flow_group_in = mlx5_vzalloc(inlen);
@@ -962,7 +962,7 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS);
        if (!root_ns) {
                esw_warn(dev, "Failed to get E-Switch egress flow namespace\n");
-               return -EIO;
+               return -EOPNOTSUPP;
        }
 
        flow_group_in = mlx5_vzalloc(inlen);
@@ -1079,7 +1079,7 @@ static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS);
        if (!root_ns) {
                esw_warn(dev, "Failed to get E-Switch ingress flow namespace\n");
-               return -EIO;
+               return -EOPNOTSUPP;
        }
 
        flow_group_in = mlx5_vzalloc(inlen);
@@ -1630,7 +1630,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
        if (!MLX5_CAP_GEN(esw->dev, eswitch_flow_table) ||
            !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
                esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
index 03293ed1cc22d2716ff5708dc2312b7291cc1899..595f7c7383b399440aedec593ae0fb0c37bb6748 100644 (file)
@@ -166,7 +166,7 @@ static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
        return 0;
 
 out_notsupp:
-       return -ENOTSUPP;
+       return -EOPNOTSUPP;
 }
 
 int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
@@ -424,6 +424,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
        root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
        if (!root_ns) {
                esw_warn(dev, "Failed to get FDB flow namespace\n");
+               err = -EOPNOTSUPP;
                goto ns_err;
        }
 
@@ -535,7 +536,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
        ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
        if (!ns) {
                esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
-               return -ENOMEM;
+               return -EOPNOTSUPP;
        }
 
        ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0, 0);
@@ -655,7 +656,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw)
                esw_warn(esw->dev, "Failed setting eswitch to offloads, err %d\n", err);
                err1 = mlx5_eswitch_enable_sriov(esw, num_vfs, SRIOV_LEGACY);
                if (err1)
-                       esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err);
+                       esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err1);
        }
        if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
                if (mlx5_eswitch_inline_mode_get(esw,
@@ -674,9 +675,14 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports)
        int vport;
        int err;
 
+       /* disable PF RoCE so missed packets don't go through RoCE steering */
+       mlx5_dev_list_lock();
+       mlx5_remove_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
+       mlx5_dev_list_unlock();
+
        err = esw_create_offloads_fdb_table(esw, nvports);
        if (err)
-               return err;
+               goto create_fdb_err;
 
        err = esw_create_offloads_table(esw);
        if (err)
@@ -696,11 +702,6 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports)
                        goto err_reps;
        }
 
-       /* disable PF RoCE so missed packets don't go through RoCE steering */
-       mlx5_dev_list_lock();
-       mlx5_remove_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
-       mlx5_dev_list_unlock();
-
        return 0;
 
 err_reps:
@@ -717,6 +718,13 @@ create_fg_err:
 
 create_ft_err:
        esw_destroy_offloads_fdb_table(esw);
+
+create_fdb_err:
+       /* enable back PF RoCE */
+       mlx5_dev_list_lock();
+       mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
+       mlx5_dev_list_unlock();
+
        return err;
 }
 
@@ -724,11 +732,6 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw)
 {
        int err, err1, num_vfs = esw->dev->priv.sriov.num_vfs;
 
-       /* enable back PF RoCE */
-       mlx5_dev_list_lock();
-       mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
-       mlx5_dev_list_unlock();
-
        mlx5_eswitch_disable_sriov(esw);
        err = mlx5_eswitch_enable_sriov(esw, num_vfs, SRIOV_LEGACY);
        if (err) {
@@ -738,6 +741,11 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw)
                        esw_warn(esw->dev, "Failed setting eswitch back to offloads, err %d\n", err);
        }
 
+       /* enable back PF RoCE */
+       mlx5_dev_list_lock();
+       mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
+       mlx5_dev_list_unlock();
+
        return err;
 }
 
index c4478ecd8056e42de2c359eb7a2abfd9e6400090..b53fc85a2375778ddd02ac07d21d88b56c49e432 100644 (file)
@@ -322,7 +322,7 @@ int mlx5_cmd_update_fte(struct mlx5_core_dev *dev,
                                                flow_table_properties_nic_receive.
                                                flow_modify_en);
        if (!atomic_mod_cap)
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        opmod = 1;
 
        return  mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte);
index 0ac7a2fc916c438bc535b20d45964009747f0b33..6346a8f5883bcc911ef422cf572fd1891ddf73c9 100644 (file)
@@ -1822,7 +1822,7 @@ static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
        struct mlx5_flow_table *ft;
 
        ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
-       if (!ns)
+       if (WARN_ON(!ns))
                return -EINVAL;
        ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL, 0);
        if (IS_ERR(ft)) {
index 6547f22e6b9b919010eada133093654348dff671..3c315eb8d270f6f94ecaea2c8ee4d78ed1244658 100644 (file)
@@ -807,7 +807,7 @@ static int mlx5_core_set_issi(struct mlx5_core_dev *dev)
                return 0;
        }
 
-       return -ENOTSUPP;
+       return -EOPNOTSUPP;
 }
 
 
@@ -1195,7 +1195,8 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
 {
        int err = 0;
 
-       mlx5_drain_health_wq(dev);
+       if (cleanup)
+               mlx5_drain_health_wq(dev);
 
        mutex_lock(&dev->intf_state_mutex);
        if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
@@ -1359,9 +1360,10 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev,
 
        mlx5_enter_error_state(dev);
        mlx5_unload_one(dev, priv, false);
-       /* In case of kernel call save the pci state */
+       /* In case of kernel call save the pci state and drain the health wq */
        if (state) {
                pci_save_state(pdev);
+               mlx5_drain_health_wq(dev);
                mlx5_pci_disable_device(dev);
        }
 
index d2ec9d232a70727df71d0c733f60c78a55415392..fd12e0a377a567c693c7f174d7762dd6071ff925 100644 (file)
@@ -620,7 +620,7 @@ static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
        u32 out[MLX5_ST_SZ_DW(qtct_reg)];
 
        if (!MLX5_CAP_GEN(mdev, ets))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
                                    MLX5_REG_QETCR, 0, 1);
@@ -632,7 +632,7 @@ static int mlx5_query_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *out,
        u32 in[MLX5_ST_SZ_DW(qtct_reg)];
 
        if (!MLX5_CAP_GEN(mdev, ets))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        memset(in, 0, sizeof(in));
        return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
index 269e4401c342d1375e70a40ba9905dddf9b65cef..7129c30a2ab477d23be1b8b8d34e7190618e0f9f 100644 (file)
@@ -532,7 +532,7 @@ int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
        if (!MLX5_CAP_GEN(mdev, vport_group_manager))
                return -EACCES;
        if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        in = mlx5_vzalloc(inlen);
        if (!in)
index d147ddd97997e3c2018f6ae9613a04474990b37e..0af3338bfcb4fbe4681afccaba3a6ca41e59a4e0 100644 (file)
@@ -209,21 +209,21 @@ MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
 /* pci_eqe_cmd_token
  * Command completion event - token
  */
-MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
+MLXSW_ITEM32(pci, eqe, cmd_token, 0x00, 16, 16);
 
 /* pci_eqe_cmd_status
  * Command completion event - status
  */
-MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
+MLXSW_ITEM32(pci, eqe, cmd_status, 0x00, 0, 8);
 
 /* pci_eqe_cmd_out_param_h
  * Command completion event - output parameter - higher part
  */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
+MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x04, 0, 32);
 
 /* pci_eqe_cmd_out_param_l
  * Command completion event - output parameter - lower part
  */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x08, 0, 32);
 
 #endif
index d768c7b6c6d6688c46077c48e25df45cdf9ad7dc..003093abb1707f0a6cdefe465e073c005d2ee3f9 100644 (file)
@@ -684,6 +684,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
                        dev_kfree_skb_any(skb_orig);
                        return NETDEV_TX_OK;
                }
+               dev_consume_skb_any(skb_orig);
        }
 
        if (eth_skb_pad(skb)) {
index 01d0efa9c5c7419b6e2fa99ed6b99562811bcbd5..9e494a446b7ea7812a409b87f92bde19a0355286 100644 (file)
@@ -1172,7 +1172,8 @@ static int mlxsw_sp_nexthop_mac_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
 
 static int
 mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp,
-                                 struct mlxsw_sp_nexthop_group *nh_grp)
+                                 struct mlxsw_sp_nexthop_group *nh_grp,
+                                 bool reallocate)
 {
        u32 adj_index = nh_grp->adj_index; /* base */
        struct mlxsw_sp_nexthop *nh;
@@ -1187,7 +1188,7 @@ mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp,
                        continue;
                }
 
-               if (nh->update) {
+               if (nh->update || reallocate) {
                        err = mlxsw_sp_nexthop_mac_update(mlxsw_sp,
                                                          adj_index, nh);
                        if (err)
@@ -1248,7 +1249,8 @@ mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
                /* Nothing was added or removed, so no need to reallocate. Just
                 * update MAC on existing adjacency indexes.
                 */
-               err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+               err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp,
+                                                       false);
                if (err) {
                        dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
                        goto set_trap;
@@ -1276,7 +1278,7 @@ mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
        nh_grp->adj_index_valid = 1;
        nh_grp->adj_index = adj_index;
        nh_grp->ecmp_size = ecmp_size;
-       err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+       err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp, true);
        if (err) {
                dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
                goto set_trap;
index 150ccf5192a9895d8e6dc1d41c3510c207d870e5..2e88115e87359777279872efaad3581078aaa59e 100644 (file)
@@ -345,6 +345,7 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
                        dev_kfree_skb_any(skb_orig);
                        return NETDEV_TX_OK;
                }
+               dev_consume_skb_any(skb_orig);
        }
        mlxsw_sx_txhdr_construct(skb, &tx_info);
        /* TX header is consumed by HW on the way so we shouldn't count its
index 8e5cb7605b0fa92d8d778e2c16cae49cdc2570db..873ce2cd76ba0540e501cf7455e8b562fb00c0e3 100644 (file)
@@ -297,7 +297,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
                list_del(&p_pkt->list_entry);
                b_last_packet = list_empty(&p_tx->active_descq);
                list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);
-               if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+               if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
                        struct qed_ooo_buffer *p_buffer;
 
                        p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
@@ -309,7 +309,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
                        b_last_frag =
                                p_tx->cur_completing_bd_idx == p_pkt->bd_used;
                        tx_frag = p_pkt->bds_set[0].tx_frag;
-                       if (p_ll2_conn->gsi_enable)
+                       if (p_ll2_conn->conn.gsi_enable)
                                qed_ll2b_release_tx_gsi_packet(p_hwfn,
                                                               p_ll2_conn->
                                                               my_id,
@@ -378,7 +378,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
 
                spin_unlock_irqrestore(&p_tx->lock, flags);
                tx_frag = p_pkt->bds_set[0].tx_frag;
-               if (p_ll2_conn->gsi_enable)
+               if (p_ll2_conn->conn.gsi_enable)
                        qed_ll2b_complete_tx_gsi_packet(p_hwfn,
                                                        p_ll2_conn->my_id,
                                                        p_pkt->cookie,
@@ -550,7 +550,7 @@ static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
 
                list_move_tail(&p_pkt->list_entry, &p_rx->free_descq);
 
-               if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
+               if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO) {
                        struct qed_ooo_buffer *p_buffer;
 
                        p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
@@ -738,7 +738,7 @@ qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
                rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id, 1,
                                               p_buffer->vlan, bd_flags,
                                               l4_hdr_offset_w,
-                                              p_ll2_conn->tx_dest, 0,
+                                              p_ll2_conn->conn.tx_dest, 0,
                                               first_frag,
                                               p_buffer->packet_length,
                                               p_buffer, true);
@@ -858,7 +858,7 @@ qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
        u16 buf_idx;
        int rc = 0;
 
-       if (p_ll2_info->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_info->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
                return rc;
 
        if (!rx_num_ooo_buffers)
@@ -901,7 +901,7 @@ static void
 qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
                                 struct qed_ll2_info *p_ll2_conn)
 {
-       if (p_ll2_conn->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_conn->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
                return;
 
        qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
@@ -913,7 +913,7 @@ static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
 {
        struct qed_ooo_buffer *p_buffer;
 
-       if (p_ll2_conn->conn_type != QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_conn->conn.conn_type != QED_LL2_TYPE_ISCSI_OOO)
                return;
 
        qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
@@ -945,23 +945,19 @@ static int qed_ll2_start_ooo(struct qed_dev *cdev,
 {
        struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
        u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;
-       struct qed_ll2_info *ll2_info;
+       struct qed_ll2_conn ll2_info;
        int rc;
 
-       ll2_info = kzalloc(sizeof(*ll2_info), GFP_KERNEL);
-       if (!ll2_info)
-               return -ENOMEM;
-       ll2_info->conn_type = QED_LL2_TYPE_ISCSI_OOO;
-       ll2_info->mtu = params->mtu;
-       ll2_info->rx_drop_ttl0_flg = params->drop_ttl0_packets;
-       ll2_info->rx_vlan_removal_en = params->rx_vlan_stripping;
-       ll2_info->tx_tc = OOO_LB_TC;
-       ll2_info->tx_dest = CORE_TX_DEST_LB;
-
-       rc = qed_ll2_acquire_connection(hwfn, ll2_info,
+       ll2_info.conn_type = QED_LL2_TYPE_ISCSI_OOO;
+       ll2_info.mtu = params->mtu;
+       ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
+       ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping;
+       ll2_info.tx_tc = OOO_LB_TC;
+       ll2_info.tx_dest = CORE_TX_DEST_LB;
+
+       rc = qed_ll2_acquire_connection(hwfn, &ll2_info,
                                        QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
                                        handle);
-       kfree(ll2_info);
        if (rc) {
                DP_INFO(cdev, "Failed to acquire LL2 OOO connection\n");
                goto out;
@@ -1006,7 +1002,7 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
                                     struct qed_ll2_info *p_ll2_conn,
                                     u8 action_on_error)
 {
-       enum qed_ll2_conn_type conn_type = p_ll2_conn->conn_type;
+       enum qed_ll2_conn_type conn_type = p_ll2_conn->conn.conn_type;
        struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;
        struct core_rx_start_ramrod_data *p_ramrod = NULL;
        struct qed_spq_entry *p_ent = NULL;
@@ -1032,7 +1028,7 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
        p_ramrod->sb_index = p_rx->rx_sb_index;
        p_ramrod->complete_event_flg = 1;
 
-       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->mtu);
+       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->conn.mtu);
        DMA_REGPAIR_LE(p_ramrod->bd_base,
                       p_rx->rxq_chain.p_phys_addr);
        cqe_pbl_size = (u16)qed_chain_get_page_cnt(&p_rx->rcq_chain);
@@ -1040,8 +1036,8 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
        DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr,
                       qed_chain_get_pbl_phys(&p_rx->rcq_chain));
 
-       p_ramrod->drop_ttl0_flg = p_ll2_conn->rx_drop_ttl0_flg;
-       p_ramrod->inner_vlan_removal_en = p_ll2_conn->rx_vlan_removal_en;
+       p_ramrod->drop_ttl0_flg = p_ll2_conn->conn.rx_drop_ttl0_flg;
+       p_ramrod->inner_vlan_removal_en = p_ll2_conn->conn.rx_vlan_removal_en;
        p_ramrod->queue_id = p_ll2_conn->queue_id;
        p_ramrod->main_func_queue = (conn_type == QED_LL2_TYPE_ISCSI_OOO) ? 0
                                                                          : 1;
@@ -1056,14 +1052,14 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,
        }
 
        p_ramrod->action_on_error.error_type = action_on_error;
-       p_ramrod->gsi_offload_flag = p_ll2_conn->gsi_enable;
+       p_ramrod->gsi_offload_flag = p_ll2_conn->conn.gsi_enable;
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
 
 static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
                                     struct qed_ll2_info *p_ll2_conn)
 {
-       enum qed_ll2_conn_type conn_type = p_ll2_conn->conn_type;
+       enum qed_ll2_conn_type conn_type = p_ll2_conn->conn.conn_type;
        struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;
        struct core_tx_start_ramrod_data *p_ramrod = NULL;
        struct qed_spq_entry *p_ent = NULL;
@@ -1075,7 +1071,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
        if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
                return 0;
 
-       if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
                p_ll2_conn->tx_stats_en = 0;
        else
                p_ll2_conn->tx_stats_en = 1;
@@ -1096,7 +1092,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
 
        p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn));
        p_ramrod->sb_index = p_tx->tx_sb_index;
-       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->mtu);
+       p_ramrod->mtu = cpu_to_le16(p_ll2_conn->conn.mtu);
        p_ramrod->stats_en = p_ll2_conn->tx_stats_en;
        p_ramrod->stats_id = p_ll2_conn->tx_stats_id;
 
@@ -1106,7 +1102,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
        p_ramrod->pbl_size = cpu_to_le16(pbl_size);
 
        memset(&pq_params, 0, sizeof(pq_params));
-       pq_params.core.tc = p_ll2_conn->tx_tc;
+       pq_params.core.tc = p_ll2_conn->conn.tx_tc;
        pq_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_CORE, &pq_params);
        p_ramrod->qm_pq_id = cpu_to_le16(pq_id);
 
@@ -1123,7 +1119,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,
                DP_NOTICE(p_hwfn, "Unknown connection type: %d\n", conn_type);
        }
 
-       p_ramrod->gsi_offload_flag = p_ll2_conn->gsi_enable;
+       p_ramrod->gsi_offload_flag = p_ll2_conn->conn.gsi_enable;
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
 
@@ -1224,7 +1220,7 @@ qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn,
 
        DP_VERBOSE(p_hwfn, QED_MSG_LL2,
                   "Allocated LL2 Rxq [Type %08x] with 0x%08x buffers\n",
-                  p_ll2_info->conn_type, rx_num_desc);
+                  p_ll2_info->conn.conn_type, rx_num_desc);
 
 out:
        return rc;
@@ -1262,7 +1258,7 @@ static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn,
 
        DP_VERBOSE(p_hwfn, QED_MSG_LL2,
                   "Allocated LL2 Txq [Type %08x] with 0x%08x buffers\n",
-                  p_ll2_info->conn_type, tx_num_desc);
+                  p_ll2_info->conn.conn_type, tx_num_desc);
 
 out:
        if (rc)
@@ -1273,7 +1269,7 @@ out:
 }
 
 int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_info *p_params,
+                              struct qed_ll2_conn *p_params,
                               u16 rx_num_desc,
                               u16 tx_num_desc,
                               u8 *p_connection_handle)
@@ -1302,15 +1298,7 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
        if (!p_ll2_info)
                return -EBUSY;
 
-       p_ll2_info->conn_type = p_params->conn_type;
-       p_ll2_info->mtu = p_params->mtu;
-       p_ll2_info->rx_drop_ttl0_flg = p_params->rx_drop_ttl0_flg;
-       p_ll2_info->rx_vlan_removal_en = p_params->rx_vlan_removal_en;
-       p_ll2_info->tx_tc = p_params->tx_tc;
-       p_ll2_info->tx_dest = p_params->tx_dest;
-       p_ll2_info->ai_err_packet_too_big = p_params->ai_err_packet_too_big;
-       p_ll2_info->ai_err_no_buf = p_params->ai_err_no_buf;
-       p_ll2_info->gsi_enable = p_params->gsi_enable;
+       p_ll2_info->conn = *p_params;
 
        rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info, rx_num_desc);
        if (rc)
@@ -1371,9 +1359,9 @@ static int qed_ll2_establish_connection_rx(struct qed_hwfn *p_hwfn,
 
        SET_FIELD(action_on_error,
                  CORE_RX_ACTION_ON_ERROR_PACKET_TOO_BIG,
-                 p_ll2_conn->ai_err_packet_too_big);
+                 p_ll2_conn->conn.ai_err_packet_too_big);
        SET_FIELD(action_on_error,
-                 CORE_RX_ACTION_ON_ERROR_NO_BUFF, p_ll2_conn->ai_err_no_buf);
+                 CORE_RX_ACTION_ON_ERROR_NO_BUFF, p_ll2_conn->conn.ai_err_no_buf);
 
        return qed_sp_ll2_rx_queue_start(p_hwfn, p_ll2_conn, action_on_error);
 }
@@ -1600,7 +1588,7 @@ static void qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,
                   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Tx Producer at [0x%04x] - set with a %04x bytes %02x BDs buffer at %08x:%08x\n",
                   p_ll2->queue_id,
                   p_ll2->cid,
-                  p_ll2->conn_type,
+                  p_ll2->conn.conn_type,
                   prod_idx,
                   first_frag_len,
                   num_of_bds,
@@ -1676,7 +1664,7 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,
                   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
                   "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 0x%04x]\n",
                   p_ll2_conn->queue_id,
-                  p_ll2_conn->cid, p_ll2_conn->conn_type, db_msg.spq_prod);
+                  p_ll2_conn->cid, p_ll2_conn->conn.conn_type, db_msg.spq_prod);
 }
 
 int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
@@ -1817,7 +1805,7 @@ int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
                qed_ll2_rxq_flush(p_hwfn, connection_handle);
        }
 
-       if (p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO)
+       if (p_ll2_conn->conn.conn_type == QED_LL2_TYPE_ISCSI_OOO)
                qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
 
        return rc;
@@ -1993,7 +1981,7 @@ static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
 
 static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
 {
-       struct qed_ll2_info ll2_info;
+       struct qed_ll2_conn ll2_info;
        struct qed_ll2_buffer *buffer, *tmp_buffer;
        enum qed_ll2_conn_type conn_type;
        struct qed_ptt *p_ptt;
@@ -2041,6 +2029,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
 
        /* Prepare the temporary ll2 information */
        memset(&ll2_info, 0, sizeof(ll2_info));
+
        ll2_info.conn_type = conn_type;
        ll2_info.mtu = params->mtu;
        ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
@@ -2120,7 +2109,6 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
        }
 
        ether_addr_copy(cdev->ll2_mac_address, params->ll2_mac_address);
-
        return 0;
 
 release_terminate_all:
index 6625a3ae5a335bcace6f99b0e3914e5472bdc06d..31417928b6354f66d7f55c28d9e52565f9f3773d 100644 (file)
@@ -112,15 +112,8 @@ struct qed_ll2_tx_queue {
        bool b_completing_packet;
 };
 
-struct qed_ll2_info {
-       /* Lock protecting the state of LL2 */
-       struct mutex mutex;
+struct qed_ll2_conn {
        enum qed_ll2_conn_type conn_type;
-       u32 cid;
-       u8 my_id;
-       u8 queue_id;
-       u8 tx_stats_id;
-       bool b_active;
        u16 mtu;
        u8 rx_drop_ttl0_flg;
        u8 rx_vlan_removal_en;
@@ -128,10 +121,21 @@ struct qed_ll2_info {
        enum core_tx_dest tx_dest;
        enum core_error_handle ai_err_packet_too_big;
        enum core_error_handle ai_err_no_buf;
+       u8 gsi_enable;
+};
+
+struct qed_ll2_info {
+       /* Lock protecting the state of LL2 */
+       struct mutex mutex;
+       struct qed_ll2_conn conn;
+       u32 cid;
+       u8 my_id;
+       u8 queue_id;
+       u8 tx_stats_id;
+       bool b_active;
        u8 tx_stats_en;
        struct qed_ll2_rx_queue rx_queue;
        struct qed_ll2_tx_queue tx_queue;
-       u8 gsi_enable;
 };
 
 /**
@@ -149,7 +153,7 @@ struct qed_ll2_info {
  * @return 0 on success, failure otherwise
  */
 int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
-                              struct qed_ll2_info *p_params,
+                              struct qed_ll2_conn *p_params,
                               u16 rx_num_desc,
                               u16 tx_num_desc,
                               u8 *p_connection_handle);
index 2a16547c89661f1a35b8a575283cc39a5eaf7f83..2dbdb329899187d021b1f74b63a9948835ec523d 100644 (file)
@@ -2632,7 +2632,7 @@ static int qed_roce_ll2_start(struct qed_dev *cdev,
 {
        struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
        struct qed_roce_ll2_info *roce_ll2;
-       struct qed_ll2_info ll2_params;
+       struct qed_ll2_conn ll2_params;
        int rc;
 
        if (!params) {
index 99a14df28b9634dd8e6fdeb6bc9bce2d219a3e1a..2851b4c5657049600c6df2c9c9fa90649cbb832a 100644 (file)
@@ -201,6 +201,13 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
                else
                        adpt->phydev = mdiobus_get_phy(mii_bus, phy_addr);
 
+               /* of_phy_find_device() claims a reference to the phydev,
+                * so we do that here manually as well. When the driver
+                * later unloads, it can unilaterally drop the reference
+                * without worrying about ACPI vs DT.
+                */
+               if (adpt->phydev)
+                       get_device(&adpt->phydev->mdio.dev);
        } else {
                struct device_node *phy_np;
 
index 422289c232bc77b2c08c49e5646967b94aeedff8..f46d300bd58597ce64cc4cefe3be2b1aa4b03afa 100644 (file)
@@ -719,8 +719,7 @@ static int emac_probe(struct platform_device *pdev)
 err_undo_napi:
        netif_napi_del(&adpt->rx_q.napi);
 err_undo_mdiobus:
-       if (!has_acpi_companion(&pdev->dev))
-               put_device(&adpt->phydev->mdio.dev);
+       put_device(&adpt->phydev->mdio.dev);
        mdiobus_unregister(adpt->mii_bus);
 err_undo_clocks:
        emac_clks_teardown(adpt);
@@ -740,8 +739,7 @@ static int emac_remove(struct platform_device *pdev)
 
        emac_clks_teardown(adpt);
 
-       if (!has_acpi_companion(&pdev->dev))
-               put_device(&adpt->phydev->mdio.dev);
+       put_device(&adpt->phydev->mdio.dev);
        mdiobus_unregister(adpt->mii_bus);
        free_netdev(netdev);
 
index 44389c90056a0f197a97f5d36478ec597f266004..8f1623bf2134700498198a98cb6aca9dddd2a6cd 100644 (file)
@@ -696,7 +696,7 @@ enum rtl_tx_desc_bit_1 {
 enum rtl_rx_desc_bit {
        /* Rx private */
        PID1            = (1 << 18), /* Protocol ID bit 1/2 */
-       PID0            = (1 << 17), /* Protocol ID bit 2/2 */
+       PID0            = (1 << 17), /* Protocol ID bit 0/2 */
 
 #define RxProtoUDP     (PID1)
 #define RxProtoTCP     (PID0)
index 92d7692c840dbc67e33ca9fe61d3496893def71d..301f48755093bb084ce7741b24091b4c14eea67b 100644 (file)
@@ -179,6 +179,49 @@ static struct mdiobb_ops bb_ops = {
        .get_mdio_data = ravb_get_mdio_data,
 };
 
+/* Free TX skb function for AVB-IP */
+static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
+{
+       struct ravb_private *priv = netdev_priv(ndev);
+       struct net_device_stats *stats = &priv->stats[q];
+       struct ravb_tx_desc *desc;
+       int free_num = 0;
+       int entry;
+       u32 size;
+
+       for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
+               bool txed;
+
+               entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
+                                            NUM_TX_DESC);
+               desc = &priv->tx_ring[q][entry];
+               txed = desc->die_dt == DT_FEMPTY;
+               if (free_txed_only && !txed)
+                       break;
+               /* Descriptor type must be checked before all other reads */
+               dma_rmb();
+               size = le16_to_cpu(desc->ds_tagl) & TX_DS;
+               /* Free the original skb. */
+               if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
+                       dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
+                                        size, DMA_TO_DEVICE);
+                       /* Last packet descriptor? */
+                       if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
+                               entry /= NUM_TX_DESC;
+                               dev_kfree_skb_any(priv->tx_skb[q][entry]);
+                               priv->tx_skb[q][entry] = NULL;
+                               if (txed)
+                                       stats->tx_packets++;
+                       }
+                       free_num++;
+               }
+               if (txed)
+                       stats->tx_bytes += size;
+               desc->die_dt = DT_EEMPTY;
+       }
+       return free_num;
+}
+
 /* Free skb's and DMA buffers for Ethernet AVB */
 static void ravb_ring_free(struct net_device *ndev, int q)
 {
@@ -194,19 +237,21 @@ static void ravb_ring_free(struct net_device *ndev, int q)
        kfree(priv->rx_skb[q]);
        priv->rx_skb[q] = NULL;
 
-       /* Free TX skb ringbuffer */
-       if (priv->tx_skb[q]) {
-               for (i = 0; i < priv->num_tx_ring[q]; i++)
-                       dev_kfree_skb(priv->tx_skb[q][i]);
-       }
-       kfree(priv->tx_skb[q]);
-       priv->tx_skb[q] = NULL;
-
        /* Free aligned TX buffers */
        kfree(priv->tx_align[q]);
        priv->tx_align[q] = NULL;
 
        if (priv->rx_ring[q]) {
+               for (i = 0; i < priv->num_rx_ring[q]; i++) {
+                       struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
+
+                       if (!dma_mapping_error(ndev->dev.parent,
+                                              le32_to_cpu(desc->dptr)))
+                               dma_unmap_single(ndev->dev.parent,
+                                                le32_to_cpu(desc->dptr),
+                                                PKT_BUF_SZ,
+                                                DMA_FROM_DEVICE);
+               }
                ring_size = sizeof(struct ravb_ex_rx_desc) *
                            (priv->num_rx_ring[q] + 1);
                dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
@@ -215,12 +260,20 @@ static void ravb_ring_free(struct net_device *ndev, int q)
        }
 
        if (priv->tx_ring[q]) {
+               ravb_tx_free(ndev, q, false);
+
                ring_size = sizeof(struct ravb_tx_desc) *
                            (priv->num_tx_ring[q] * NUM_TX_DESC + 1);
                dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
                                  priv->tx_desc_dma[q]);
                priv->tx_ring[q] = NULL;
        }
+
+       /* Free TX skb ringbuffer.
+        * SKBs are freed by ravb_tx_free() call above.
+        */
+       kfree(priv->tx_skb[q]);
+       priv->tx_skb[q] = NULL;
 }
 
 /* Format skb and descriptor buffer for Ethernet AVB */
@@ -431,44 +484,6 @@ static int ravb_dmac_init(struct net_device *ndev)
        return 0;
 }
 
-/* Free TX skb function for AVB-IP */
-static int ravb_tx_free(struct net_device *ndev, int q)
-{
-       struct ravb_private *priv = netdev_priv(ndev);
-       struct net_device_stats *stats = &priv->stats[q];
-       struct ravb_tx_desc *desc;
-       int free_num = 0;
-       int entry;
-       u32 size;
-
-       for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
-               entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
-                                            NUM_TX_DESC);
-               desc = &priv->tx_ring[q][entry];
-               if (desc->die_dt != DT_FEMPTY)
-                       break;
-               /* Descriptor type must be checked before all other reads */
-               dma_rmb();
-               size = le16_to_cpu(desc->ds_tagl) & TX_DS;
-               /* Free the original skb. */
-               if (priv->tx_skb[q][entry / NUM_TX_DESC]) {
-                       dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
-                                        size, DMA_TO_DEVICE);
-                       /* Last packet descriptor? */
-                       if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) {
-                               entry /= NUM_TX_DESC;
-                               dev_kfree_skb_any(priv->tx_skb[q][entry]);
-                               priv->tx_skb[q][entry] = NULL;
-                               stats->tx_packets++;
-                       }
-                       free_num++;
-               }
-               stats->tx_bytes += size;
-               desc->die_dt = DT_EEMPTY;
-       }
-       return free_num;
-}
-
 static void ravb_get_tx_tstamp(struct net_device *ndev)
 {
        struct ravb_private *priv = netdev_priv(ndev);
@@ -902,7 +917,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
                        spin_lock_irqsave(&priv->lock, flags);
                        /* Clear TX interrupt */
                        ravb_write(ndev, ~mask, TIS);
-                       ravb_tx_free(ndev, q);
+                       ravb_tx_free(ndev, q, true);
                        netif_wake_subqueue(ndev, q);
                        mmiowb();
                        spin_unlock_irqrestore(&priv->lock, flags);
@@ -926,14 +941,10 @@ static int ravb_poll(struct napi_struct *napi, int budget)
        /* Receive error message handling */
        priv->rx_over_errors =  priv->stats[RAVB_BE].rx_over_errors;
        priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
-       if (priv->rx_over_errors != ndev->stats.rx_over_errors) {
+       if (priv->rx_over_errors != ndev->stats.rx_over_errors)
                ndev->stats.rx_over_errors = priv->rx_over_errors;
-               netif_err(priv, rx_err, ndev, "Receive Descriptor Empty\n");
-       }
-       if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors) {
+       if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
                ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
-               netif_err(priv, rx_err, ndev, "Receive FIFO Overflow\n");
-       }
 out:
        return budget - quota;
 }
@@ -1508,6 +1519,19 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) +
                 entry / NUM_TX_DESC * DPTR_ALIGN;
        len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data;
+       /* Zero length DMA descriptors are problematic as they seem to
+        * terminate DMA transfers. Avoid them by simply using a length of
+        * DPTR_ALIGN (4) when skb data is aligned to DPTR_ALIGN.
+        *
+        * As skb is guaranteed to have at least ETH_ZLEN (60) bytes of
+        * data by the call to skb_put_padto() above this is safe with
+        * respect to both the length of the first DMA descriptor (len)
+        * overflowing the available data and the length of the second DMA
+        * descriptor (skb->len - len) being negative.
+        */
+       if (len == 0)
+               len = DPTR_ALIGN;
+
        memcpy(buffer, skb->data, len);
        dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE);
        if (dma_mapping_error(ndev->dev.parent, dma_addr))
@@ -1558,7 +1582,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
        priv->cur_tx[q] += NUM_TX_DESC;
        if (priv->cur_tx[q] - priv->dirty_tx[q] >
-           (priv->num_tx_ring[q] - 1) * NUM_TX_DESC && !ravb_tx_free(ndev, q))
+           (priv->num_tx_ring[q] - 1) * NUM_TX_DESC &&
+           !ravb_tx_free(ndev, q, true))
                netif_stop_subqueue(ndev, q);
 
 exit:
index 00fafabab1d08ed505130ceab5306255c9910087..f729a6b43958cc82a1b2d38293cb50baf767f39a 100644 (file)
@@ -574,6 +574,7 @@ static struct sh_eth_cpu_data r8a7740_data = {
        .rpadir_value   = 2 << 16,
        .no_trimd       = 1,
        .no_ade         = 1,
+       .hw_crc         = 1,
        .tsu            = 1,
        .select_mii     = 1,
        .shift_rd0      = 1,
@@ -802,7 +803,7 @@ static struct sh_eth_cpu_data sh7734_data = {
 
        .ecsr_value     = ECSR_ICD | ECSR_MPD,
        .ecsipr_value   = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
-       .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+       .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003f07ff,
 
        .tx_check       = EESR_TC1 | EESR_FTC,
        .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
@@ -832,7 +833,7 @@ static struct sh_eth_cpu_data sh7763_data = {
 
        .ecsr_value     = ECSR_ICD | ECSR_MPD,
        .ecsipr_value   = ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
-       .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+       .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003f07ff,
 
        .tx_check       = EESR_TC1 | EESR_FTC,
        .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
index be3c91c7f211d94ad7386b77de73676933a46dcd..5484fd726d5af7f5f10708c57d062b9992be655d 100644 (file)
@@ -305,8 +305,12 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
 {
        void __iomem *ioaddr = hw->pcsr;
        u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
+       u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
        int ret = 0;
 
+       /* Discard masked bits */
+       intr_status &= ~intr_mask;
+
        /* Not used events (e.g. MMC interrupts) are not handled. */
        if ((intr_status & GMAC_INT_STATUS_MMCTIS))
                x->mmc_tx_irq_n++;
index 39eb7a65bb9f6a6137ffe13c4c2e776720311db1..e3f6389e1b01c5bba89c9cf3b632113fa9b4db42 100644 (file)
@@ -3319,8 +3319,16 @@ int stmmac_dvr_probe(struct device *device,
                ndev->max_mtu = JUMBO_LEN;
        else
                ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
-       if (priv->plat->maxmtu < ndev->max_mtu)
+       /* Will not overwrite ndev->max_mtu if plat->maxmtu > ndev->max_mtu
+        * as well as plat->maxmtu < ndev->min_mtu which is a invalid range.
+        */
+       if ((priv->plat->maxmtu < ndev->max_mtu) &&
+           (priv->plat->maxmtu >= ndev->min_mtu))
                ndev->max_mtu = priv->plat->maxmtu;
+       else if (priv->plat->maxmtu < ndev->min_mtu)
+               dev_warn(priv->device,
+                        "%s: warning: maxmtu having invalid value (%d)\n",
+                        __func__, priv->plat->maxmtu);
 
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
@@ -3332,7 +3340,8 @@ int stmmac_dvr_probe(struct device *device,
         */
        if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
                priv->use_riwt = 1;
-               netdev_info(priv->dev, "Enable RX Mitigation via HW Watchdog Timer\n");
+               dev_info(priv->device,
+                        "Enable RX Mitigation via HW Watchdog Timer\n");
        }
 
        netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
@@ -3358,17 +3367,17 @@ int stmmac_dvr_probe(struct device *device,
                /* MDIO bus Registration */
                ret = stmmac_mdio_register(ndev);
                if (ret < 0) {
-                       netdev_err(priv->dev,
-                                  "%s: MDIO bus (id: %d) registration failed",
-                                  __func__, priv->plat->bus_id);
+                       dev_err(priv->device,
+                               "%s: MDIO bus (id: %d) registration failed",
+                               __func__, priv->plat->bus_id);
                        goto error_mdio_register;
                }
        }
 
        ret = register_netdev(ndev);
        if (ret) {
-               netdev_err(priv->dev, "%s: ERROR %i registering the device\n",
-                          __func__, ret);
+               dev_err(priv->device, "%s: ERROR %i registering the device\n",
+                       __func__, ret);
                goto error_netdev_register;
        }
 
index a2831773431a6c19d185b2e82e50897aaf7ef7d8..3da4737620cb3fbf50e16c2cf61de3dbfd3e2355 100644 (file)
@@ -89,6 +89,9 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
 
        /* Set default value for unicast filter entries */
        plat->unicast_filter_entries = 1;
+
+       /* Set the maxmtu to a default of JUMBO_LEN */
+       plat->maxmtu = JUMBO_LEN;
 }
 
 static int quark_default_data(struct plat_stmmacenet_data *plat,
@@ -126,6 +129,9 @@ static int quark_default_data(struct plat_stmmacenet_data *plat,
        /* Set default value for unicast filter entries */
        plat->unicast_filter_entries = 1;
 
+       /* Set the maxmtu to a default of JUMBO_LEN */
+       plat->maxmtu = JUMBO_LEN;
+
        return 0;
 }
 
index 082cd48db6a769b43507be7442ca6d9ff0099c5f..36942f5a6a53adfc20bd254b0045fad51e398c12 100644 (file)
@@ -351,6 +351,7 @@ void stmmac_remove_config_dt(struct platform_device *pdev,
        if (of_phy_is_fixed_link(np))
                of_phy_deregister_fixed_link(np);
        of_node_put(plat->phy_node);
+       of_node_put(plat->mdio_node);
 }
 #else
 struct plat_stmmacenet_data *
index 77c88fcf2b86f610d8797aec75fba1ac0ba83561..9b8a30bf939bf946baed5f93228178e5fa686037 100644 (file)
@@ -1210,7 +1210,7 @@ int cpmac_init(void)
                goto fail_alloc;
        }
 
-#warning FIXME: unhardcode gpio&reset bits
+       /* FIXME: unhardcode gpio&reset bits */
        ar7_gpio_disable(26);
        ar7_gpio_disable(27);
        ar7_device_reset(AR7_RESET_BIT_CPMAC_LO);
index b203143647e6c0c39ae17b722366e52fa8f3ade8..65088224c207d9b6155192281b551cc823045b48 100644 (file)
@@ -3160,7 +3160,7 @@ static int cpsw_resume(struct device *dev)
 {
        struct platform_device  *pdev = to_platform_device(dev);
        struct net_device       *ndev = platform_get_drvdata(pdev);
-       struct cpsw_common      *cpsw = netdev_priv(ndev);
+       struct cpsw_common      *cpsw = ndev_to_cpsw(ndev);
 
        /* Select default pin state */
        pinctrl_pm_select_default_state(dev);
index 93dc10b10c0901c8974c4990eb87a22d6411e690..aa02a03a6d8db22996941cd53d4d12968a4e0ee2 100644 (file)
 /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
 #define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
 
+#ifdef __BIG_ENDIAN
+#define xemaclite_readl                ioread32be
+#define xemaclite_writel       iowrite32be
+#else
+#define xemaclite_readl                ioread32
+#define xemaclite_writel       iowrite32
+#endif
+
 /**
  * struct net_local - Our private per device data
  * @ndev:              instance of the network device
@@ -156,15 +164,15 @@ static void xemaclite_enable_interrupts(struct net_local *drvdata)
        u32 reg_data;
 
        /* Enable the Tx interrupts for the first Buffer */
-       reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
-       __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
-                    drvdata->base_addr + XEL_TSR_OFFSET);
+       reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+       xemaclite_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
+                        drvdata->base_addr + XEL_TSR_OFFSET);
 
        /* Enable the Rx interrupts for the first buffer */
-       __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
+       xemaclite_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
 
        /* Enable the Global Interrupt Enable */
-       __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+       xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 }
 
 /**
@@ -179,17 +187,17 @@ static void xemaclite_disable_interrupts(struct net_local *drvdata)
        u32 reg_data;
 
        /* Disable the Global Interrupt Enable */
-       __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
+       xemaclite_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
 
        /* Disable the Tx interrupts for the first buffer */
-       reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
-       __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
-                    drvdata->base_addr + XEL_TSR_OFFSET);
+       reg_data = xemaclite_readl(drvdata->base_addr + XEL_TSR_OFFSET);
+       xemaclite_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
+                        drvdata->base_addr + XEL_TSR_OFFSET);
 
        /* Disable the Rx interrupts for the first buffer */
-       reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
-       __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
-                    drvdata->base_addr + XEL_RSR_OFFSET);
+       reg_data = xemaclite_readl(drvdata->base_addr + XEL_RSR_OFFSET);
+       xemaclite_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
+                        drvdata->base_addr + XEL_RSR_OFFSET);
 }
 
 /**
@@ -321,7 +329,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
                byte_count = ETH_FRAME_LEN;
 
        /* Check if the expected buffer is available */
-       reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+       reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
        if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
             XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
 
@@ -334,7 +342,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
 
                addr = (void __iomem __force *)((u32 __force)addr ^
                                                 XEL_BUFFER_OFFSET);
-               reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+               reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
 
                if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
                     XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
@@ -345,16 +353,16 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
        /* Write the frame to the buffer */
        xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
 
-       __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
-                    addr + XEL_TPLR_OFFSET);
+       xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK),
+                        addr + XEL_TPLR_OFFSET);
 
        /* Update the Tx Status Register to indicate that there is a
         * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
         * is used by the interrupt handler to check whether a frame
         * has been transmitted */
-       reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
+       reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
        reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
-       __raw_writel(reg_data, addr + XEL_TSR_OFFSET);
+       xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET);
 
        return 0;
 }
@@ -369,7 +377,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
  *
  * Return:     Total number of bytes received
  */
-static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
+static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
 {
        void __iomem *addr;
        u16 length, proto_type;
@@ -379,7 +387,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
 
        /* Verify which buffer has valid data */
-       reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+       reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
 
        if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
                if (drvdata->rx_ping_pong != 0)
@@ -396,27 +404,28 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
                        return 0;       /* No data was available */
 
                /* Verify that buffer has valid data */
-               reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+               reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
                if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
                     XEL_RSR_RECV_DONE_MASK)
                        return 0;       /* No data was available */
        }
 
        /* Get the protocol type of the ethernet frame that arrived */
-       proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
+       proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET +
                        XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
                        XEL_RPLR_LENGTH_MASK);
 
        /* Check if received ethernet frame is a raw ethernet frame
         * or an IP packet or an ARP packet */
-       if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
+       if (proto_type > ETH_DATA_LEN) {
 
                if (proto_type == ETH_P_IP) {
-                       length = ((ntohl(__raw_readl(addr +
+                       length = ((ntohl(xemaclite_readl(addr +
                                        XEL_HEADER_IP_LENGTH_OFFSET +
                                        XEL_RXBUFF_OFFSET)) >>
                                        XEL_HEADER_SHIFT) &
                                        XEL_RPLR_LENGTH_MASK);
+                       length = min_t(u16, length, ETH_DATA_LEN);
                        length += ETH_HLEN + ETH_FCS_LEN;
 
                } else if (proto_type == ETH_P_ARP)
@@ -429,14 +438,17 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
                /* Use the length in the frame, plus the header and trailer */
                length = proto_type + ETH_HLEN + ETH_FCS_LEN;
 
+       if (WARN_ON(length > maxlen))
+               length = maxlen;
+
        /* Read from the EmacLite device */
        xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
                                data, length);
 
        /* Acknowledge the frame */
-       reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
+       reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
        reg_data &= ~XEL_RSR_RECV_DONE_MASK;
-       __raw_writel(reg_data, addr + XEL_RSR_OFFSET);
+       xemaclite_writel(reg_data, addr + XEL_RSR_OFFSET);
 
        return length;
 }
@@ -463,14 +475,14 @@ static void xemaclite_update_address(struct net_local *drvdata,
 
        xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
 
-       __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
+       xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
 
        /* Update the MAC address in the EmacLite */
-       reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
-       __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
+       reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
+       xemaclite_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
 
        /* Wait for EmacLite to finish with the MAC address update */
-       while ((__raw_readl(addr + XEL_TSR_OFFSET) &
+       while ((xemaclite_readl(addr + XEL_TSR_OFFSET) &
                XEL_TSR_PROG_MAC_ADDR) != 0)
                ;
 }
@@ -603,7 +615,7 @@ static void xemaclite_rx_handler(struct net_device *dev)
 
        skb_reserve(skb, 2);
 
-       len = xemaclite_recv_data(lp, (u8 *) skb->data);
+       len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
 
        if (!len) {
                dev->stats.rx_errors++;
@@ -640,32 +652,32 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
        u32 tx_status;
 
        /* Check if there is Rx Data available */
-       if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
+       if ((xemaclite_readl(base_addr + XEL_RSR_OFFSET) &
                         XEL_RSR_RECV_DONE_MASK) ||
-           (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
+           (xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
                         & XEL_RSR_RECV_DONE_MASK))
 
                xemaclite_rx_handler(dev);
 
        /* Check if the Transmission for the first buffer is completed */
-       tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
+       tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET);
        if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
                (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 
                tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
-               __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
+               xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET);
 
                tx_complete = true;
        }
 
        /* Check if the Transmission for the second buffer is completed */
-       tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+       tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
        if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
                (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 
                tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
-               __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
-                            XEL_TSR_OFFSET);
+               xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
+                                XEL_TSR_OFFSET);
 
                tx_complete = true;
        }
@@ -698,7 +710,7 @@ static int xemaclite_mdio_wait(struct net_local *lp)
        /* wait for the MDIO interface to not be busy or timeout
           after some time.
        */
-       while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
+       while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
                        XEL_MDIOCTRL_MDIOSTS_MASK) {
                if (time_before_eq(end, jiffies)) {
                        WARN_ON(1);
@@ -734,17 +746,17 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
         * MDIO Address register. Set the Status bit in the MDIO Control
         * register to start a MDIO read transaction.
         */
-       ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
-       __raw_writel(XEL_MDIOADDR_OP_MASK |
-                    ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
-                    lp->base_addr + XEL_MDIOADDR_OFFSET);
-       __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
-                    lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       xemaclite_writel(XEL_MDIOADDR_OP_MASK |
+                        ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+                        lp->base_addr + XEL_MDIOADDR_OFFSET);
+       xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+                        lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
        if (xemaclite_mdio_wait(lp))
                return -ETIMEDOUT;
 
-       rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
+       rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET);
 
        dev_dbg(&lp->ndev->dev,
                "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
@@ -781,13 +793,13 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
         * Data register. Finally, set the Status bit in the MDIO Control
         * register to start a MDIO write transaction.
         */
-       ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
-       __raw_writel(~XEL_MDIOADDR_OP_MASK &
-                    ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
-                    lp->base_addr + XEL_MDIOADDR_OFFSET);
-       __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
-       __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
-                    lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       ctrl_reg = xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       xemaclite_writel(~XEL_MDIOADDR_OP_MASK &
+                        ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
+                        lp->base_addr + XEL_MDIOADDR_OFFSET);
+       xemaclite_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
+       xemaclite_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
+                        lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
        return 0;
 }
@@ -834,8 +846,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
        /* Enable the MDIO bus by asserting the enable bit in MDIO Control
         * register.
         */
-       __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
-                    lp->base_addr + XEL_MDIOCTRL_OFFSET);
+       xemaclite_writel(XEL_MDIOCTRL_MDIOEN_MASK,
+                        lp->base_addr + XEL_MDIOCTRL_OFFSET);
 
        bus = mdiobus_alloc();
        if (!bus) {
@@ -1140,8 +1152,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
        }
 
        /* Clear the Tx CSR's in case this is a restart */
-       __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
-       __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
+       xemaclite_writel(0, lp->base_addr + XEL_TSR_OFFSET);
+       xemaclite_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 
        /* Set the MAC address in the EmacLite device */
        xemaclite_update_address(lp, ndev->dev_addr);
index 8b6810bad54b73fc90da579521e1e20050933aac..99d3df788ce81e6f423c7458466812607df68ed1 100644 (file)
@@ -69,7 +69,6 @@ struct gtp_dev {
        struct socket           *sock0;
        struct socket           *sock1u;
 
-       struct net              *net;
        struct net_device       *dev;
 
        unsigned int            hash_size;
@@ -316,7 +315,7 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
        netdev_dbg(gtp->dev, "encap_recv sk=%p\n", sk);
 
-       xnet = !net_eq(gtp->net, dev_net(gtp->dev));
+       xnet = !net_eq(sock_net(sk), dev_net(gtp->dev));
 
        switch (udp_sk(sk)->encap_type) {
        case UDP_ENCAP_GTP0:
@@ -612,7 +611,7 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
                                    pktinfo.fl4.saddr, pktinfo.fl4.daddr,
                                    pktinfo.iph->tos,
                                    ip4_dst_hoplimit(&pktinfo.rt->dst),
-                                   htons(IP_DF),
+                                   0,
                                    pktinfo.gtph_port, pktinfo.gtph_port,
                                    true, false);
                break;
@@ -658,7 +657,7 @@ static void gtp_link_setup(struct net_device *dev)
 static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
 static void gtp_hashtable_free(struct gtp_dev *gtp);
 static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-                           int fd_gtp0, int fd_gtp1, struct net *src_net);
+                           int fd_gtp0, int fd_gtp1);
 
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
                        struct nlattr *tb[], struct nlattr *data[])
@@ -675,7 +674,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
        fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
        fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
 
-       err = gtp_encap_enable(dev, gtp, fd0, fd1, src_net);
+       err = gtp_encap_enable(dev, gtp, fd0, fd1);
        if (err < 0)
                goto out_err;
 
@@ -821,7 +820,7 @@ static void gtp_hashtable_free(struct gtp_dev *gtp)
 }
 
 static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-                           int fd_gtp0, int fd_gtp1, struct net *src_net)
+                           int fd_gtp0, int fd_gtp1)
 {
        struct udp_tunnel_sock_cfg tuncfg = {NULL};
        struct socket *sock0, *sock1u;
@@ -858,7 +857,6 @@ static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 
        gtp->sock0 = sock0;
        gtp->sock1u = sock1u;
-       gtp->net = src_net;
 
        tuncfg.sk_user_data = gtp;
        tuncfg.encap_rcv = gtp_encap_recv;
@@ -1376,3 +1374,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <hwelte@sysmocom.de>");
 MODULE_DESCRIPTION("Interface driver for GTP encapsulated traffic");
 MODULE_ALIAS_RTNL_LINK("gtp");
+MODULE_ALIAS_GENL_FAMILY("gtp");
index ece59c54a653348014b686882e28e5bf1b335e37..4a40a3d825b41c2758a086a40cb216d6165f1cfa 100644 (file)
@@ -648,8 +648,8 @@ static void ax_setup(struct net_device *dev)
 {
        /* Finish setting up the DEVICE info. */
        dev->mtu             = AX_MTU;
-       dev->hard_header_len = 0;
-       dev->addr_len        = 0;
+       dev->hard_header_len = AX25_MAX_HEADER_LEN;
+       dev->addr_len        = AX25_ADDR_LEN;
        dev->type            = ARPHRD_AX25;
        dev->tx_queue_len    = 10;
        dev->header_ops      = &ax25_header_ops;
index 5a1cc089acb7fd2e79c18876cd7951f6dfb6e747..86e5749226ef4cf65d6070bca1ab0d4be35bf2e0 100644 (file)
@@ -1295,6 +1295,9 @@ void netvsc_channel_cb(void *context)
        ndev = hv_get_drvdata(device);
        buffer = get_per_channel_state(channel);
 
+       /* commit_rd_index() -> hv_signal_on_read() needs this. */
+       init_cached_read_index(channel);
+
        do {
                desc = get_next_pkt_raw(channel);
                if (desc != NULL) {
@@ -1347,6 +1350,9 @@ void netvsc_channel_cb(void *context)
 
                        bufferlen = bytes_recvd;
                }
+
+               init_cached_read_index(channel);
+
        } while (1);
 
        if (bufferlen > NETVSC_PACKET_SIZE)
index c9414c0548526657e78f77eb792f14df278eb376..fcab8019dda08ad430d126f9f044f39291a7a154 100644 (file)
@@ -659,6 +659,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
         * policy filters on the host). Deliver these via the VF
         * interface in the guest.
         */
+       rcu_read_lock();
        vf_netdev = rcu_dereference(net_device_ctx->vf_netdev);
        if (vf_netdev && (vf_netdev->flags & IFF_UP))
                net = vf_netdev;
@@ -667,6 +668,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci);
        if (unlikely(!skb)) {
                ++net->stats.rx_dropped;
+               rcu_read_unlock();
                return NVSP_STAT_FAIL;
        }
 
@@ -696,6 +698,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
         * TODO - use NAPI?
         */
        netif_rx(skb);
+       rcu_read_unlock();
 
        return 0;
 }
index 46d53a6c8cf868a18ab82a27e730c36e1bc6fb0b..76ba7ecfe14290c7800879c0f80b284f54299ca7 100644 (file)
@@ -1715,9 +1715,9 @@ static int at86rf230_probe(struct spi_device *spi)
        /* Reset */
        if (gpio_is_valid(rstn)) {
                udelay(1);
-               gpio_set_value(rstn, 0);
+               gpio_set_value_cansleep(rstn, 0);
                udelay(1);
-               gpio_set_value(rstn, 1);
+               gpio_set_value_cansleep(rstn, 1);
                usleep_range(120, 240);
        }
 
index 1253f864737ae3cfb10a95ee8c916b5c04dd94b6..ef688518ad77d7ec004e265c3ee9a0086228271a 100644 (file)
@@ -117,13 +117,26 @@ static int atusb_read_reg(struct atusb *atusb, uint8_t reg)
 {
        struct usb_device *usb_dev = atusb->usb_dev;
        int ret;
+       uint8_t *buffer;
        uint8_t value;
 
+       buffer = kmalloc(1, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
        dev_dbg(&usb_dev->dev, "atusb: reg = 0x%x\n", reg);
        ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
                                ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
-                               0, reg, &value, 1, 1000);
-       return ret >= 0 ? value : ret;
+                               0, reg, buffer, 1, 1000);
+
+       if (ret >= 0) {
+               value = buffer[0];
+               kfree(buffer);
+               return value;
+       } else {
+               kfree(buffer);
+               return ret;
+       }
 }
 
 static int atusb_write_subreg(struct atusb *atusb, uint8_t reg, uint8_t mask,
@@ -549,13 +562,6 @@ static int
 atusb_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
 {
        struct atusb *atusb = hw->priv;
-       struct device *dev = &atusb->usb_dev->dev;
-
-       if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 3) {
-               dev_info(dev, "Automatic frame retransmission is only available from "
-                       "firmware version 0.3. Please update if you want this feature.");
-               return -EINVAL;
-       }
 
        return atusb_write_subreg(atusb, SR_MAX_FRAME_RETRIES, retries);
 }
@@ -608,9 +614,13 @@ static const struct ieee802154_ops atusb_ops = {
 static int atusb_get_and_show_revision(struct atusb *atusb)
 {
        struct usb_device *usb_dev = atusb->usb_dev;
-       unsigned char buffer[3];
+       unsigned char *buffer;
        int ret;
 
+       buffer = kmalloc(3, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
        /* Get a couple of the ATMega Firmware values */
        ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
                                ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0,
@@ -631,15 +641,20 @@ static int atusb_get_and_show_revision(struct atusb *atusb)
                dev_info(&usb_dev->dev, "Please update to version 0.2 or newer");
        }
 
+       kfree(buffer);
        return ret;
 }
 
 static int atusb_get_and_show_build(struct atusb *atusb)
 {
        struct usb_device *usb_dev = atusb->usb_dev;
-       char build[ATUSB_BUILD_SIZE + 1];
+       char *build;
        int ret;
 
+       build = kmalloc(ATUSB_BUILD_SIZE + 1, GFP_KERNEL);
+       if (!build)
+               return -ENOMEM;
+
        ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
                                ATUSB_BUILD, ATUSB_REQ_FROM_DEV, 0, 0,
                                build, ATUSB_BUILD_SIZE, 1000);
@@ -648,6 +663,7 @@ static int atusb_get_and_show_build(struct atusb *atusb)
                dev_info(&usb_dev->dev, "Firmware: build %s\n", build);
        }
 
+       kfree(build);
        return ret;
 }
 
@@ -698,7 +714,7 @@ fail:
 static int atusb_set_extended_addr(struct atusb *atusb)
 {
        struct usb_device *usb_dev = atusb->usb_dev;
-       unsigned char buffer[IEEE802154_EXTENDED_ADDR_LEN];
+       unsigned char *buffer;
        __le64 extended_addr;
        u64 addr;
        int ret;
@@ -710,12 +726,20 @@ static int atusb_set_extended_addr(struct atusb *atusb)
                return 0;
        }
 
+       buffer = kmalloc(IEEE802154_EXTENDED_ADDR_LEN, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
        /* Firmware is new enough so we fetch the address from EEPROM */
        ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
                                ATUSB_EUI64_READ, ATUSB_REQ_FROM_DEV, 0, 0,
                                buffer, IEEE802154_EXTENDED_ADDR_LEN, 1000);
-       if (ret < 0)
-               dev_err(&usb_dev->dev, "failed to fetch extended address\n");
+       if (ret < 0) {
+               dev_err(&usb_dev->dev, "failed to fetch extended address, random address set\n");
+               ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
+               kfree(buffer);
+               return ret;
+       }
 
        memcpy(&extended_addr, buffer, IEEE802154_EXTENDED_ADDR_LEN);
        /* Check if read address is not empty and the unicast bit is set correctly */
@@ -729,6 +753,7 @@ static int atusb_set_extended_addr(struct atusb *atusb)
                        &addr);
        }
 
+       kfree(buffer);
        return ret;
 }
 
@@ -770,8 +795,7 @@ static int atusb_probe(struct usb_interface *interface,
 
        hw->parent = &usb_dev->dev;
        hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
-                   IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS |
-                   IEEE802154_HW_FRAME_RETRIES;
+                   IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS;
 
        hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL |
                         WPAN_PHY_FLAG_CCA_MODE;
@@ -800,6 +824,9 @@ static int atusb_probe(struct usb_interface *interface,
        atusb_get_and_show_build(atusb);
        atusb_set_extended_addr(atusb);
 
+       if (atusb->fw_ver_maj >= 0 && atusb->fw_ver_min >= 3)
+               hw->flags |= IEEE802154_HW_FRAME_RETRIES;
+
        ret = atusb_get_and_clear_error(atusb);
        if (ret) {
                dev_err(&atusb->usb_dev->dev,
index 1e05b7c2d157a22e06d115bcdd1d268876be03a7..0844f849641346b092e83923c1d196709b355e4c 100644 (file)
@@ -164,6 +164,7 @@ static void loopback_setup(struct net_device *dev)
 {
        dev->mtu                = 64 * 1024;
        dev->hard_header_len    = ETH_HLEN;     /* 14   */
+       dev->min_header_len     = ETH_HLEN;     /* 14   */
        dev->addr_len           = ETH_ALEN;     /* 6    */
        dev->type               = ARPHRD_LOOPBACK;      /* 0x0001*/
        dev->flags              = IFF_LOOPBACK;
index 5c26653eceb5660c0cd12b1a6669a58525fe7207..c27011bbe30c52d2eb892ab0d86f8cf3d6f4deb9 100644 (file)
@@ -681,7 +681,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
        size_t linear;
 
        if (q->flags & IFF_VNET_HDR) {
-               vnet_hdr_len = q->vnet_hdr_sz;
+               vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
 
                err = -EINVAL;
                if (len < vnet_hdr_len)
@@ -820,12 +820,12 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 
        if (q->flags & IFF_VNET_HDR) {
                struct virtio_net_hdr vnet_hdr;
-               vnet_hdr_len = q->vnet_hdr_sz;
+               vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
                if (iov_iter_count(iter) < vnet_hdr_len)
                        return -EINVAL;
 
                if (virtio_net_hdr_from_skb(skb, &vnet_hdr,
-                                           macvtap_is_little_endian(q)))
+                                           macvtap_is_little_endian(q), true))
                        BUG();
 
                if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) !=
index d361835b315dd6b9ed542a48515e85c8024192d3..8dbd59baa34d5ed9eda97396f38b5ab38e96416a 100644 (file)
@@ -279,6 +279,7 @@ config MARVELL_PHY
 
 config MESON_GXL_PHY
        tristate "Amlogic Meson GXL Internal PHY"
+       depends on ARCH_MESON || COMPILE_TEST
        ---help---
          Currently has a driver for the Amlogic Meson GXL Internal PHY
 
index e741bf614c4eeca4f4c041bff53880a5ca8c7439..b0492ef2cdaa0d360928e3e65a14808e336c40ec 100644 (file)
@@ -21,6 +21,23 @@ MODULE_DESCRIPTION("Broadcom 63xx internal PHY driver");
 MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
 MODULE_LICENSE("GPL");
 
+static int bcm63xx_config_intr(struct phy_device *phydev)
+{
+       int reg, err;
+
+       reg = phy_read(phydev, MII_BCM63XX_IR);
+       if (reg < 0)
+               return reg;
+
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               reg &= ~MII_BCM63XX_IR_GMASK;
+       else
+               reg |= MII_BCM63XX_IR_GMASK;
+
+       err = phy_write(phydev, MII_BCM63XX_IR, reg);
+       return err;
+}
+
 static int bcm63xx_config_init(struct phy_device *phydev)
 {
        int reg, err;
@@ -55,7 +72,7 @@ static struct phy_driver bcm63xx_driver[] = {
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
        .ack_interrupt  = bcm_phy_ack_intr,
-       .config_intr    = bcm_phy_config_intr,
+       .config_intr    = bcm63xx_config_intr,
 }, {
        /* same phy as above, with just a different OUI */
        .phy_id         = 0x002bdc00,
@@ -67,7 +84,7 @@ static struct phy_driver bcm63xx_driver[] = {
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
        .ack_interrupt  = bcm_phy_ack_intr,
-       .config_intr    = bcm_phy_config_intr,
+       .config_intr    = bcm63xx_config_intr,
 } };
 
 module_phy_driver(bcm63xx_driver);
index 800b39f0627943343c4276de637b30be4692352f..a10d0e7fc5f7010537560552cd822e59fd2d8469 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/phy.h>
 
 #define TI_DP83848C_PHY_ID             0x20005ca0
+#define TI_DP83620_PHY_ID              0x20005ce0
 #define NS_DP83848C_PHY_ID             0x20005c90
 #define TLK10X_PHY_ID                  0x2000a210
 #define TI_DP83822_PHY_ID              0x2000a240
@@ -77,6 +78,7 @@ static int dp83848_config_intr(struct phy_device *phydev)
 static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
        { TI_DP83848C_PHY_ID, 0xfffffff0 },
        { NS_DP83848C_PHY_ID, 0xfffffff0 },
+       { TI_DP83620_PHY_ID, 0xfffffff0 },
        { TLK10X_PHY_ID, 0xfffffff0 },
        { TI_DP83822_PHY_ID, 0xfffffff0 },
        { }
@@ -106,6 +108,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
 static struct phy_driver dp83848_driver[] = {
        DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"),
        DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"),
+       DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"),
        DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
        DP83848_PHY_DRIVER(TI_DP83822_PHY_ID, "TI DP83822 10/100 Mbps PHY"),
 };
index 1b639242f9e23170e69f7b7669ba82d8d4263fb5..ca1b462bf7b2782412014b63a0578aa328d9d4e1 100644 (file)
@@ -29,6 +29,7 @@
 #define MII_DP83867_MICR       0x12
 #define MII_DP83867_ISR                0x13
 #define DP83867_CTRL           0x1f
+#define DP83867_CFG3           0x1e
 
 /* Extended Registers */
 #define DP83867_RGMIICTL       0x0032
@@ -98,6 +99,8 @@ static int dp83867_config_intr(struct phy_device *phydev)
                micr_status |=
                        (MII_DP83867_MICR_AN_ERR_INT_EN |
                        MII_DP83867_MICR_SPEED_CHNG_INT_EN |
+                       MII_DP83867_MICR_AUTONEG_COMP_INT_EN |
+                       MII_DP83867_MICR_LINK_STS_CHNG_INT_EN |
                        MII_DP83867_MICR_DUP_MODE_CHNG_INT_EN |
                        MII_DP83867_MICR_SLEEP_MODE_CHNG_INT_EN);
 
@@ -129,12 +132,16 @@ static int dp83867_of_init(struct phy_device *phydev)
 
        ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
                                   &dp83867->rx_id_delay);
-       if (ret)
+       if (ret &&
+           (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+            phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
                return ret;
 
        ret = of_property_read_u32(of_node, "ti,tx-internal-delay",
                                   &dp83867->tx_id_delay);
-       if (ret)
+       if (ret &&
+           (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+            phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
                return ret;
 
        return of_property_read_u32(of_node, "ti,fifo-depth",
@@ -214,6 +221,13 @@ static int dp83867_config_init(struct phy_device *phydev)
                }
        }
 
+       /* Enable Interrupt output INT_OE in CFG3 register */
+       if (phy_interrupt_is_valid(phydev)) {
+               val = phy_read(phydev, DP83867_CFG3);
+               val |= BIT(7);
+               phy_write(phydev, DP83867_CFG3, val);
+       }
+
        return 0;
 }
 
index e269262471a44fdcbfc9ef3c5833bf3ceb78624e..ed0d235cf850ea11564bb446f8c8fc53879a9e73 100644 (file)
@@ -1192,7 +1192,8 @@ static int marvell_read_status(struct phy_device *phydev)
        int err;
 
        /* Check the fiber mode first */
-       if (phydev->supported & SUPPORTED_FIBRE) {
+       if (phydev->supported & SUPPORTED_FIBRE &&
+           phydev->interface != PHY_INTERFACE_MODE_SGMII) {
                err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_M1111_FIBER);
                if (err < 0)
                        goto error;
@@ -1678,6 +1679,8 @@ static struct phy_driver marvell_drivers[] = {
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
                .did_interrupt = &m88e1121_did_interrupt,
+               .get_wol = &m88e1318_get_wol,
+               .set_wol = &m88e1318_set_wol,
                .resume = &marvell_resume,
                .suspend = &marvell_suspend,
                .get_sset_count = marvell_get_sset_count,
index c0b4e65267af8b541974bd3a246897e1c38a9ac9..46fe1ae919a30a9a9b7644b5862f4a5bfa0b56ef 100644 (file)
@@ -81,8 +81,6 @@ static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg)
        if (rc)
                return rc;
 
-       iproc_mdio_config_clk(priv->base);
-
        /* Prepare the read operation */
        cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
                (reg << MII_DATA_RA_SHIFT) |
@@ -112,8 +110,6 @@ static int iproc_mdio_write(struct mii_bus *bus, int phy_id,
        if (rc)
                return rc;
 
-       iproc_mdio_config_clk(priv->base);
-
        /* Prepare the write operation */
        cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) |
                (reg << MII_DATA_RA_SHIFT) |
@@ -163,6 +159,8 @@ static int iproc_mdio_probe(struct platform_device *pdev)
        bus->read = iproc_mdio_read;
        bus->write = iproc_mdio_write;
 
+       iproc_mdio_config_clk(priv->base);
+
        rc = of_mdiobus_register(bus, pdev->dev.of_node);
        if (rc) {
                dev_err(&pdev->dev, "MDIO bus registration failed\n");
index 9a77289109b721ed5190f214bb4d6f22d2098424..6742070ca676f57694a9a6cb11364941deb520a0 100644 (file)
@@ -1008,6 +1008,20 @@ static struct phy_driver ksphy_driver[] = {
        .get_stats      = kszphy_get_stats,
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
+}, {
+       .phy_id         = PHY_ID_KSZ8795,
+       .phy_id_mask    = MICREL_PHY_ID_MASK,
+       .name           = "Micrel KSZ8795",
+       .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = kszphy_config_init,
+       .config_aneg    = ksz8873mll_config_aneg,
+       .read_status    = ksz8873mll_read_status,
+       .get_sset_count = kszphy_get_sset_count,
+       .get_strings    = kszphy_get_strings,
+       .get_stats      = kszphy_get_stats,
+       .suspend        = genphy_suspend,
+       .resume         = genphy_resume,
 } };
 
 module_phy_driver(ksphy_driver);
index 25f93a98863b79be76ac72b814d5dd4ff75c89a9..7cc1b7dcfe058fe48cb7209499caa1073ad2c1e9 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/phy_led_triggers.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/mdio.h>
@@ -649,14 +650,18 @@ void phy_start_machine(struct phy_device *phydev)
  * phy_trigger_machine - trigger the state machine to run
  *
  * @phydev: the phy_device struct
+ * @sync: indicate whether we should wait for the workqueue cancelation
  *
  * Description: There has been a change in state which requires that the
  *   state machine runs.
  */
 
-static void phy_trigger_machine(struct phy_device *phydev)
+static void phy_trigger_machine(struct phy_device *phydev, bool sync)
 {
-       cancel_delayed_work_sync(&phydev->state_queue);
+       if (sync)
+               cancel_delayed_work_sync(&phydev->state_queue);
+       else
+               cancel_delayed_work(&phydev->state_queue);
        queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);
 }
 
@@ -693,7 +698,7 @@ static void phy_error(struct phy_device *phydev)
        phydev->state = PHY_HALTED;
        mutex_unlock(&phydev->lock);
 
-       phy_trigger_machine(phydev);
+       phy_trigger_machine(phydev, false);
 }
 
 /**
@@ -840,7 +845,7 @@ void phy_change(struct phy_device *phydev)
        }
 
        /* reschedule state queue work to run as soon as possible */
-       phy_trigger_machine(phydev);
+       phy_trigger_machine(phydev, true);
        return;
 
 ignore:
@@ -942,7 +947,7 @@ void phy_start(struct phy_device *phydev)
        if (do_resume)
                phy_resume(phydev);
 
-       phy_trigger_machine(phydev);
+       phy_trigger_machine(phydev, true);
 }
 EXPORT_SYMBOL(phy_start);
 
@@ -1065,6 +1070,15 @@ void phy_state_machine(struct work_struct *work)
                        if (old_link != phydev->link)
                                phydev->state = PHY_CHANGELINK;
                }
+               /*
+                * Failsafe: check that nobody set phydev->link=0 between two
+                * poll cycles, otherwise we won't leave RUNNING state as long
+                * as link remains down.
+                */
+               if (!phydev->link && phydev->state == PHY_RUNNING) {
+                       phydev->state = PHY_CHANGELINK;
+                       phydev_err(phydev, "no link in PHY_RUNNING\n");
+               }
                break;
        case PHY_CHANGELINK:
                err = phy_read_status(phydev);
index 92b08383cafa8b88e8d5b79ea3a5c0da9998770f..8c8e15b8739dec0ae96d72b514045a99eb1ed7e1 100644 (file)
@@ -908,6 +908,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
        struct module *ndev_owner = dev->dev.parent->driver->owner;
        struct mii_bus *bus = phydev->mdio.bus;
        struct device *d = &phydev->mdio.dev;
+       bool using_genphy = false;
        int err;
 
        /* For Ethernet device drivers that register their own MDIO bus, we
@@ -933,12 +934,22 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
                        d->driver =
                                &genphy_driver[GENPHY_DRV_1G].mdiodrv.driver;
 
+               using_genphy = true;
+       }
+
+       if (!try_module_get(d->driver->owner)) {
+               dev_err(&dev->dev, "failed to get the device driver module\n");
+               err = -EIO;
+               goto error_put_device;
+       }
+
+       if (using_genphy) {
                err = d->driver->probe(d);
                if (err >= 0)
                        err = device_bind_driver(d);
 
                if (err)
-                       goto error;
+                       goto error_module_put;
        }
 
        if (phydev->attached_dev) {
@@ -975,7 +986,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
        return err;
 
 error:
+       /* phy_detach() does all of the cleanup below */
        phy_detach(phydev);
+       return err;
+
+error_module_put:
+       module_put(d->driver->owner);
+error_put_device:
        put_device(d);
        if (ndev_owner != bus->owner)
                module_put(bus->owner);
@@ -1039,6 +1056,8 @@ void phy_detach(struct phy_device *phydev)
 
        phy_led_triggers_unregister(phydev);
 
+       module_put(phydev->mdio.dev.driver->owner);
+
        /* If the device had no specific driver before (i.e. - it
         * was using the generic driver), we unbind the device
         * from the generic driver so that there's a chance a
index fa62bdf2f52694dece215d2b62e548026e482c38..94ca42e630bbead0c4fcae0b2ef6c8b19296bb69 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/leds.h>
 #include <linux/phy.h>
+#include <linux/phy_led_triggers.h>
 #include <linux/netdevice.h>
 
 static struct phy_led_trigger *phy_speed_to_led_trigger(struct phy_device *phy,
@@ -102,8 +103,10 @@ int phy_led_triggers_register(struct phy_device *phy)
                                            sizeof(struct phy_led_trigger) *
                                                   phy->phy_num_led_triggers,
                                            GFP_KERNEL);
-       if (!phy->phy_led_triggers)
-               return -ENOMEM;
+       if (!phy->phy_led_triggers) {
+               err = -ENOMEM;
+               goto out_clear;
+       }
 
        for (i = 0; i < phy->phy_num_led_triggers; i++) {
                err = phy_led_trigger_register(phy, &phy->phy_led_triggers[i],
@@ -120,6 +123,8 @@ out_unreg:
        while (i--)
                phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
        devm_kfree(&phy->mdio.dev, phy->phy_led_triggers);
+out_clear:
+       phy->phy_num_led_triggers = 0;
        return err;
 }
 EXPORT_SYMBOL_GPL(phy_led_triggers_register);
index cd8e02c94be0e514f226b8109e59e5ec29dad7de..bfabe180053e414dee777e0e56b24eceef05c918 100644 (file)
@@ -1170,9 +1170,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        }
 
        if (tun->flags & IFF_VNET_HDR) {
-               if (len < tun->vnet_hdr_sz)
+               int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
+
+               if (len < vnet_hdr_sz)
                        return -EINVAL;
-               len -= tun->vnet_hdr_sz;
+               len -= vnet_hdr_sz;
 
                if (!copy_from_iter_full(&gso, sizeof(gso), from))
                        return -EFAULT;
@@ -1183,7 +1185,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 
                if (tun16_to_cpu(tun, gso.hdr_len) > len)
                        return -EINVAL;
-               iov_iter_advance(from, tun->vnet_hdr_sz - sizeof(gso));
+               iov_iter_advance(from, vnet_hdr_sz - sizeof(gso));
        }
 
        if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) {
@@ -1335,7 +1337,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                vlan_hlen = VLAN_HLEN;
 
        if (tun->flags & IFF_VNET_HDR)
-               vnet_hdr_sz = tun->vnet_hdr_sz;
+               vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz);
 
        total = skb->len + vlan_hlen + vnet_hdr_sz;
 
@@ -1360,7 +1362,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                        return -EINVAL;
 
                if (virtio_net_hdr_from_skb(skb, &gso,
-                                           tun_is_little_endian(tun))) {
+                                           tun_is_little_endian(tun), true)) {
                        struct skb_shared_info *sinfo = skb_shinfo(skb);
                        pr_err("unexpected GSO type: "
                               "0x%x, gso_size %d, hdr_len %d\n",
index 3daa41bdd4eae0e5d44451458cb456175f8aedb2..0acc9b640419a2e94bc9a2d3d43a5a2a65800c8b 100644 (file)
@@ -776,7 +776,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
        struct net_device *netdev;
        struct catc *catc;
        u8 broadcast[ETH_ALEN];
-       int i, pktsz;
+       int pktsz, ret;
 
        if (usb_set_interface(usbdev,
                        intf->altsetting->desc.bInterfaceNumber, 1)) {
@@ -811,12 +811,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
        if ((!catc->ctrl_urb) || (!catc->tx_urb) || 
            (!catc->rx_urb) || (!catc->irq_urb)) {
                dev_err(&intf->dev, "No free urbs available.\n");
-               usb_free_urb(catc->ctrl_urb);
-               usb_free_urb(catc->tx_urb);
-               usb_free_urb(catc->rx_urb);
-               usb_free_urb(catc->irq_urb);
-               free_netdev(netdev);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail_free;
        }
 
        /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
@@ -844,15 +840,24 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                 catc->irq_buf, 2, catc_irq_done, catc, 1);
 
        if (!catc->is_f5u011) {
+               u32 *buf;
+               int i;
+
                dev_dbg(dev, "Checking memory size\n");
 
-               i = 0x12345678;
-               catc_write_mem(catc, 0x7a80, &i, 4);
-               i = 0x87654321; 
-               catc_write_mem(catc, 0xfa80, &i, 4);
-               catc_read_mem(catc, 0x7a80, &i, 4);
+               buf = kmalloc(4, GFP_KERNEL);
+               if (!buf) {
+                       ret = -ENOMEM;
+                       goto fail_free;
+               }
+
+               *buf = 0x12345678;
+               catc_write_mem(catc, 0x7a80, buf, 4);
+               *buf = 0x87654321;
+               catc_write_mem(catc, 0xfa80, buf, 4);
+               catc_read_mem(catc, 0x7a80, buf, 4);
          
-               switch (i) {
+               switch (*buf) {
                case 0x12345678:
                        catc_set_reg(catc, TxBufCount, 8);
                        catc_set_reg(catc, RxBufCount, 32);
@@ -867,6 +872,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                        dev_dbg(dev, "32k Memory\n");
                        break;
                }
+
+               kfree(buf);
          
                dev_dbg(dev, "Getting MAC from SEEROM.\n");
          
@@ -913,16 +920,21 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
        usb_set_intfdata(intf, catc);
 
        SET_NETDEV_DEV(netdev, &intf->dev);
-       if (register_netdev(netdev) != 0) {
-               usb_set_intfdata(intf, NULL);
-               usb_free_urb(catc->ctrl_urb);
-               usb_free_urb(catc->tx_urb);
-               usb_free_urb(catc->rx_urb);
-               usb_free_urb(catc->irq_urb);
-               free_netdev(netdev);
-               return -EIO;
-       }
+       ret = register_netdev(netdev);
+       if (ret)
+               goto fail_clear_intfdata;
+
        return 0;
+
+fail_clear_intfdata:
+       usb_set_intfdata(intf, NULL);
+fail_free:
+       usb_free_urb(catc->ctrl_urb);
+       usb_free_urb(catc->tx_urb);
+       usb_free_urb(catc->rx_urb);
+       usb_free_urb(catc->irq_urb);
+       free_netdev(netdev);
+       return ret;
 }
 
 static void catc_disconnect(struct usb_interface *intf)
index fe7b2886cb6b8fea8935c739d7d50999ed414fcb..86144f9a80ee84a5d4914dace38fdd8ef2932672 100644 (file)
@@ -531,6 +531,7 @@ static const struct driver_info wwan_info = {
 #define SAMSUNG_VENDOR_ID      0x04e8
 #define LENOVO_VENDOR_ID       0x17ef
 #define NVIDIA_VENDOR_ID       0x0955
+#define HP_VENDOR_ID           0x03f0
 
 static const struct usb_device_id      products[] = {
 /* BLACKLIST !!
@@ -677,6 +678,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* HP lt2523 (Novatel E371) - handled by qmi_wwan */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(HP_VENDOR_ID, 0x421d, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* AnyDATA ADU960S - handled by qmi_wwan */
 {
        USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM,
index 24e803fe9a534c2e23dee6418496dd2755ff8de9..36674484c6fb9b73011619824f7bc60c50b9c1ad 100644 (file)
@@ -126,40 +126,61 @@ static void async_ctrl_callback(struct urb *urb)
 
 static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
 {
+       u8 *buf;
        int ret;
 
+       buf = kmalloc(size, GFP_NOIO);
+       if (!buf)
+               return -ENOMEM;
+
        ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
                              PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
-                             indx, data, size, 1000);
+                             indx, buf, size, 1000);
        if (ret < 0)
                netif_dbg(pegasus, drv, pegasus->net,
                          "%s returned %d\n", __func__, ret);
+       else if (ret <= size)
+               memcpy(data, buf, ret);
+       kfree(buf);
        return ret;
 }
 
-static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
+static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
+                        const void *data)
 {
+       u8 *buf;
        int ret;
 
+       buf = kmemdup(data, size, GFP_NOIO);
+       if (!buf)
+               return -ENOMEM;
+
        ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
                              PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
-                             indx, data, size, 100);
+                             indx, buf, size, 100);
        if (ret < 0)
                netif_dbg(pegasus, drv, pegasus->net,
                          "%s returned %d\n", __func__, ret);
+       kfree(buf);
        return ret;
 }
 
 static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
 {
+       u8 *buf;
        int ret;
 
+       buf = kmemdup(&data, 1, GFP_NOIO);
+       if (!buf)
+               return -ENOMEM;
+
        ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
                              PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
-                             indx, &data, 1, 1000);
+                             indx, buf, 1, 1000);
        if (ret < 0)
                netif_dbg(pegasus, drv, pegasus->net,
                          "%s returned %d\n", __func__, ret);
+       kfree(buf);
        return ret;
 }
 
index 6fe1cdb0174f6cf91f8445dbe86a3e977d327255..24d5272cdce51091a26a116205d8ca2ae5be03d9 100644 (file)
@@ -654,6 +654,13 @@ static const struct usb_device_id products[] = {
                                              USB_CDC_PROTO_NONE),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* HP lt2523 (Novatel E371) */
+               USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
        {       /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
                USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7),
                .driver_info = (unsigned long)&qmi_wwan_info,
index 7dc61228c55b8af26f0623fa4cfb9dd512cd97ac..ad42295356dd32b70009852247151b4856deea86 100644 (file)
@@ -32,7 +32,7 @@
 #define NETNEXT_VERSION                "08"
 
 /* Information for net */
-#define NET_VERSION            "6"
+#define NET_VERSION            "8"
 
 #define DRIVER_VERSION         "v1." NETNEXT_VERSION "." NET_VERSION
 #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
@@ -1730,7 +1730,7 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
        u8 checksum = CHECKSUM_NONE;
        u32 opts2, opts3;
 
-       if (tp->version == RTL_VER_01 || tp->version == RTL_VER_02)
+       if (!(tp->netdev->features & NETIF_F_RXCSUM))
                goto return_result;
 
        opts2 = le32_to_cpu(rx_desc->opts2);
@@ -1936,6 +1936,9 @@ static int r8152_poll(struct napi_struct *napi, int budget)
                napi_complete(napi);
                if (!list_empty(&tp->rx_done))
                        napi_schedule(napi);
+               else if (!skb_queue_empty(&tp->tx_queue) &&
+                        !list_empty(&tp->tx_free))
+                       napi_schedule(napi);
        }
 
        return work_done;
@@ -3155,10 +3158,13 @@ static void set_carrier(struct r8152 *tp)
                if (!netif_carrier_ok(netdev)) {
                        tp->rtl_ops.enable(tp);
                        set_bit(RTL8152_SET_RX_MODE, &tp->flags);
+                       netif_stop_queue(netdev);
                        napi_disable(&tp->napi);
                        netif_carrier_on(netdev);
                        rtl_start_rx(tp);
                        napi_enable(&tp->napi);
+                       netif_wake_queue(netdev);
+                       netif_info(tp, link, netdev, "carrier on\n");
                }
        } else {
                if (netif_carrier_ok(netdev)) {
@@ -3166,6 +3172,7 @@ static void set_carrier(struct r8152 *tp)
                        napi_disable(&tp->napi);
                        tp->rtl_ops.disable(tp);
                        napi_enable(&tp->napi);
+                       netif_info(tp, link, netdev, "carrier off\n");
                }
        }
 }
@@ -3515,12 +3522,12 @@ static int rtl8152_pre_reset(struct usb_interface *intf)
        if (!netif_running(netdev))
                return 0;
 
+       netif_stop_queue(netdev);
        napi_disable(&tp->napi);
        clear_bit(WORK_ENABLE, &tp->flags);
        usb_kill_urb(tp->intr_urb);
        cancel_delayed_work_sync(&tp->schedule);
        if (netif_carrier_ok(netdev)) {
-               netif_stop_queue(netdev);
                mutex_lock(&tp->control);
                tp->rtl_ops.disable(tp);
                mutex_unlock(&tp->control);
@@ -3545,12 +3552,17 @@ static int rtl8152_post_reset(struct usb_interface *intf)
        if (netif_carrier_ok(netdev)) {
                mutex_lock(&tp->control);
                tp->rtl_ops.enable(tp);
+               rtl_start_rx(tp);
                rtl8152_set_rx_mode(netdev);
                mutex_unlock(&tp->control);
-               netif_wake_queue(netdev);
        }
 
        napi_enable(&tp->napi);
+       netif_wake_queue(netdev);
+       usb_submit_urb(tp->intr_urb, GFP_KERNEL);
+
+       if (!list_empty(&tp->rx_done))
+               napi_schedule(&tp->napi);
 
        return 0;
 }
@@ -3572,43 +3584,98 @@ static bool delay_autosuspend(struct r8152 *tp)
         */
        if (!sw_linking && tp->rtl_ops.in_nway(tp))
                return true;
+       else if (!skb_queue_empty(&tp->tx_queue))
+               return true;
        else
                return false;
 }
 
-static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
+static int rtl8152_rumtime_suspend(struct r8152 *tp)
 {
-       struct r8152 *tp = usb_get_intfdata(intf);
        struct net_device *netdev = tp->netdev;
        int ret = 0;
 
-       mutex_lock(&tp->control);
+       set_bit(SELECTIVE_SUSPEND, &tp->flags);
+       smp_mb__after_atomic();
+
+       if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
+               u32 rcr = 0;
 
-       if (PMSG_IS_AUTO(message)) {
-               if (netif_running(netdev) && delay_autosuspend(tp)) {
+               if (delay_autosuspend(tp)) {
+                       clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+                       smp_mb__after_atomic();
                        ret = -EBUSY;
                        goto out1;
                }
 
-               set_bit(SELECTIVE_SUSPEND, &tp->flags);
-       } else {
-               netif_device_detach(netdev);
+               if (netif_carrier_ok(netdev)) {
+                       u32 ocp_data;
+
+                       rcr = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
+                       ocp_data = rcr & ~RCR_ACPT_ALL;
+                       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
+                       rxdy_gated_en(tp, true);
+                       ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA,
+                                                PLA_OOB_CTRL);
+                       if (!(ocp_data & RXFIFO_EMPTY)) {
+                               rxdy_gated_en(tp, false);
+                               ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+                               clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+                               smp_mb__after_atomic();
+                               ret = -EBUSY;
+                               goto out1;
+                       }
+               }
+
+               clear_bit(WORK_ENABLE, &tp->flags);
+               usb_kill_urb(tp->intr_urb);
+
+               tp->rtl_ops.autosuspend_en(tp, true);
+
+               if (netif_carrier_ok(netdev)) {
+                       napi_disable(&tp->napi);
+                       rtl_stop_rx(tp);
+                       rxdy_gated_en(tp, false);
+                       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, rcr);
+                       napi_enable(&tp->napi);
+               }
        }
 
+out1:
+       return ret;
+}
+
+static int rtl8152_system_suspend(struct r8152 *tp)
+{
+       struct net_device *netdev = tp->netdev;
+       int ret = 0;
+
+       netif_device_detach(netdev);
+
        if (netif_running(netdev) && test_bit(WORK_ENABLE, &tp->flags)) {
                clear_bit(WORK_ENABLE, &tp->flags);
                usb_kill_urb(tp->intr_urb);
                napi_disable(&tp->napi);
-               if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
-                       rtl_stop_rx(tp);
-                       tp->rtl_ops.autosuspend_en(tp, true);
-               } else {
-                       cancel_delayed_work_sync(&tp->schedule);
-                       tp->rtl_ops.down(tp);
-               }
+               cancel_delayed_work_sync(&tp->schedule);
+               tp->rtl_ops.down(tp);
                napi_enable(&tp->napi);
        }
-out1:
+
+       return ret;
+}
+
+static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct r8152 *tp = usb_get_intfdata(intf);
+       int ret;
+
+       mutex_lock(&tp->control);
+
+       if (PMSG_IS_AUTO(message))
+               ret = rtl8152_rumtime_suspend(tp);
+       else
+               ret = rtl8152_system_suspend(tp);
+
        mutex_unlock(&tp->control);
 
        return ret;
@@ -3629,12 +3696,15 @@ static int rtl8152_resume(struct usb_interface *intf)
        if (netif_running(tp->netdev) && tp->netdev->flags & IFF_UP) {
                if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
                        tp->rtl_ops.autosuspend_en(tp, false);
-                       clear_bit(SELECTIVE_SUSPEND, &tp->flags);
                        napi_disable(&tp->napi);
                        set_bit(WORK_ENABLE, &tp->flags);
                        if (netif_carrier_ok(tp->netdev))
                                rtl_start_rx(tp);
                        napi_enable(&tp->napi);
+                       clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+                       smp_mb__after_atomic();
+                       if (!list_empty(&tp->rx_done))
+                               napi_schedule(&tp->napi);
                } else {
                        tp->rtl_ops.up(tp);
                        netif_carrier_off(tp->netdev);
@@ -4308,6 +4378,11 @@ static int rtl8152_probe(struct usb_interface *intf,
                                NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
                                NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
+       if (tp->version == RTL_VER_01) {
+               netdev->features &= ~NETIF_F_RXCSUM;
+               netdev->hw_features &= ~NETIF_F_RXCSUM;
+       }
+
        netdev->ethtool_ops = &ops;
        netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
 
index 95b7bd0d7abcac85482da6067626e034a57b56b3..c81c79110cefca9443d614679d8e7cdd4b3295c3 100644 (file)
@@ -155,16 +155,36 @@ static const char driver_name [] = "rtl8150";
 */
 static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
 {
-       return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-                              RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
-                              indx, 0, data, size, 500);
+       void *buf;
+       int ret;
+
+       buf = kmalloc(size, GFP_NOIO);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+                             RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
+                             indx, 0, buf, size, 500);
+       if (ret > 0 && ret <= size)
+               memcpy(data, buf, ret);
+       kfree(buf);
+       return ret;
 }
 
-static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
+static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data)
 {
-       return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-                              RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
-                              indx, 0, data, size, 500);
+       void *buf;
+       int ret;
+
+       buf = kmemdup(data, size, GFP_NOIO);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+                             RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
+                             indx, 0, buf, size, 500);
+       kfree(buf);
+       return ret;
 }
 
 static void async_set_reg_cb(struct urb *urb)
index 12071f1582df2c9b4e867e432f972659d3f78dc4..d9440bc022f2c40d965f6a6dd804f7ba74944cbc 100644 (file)
@@ -73,8 +73,6 @@ static        atomic_t iface_counter = ATOMIC_INIT(0);
 /* Private data structure */
 struct sierra_net_data {
 
-       u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */
-
        u16 link_up;            /* air link up or down */
        u8 tx_hdr_template[4];  /* part of HIP hdr for tx'd packets */
 
@@ -122,6 +120,7 @@ struct param {
 
 /* LSI Protocol types */
 #define SIERRA_NET_PROTOCOL_UMTS      0x01
+#define SIERRA_NET_PROTOCOL_UMTS_DS   0x04
 /* LSI Coverage */
 #define SIERRA_NET_COVERAGE_NONE      0x00
 #define SIERRA_NET_COVERAGE_NOPACKET  0x01
@@ -129,7 +128,8 @@ struct param {
 /* LSI Session */
 #define SIERRA_NET_SESSION_IDLE       0x00
 /* LSI Link types */
-#define SIERRA_NET_AS_LINK_TYPE_IPv4  0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPV4  0x00
+#define SIERRA_NET_AS_LINK_TYPE_IPV6  0x02
 
 struct lsi_umts {
        u8 protocol;
@@ -137,9 +137,14 @@ struct lsi_umts {
        __be16 length;
        /* eventually use a union for the rest - assume umts for now */
        u8 coverage;
-       u8 unused2[41];
+       u8 network_len; /* network name len */
+       u8 network[40]; /* network name (UCS2, bigendian) */
        u8 session_state;
        u8 unused3[33];
+} __packed;
+
+struct lsi_umts_single {
+       struct lsi_umts lsi;
        u8 link_type;
        u8 pdp_addr_len; /* NW-supplied PDP address len */
        u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */
@@ -158,10 +163,31 @@ struct lsi_umts {
        u8 reserved[8];
 } __packed;
 
+struct lsi_umts_dual {
+       struct lsi_umts lsi;
+       u8 pdp_addr4_len; /* NW-supplied PDP IPv4 address len */
+       u8 pdp_addr4[4];  /* NW-supplied PDP IPv4 address (bigendian)) */
+       u8 pdp_addr6_len; /* NW-supplied PDP IPv6 address len */
+       u8 pdp_addr6[16]; /* NW-supplied PDP IPv6 address (bigendian)) */
+       u8 unused4[23];
+       u8 dns1_addr4_len; /* NW-supplied 1st DNS v4 address len (bigendian) */
+       u8 dns1_addr4[4];  /* NW-supplied 1st DNS v4 address */
+       u8 dns1_addr6_len; /* NW-supplied 1st DNS v6 address len */
+       u8 dns1_addr6[16]; /* NW-supplied 1st DNS v6 address (bigendian)*/
+       u8 dns2_addr4_len; /* NW-supplied 2nd DNS v4 address len (bigendian) */
+       u8 dns2_addr4[4];  /* NW-supplied 2nd DNS v4 address */
+       u8 dns2_addr6_len; /* NW-supplied 2nd DNS v6 address len */
+       u8 dns2_addr6[16]; /* NW-supplied 2nd DNS v6 address (bigendian)*/
+       u8 unused5[68];
+} __packed;
+
 #define SIERRA_NET_LSI_COMMON_LEN      4
-#define SIERRA_NET_LSI_UMTS_LEN        (sizeof(struct lsi_umts))
+#define SIERRA_NET_LSI_UMTS_LEN        (sizeof(struct lsi_umts_single))
 #define SIERRA_NET_LSI_UMTS_STATUS_LEN \
        (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
+#define SIERRA_NET_LSI_UMTS_DS_LEN     (sizeof(struct lsi_umts_dual))
+#define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \
+       (SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN)
 
 /* Forward definitions */
 static void sierra_sync_timer(unsigned long syncdata);
@@ -190,10 +216,11 @@ static inline void sierra_net_set_private(struct usbnet *dev,
        dev->data[0] = (unsigned long)priv;
 }
 
-/* is packet IPv4 */
+/* is packet IPv4/IPv6 */
 static inline int is_ip(struct sk_buff *skb)
 {
-       return skb->protocol == cpu_to_be16(ETH_P_IP);
+       return skb->protocol == cpu_to_be16(ETH_P_IP) ||
+              skb->protocol == cpu_to_be16(ETH_P_IPV6);
 }
 
 /*
@@ -349,49 +376,54 @@ static inline int sierra_net_is_valid_addrlen(u8 len)
 static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
 {
        struct lsi_umts *lsi = (struct lsi_umts *)data;
+       u32 expected_length;
 
-       if (datalen < sizeof(struct lsi_umts)) {
-               netdev_err(dev->net, "%s: Data length %d, exp %Zu\n",
-                               __func__, datalen,
-                               sizeof(struct lsi_umts));
+       if (datalen < sizeof(struct lsi_umts_single)) {
+               netdev_err(dev->net, "%s: Data length %d, exp >= %Zu\n",
+                          __func__, datalen, sizeof(struct lsi_umts_single));
                return -1;
        }
 
-       if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) {
-               netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
-                               __func__, be16_to_cpu(lsi->length),
-                               (u32)SIERRA_NET_LSI_UMTS_STATUS_LEN);
-               return -1;
+       /* Validate the session state */
+       if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
+               netdev_err(dev->net, "Session idle, 0x%02x\n",
+                          lsi->session_state);
+               return 0;
        }
 
        /* Validate the protocol  - only support UMTS for now */
-       if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) {
+       if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS) {
+               struct lsi_umts_single *single = (struct lsi_umts_single *)lsi;
+
+               /* Validate the link type */
+               if (single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 &&
+                   single->link_type != SIERRA_NET_AS_LINK_TYPE_IPV6) {
+                       netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
+                                  single->link_type);
+                       return -1;
+               }
+               expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN;
+       } else if (lsi->protocol == SIERRA_NET_PROTOCOL_UMTS_DS) {
+               expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN;
+       } else {
                netdev_err(dev->net, "Protocol unsupported, 0x%02x\n",
-                       lsi->protocol);
+                          lsi->protocol);
                return -1;
        }
 
-       /* Validate the link type */
-       if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) {
-               netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
-                       lsi->link_type);
+       if (be16_to_cpu(lsi->length) != expected_length) {
+               netdev_err(dev->net, "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n",
+                          __func__, be16_to_cpu(lsi->length), expected_length);
                return -1;
        }
 
        /* Validate the coverage */
-       if (lsi->coverage == SIERRA_NET_COVERAGE_NONE
-          || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
+       if (lsi->coverage == SIERRA_NET_COVERAGE_NONE ||
+           lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
                netdev_err(dev->net, "No coverage, 0x%02x\n", lsi->coverage);
                return 0;
        }
 
-       /* Validate the session state */
-       if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
-               netdev_err(dev->net, "Session idle, 0x%02x\n",
-                       lsi->session_state);
-               return 0;
-       }
-
        /* Set link_sense true */
        return 1;
 }
@@ -652,7 +684,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
        u8      numendpoints;
        u16     fwattr = 0;
        int     status;
-       struct ethhdr *eth;
        struct sierra_net_data *priv;
        static const u8 sync_tmplate[sizeof(priv->sync_msg)] = {
                0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
@@ -690,11 +721,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
        dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
 
-       /* we will have to manufacture ethernet headers, prepare template */
-       eth = (struct ethhdr *)priv->ethr_hdr_tmpl;
-       memcpy(&eth->h_dest, dev->net->dev_addr, ETH_ALEN);
-       eth->h_proto = cpu_to_be16(ETH_P_IP);
-
        /* prepare shutdown message template */
        memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
        /* set context index initially to 0 - prepares tx hdr template */
@@ -824,9 +850,14 @@ static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
                skb_pull(skb, hh.hdrlen);
 
-               /* We are going to accept this packet, prepare it */
-               memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
-                       ETH_HLEN);
+               /* We are going to accept this packet, prepare it.
+                * In case protocol is IPv6, keep it, otherwise force IPv4.
+                */
+               skb_reset_mac_header(skb);
+               if (eth_hdr(skb)->h_proto != cpu_to_be16(ETH_P_IPV6))
+                       eth_hdr(skb)->h_proto = cpu_to_be16(ETH_P_IP);
+               eth_zero_addr(eth_hdr(skb)->h_source);
+               memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
 
                /* Last packet in batch handled by usbnet */
                if (hh.payload_len.word == skb->len)
index 4a105006ca637bc985698fa378ff6d14e1494b3f..765c2d6358daf38203cdb1a50a31cc04f65c1968 100644 (file)
@@ -48,8 +48,16 @@ module_param(gso, bool, 0444);
  */
 DECLARE_EWMA(pkt_len, 1, 64)
 
+/* With mergeable buffers we align buffer address and use the low bits to
+ * encode its true size. Buffer size is up to 1 page so we need to align to
+ * square root of page size to ensure we reserve enough bits to encode the true
+ * size.
+ */
+#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2)
+
 /* Minimum alignment for mergeable packet buffers. */
-#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
+#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \
+                                  1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT)
 
 #define VIRTNET_DRIVER_VERSION "1.0.0"
 
@@ -1104,7 +1112,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
                hdr = skb_vnet_hdr(skb);
 
        if (virtio_net_hdr_from_skb(skb, &hdr->hdr,
-                                   virtio_is_little_endian(vi->vdev)))
+                                   virtio_is_little_endian(vi->vdev), false))
                BUG();
 
        if (vi->mergeable_rx_bufs)
@@ -1707,6 +1715,11 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog)
        u16 xdp_qp = 0, curr_qp;
        int i, err;
 
+       if (prog && prog->xdp_adjust_head) {
+               netdev_warn(dev, "Does not support bpf_xdp_adjust_head()\n");
+               return -EOPNOTSUPP;
+       }
+
        if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
            virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
            virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
@@ -1890,8 +1903,12 @@ static void free_receive_page_frags(struct virtnet_info *vi)
                        put_page(vi->rq[i].alloc_frag.page);
 }
 
-static bool is_xdp_queue(struct virtnet_info *vi, int q)
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
 {
+       /* For small receive mode always use kfree_skb variants */
+       if (!vi->mergeable_rx_bufs)
+               return false;
+
        if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
                return false;
        else if (q < vi->curr_queue_pairs)
@@ -1908,7 +1925,7 @@ 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_queue(vi, i))
+                       if (!is_xdp_raw_buffer_queue(vi, i))
                                dev_kfree_skb(buf);
                        else
                                put_page(virt_to_head_page(buf));
index 23dfb0eac0981704f2770bc3abe9bb32a80e3fc9..454f907d419a7f87cc0ae1813f40c054726be7e8 100644 (file)
@@ -263,7 +263,9 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
                .flowi4_iif = LOOPBACK_IFINDEX,
                .flowi4_tos = RT_TOS(ip4h->tos),
                .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_SKIP_NH_OIF,
+               .flowi4_proto = ip4h->protocol,
                .daddr = ip4h->daddr,
+               .saddr = ip4h->saddr,
        };
        struct net *net = dev_net(vrf_dev);
        struct rtable *rt;
@@ -1250,6 +1252,8 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]);
+       if (vrf->tb_id == RT_TABLE_UNSPEC)
+               return -EINVAL;
 
        dev->priv_flags |= IFF_L3MDEV_MASTER;
 
index bb70dd5723b587c7d886446547dcec3659a583e4..30b04cf2bb1e08f89ac93c086b17bf8d59df6b37 100644 (file)
@@ -1798,7 +1798,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
 static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device *dev,
                                      struct vxlan_sock *sock4,
                                      struct sk_buff *skb, int oif, u8 tos,
-                                     __be32 daddr, __be32 *saddr,
+                                     __be32 daddr, __be32 *saddr, __be16 dport, __be16 sport,
                                      struct dst_cache *dst_cache,
                                      const struct ip_tunnel_info *info)
 {
@@ -1824,6 +1824,8 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device
        fl4.flowi4_proto = IPPROTO_UDP;
        fl4.daddr = daddr;
        fl4.saddr = *saddr;
+       fl4.fl4_dport = dport;
+       fl4.fl4_sport = sport;
 
        rt = ip_route_output_key(vxlan->net, &fl4);
        if (likely(!IS_ERR(rt))) {
@@ -1851,6 +1853,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
                                          __be32 label,
                                          const struct in6_addr *daddr,
                                          struct in6_addr *saddr,
+                                         __be16 dport, __be16 sport,
                                          struct dst_cache *dst_cache,
                                          const struct ip_tunnel_info *info)
 {
@@ -1877,6 +1880,8 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
        fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
        fl6.flowi6_mark = skb->mark;
        fl6.flowi6_proto = IPPROTO_UDP;
+       fl6.fl6_dport = dport;
+       fl6.fl6_sport = sport;
 
        err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
                                         sock6->sock->sk,
@@ -2068,6 +2073,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                                     rdst ? rdst->remote_ifindex : 0, tos,
                                     dst->sin.sin_addr.s_addr,
                                     &src->sin.sin_addr.s_addr,
+                                    dst_port, src_port,
                                     dst_cache, info);
                if (IS_ERR(rt)) {
                        err = PTR_ERR(rt);
@@ -2104,6 +2110,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                                        rdst ? rdst->remote_ifindex : 0, tos,
                                        label, &dst->sin6.sin6_addr,
                                        &src->sin6.sin6_addr,
+                                       dst_port, src_port,
                                        dst_cache, info);
                if (IS_ERR(ndst)) {
                        err = PTR_ERR(ndst);
@@ -2261,7 +2268,7 @@ static void vxlan_cleanup(unsigned long arg)
                                = container_of(p, struct vxlan_fdb, hlist);
                        unsigned long timeout;
 
-                       if (f->state & NUD_PERMANENT)
+                       if (f->state & (NUD_PERMANENT | NUD_NOARP))
                                continue;
 
                        timeout = f->used + vxlan->cfg.age_interval * HZ;
@@ -2347,7 +2354,7 @@ static int vxlan_open(struct net_device *dev)
 }
 
 /* Purge the forwarding table */
-static void vxlan_flush(struct vxlan_dev *vxlan)
+static void vxlan_flush(struct vxlan_dev *vxlan, bool do_all)
 {
        unsigned int h;
 
@@ -2357,6 +2364,8 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
                hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
                        struct vxlan_fdb *f
                                = container_of(p, struct vxlan_fdb, hlist);
+                       if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
+                               continue;
                        /* the all_zeros_mac entry is deleted at vxlan_uninit */
                        if (!is_zero_ether_addr(f->eth_addr))
                                vxlan_fdb_destroy(vxlan, f);
@@ -2378,7 +2387,7 @@ static int vxlan_stop(struct net_device *dev)
 
        del_timer_sync(&vxlan->age_timer);
 
-       vxlan_flush(vxlan);
+       vxlan_flush(vxlan, false);
        vxlan_sock_release(vxlan);
 
        return ret;
@@ -2430,7 +2439,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 
                rt = vxlan_get_route(vxlan, dev, sock4, skb, 0, info->key.tos,
                                     info->key.u.ipv4.dst,
-                                    &info->key.u.ipv4.src, NULL, info);
+                                    &info->key.u.ipv4.src, dport, sport,
+                                    &info->dst_cache, info);
                if (IS_ERR(rt))
                        return PTR_ERR(rt);
                ip_rt_put(rt);
@@ -2441,7 +2451,8 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 
                ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, info->key.tos,
                                        info->key.label, &info->key.u.ipv6.dst,
-                                       &info->key.u.ipv6.src, NULL, info);
+                                       &info->key.u.ipv6.src, dport, sport,
+                                       &info->dst_cache, info);
                if (IS_ERR(ndst))
                        return PTR_ERR(ndst);
                dst_release(ndst);
@@ -2883,7 +2894,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
        memcpy(&vxlan->cfg, conf, sizeof(*conf));
        if (!vxlan->cfg.dst_port) {
                if (conf->flags & VXLAN_F_GPE)
-                       vxlan->cfg.dst_port = 4790; /* IANA assigned VXLAN-GPE port */
+                       vxlan->cfg.dst_port = htons(4790); /* IANA VXLAN-GPE port */
                else
                        vxlan->cfg.dst_port = default_port;
        }
@@ -3051,6 +3062,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
 
+       vxlan_flush(vxlan, true);
+
        spin_lock(&vn->sock_lock);
        if (!hlist_unhashed(&vxlan->hlist))
                hlist_del_rcu(&vxlan->hlist);
index d02ca1491d16cede66389540f8cb92dda5749ff3..8d3e53fac1dabc01ed875b6f8c2863bb908f770c 100644 (file)
@@ -91,7 +91,7 @@
 
 #define IWL8000_FW_PRE "iwlwifi-8000C-"
 #define IWL8000_MODULE_FIRMWARE(api) \
-       IWL8000_FW_PRE "-" __stringify(api) ".ucode"
+       IWL8000_FW_PRE __stringify(api) ".ucode"
 
 #define IWL8265_FW_PRE "iwlwifi-8265-"
 #define IWL8265_MODULE_FIRMWARE(api) \
index 636c8b03e31892bd30e3a3d7a6b1e9b8a8eb02ea..09e9e2e3ed040202f0cb40c1e326584b0fa7465a 100644 (file)
@@ -1164,9 +1164,10 @@ static void iwl_mvm_realloc_queues_after_restart(struct iwl_mvm *mvm,
                .frame_limit = IWL_FRAME_LIMIT,
        };
 
-       /* Make sure reserved queue is still marked as such (or allocated) */
-       mvm->queue_info[mvm_sta->reserved_queue].status =
-               IWL_MVM_QUEUE_RESERVED;
+       /* Make sure reserved queue is still marked as such (if allocated) */
+       if (mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE)
+               mvm->queue_info[mvm_sta->reserved_queue].status =
+                       IWL_MVM_QUEUE_RESERVED;
 
        for (i = 0; i <= IWL_MAX_TID_COUNT; i++) {
                struct iwl_mvm_tid_data *tid_data = &mvm_sta->tid_data[i];
index 63a051be832ed44b30978b4d031464b15765df20..bec7d9c46087d3c8fed48d5858f4f116797eceed 100644 (file)
@@ -843,8 +843,10 @@ static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm)
                return;
 
        IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n");
-       thermal_zone_device_unregister(mvm->tz_device.tzone);
-       mvm->tz_device.tzone = NULL;
+       if (mvm->tz_device.tzone) {
+               thermal_zone_device_unregister(mvm->tz_device.tzone);
+               mvm->tz_device.tzone = NULL;
+       }
 }
 
 static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
@@ -853,8 +855,10 @@ static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
                return;
 
        IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
-       thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
-       mvm->cooling_dev.cdev = NULL;
+       if (mvm->cooling_dev.cdev) {
+               thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
+               mvm->cooling_dev.cdev = NULL;
+       }
 }
 #endif /* CONFIG_THERMAL */
 
index bc7397d709d3ac5ff85b9a1057e43a93500587fc..08bc7822f8209d0a9136357edb18683092c86c18 100644 (file)
@@ -16,7 +16,7 @@
 /********************************************************************/
 int orinoco_mic_init(struct orinoco_private *priv)
 {
-       priv->tx_tfm_mic = crypto_alloc_ahash("michael_mic", 0,
+       priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0,
                                              CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->tx_tfm_mic)) {
                printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
@@ -25,7 +25,7 @@ int orinoco_mic_init(struct orinoco_private *priv)
                return -ENOMEM;
        }
 
-       priv->rx_tfm_mic = crypto_alloc_ahash("michael_mic", 0,
+       priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0,
                                              CRYPTO_ALG_ASYNC);
        if (IS_ERR(priv->rx_tfm_mic)) {
                printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
@@ -40,17 +40,16 @@ int orinoco_mic_init(struct orinoco_private *priv)
 void orinoco_mic_free(struct orinoco_private *priv)
 {
        if (priv->tx_tfm_mic)
-               crypto_free_ahash(priv->tx_tfm_mic);
+               crypto_free_shash(priv->tx_tfm_mic);
        if (priv->rx_tfm_mic)
-               crypto_free_ahash(priv->rx_tfm_mic);
+               crypto_free_shash(priv->rx_tfm_mic);
 }
 
-int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
+int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
                u8 *da, u8 *sa, u8 priority,
                u8 *data, size_t data_len, u8 *mic)
 {
-       AHASH_REQUEST_ON_STACK(req, tfm_michael);
-       struct scatterlist sg[2];
+       SHASH_DESC_ON_STACK(desc, tfm_michael);
        u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
        int err;
 
@@ -67,18 +66,27 @@ int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
        hdr[ETH_ALEN * 2 + 2] = 0;
        hdr[ETH_ALEN * 2 + 3] = 0;
 
-       /* Use scatter gather to MIC header and data in one go */
-       sg_init_table(sg, 2);
-       sg_set_buf(&sg[0], hdr, sizeof(hdr));
-       sg_set_buf(&sg[1], data, data_len);
+       desc->tfm = tfm_michael;
+       desc->flags = 0;
 
-       if (crypto_ahash_setkey(tfm_michael, key, MIC_KEYLEN))
-               return -1;
+       err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
+       if (err)
+               return err;
+
+       err = crypto_shash_init(desc);
+       if (err)
+               return err;
+
+       err = crypto_shash_update(desc, hdr, sizeof(hdr));
+       if (err)
+               return err;
+
+       err = crypto_shash_update(desc, data, data_len);
+       if (err)
+               return err;
+
+       err = crypto_shash_final(desc, mic);
+       shash_desc_zero(desc);
 
-       ahash_request_set_tfm(req, tfm_michael);
-       ahash_request_set_callback(req, 0, NULL, NULL);
-       ahash_request_set_crypt(req, sg, mic, data_len + sizeof(hdr));
-       err = crypto_ahash_digest(req);
-       ahash_request_zero(req);
        return err;
 }
index ce731d05cc98cd2d0b6415f66868d3ad517b4753..e8724e8892194bb3e732078b3561ab031071a061 100644 (file)
@@ -6,6 +6,7 @@
 #define _ORINOCO_MIC_H_
 
 #include <linux/types.h>
+#include <crypto/hash.h>
 
 #define MICHAEL_MIC_LEN 8
 
@@ -15,7 +16,7 @@ struct crypto_ahash;
 
 int orinoco_mic_init(struct orinoco_private *priv);
 void orinoco_mic_free(struct orinoco_private *priv);
-int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key,
+int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
                u8 *da, u8 *sa, u8 priority,
                u8 *data, size_t data_len, u8 *mic);
 
index 2f0c84b1c440cd1160bdebc3cabcb13be110a73e..5fa1c3e3713f835387353ba781cbb24ce95df6dc 100644 (file)
@@ -152,8 +152,8 @@ struct orinoco_private {
        u8 *wpa_ie;
        int wpa_ie_len;
 
-       struct crypto_ahash *rx_tfm_mic;
-       struct crypto_ahash *tx_tfm_mic;
+       struct crypto_shash *rx_tfm_mic;
+       struct crypto_shash *tx_tfm_mic;
 
        unsigned int wpa_enabled:1;
        unsigned int tkip_cm_active:1;
index 691ddef1ae28eab7d2a193fca3a72baa7871e480..a33a06d58a9ae8496e9baa2cd7a6e2ac1f3087e2 100644 (file)
@@ -92,7 +92,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-       char *fw_name = "rtlwifi/rtl8192cfwU.bin";
+       char *fw_name;
 
        rtl8192ce_bt_reg_init(hw);
 
@@ -164,8 +164,13 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
        }
 
        /* request fw */
-       if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
+       if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+           !IS_92C_SERIAL(rtlhal->version))
+               fw_name = "rtlwifi/rtl8192cfwU.bin";
+       else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
                fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+       else
+               fw_name = "rtlwifi/rtl8192cfw.bin";
 
        rtlpriv->max_fw_size = 0x4000;
        pr_info("Using firmware %s\n", fw_name);
index 0a508649903d73fe4b9a643a5e7e43577abc22c9..49015b05f3d1a048ee6e3ac00426ea76cd5bab44 100644 (file)
@@ -1063,6 +1063,7 @@ int rtl_usb_probe(struct usb_interface *intf,
                return -ENOMEM;
        }
        rtlpriv = hw->priv;
+       rtlpriv->hw = hw;
        rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
                                    GFP_KERNEL);
        if (!rtlpriv->usb_data)
index 3ce1f7da864742a2aa1fe268ffd440b09764ea05..530586be05b4357dc8ee6439b7a9e225bce012c6 100644 (file)
@@ -113,10 +113,10 @@ struct xenvif_stats {
         * A subset of struct net_device_stats that contains only the
         * fields that are updated in netback.c for each queue.
         */
-       unsigned int rx_bytes;
-       unsigned int rx_packets;
-       unsigned int tx_bytes;
-       unsigned int tx_packets;
+       u64 rx_bytes;
+       u64 rx_packets;
+       u64 tx_bytes;
+       u64 tx_packets;
 
        /* Additional stats used by xenvif */
        unsigned long rx_gso_checksum_fixup;
index e30ffd29b7e913f2514c4c925979ffd474190acc..50fa1692d98516acc8257f7480c4d9ddc9f443ea 100644 (file)
@@ -221,18 +221,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
 {
        struct xenvif *vif = netdev_priv(dev);
        struct xenvif_queue *queue = NULL;
-       unsigned int num_queues = vif->num_queues;
-       unsigned long rx_bytes = 0;
-       unsigned long rx_packets = 0;
-       unsigned long tx_bytes = 0;
-       unsigned long tx_packets = 0;
+       u64 rx_bytes = 0;
+       u64 rx_packets = 0;
+       u64 tx_bytes = 0;
+       u64 tx_packets = 0;
        unsigned int index;
 
+       spin_lock(&vif->lock);
        if (vif->queues == NULL)
                goto out;
 
        /* Aggregate tx and rx stats from each queue */
-       for (index = 0; index < num_queues; ++index) {
+       for (index = 0; index < vif->num_queues; ++index) {
                queue = &vif->queues[index];
                rx_bytes += queue->stats.rx_bytes;
                rx_packets += queue->stats.rx_packets;
@@ -241,6 +241,8 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
        }
 
 out:
+       spin_unlock(&vif->lock);
+
        vif->dev->stats.rx_bytes = rx_bytes;
        vif->dev->stats.rx_packets = rx_packets;
        vif->dev->stats.tx_bytes = tx_bytes;
index 3124eaec942745fe9eb6cd4a49ee8bc633d80e67..85b742e1c42fa75bc771db4e8b91f80f3fe68d75 100644 (file)
@@ -493,11 +493,22 @@ static int backend_create_xenvif(struct backend_info *be)
 static void backend_disconnect(struct backend_info *be)
 {
        if (be->vif) {
+               unsigned int queue_index;
+
                xen_unregister_watchers(be->vif);
 #ifdef CONFIG_DEBUG_FS
                xenvif_debugfs_delif(be->vif);
 #endif /* CONFIG_DEBUG_FS */
                xenvif_disconnect_data(be->vif);
+               for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
+                       xenvif_deinit_queue(&be->vif->queues[queue_index]);
+
+               spin_lock(&be->vif->lock);
+               vfree(be->vif->queues);
+               be->vif->num_queues = 0;
+               be->vif->queues = NULL;
+               spin_unlock(&be->vif->lock);
+
                xenvif_disconnect_ctrl(be->vif);
        }
 }
@@ -1034,6 +1045,8 @@ static void connect(struct backend_info *be)
 err:
        if (be->vif->num_queues > 0)
                xenvif_disconnect_data(be->vif); /* Clean up existing queues */
+       for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
+               xenvif_deinit_queue(&be->vif->queues[queue_index]);
        vfree(be->vif->queues);
        be->vif->queues = NULL;
        be->vif->num_queues = 0;
index a479cd99911d8a06cdc37b92682b58b101500846..1e4125a98291245f5e806a79247a92ca1418092b 100644 (file)
@@ -281,6 +281,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
 {
        RING_IDX req_prod = queue->rx.req_prod_pvt;
        int notify;
+       int err = 0;
 
        if (unlikely(!netif_carrier_ok(queue->info->netdev)))
                return;
@@ -295,8 +296,10 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
                struct xen_netif_rx_request *req;
 
                skb = xennet_alloc_one_rx_buffer(queue);
-               if (!skb)
+               if (!skb) {
+                       err = -ENOMEM;
                        break;
+               }
 
                id = xennet_rxidx(req_prod);
 
@@ -320,8 +323,13 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
 
        queue->rx.req_prod_pvt = req_prod;
 
-       /* Not enough requests? Try again later. */
-       if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) {
+       /* Try again later if there are not enough requests or skb allocation
+        * failed.
+        * Enough requests is quantified as the sum of newly created slots and
+        * the unconsumed slots at the backend.
+        */
+       if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN ||
+           unlikely(err)) {
                mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
                return;
        }
@@ -1379,6 +1387,8 @@ static void xennet_disconnect_backend(struct netfront_info *info)
        for (i = 0; i < num_queues && info->queues; ++i) {
                struct netfront_queue *queue = &info->queues[i];
 
+               del_timer_sync(&queue->rx_refill_timer);
+
                if (queue->tx_irq && (queue->tx_irq == queue->rx_irq))
                        unbind_from_irqhandler(queue->tx_irq, queue);
                if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) {
@@ -1733,7 +1743,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
 
                if (netif_running(info->netdev))
                        napi_disable(&queue->napi);
-               del_timer_sync(&queue->rx_refill_timer);
                netif_napi_del(&queue->napi);
        }
 
@@ -1822,27 +1831,19 @@ static int talk_to_netback(struct xenbus_device *dev,
                xennet_destroy_queues(info);
 
        err = xennet_create_queues(info, &num_queues);
-       if (err < 0)
-               goto destroy_ring;
+       if (err < 0) {
+               xenbus_dev_fatal(dev, err, "creating queues");
+               kfree(info->queues);
+               info->queues = NULL;
+               goto out;
+       }
 
        /* Create shared ring, alloc event channel -- for each queue */
        for (i = 0; i < num_queues; ++i) {
                queue = &info->queues[i];
                err = setup_netfront(dev, queue, feature_split_evtchn);
-               if (err) {
-                       /* setup_netfront() will tidy up the current
-                        * queue on error, but we need to clean up
-                        * those already allocated.
-                        */
-                       if (i > 0) {
-                               rtnl_lock();
-                               netif_set_real_num_tx_queues(info->netdev, i);
-                               rtnl_unlock();
-                               goto destroy_ring;
-                       } else {
-                               goto out;
-                       }
-               }
+               if (err)
+                       goto destroy_ring;
        }
 
 again:
@@ -1932,9 +1933,10 @@ abort_transaction_no_dev_fatal:
        xenbus_transaction_end(xbt, 1);
  destroy_ring:
        xennet_disconnect_backend(info);
-       kfree(info->queues);
-       info->queues = NULL;
+       xennet_destroy_queues(info);
  out:
+       unregister_netdev(info->netdev);
+       xennet_free_netdev(info->netdev);
        return err;
 }
 
index eca9688bf9d9fdff11ea091b9b2e3d9c115ab8e0..c00238491673766e05bc5bd2d2d3bec4aac30484 100644 (file)
@@ -1629,6 +1629,28 @@ static void atom_deinit_dev(struct intel_ntb_dev *ndev)
 
 /* Skylake Xeon NTB */
 
+static int skx_poll_link(struct intel_ntb_dev *ndev)
+{
+       u16 reg_val;
+       int rc;
+
+       ndev->reg->db_iowrite(ndev->db_link_mask,
+                             ndev->self_mmio +
+                             ndev->self_reg->db_clear);
+
+       rc = pci_read_config_word(ndev->ntb.pdev,
+                                 SKX_LINK_STATUS_OFFSET, &reg_val);
+       if (rc)
+               return 0;
+
+       if (reg_val == ndev->lnk_sta)
+               return 0;
+
+       ndev->lnk_sta = reg_val;
+
+       return 1;
+}
+
 static u64 skx_db_ioread(void __iomem *mmio)
 {
        return ioread64(mmio);
@@ -2852,7 +2874,7 @@ static struct intel_b2b_addr xeon_b2b_dsd_addr = {
 };
 
 static const struct intel_ntb_reg skx_reg = {
-       .poll_link              = xeon_poll_link,
+       .poll_link              = skx_poll_link,
        .link_is_up             = xeon_link_is_up,
        .db_ioread              = skx_db_ioread,
        .db_iowrite             = skx_db_iowrite,
index f81aa4b18d9f4dd76ec0be63f46865d3b04f89c6..02ca45fdd89203f31246f552811b1264059232d6 100644 (file)
@@ -1802,7 +1802,7 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
 
        node = dev_to_node(&ndev->dev);
 
-       free_queue = ffs(nt->qp_bitmap);
+       free_queue = ffs(nt->qp_bitmap_free);
        if (!free_queue)
                goto err;
 
@@ -2273,9 +2273,8 @@ module_init(ntb_transport_init);
 
 static void __exit ntb_transport_exit(void)
 {
-       debugfs_remove_recursive(nt_debugfs_dir);
-
        ntb_unregister_client(&ntb_transport_client);
        bus_unregister(&ntb_transport_bus);
+       debugfs_remove_recursive(nt_debugfs_dir);
 }
 module_exit(ntb_transport_exit);
index e75d4fdc08663905eace859cff6cdebdb97e92b5..434e1d474f3340e1d35b48c924a6bebfbfb0fa67 100644 (file)
@@ -265,6 +265,8 @@ static ssize_t perf_copy(struct pthr_ctx *pctx, char __iomem *dst,
        if (dma_submit_error(cookie))
                goto err_set_unmap;
 
+       dmaengine_unmap_put(unmap);
+
        atomic_inc(&pctx->dma_sync);
        dma_async_issue_pending(chan);
 
index 6307088b375f2d899002f9fc9fae16c387357598..ce3e8dfa10ad5ccc5285621e5c5b27b5c557e16b 100644 (file)
@@ -52,17 +52,17 @@ static void namespace_blk_release(struct device *dev)
        kfree(nsblk);
 }
 
-static struct device_type namespace_io_device_type = {
+static const struct device_type namespace_io_device_type = {
        .name = "nd_namespace_io",
        .release = namespace_io_release,
 };
 
-static struct device_type namespace_pmem_device_type = {
+static const struct device_type namespace_pmem_device_type = {
        .name = "nd_namespace_pmem",
        .release = namespace_pmem_release,
 };
 
-static struct device_type namespace_blk_device_type = {
+static const struct device_type namespace_blk_device_type = {
        .name = "nd_namespace_blk",
        .release = namespace_blk_release,
 };
@@ -957,25 +957,28 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)
 {
        resource_size_t allocated = 0, available = 0;
        struct nd_region *nd_region = to_nd_region(dev->parent);
+       struct nd_namespace_common *ndns = to_ndns(dev);
        struct nd_mapping *nd_mapping;
        struct nvdimm_drvdata *ndd;
        struct nd_label_id label_id;
        u32 flags = 0, remainder;
+       int rc, i, id = -1;
        u8 *uuid = NULL;
-       int rc, i;
 
-       if (dev->driver || to_ndns(dev)->claim)
+       if (dev->driver || ndns->claim)
                return -EBUSY;
 
        if (is_namespace_pmem(dev)) {
                struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
 
                uuid = nspm->uuid;
+               id = nspm->id;
        } else if (is_namespace_blk(dev)) {
                struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
 
                uuid = nsblk->uuid;
                flags = NSLABEL_FLAG_LOCAL;
+               id = nsblk->id;
        }
 
        /*
@@ -1034,20 +1037,17 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)
 
                nd_namespace_pmem_set_resource(nd_region, nspm,
                                val * nd_region->ndr_mappings);
-       } else if (is_namespace_blk(dev)) {
-               struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
-
-               /*
-                * Try to delete the namespace if we deleted all of its
-                * allocation, this is not the seed device for the
-                * region, and it is not actively claimed by a btt
-                * instance.
-                */
-               if (val == 0 && nd_region->ns_seed != dev
-                               && !nsblk->common.claim)
-                       nd_device_unregister(dev, ND_ASYNC);
        }
 
+       /*
+        * Try to delete the namespace if we deleted all of its
+        * allocation, this is not the seed or 0th device for the
+        * region, and it is not actively claimed by a btt, pfn, or dax
+        * instance.
+        */
+       if (val == 0 && id != 0 && nd_region->ns_seed != dev && !ndns->claim)
+               nd_device_unregister(dev, ND_ASYNC);
+
        return rc;
 }
 
index a2ac9e641aa9341f2fcca9fa8b968fd874e80a90..6c033c9a2f06921feb49e3ba396d6cf150e19801 100644 (file)
@@ -627,15 +627,12 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
        size = resource_size(&nsio->res);
        npfns = (size - start_pad - end_trunc - SZ_8K) / SZ_4K;
        if (nd_pfn->mode == PFN_MODE_PMEM) {
-               unsigned long memmap_size;
-
                /*
                 * vmemmap_populate_hugepages() allocates the memmap array in
                 * HPAGE_SIZE chunks.
                 */
-               memmap_size = ALIGN(64 * npfns, HPAGE_SIZE);
-               offset = ALIGN(start + SZ_8K + memmap_size + dax_label_reserve,
-                               nd_pfn->align) - start;
+               offset = ALIGN(start + SZ_8K + 64 * npfns + dax_label_reserve,
+                               max(nd_pfn->align, HPAGE_SIZE)) - start;
        } else if (nd_pfn->mode == PFN_MODE_RAM)
                offset = ALIGN(start + SZ_8K + dax_label_reserve,
                                nd_pfn->align) - start;
index 7282d7495bf1f0a1bf6685012dafb1d9cc60bfa4..5b536be5a12eb97023745a59f65283280b7b3675 100644 (file)
@@ -90,7 +90,9 @@ static int read_pmem(struct page *page, unsigned int off,
 
        rc = memcpy_from_pmem(mem + off, pmem_addr, len);
        kunmap_atomic(mem);
-       return rc;
+       if (rc)
+               return -EIO;
+       return 0;
 }
 
 static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
index 2fc86dc7a8df3e487c8222fa84310e7832c9c0a8..8a3c3e32a704b3e359a78ed06e95c6e977f322bc 100644 (file)
@@ -1106,12 +1106,7 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl, u64 cap)
        if (ret)
                return ret;
 
-       /* Checking for ctrl->tagset is a trick to avoid sleeping on module
-        * load, since we only need the quirk on reset_controller. Notice
-        * that the HGST device needs this delay only in firmware activation
-        * procedure; unfortunately we have no (easy) way to verify this.
-        */
-       if ((ctrl->quirks & NVME_QUIRK_DELAY_BEFORE_CHK_RDY) && ctrl->tagset)
+       if (ctrl->quirks & NVME_QUIRK_DELAY_BEFORE_CHK_RDY)
                msleep(NVME_QUIRK_DELAY_AMOUNT);
 
        return nvme_wait_ready(ctrl, cap, false);
index aa0bc60810a74ff93cf05b294b2a9d4968ecf397..e65041c640cbc5bad3c284b77690605f071edfc3 100644 (file)
@@ -1654,23 +1654,22 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
                struct nvme_fc_fcp_op *op)
 {
        struct nvmefc_fcp_req *freq = &op->fcp_req;
-       u32 map_len = nvme_map_len(rq);
        enum dma_data_direction dir;
        int ret;
 
        freq->sg_cnt = 0;
 
-       if (!map_len)
+       if (!blk_rq_payload_bytes(rq))
                return 0;
 
        freq->sg_table.sgl = freq->first_sgl;
-       ret = sg_alloc_table_chained(&freq->sg_table, rq->nr_phys_segments,
-                       freq->sg_table.sgl);
+       ret = sg_alloc_table_chained(&freq->sg_table,
+                       blk_rq_nr_phys_segments(rq), freq->sg_table.sgl);
        if (ret)
                return -ENOMEM;
 
        op->nents = blk_rq_map_sg(rq->q, rq, freq->sg_table.sgl);
-       WARN_ON(op->nents > rq->nr_phys_segments);
+       WARN_ON(op->nents > blk_rq_nr_phys_segments(rq));
        dir = (rq_data_dir(rq) == WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
        freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
                                op->nents, dir);
@@ -1854,7 +1853,7 @@ nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (ret)
                return ret;
 
-       data_len = nvme_map_len(rq);
+       data_len = blk_rq_payload_bytes(rq);
        if (data_len)
                io_dir = ((rq_data_dir(rq) == WRITE) ?
                                        NVMEFC_FCP_WRITE : NVMEFC_FCP_READ);
index 6377e14586dc5c837749049cf3dafc7b210a3026..aead6d08ed2c83b4f67e9087b0ca446247b57d18 100644 (file)
@@ -225,14 +225,6 @@ static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector)
        return (sector >> (ns->lba_shift - 9));
 }
 
-static inline unsigned nvme_map_len(struct request *rq)
-{
-       if (req_op(rq) == REQ_OP_DISCARD)
-               return sizeof(struct nvme_dsm_range);
-       else
-               return blk_rq_bytes(rq);
-}
-
 static inline void nvme_cleanup_cmd(struct request *req)
 {
        if (req->rq_flags & RQF_SPECIAL_PAYLOAD) {
index 19beeb7b2ac26a5bf0f81bf4e8b995bf29dba195..3faefabf339c98d221373437e411512543d29263 100644 (file)
@@ -306,11 +306,11 @@ static __le64 **iod_list(struct request *req)
        return (__le64 **)(iod->sg + blk_rq_nr_phys_segments(req));
 }
 
-static int nvme_init_iod(struct request *rq, unsigned size,
-               struct nvme_dev *dev)
+static int nvme_init_iod(struct request *rq, struct nvme_dev *dev)
 {
        struct nvme_iod *iod = blk_mq_rq_to_pdu(rq);
        int nseg = blk_rq_nr_phys_segments(rq);
+       unsigned int size = blk_rq_payload_bytes(rq);
 
        if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) {
                iod->sg = kmalloc(nvme_iod_alloc_size(dev, size, nseg), GFP_ATOMIC);
@@ -420,12 +420,11 @@ static void nvme_dif_complete(u32 p, u32 v, struct t10_pi_tuple *pi)
 }
 #endif
 
-static bool nvme_setup_prps(struct nvme_dev *dev, struct request *req,
-               int total_len)
+static bool nvme_setup_prps(struct nvme_dev *dev, struct request *req)
 {
        struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
        struct dma_pool *pool;
-       int length = total_len;
+       int length = blk_rq_payload_bytes(req);
        struct scatterlist *sg = iod->sg;
        int dma_len = sg_dma_len(sg);
        u64 dma_addr = sg_dma_address(sg);
@@ -501,7 +500,7 @@ static bool nvme_setup_prps(struct nvme_dev *dev, struct request *req,
 }
 
 static int nvme_map_data(struct nvme_dev *dev, struct request *req,
-               unsigned size, struct nvme_command *cmnd)
+               struct nvme_command *cmnd)
 {
        struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
        struct request_queue *q = req->q;
@@ -519,7 +518,7 @@ static int nvme_map_data(struct nvme_dev *dev, struct request *req,
                                DMA_ATTR_NO_WARN))
                goto out;
 
-       if (!nvme_setup_prps(dev, req, size))
+       if (!nvme_setup_prps(dev, req))
                goto out_unmap;
 
        ret = BLK_MQ_RQ_QUEUE_ERROR;
@@ -580,7 +579,6 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
        struct nvme_dev *dev = nvmeq->dev;
        struct request *req = bd->rq;
        struct nvme_command cmnd;
-       unsigned map_len;
        int ret = BLK_MQ_RQ_QUEUE_OK;
 
        /*
@@ -600,13 +598,12 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (ret != BLK_MQ_RQ_QUEUE_OK)
                return ret;
 
-       map_len = nvme_map_len(req);
-       ret = nvme_init_iod(req, map_len, dev);
+       ret = nvme_init_iod(req, dev);
        if (ret != BLK_MQ_RQ_QUEUE_OK)
                goto out_free_cmd;
 
        if (blk_rq_nr_phys_segments(req))
-               ret = nvme_map_data(dev, req, map_len, &cmnd);
+               ret = nvme_map_data(dev, req, &cmnd);
 
        if (ret != BLK_MQ_RQ_QUEUE_OK)
                goto out_cleanup_iod;
index f587af345889eb1b32a1f4f87dbe0c9a3a30ae42..557f29b1f1bb23e4e5cded156db21b4f981b585a 100644 (file)
@@ -981,8 +981,7 @@ static int nvme_rdma_map_sg_fr(struct nvme_rdma_queue *queue,
 }
 
 static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
-               struct request *rq, unsigned int map_len,
-               struct nvme_command *c)
+               struct request *rq, struct nvme_command *c)
 {
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
        struct nvme_rdma_device *dev = queue->device;
@@ -1014,9 +1013,9 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
        }
 
        if (count == 1) {
-               if (rq_data_dir(rq) == WRITE &&
-                   map_len <= nvme_rdma_inline_data_size(queue) &&
-                   nvme_rdma_queue_idx(queue))
+               if (rq_data_dir(rq) == WRITE && nvme_rdma_queue_idx(queue) &&
+                   blk_rq_payload_bytes(rq) <=
+                               nvme_rdma_inline_data_size(queue))
                        return nvme_rdma_map_sg_inline(queue, req, c);
 
                if (dev->pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY)
@@ -1422,7 +1421,7 @@ static inline bool nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue,
                struct request *rq)
 {
        if (unlikely(!test_bit(NVME_RDMA_Q_LIVE, &queue->flags))) {
-               struct nvme_command *cmd = (struct nvme_command *)rq->cmd;
+               struct nvme_command *cmd = nvme_req(rq)->cmd;
 
                if (rq->cmd_type != REQ_TYPE_DRV_PRIV ||
                    cmd->common.opcode != nvme_fabrics_command ||
@@ -1444,7 +1443,6 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
        struct nvme_command *c = sqe->data;
        bool flush = false;
        struct ib_device *dev;
-       unsigned int map_len;
        int ret;
 
        WARN_ON_ONCE(rq->tag < 0);
@@ -1462,8 +1460,7 @@ static int nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
 
        blk_mq_start_request(rq);
 
-       map_len = nvme_map_len(rq);
-       ret = nvme_rdma_map_data(queue, rq, map_len, c);
+       ret = nvme_rdma_map_data(queue, rq, c);
        if (ret < 0) {
                dev_err(queue->ctrl->ctrl.device,
                             "Failed to map data (%d)\n", ret);
index 6f5074153dcd9ea921f35751bbd622c18f227e49..be8c800078e2a6cbffa43208aa0326994d8e4bf5 100644 (file)
@@ -631,6 +631,7 @@ static void nvmet_subsys_release(struct config_item *item)
 {
        struct nvmet_subsys *subsys = to_subsys(item);
 
+       nvmet_subsys_del_ctrls(subsys);
        nvmet_subsys_put(subsys);
 }
 
index b1d66ed655c9ec36261fb4d31bca06555cccca39..fc5ba2f9e15f47fe8bd13795bdb9d6caaa532b93 100644 (file)
@@ -200,7 +200,7 @@ static void nvmet_keep_alive_timer(struct work_struct *work)
        pr_err("ctrl %d keep-alive timer (%d seconds) expired!\n",
                ctrl->cntlid, ctrl->kato);
 
-       ctrl->ops->delete_ctrl(ctrl);
+       nvmet_ctrl_fatal_error(ctrl);
 }
 
 static void nvmet_start_keep_alive_timer(struct nvmet_ctrl *ctrl)
@@ -816,6 +816,9 @@ static void nvmet_ctrl_free(struct kref *ref)
        list_del(&ctrl->subsys_entry);
        mutex_unlock(&subsys->lock);
 
+       flush_work(&ctrl->async_event_work);
+       cancel_work_sync(&ctrl->fatal_err_work);
+
        ida_simple_remove(&subsys->cntlid_ida, ctrl->cntlid);
        nvmet_subsys_put(subsys);
 
@@ -935,6 +938,16 @@ static void nvmet_subsys_free(struct kref *ref)
        kfree(subsys);
 }
 
+void nvmet_subsys_del_ctrls(struct nvmet_subsys *subsys)
+{
+       struct nvmet_ctrl *ctrl;
+
+       mutex_lock(&subsys->lock);
+       list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
+               ctrl->ops->delete_ctrl(ctrl);
+       mutex_unlock(&subsys->lock);
+}
+
 void nvmet_subsys_put(struct nvmet_subsys *subsys)
 {
        kref_put(&subsys->ref, nvmet_subsys_free);
index 173e842f19c975a4a849c4120fcfcdcee73c26c1..ba57f9852bde33b0ff3d0655d4c08313632a3a8f 100644 (file)
@@ -1314,7 +1314,7 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
                        (struct fcnvme_ls_disconnect_rqst *)iod->rqstbuf;
        struct fcnvme_ls_disconnect_acc *acc =
                        (struct fcnvme_ls_disconnect_acc *)iod->rspbuf;
-       struct nvmet_fc_tgt_queue *queue;
+       struct nvmet_fc_tgt_queue *queue = NULL;
        struct nvmet_fc_tgt_assoc *assoc;
        int ret = 0;
        bool del_assoc = false;
@@ -1348,7 +1348,18 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
                assoc = nvmet_fc_find_target_assoc(tgtport,
                                be64_to_cpu(rqst->associd.association_id));
                iod->assoc = assoc;
-               if (!assoc)
+               if (assoc) {
+                       if (rqst->discon_cmd.scope ==
+                                       FCNVME_DISCONN_CONNECTION) {
+                               queue = nvmet_fc_find_target_queue(tgtport,
+                                               be64_to_cpu(
+                                                       rqst->discon_cmd.id));
+                               if (!queue) {
+                                       nvmet_fc_tgt_a_put(assoc);
+                                       ret = VERR_NO_CONN;
+                               }
+                       }
+               } else
                        ret = VERR_NO_ASSOC;
        }
 
@@ -1373,21 +1384,18 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
                        FCNVME_LS_DISCONNECT);
 
 
-       if (rqst->discon_cmd.scope == FCNVME_DISCONN_CONNECTION) {
-               queue = nvmet_fc_find_target_queue(tgtport,
-                                       be64_to_cpu(rqst->discon_cmd.id));
-               if (queue) {
-                       int qid = queue->qid;
+       /* are we to delete a Connection ID (queue) */
+       if (queue) {
+               int qid = queue->qid;
 
-                       nvmet_fc_delete_target_queue(queue);
+               nvmet_fc_delete_target_queue(queue);
 
-                       /* release the get taken by find_target_queue */
-                       nvmet_fc_tgt_q_put(queue);
+               /* release the get taken by find_target_queue */
+               nvmet_fc_tgt_q_put(queue);
 
-                       /* tear association down if io queue terminated */
-                       if (!qid)
-                               del_assoc = true;
-               }
+               /* tear association down if io queue terminated */
+               if (!qid)
+                       del_assoc = true;
        }
 
        /* release get taken in nvmet_fc_find_target_assoc */
index 23d5eb1c944f64c485fef8551a41a72151492f2c..cc7ad06b43a78a029dd76fac575c3f6ee57c9e92 100644 (file)
@@ -282,6 +282,7 @@ void nvmet_ctrl_put(struct nvmet_ctrl *ctrl);
 struct nvmet_subsys *nvmet_subsys_alloc(const char *subsysnqn,
                enum nvme_subsys_type type);
 void nvmet_subsys_put(struct nvmet_subsys *subsys);
+void nvmet_subsys_del_ctrls(struct nvmet_subsys *subsys);
 
 struct nvmet_ns *nvmet_find_namespace(struct nvmet_ctrl *ctrl, __le32 nsid);
 void nvmet_put_namespace(struct nvmet_ns *ns);
index 8c3760a78ac080af522afb5892d471063243bd7b..60990220bd831074bc3c8fdbd044ee3aed37a2db 100644 (file)
@@ -438,6 +438,10 @@ static int nvmet_rdma_post_recv(struct nvmet_rdma_device *ndev,
 {
        struct ib_recv_wr *bad_wr;
 
+       ib_dma_sync_single_for_device(ndev->device,
+               cmd->sge[0].addr, cmd->sge[0].length,
+               DMA_FROM_DEVICE);
+
        if (ndev->srq)
                return ib_post_srq_recv(ndev->srq, &cmd->wr, &bad_wr);
        return ib_post_recv(cmd->queue->cm_id->qp, &cmd->wr, &bad_wr);
@@ -538,6 +542,11 @@ static void nvmet_rdma_queue_response(struct nvmet_req *req)
                first_wr = &rsp->send_wr;
 
        nvmet_rdma_post_recv(rsp->queue->dev, rsp->cmd);
+
+       ib_dma_sync_single_for_device(rsp->queue->dev->device,
+               rsp->send_sge.addr, rsp->send_sge.length,
+               DMA_TO_DEVICE);
+
        if (ib_post_send(cm_id->qp, first_wr, &bad_wr)) {
                pr_err("sending cmd response failed\n");
                nvmet_rdma_release_rsp(rsp);
@@ -698,6 +707,14 @@ static void nvmet_rdma_handle_command(struct nvmet_rdma_queue *queue,
        cmd->n_rdma = 0;
        cmd->req.port = queue->port;
 
+
+       ib_dma_sync_single_for_cpu(queue->dev->device,
+               cmd->cmd->sge[0].addr, cmd->cmd->sge[0].length,
+               DMA_FROM_DEVICE);
+       ib_dma_sync_single_for_cpu(queue->dev->device,
+               cmd->send_sge.addr, cmd->send_sge.length,
+               DMA_TO_DEVICE);
+
        if (!nvmet_req_init(&cmd->req, &queue->nvme_cq,
                        &queue->nvme_sq, &nvmet_rdma_ops))
                return;
index 965911d9b36a77af3867ff6361169f977e71392b..398ea7f54826b6bef0db0aa35aa2b1bb8493f432 100644 (file)
@@ -981,8 +981,8 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
  * @cell: nvmem cell to be read.
  * @len: pointer to length of cell which will be populated on successful read.
  *
- * Return: ERR_PTR() on error or a valid pointer to a char * buffer on success.
- * The buffer should be freed by the consumer with a kfree().
+ * Return: ERR_PTR() on error or a valid pointer to a buffer on success. The
+ * buffer should be freed by the consumer with a kfree().
  */
 void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
 {
index ac27b9bac3b9a9abe219e7d60fab8ea946c0abd8..8e7b120696fa91da63a44bc7f4f8422b5d24bc7e 100644 (file)
@@ -71,7 +71,7 @@ static struct nvmem_config imx_ocotp_nvmem_config = {
 
 static const struct of_device_id imx_ocotp_dt_ids[] = {
        { .compatible = "fsl,imx6q-ocotp",  (void *)128 },
-       { .compatible = "fsl,imx6sl-ocotp", (void *)32 },
+       { .compatible = "fsl,imx6sl-ocotp", (void *)64 },
        { .compatible = "fsl,imx6sx-ocotp", (void *)128 },
        { },
 };
index b5305f08b1848bf123f3448fba123a2761e17286..2bdb6c3893281c65d12a3916c037c07acba8480d 100644 (file)
@@ -21,11 +21,11 @@ static int qfprom_reg_read(void *context,
                        unsigned int reg, void *_val, size_t bytes)
 {
        void __iomem *base = context;
-       u32 *val = _val;
-       int i = 0, words = bytes / 4;
+       u8 *val = _val;
+       int i = 0, words = bytes;
 
        while (words--)
-               *val++ = readl(base + reg + (i++ * 4));
+               *val++ = readb(base + reg + i++);
 
        return 0;
 }
@@ -34,11 +34,11 @@ static int qfprom_reg_write(void *context,
                         unsigned int reg, void *_val, size_t bytes)
 {
        void __iomem *base = context;
-       u32 *val = _val;
-       int i = 0, words = bytes / 4;
+       u8 *val = _val;
+       int i = 0, words = bytes;
 
        while (words--)
-               writel(*val++, base + reg + (i++ * 4));
+               writeb(*val++, base + reg + i++);
 
        return 0;
 }
@@ -53,7 +53,7 @@ static int qfprom_remove(struct platform_device *pdev)
 static struct nvmem_config econfig = {
        .name = "qfprom",
        .owner = THIS_MODULE,
-       .stride = 4,
+       .stride = 1,
        .word_size = 1,
        .reg_read = qfprom_reg_read,
        .reg_write = qfprom_reg_write,
index dd6d4ccb41e4df9e97cd54d5f19337f3c69a6266..3858b87fd0bb7d35656161aa0a4d55855bf689c9 100644 (file)
@@ -293,7 +293,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
                p->irq = PARPORT_IRQ_NONE;
        }
        if (p->irq != PARPORT_IRQ_NONE) {
-               printk(", irq %d", p->irq);
+               pr_cont(", irq %d", p->irq);
 
                if (p->dma == PARPORT_DMA_AUTO) {
                        p->dma = PARPORT_DMA_NONE;
@@ -303,8 +303,8 @@ struct parport *parport_gsc_probe_port(unsigned long base,
                                            is mandatory (see above) */
                p->dma = PARPORT_DMA_NONE;
 
-       printk(" [");
-#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
+       pr_cont(" [");
+#define printmode(x) {if(p->modes&PARPORT_MODE_##x){pr_cont("%s%s",f?",":"",#x);f++;}}
        {
                int f = 0;
                printmode(PCSPP);
@@ -315,7 +315,7 @@ struct parport *parport_gsc_probe_port(unsigned long base,
 //             printmode(DMA);
        }
 #undef printmode
-       printk("]\n");
+       pr_cont("]\n");
 
        if (p->irq != PARPORT_IRQ_NONE) {
                if (request_irq (p->irq, parport_irq_handler,
index 1f38d0836751af9f823d848218d7dc17d9dad43f..f1b633bce525f9752bcb2cba15a5e1e770c89c0f 100644 (file)
@@ -517,7 +517,7 @@ static int xgene_msi_probe(struct platform_device *pdev)
 
        rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/xgene:online",
                               xgene_msi_hwirq_alloc, NULL);
-       if (rc)
+       if (rc < 0)
                goto err_cpuhp;
        pci_xgene_online = rc;
        rc = cpuhp_setup_state(CPUHP_PCI_XGENE_DEAD, "pci/xgene:dead", NULL,
index bed19994c1e94d4e32c134e58133c4acd8b8bd88..af8f6e92e8851ca84b459e4587508960b225d336 100644 (file)
@@ -807,11 +807,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
 {
        u32 val;
 
-       /* get iATU unroll support */
-       pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
-       dev_dbg(pp->dev, "iATU unroll: %s\n",
-               pp->iatu_unroll_enabled ? "enabled" : "disabled");
-
        /* set the number of lanes */
        val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL);
        val &= ~PORT_LINK_MODE_MASK;
@@ -882,6 +877,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
         * we should not program the ATU here.
         */
        if (!pp->ops->rd_other_conf) {
+               /* get iATU unroll support */
+               pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
+               dev_dbg(pp->dev, "iATU unroll: %s\n",
+                       pp->iatu_unroll_enabled ? "enabled" : "disabled");
+
                dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
                                          PCIE_ATU_TYPE_MEM, pp->mem_base,
                                          pp->mem_bus_addr, pp->mem_size);
index 10c9c0ba8ff2394dc8b43d640e5dbd4d53c5e84e..ec0b4c11ccd9dc95cdb738d03ae292744e34127e 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <linux/pm_runtime.h>
 #include <linux/pci.h>
 #include "../pci.h"
 #include "pciehp.h"
@@ -99,7 +98,6 @@ static int board_added(struct slot *p_slot)
        pciehp_green_led_blink(p_slot);
 
        /* Check link training status */
-       pm_runtime_get_sync(&ctrl->pcie->port->dev);
        retval = pciehp_check_link_status(ctrl);
        if (retval) {
                ctrl_err(ctrl, "Failed to check link status\n");
@@ -120,14 +118,12 @@ static int board_added(struct slot *p_slot)
                if (retval != -EEXIST)
                        goto err_exit;
        }
-       pm_runtime_put(&ctrl->pcie->port->dev);
 
        pciehp_green_led_on(p_slot);
        pciehp_set_attention_status(p_slot, 0);
        return 0;
 
 err_exit:
-       pm_runtime_put(&ctrl->pcie->port->dev);
        set_slot_off(ctrl, p_slot);
        return retval;
 }
@@ -141,9 +137,7 @@ static int remove_board(struct slot *p_slot)
        int retval;
        struct controller *ctrl = p_slot->ctrl;
 
-       pm_runtime_get_sync(&ctrl->pcie->port->dev);
        retval = pciehp_unconfigure_device(p_slot);
-       pm_runtime_put(&ctrl->pcie->port->dev);
        if (retval)
                return retval;
 
index 50c5003295ca535036b056d7855caf0c96473f13..7f73bacf13ed9ef212ef5c51d0ab301310be3a75 100644 (file)
@@ -1206,6 +1206,16 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
        if (flags & PCI_IRQ_AFFINITY) {
                if (!affd)
                        affd = &msi_default_affd;
+
+               if (affd->pre_vectors + affd->post_vectors > min_vecs)
+                       return -EINVAL;
+
+               /*
+                * If there aren't any vectors left after applying the pre/post
+                * vectors don't bother with assigning affinity.
+                */
+               if (affd->pre_vectors + affd->post_vectors == min_vecs)
+                       affd = NULL;
        } else {
                if (WARN_ON(affd))
                        affd = NULL;
index a881c0d3d2e87e023bd9f68eb35b9d57ac2e3a9f..7904d02ffdb97e5f23d915e9c83edbf599ddf58b 100644 (file)
@@ -2241,10 +2241,13 @@ bool pci_bridge_d3_possible(struct pci_dev *bridge)
                        return false;
 
                /*
-                * Hotplug ports handled by firmware in System Management Mode
+                * Hotplug interrupts cannot be delivered if the link is down,
+                * so parents of a hotplug port must stay awake. In addition,
+                * hotplug ports handled by firmware in System Management Mode
                 * may not be put into D3 by the OS (Thunderbolt on non-Macs).
+                * For simplicity, disallow in general for now.
                 */
-               if (bridge->is_hotplug_bridge && !pciehp_is_native(bridge))
+               if (bridge->is_hotplug_bridge)
                        return false;
 
                if (pci_bridge_d3_force)
@@ -2276,10 +2279,7 @@ static int pci_dev_check_d3cold(struct pci_dev *dev, void *data)
             !pci_pme_capable(dev, PCI_D3cold)) ||
 
            /* If it is a bridge it must be allowed to go to D3. */
-           !pci_power_manageable(dev) ||
-
-           /* Hotplug interrupts cannot be delivered if the link is down. */
-           dev->is_hotplug_bridge)
+           !pci_power_manageable(dev))
 
                *d3cold_ok = false;
 
index 17ac1dce32867051298a5489841de8b636835a68..3dd8bcbb3011babd4ad4271d6f6f64733bd9b3f1 100644 (file)
@@ -532,25 +532,32 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
        link = kzalloc(sizeof(*link), GFP_KERNEL);
        if (!link)
                return NULL;
+
        INIT_LIST_HEAD(&link->sibling);
        INIT_LIST_HEAD(&link->children);
        INIT_LIST_HEAD(&link->link);
        link->pdev = pdev;
-       if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) {
+
+       /*
+        * Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
+        * hierarchies.
+        */
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
+           pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) {
+               link->root = link;
+       } else {
                struct pcie_link_state *parent;
+
                parent = pdev->bus->parent->self->link_state;
                if (!parent) {
                        kfree(link);
                        return NULL;
                }
+
                link->parent = parent;
+               link->root = link->parent->root;
                list_add(&link->link, &parent->children);
        }
-       /* Setup a pointer to the root port link */
-       if (!link->parent)
-               link->root = link;
-       else
-               link->root = link->parent->root;
 
        list_add(&link->sibling, &link_list);
        pdev->link_state = link;
index 717529331dace5f45bb7337b1fb28adb7e81db5c..2dd1c68e6de8e88aa4757a1e6262cff64521db13 100644 (file)
@@ -433,6 +433,17 @@ static int pcie_pme_resume(struct pcie_device *srv)
        return 0;
 }
 
+/**
+ * pcie_pme_remove - Prepare PCIe PME service device for removal.
+ * @srv - PCIe service device to remove.
+ */
+static void pcie_pme_remove(struct pcie_device *srv)
+{
+       pcie_pme_suspend(srv);
+       free_irq(srv->irq, srv);
+       kfree(get_service_data(srv));
+}
+
 static struct pcie_port_service_driver pcie_pme_driver = {
        .name           = "pcie_pme",
        .port_type      = PCI_EXP_TYPE_ROOT_PORT,
@@ -441,6 +452,7 @@ static struct pcie_port_service_driver pcie_pme_driver = {
        .probe          = pcie_pme_probe,
        .suspend        = pcie_pme_suspend,
        .resume         = pcie_pme_resume,
+       .remove         = pcie_pme_remove,
 };
 
 /**
index e164b5c9f0f03d953e825150977fe0c571b40690..204960e70333f1dbe49d03ffffac7393f06a37c4 100644 (file)
@@ -1169,6 +1169,7 @@ void set_pcie_port_type(struct pci_dev *pdev)
        pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
        if (!pos)
                return;
+
        pdev->pcie_cap = pos;
        pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
        pdev->pcie_flags_reg = reg16;
@@ -1176,13 +1177,14 @@ void set_pcie_port_type(struct pci_dev *pdev)
        pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;
 
        /*
-        * A Root Port is always the upstream end of a Link.  No PCIe
-        * component has two Links.  Two Links are connected by a Switch
-        * that has a Port on each Link and internal logic to connect the
-        * two Ports.
+        * A Root Port or a PCI-to-PCIe bridge is always the upstream end
+        * of a Link.  No PCIe component has two Links.  Two Links are
+        * connected by a Switch that has a Port on each Link and internal
+        * logic to connect the two Ports.
         */
        type = pci_pcie_type(pdev);
-       if (type == PCI_EXP_TYPE_ROOT_PORT)
+       if (type == PCI_EXP_TYPE_ROOT_PORT ||
+           type == PCI_EXP_TYPE_PCIE_BRIDGE)
                pdev->has_secondary_link = 1;
        else if (type == PCI_EXP_TYPE_UPSTREAM ||
                 type == PCI_EXP_TYPE_DOWNSTREAM) {
index 09172043d5890735127b0f79275a98704cdbd2b6..c617ec49e9edeeebb1f33b78fa6b7214fb23207c 100644 (file)
@@ -217,7 +217,7 @@ static const struct berlin_desc_group berlin4ct_soc_pinctrl_groups[] = {
        BERLIN_PINCTRL_GROUP("SCRD0_CRD_PRES", 0xc, 0x3, 0x15,
                        BERLIN_PINCTRL_FUNCTION(0x0, "gpio"), /* GPIO20 */
                        BERLIN_PINCTRL_FUNCTION(0x1, "scrd0"), /* crd pres */
-                       BERLIN_PINCTRL_FUNCTION(0x1, "sd1a")), /* DAT3 */
+                       BERLIN_PINCTRL_FUNCTION(0x3, "sd1a")), /* DAT3 */
        BERLIN_PINCTRL_GROUP("SPI1_SS0n", 0xc, 0x3, 0x18,
                        BERLIN_PINCTRL_FUNCTION(0x0, "spi1"), /* SS0n */
                        BERLIN_PINCTRL_FUNCTION(0x1, "gpio"), /* GPIO37 */
index 37300634b7d2c853a05f5dcecce6b9d46d187b59..d94aef17348b4b88f3952670886b863b952cfc60 100644 (file)
@@ -731,16 +731,23 @@ static void __iomem *byt_gpio_reg(struct byt_gpio *vg, unsigned int offset,
                                  int reg)
 {
        struct byt_community *comm = byt_get_community(vg, offset);
-       u32 reg_offset = 0;
+       u32 reg_offset;
 
        if (!comm)
                return NULL;
 
        offset -= comm->pin_base;
-       if (reg == BYT_INT_STAT_REG)
+       switch (reg) {
+       case BYT_INT_STAT_REG:
                reg_offset = (offset / 32) * 4;
-       else
+               break;
+       case BYT_DEBOUNCE_REG:
+               reg_offset = 0;
+               break;
+       default:
                reg_offset = comm->pad_map[offset] * 16;
+               break;
+       }
 
        return comm->reg_base + reg_offset + reg;
 }
@@ -1092,6 +1099,7 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
        enum pin_config_param param = pinconf_to_config_param(*config);
        void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
        void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+       void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
        unsigned long flags;
        u32 conf, pull, val, debounce;
        u16 arg = 0;
@@ -1128,7 +1136,7 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
                        return -EINVAL;
 
                raw_spin_lock_irqsave(&vg->lock, flags);
-               debounce = readl(byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG));
+               debounce = readl(db_reg);
                raw_spin_unlock_irqrestore(&vg->lock, flags);
 
                switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
@@ -1176,6 +1184,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
        unsigned int param, arg;
        void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
        void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+       void __iomem *db_reg = byt_gpio_reg(vg, offset, BYT_DEBOUNCE_REG);
        unsigned long flags;
        u32 conf, val, debounce;
        int i, ret = 0;
@@ -1238,36 +1247,44 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
 
                        break;
                case PIN_CONFIG_INPUT_DEBOUNCE:
-                       debounce = readl(byt_gpio_reg(vg, offset,
-                                                     BYT_DEBOUNCE_REG));
-                       conf &= ~BYT_DEBOUNCE_PULSE_MASK;
+                       debounce = readl(db_reg);
+                       debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
+
+                       if (arg)
+                               conf |= BYT_DEBOUNCE_EN;
+                       else
+                               conf &= ~BYT_DEBOUNCE_EN;
 
                        switch (arg) {
                        case 375:
-                               conf |= BYT_DEBOUNCE_PULSE_375US;
+                               debounce |= BYT_DEBOUNCE_PULSE_375US;
                                break;
                        case 750:
-                               conf |= BYT_DEBOUNCE_PULSE_750US;
+                               debounce |= BYT_DEBOUNCE_PULSE_750US;
                                break;
                        case 1500:
-                               conf |= BYT_DEBOUNCE_PULSE_1500US;
+                               debounce |= BYT_DEBOUNCE_PULSE_1500US;
                                break;
                        case 3000:
-                               conf |= BYT_DEBOUNCE_PULSE_3MS;
+                               debounce |= BYT_DEBOUNCE_PULSE_3MS;
                                break;
                        case 6000:
-                               conf |= BYT_DEBOUNCE_PULSE_6MS;
+                               debounce |= BYT_DEBOUNCE_PULSE_6MS;
                                break;
                        case 12000:
-                               conf |= BYT_DEBOUNCE_PULSE_12MS;
+                               debounce |= BYT_DEBOUNCE_PULSE_12MS;
                                break;
                        case 24000:
-                               conf |= BYT_DEBOUNCE_PULSE_24MS;
+                               debounce |= BYT_DEBOUNCE_PULSE_24MS;
                                break;
                        default:
-                               ret = -EINVAL;
+                               if (arg)
+                                       ret = -EINVAL;
+                               break;
                        }
 
+                       if (!ret)
+                               writel(debounce, db_reg);
                        break;
                default:
                        ret = -ENOTSUPP;
@@ -1606,7 +1623,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
                        continue;
                }
 
+               raw_spin_lock(&vg->lock);
                pending = readl(reg);
+               raw_spin_unlock(&vg->lock);
                for_each_set_bit(pin, &pending, 32) {
                        virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
                        generic_handle_irq(virq);
@@ -1617,6 +1636,8 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
 
 static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 {
+       struct gpio_chip *gc = &vg->chip;
+       struct device *dev = &vg->pdev->dev;
        void __iomem *reg;
        u32 base, value;
        int i;
@@ -1638,10 +1659,12 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
                }
 
                value = readl(reg);
-               if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i) &&
-                   !(value & BYT_DIRECT_IRQ_EN)) {
+               if (value & BYT_DIRECT_IRQ_EN) {
+                       clear_bit(i, gc->irq_valid_mask);
+                       dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
+               } else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
                        byt_gpio_clear_triggering(vg, i);
-                       dev_dbg(&vg->pdev->dev, "disabling GPIO %d\n", i);
+                       dev_dbg(dev, "disabling GPIO %d\n", i);
                }
        }
 
@@ -1680,6 +1703,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
        gc->can_sleep   = false;
        gc->parent      = &vg->pdev->dev;
        gc->ngpio       = vg->soc_data->npins;
+       gc->irq_need_valid_mask = true;
 
 #ifdef CONFIG_PM_SLEEP
        vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
index 59cb7a6fc5bef316d042f93da72792edca2ea8d9..901b356b09d71679a2b4a03f7cd57b30a22fa6f4 100644 (file)
@@ -19,7 +19,7 @@
 
 #define BXT_PAD_OWN    0x020
 #define BXT_HOSTSW_OWN 0x080
-#define BXT_PADCFGLOCK 0x090
+#define BXT_PADCFGLOCK 0x060
 #define BXT_GPI_IE     0x110
 
 #define BXT_COMMUNITY(s, e)                            \
index 1e139672f1af9da0fa7ff4af1a919395e2ea6957..6df35dcb29aea68c0ddec6cbd29bb1c9a3abd56c 100644 (file)
@@ -353,6 +353,21 @@ static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
        return 0;
 }
 
+static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
+{
+       u32 value;
+
+       value = readl(padcfg0);
+       if (input) {
+               value &= ~PADCFG0_GPIORXDIS;
+               value |= PADCFG0_GPIOTXDIS;
+       } else {
+               value &= ~PADCFG0_GPIOTXDIS;
+               value |= PADCFG0_GPIORXDIS;
+       }
+       writel(value, padcfg0);
+}
+
 static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
                                     struct pinctrl_gpio_range *range,
                                     unsigned pin)
@@ -375,11 +390,11 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
        /* Disable SCI/SMI/NMI generation */
        value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
        value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
-       /* Disable TX buffer and enable RX (this will be input) */
-       value &= ~PADCFG0_GPIORXDIS;
-       value |= PADCFG0_GPIOTXDIS;
        writel(value, padcfg0);
 
+       /* Disable TX buffer and enable RX (this will be input) */
+       __intel_gpio_set_direction(padcfg0, true);
+
        raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 
        return 0;
@@ -392,18 +407,11 @@ static int intel_gpio_set_direction(struct pinctrl_dev *pctldev,
        struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
        void __iomem *padcfg0;
        unsigned long flags;
-       u32 value;
 
        raw_spin_lock_irqsave(&pctrl->lock, flags);
 
        padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
-
-       value = readl(padcfg0);
-       if (input)
-               value |= PADCFG0_GPIOTXDIS;
-       else
-               value &= ~PADCFG0_GPIOTXDIS;
-       writel(value, padcfg0);
+       __intel_gpio_set_direction(padcfg0, input);
 
        raw_spin_unlock_irqrestore(&pctrl->lock, flags);
 
index b21896126f760a5cbae044ab13cba527e9dbfeff..4d4ef42a39b5faaa1969d20a5aeeedffef90074c 100644 (file)
@@ -794,6 +794,9 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
        unsigned int i;
        int ret;
 
+       if (!mrfld_buf_available(mp, pin))
+               return -ENOTSUPP;
+
        for (i = 0; i < nconfigs; i++) {
                switch (pinconf_to_config_param(configs[i])) {
                case PIN_CONFIG_BIAS_DISABLE:
index c3928aa3fefa9a1d24b0214e877bbac2bc15f67e..e0bca4df2a2f3188da0d559a29013893a5bea528 100644 (file)
@@ -253,9 +253,8 @@ static const unsigned int uart_tx_ao_a_pins[]       = { PIN(GPIOAO_0, 0) };
 static const unsigned int uart_rx_ao_a_pins[]  = { PIN(GPIOAO_1, 0) };
 static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) };
 static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) };
-static const unsigned int uart_tx_ao_b_pins[]  = { PIN(GPIOAO_0, 0) };
-static const unsigned int uart_rx_ao_b_pins[]  = { PIN(GPIOAO_1, 0),
-                                                   PIN(GPIOAO_5, 0) };
+static const unsigned int uart_tx_ao_b_pins[]  = { PIN(GPIOAO_4, 0) };
+static const unsigned int uart_rx_ao_b_pins[]  = { PIN(GPIOAO_5, 0) };
 static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) };
 static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) };
 
@@ -498,7 +497,7 @@ static struct meson_pmx_group meson_gxbb_aobus_groups[] = {
        GPIO_GROUP(GPIOAO_13, 0),
 
        /* bank AO */
-       GROUP(uart_tx_ao_b,     0,      26),
+       GROUP(uart_tx_ao_b,     0,      24),
        GROUP(uart_rx_ao_b,     0,      25),
        GROUP(uart_tx_ao_a,     0,      12),
        GROUP(uart_rx_ao_a,     0,      11),
index 25694f7094c714bbf35eee2ae7b51e2b4ce5b1e9..b69743b07a1d591ace36d410583231319234d4f0 100644 (file)
@@ -214,9 +214,8 @@ static const unsigned int uart_tx_ao_a_pins[]       = { PIN(GPIOAO_0, 0) };
 static const unsigned int uart_rx_ao_a_pins[]  = { PIN(GPIOAO_1, 0) };
 static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) };
 static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) };
-static const unsigned int uart_tx_ao_b_pins[]  = { PIN(GPIOAO_0, 0) };
-static const unsigned int uart_rx_ao_b_pins[]  = { PIN(GPIOAO_1, 0),
-                                                   PIN(GPIOAO_5, 0) };
+static const unsigned int uart_tx_ao_b_pins[]  = { PIN(GPIOAO_4, 0) };
+static const unsigned int uart_rx_ao_b_pins[]  = { PIN(GPIOAO_5, 0) };
 static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) };
 static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) };
 
@@ -409,7 +408,7 @@ static struct meson_pmx_group meson_gxl_aobus_groups[] = {
        GPIO_GROUP(GPIOAO_9, 0),
 
        /* bank AO */
-       GROUP(uart_tx_ao_b,     0,      26),
+       GROUP(uart_tx_ao_b,     0,      24),
        GROUP(uart_rx_ao_b,     0,      25),
        GROUP(uart_tx_ao_a,     0,      12),
        GROUP(uart_rx_ao_a,     0,      11),
index a579126832afde2d758d629f58338af2d9e9378f..620c231a2889ef6879269a80ccbfaa3e4493958f 100644 (file)
@@ -212,7 +212,7 @@ static int meson_pmx_request_gpio(struct pinctrl_dev *pcdev,
 {
        struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
 
-       meson_pmx_disable_other_groups(pc, range->pin_base + offset, -1);
+       meson_pmx_disable_other_groups(pc, offset, -1);
 
        return 0;
 }
index aea310a918210ebc96bcb2739ac3c50d10329f8d..537b52055756645a8f225dd7e96b191d7d841e96 100644 (file)
@@ -202,6 +202,8 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
                        i = 128;
                        pin_num = AMD_GPIO_PINS_BANK2 + i;
                        break;
+               default:
+                       return;
                }
 
                for (; i < pin_num; i++) {
@@ -382,26 +384,21 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
        int ret = 0;
        u32 pin_reg;
-       unsigned long flags;
-       bool level_trig;
-       u32 active_level;
+       unsigned long flags, irq_flags;
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
        spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
 
-       /*
-        * When level_trig is set EDGE and active_level is set HIGH in BIOS
-        * default settings, ignore incoming settings from client and use
-        * BIOS settings to configure GPIO register.
+       /* Ignore the settings coming from the client and
+        * read the values from the ACPI tables
+        * while setting the trigger type
         */
-       level_trig = !(pin_reg & (LEVEL_TRIGGER << LEVEL_TRIG_OFF));
-       active_level = pin_reg & (ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
 
-       if(level_trig &&
-          ((active_level >> ACTIVE_LEVEL_OFF) == ACTIVE_HIGH))
-               type = IRQ_TYPE_EDGE_FALLING;
+       irq_flags = irq_get_trigger_type(d->irq);
+       if (irq_flags != IRQ_TYPE_NONE)
+               type = irq_flags;
 
        switch (type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_RISING:
index 12f7d1eb65bc71e891f3eb88a750953dbd1ce68b..07409fde02b23f85005c0403ba146fce50cde970 100644 (file)
@@ -56,6 +56,17 @@ static const struct samsung_pin_bank_type bank_type_alive = {
        .reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
 };
 
+/* Exynos5433 has the 4bit widths for PINCFG_TYPE_DRV bitfields. */
+static const struct samsung_pin_bank_type exynos5433_bank_type_off = {
+       .fld_width = { 4, 1, 2, 4, 2, 2, },
+       .reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
+};
+
+static const struct samsung_pin_bank_type exynos5433_bank_type_alive = {
+       .fld_width = { 4, 1, 2, 4, },
+       .reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
+};
+
 static void exynos_irq_mask(struct irq_data *irqd)
 {
        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
@@ -1335,82 +1346,82 @@ const struct samsung_pin_ctrl exynos5420_pin_ctrl[] __initconst = {
 
 /* pin banks of exynos5433 pin-controller - ALIVE */
 static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = {
-       EXYNOS_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
-       EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
-       EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
-       EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
-       EXYNOS_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1),
-       EXYNOS_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1),
-       EXYNOS_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1),
-       EXYNOS_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1),
-       EXYNOS_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1),
+       EXYNOS5433_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
+       EXYNOS5433_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
+       EXYNOS5433_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
+       EXYNOS5433_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
+       EXYNOS5433_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1),
+       EXYNOS5433_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1),
+       EXYNOS5433_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1),
+       EXYNOS5433_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1),
+       EXYNOS5433_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1),
 };
 
 /* pin banks of exynos5433 pin-controller - AUD */
 static const struct samsung_pin_bank_data exynos5433_pin_banks1[] = {
-       EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
-       EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
+       EXYNOS5433_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
 };
 
 /* pin banks of exynos5433 pin-controller - CPIF */
 static const struct samsung_pin_bank_data exynos5433_pin_banks2[] = {
-       EXYNOS_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
 };
 
 /* pin banks of exynos5433 pin-controller - eSE */
 static const struct samsung_pin_bank_data exynos5433_pin_banks3[] = {
-       EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
 };
 
 /* pin banks of exynos5433 pin-controller - FINGER */
 static const struct samsung_pin_bank_data exynos5433_pin_banks4[] = {
-       EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
 };
 
 /* pin banks of exynos5433 pin-controller - FSYS */
 static const struct samsung_pin_bank_data exynos5433_pin_banks5[] = {
-       EXYNOS_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
-       EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
-       EXYNOS_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
-       EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpr1", 0x0c),
-       EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpr2", 0x10),
-       EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpr3", 0x14),
+       EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
+       EXYNOS5433_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x060, "gpr1", 0x0c),
+       EXYNOS5433_PIN_BANK_EINTG(2, 0x080, "gpr2", 0x10),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x0a0, "gpr3", 0x14),
 };
 
 /* pin banks of exynos5433 pin-controller - IMEM */
 static const struct samsung_pin_bank_data exynos5433_pin_banks6[] = {
-       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
 };
 
 /* pin banks of exynos5433 pin-controller - NFC */
 static const struct samsung_pin_bank_data exynos5433_pin_banks7[] = {
-       EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
 };
 
 /* pin banks of exynos5433 pin-controller - PERIC */
 static const struct samsung_pin_bank_data exynos5433_pin_banks8[] = {
-       EXYNOS_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
-       EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
-       EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
-       EXYNOS_PIN_BANK_EINTG(2, 0x060, "gpc1", 0x0c),
-       EXYNOS_PIN_BANK_EINTG(6, 0x080, "gpc2", 0x10),
-       EXYNOS_PIN_BANK_EINTG(8, 0x0a0, "gpc3", 0x14),
-       EXYNOS_PIN_BANK_EINTG(2, 0x0c0, "gpg0", 0x18),
-       EXYNOS_PIN_BANK_EINTG(4, 0x0e0, "gpd0", 0x1c),
-       EXYNOS_PIN_BANK_EINTG(6, 0x100, "gpd1", 0x20),
-       EXYNOS_PIN_BANK_EINTG(8, 0x120, "gpd2", 0x24),
-       EXYNOS_PIN_BANK_EINTG(5, 0x140, "gpd4", 0x28),
-       EXYNOS_PIN_BANK_EINTG(2, 0x160, "gpd8", 0x2c),
-       EXYNOS_PIN_BANK_EINTG(7, 0x180, "gpd6", 0x30),
-       EXYNOS_PIN_BANK_EINTG(3, 0x1a0, "gpd7", 0x34),
-       EXYNOS_PIN_BANK_EINTG(5, 0x1c0, "gpg1", 0x38),
-       EXYNOS_PIN_BANK_EINTG(2, 0x1e0, "gpg2", 0x3c),
-       EXYNOS_PIN_BANK_EINTG(8, 0x200, "gpg3", 0x40),
+       EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
+       EXYNOS5433_PIN_BANK_EINTG(2, 0x060, "gpc1", 0x0c),
+       EXYNOS5433_PIN_BANK_EINTG(6, 0x080, "gpc2", 0x10),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x0a0, "gpc3", 0x14),
+       EXYNOS5433_PIN_BANK_EINTG(2, 0x0c0, "gpg0", 0x18),
+       EXYNOS5433_PIN_BANK_EINTG(4, 0x0e0, "gpd0", 0x1c),
+       EXYNOS5433_PIN_BANK_EINTG(6, 0x100, "gpd1", 0x20),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x120, "gpd2", 0x24),
+       EXYNOS5433_PIN_BANK_EINTG(5, 0x140, "gpd4", 0x28),
+       EXYNOS5433_PIN_BANK_EINTG(2, 0x160, "gpd8", 0x2c),
+       EXYNOS5433_PIN_BANK_EINTG(7, 0x180, "gpd6", 0x30),
+       EXYNOS5433_PIN_BANK_EINTG(3, 0x1a0, "gpd7", 0x34),
+       EXYNOS5433_PIN_BANK_EINTG(5, 0x1c0, "gpg1", 0x38),
+       EXYNOS5433_PIN_BANK_EINTG(2, 0x1e0, "gpg2", 0x3c),
+       EXYNOS5433_PIN_BANK_EINTG(8, 0x200, "gpg3", 0x40),
 };
 
 /* pin banks of exynos5433 pin-controller - TOUCH */
 static const struct samsung_pin_bank_data exynos5433_pin_banks9[] = {
-       EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
+       EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
 };
 
 /*
index 5821525a2c8473fa026b3dc84cd6eb999c243b2a..a473092fb8d2362f11a1a48beb7f545b7c9f25ce 100644 (file)
                .pctl_res_idx   = pctl_idx,             \
        }                                               \
 
+#define EXYNOS5433_PIN_BANK_EINTG(pins, reg, id, offs)         \
+       {                                                       \
+               .type           = &exynos5433_bank_type_off,    \
+               .pctl_offset    = reg,                          \
+               .nr_pins        = pins,                         \
+               .eint_type      = EINT_TYPE_GPIO,               \
+               .eint_offset    = offs,                         \
+               .name           = id                            \
+       }
+
+#define EXYNOS5433_PIN_BANK_EINTW(pins, reg, id, offs)         \
+       {                                                       \
+               .type           = &exynos5433_bank_type_alive,  \
+               .pctl_offset    = reg,                          \
+               .nr_pins        = pins,                         \
+               .eint_type      = EINT_TYPE_WKUP,               \
+               .eint_offset    = offs,                         \
+               .name           = id                            \
+       }
+
+#define EXYNOS5433_PIN_BANK_EINTW_EXT(pins, reg, id, offs, pctl_idx) \
+       {                                                       \
+               .type           = &exynos5433_bank_type_alive,  \
+               .pctl_offset    = reg,                          \
+               .nr_pins        = pins,                         \
+               .eint_type      = EINT_TYPE_WKUP,               \
+               .eint_offset    = offs,                         \
+               .name           = id,                           \
+               .pctl_res_idx   = pctl_idx,                     \
+       }                                                       \
+
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
index 0eb51e33cb1be5412ab11d10e7cdb474a2faa061..207a8de4e1ed851cf542aa4af008e8f74102cad3 100644 (file)
@@ -564,8 +564,7 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
                        val = arg / 10 - 1;
                        break;
                case PIN_CONFIG_BIAS_DISABLE:
-                       val = 0;
-                       break;
+                       continue;
                case PIN_CONFIG_BIAS_PULL_UP:
                        if (arg == 0)
                                return -EINVAL;
index aa8bd9794683b715013c82aa9220d11cfb0ea595..96686336e3a396254b9473f01f1776e0297301ce 100644 (file)
@@ -561,7 +561,7 @@ static const int ether_rgmii_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                          0, 0, 0, 0};
 static const unsigned ether_rmii_pins[] = {30, 31, 32, 33, 34, 35, 36, 37, 39,
                                           41, 42, 45};
-static const int ether_rmii_muxvals[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+static const int ether_rmii_muxvals[] = {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1};
 static const unsigned i2c0_pins[] = {63, 64};
 static const int i2c0_muxvals[] = {0, 0};
 static const unsigned i2c1_pins[] = {65, 66};
index 5fe8be089b8b2dc51ced608e0790c7ce05b8dd18..59aa8e302bc3f9ab9dd26b43e6bf53ef812631fd 100644 (file)
@@ -1034,7 +1034,7 @@ config SURFACE_PRO3_BUTTON
 
 config SURFACE_3_BUTTON
        tristate "Power/home/volume buttons driver for Microsoft Surface 3 tablet"
-       depends on ACPI && KEYBOARD_GPIO
+       depends on ACPI && KEYBOARD_GPIO && I2C
        ---help---
          This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
 
index 61f39abf5dc8f24b738a2dafc5117b40a2521fd5..82d67715ce76d9ff0442ecdcdbd2dbb324380203 100644 (file)
@@ -177,43 +177,43 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event);
 
 #if IS_ENABLED(CONFIG_LEDS_CLASS)
 static enum led_brightness logolamp_get(struct led_classdev *cdev);
-static void logolamp_set(struct led_classdev *cdev,
+static int logolamp_set(struct led_classdev *cdev,
                               enum led_brightness brightness);
 
 static struct led_classdev logolamp_led = {
  .name = "fujitsu::logolamp",
  .brightness_get = logolamp_get,
- .brightness_set = logolamp_set
+ .brightness_set_blocking = logolamp_set
 };
 
 static enum led_brightness kblamps_get(struct led_classdev *cdev);
-static void kblamps_set(struct led_classdev *cdev,
+static int kblamps_set(struct led_classdev *cdev,
                               enum led_brightness brightness);
 
 static struct led_classdev kblamps_led = {
  .name = "fujitsu::kblamps",
  .brightness_get = kblamps_get,
- .brightness_set = kblamps_set
+ .brightness_set_blocking = kblamps_set
 };
 
 static enum led_brightness radio_led_get(struct led_classdev *cdev);
-static void radio_led_set(struct led_classdev *cdev,
+static int radio_led_set(struct led_classdev *cdev,
                               enum led_brightness brightness);
 
 static struct led_classdev radio_led = {
  .name = "fujitsu::radio_led",
  .brightness_get = radio_led_get,
- .brightness_set = radio_led_set
+ .brightness_set_blocking = radio_led_set
 };
 
 static enum led_brightness eco_led_get(struct led_classdev *cdev);
-static void eco_led_set(struct led_classdev *cdev,
+static int eco_led_set(struct led_classdev *cdev,
                               enum led_brightness brightness);
 
 static struct led_classdev eco_led = {
  .name = "fujitsu::eco_led",
  .brightness_get = eco_led_get,
- .brightness_set = eco_led_set
+ .brightness_set_blocking = eco_led_set
 };
 #endif
 
@@ -267,48 +267,48 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
 #if IS_ENABLED(CONFIG_LEDS_CLASS)
 /* LED class callbacks */
 
-static void logolamp_set(struct led_classdev *cdev,
+static int logolamp_set(struct led_classdev *cdev,
                               enum led_brightness brightness)
 {
        if (brightness >= LED_FULL) {
                call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON);
-               call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON);
+               return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON);
        } else if (brightness >= LED_HALF) {
                call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON);
-               call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF);
+               return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF);
        } else {
-               call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF);
+               return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF);
        }
 }
 
-static void kblamps_set(struct led_classdev *cdev,
+static int kblamps_set(struct led_classdev *cdev,
                               enum led_brightness brightness)
 {
        if (brightness >= LED_FULL)
-               call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON);
+               return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON);
        else
-               call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
+               return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
 }
 
-static void radio_led_set(struct led_classdev *cdev,
+static int radio_led_set(struct led_classdev *cdev,
                                enum led_brightness brightness)
 {
        if (brightness >= LED_FULL)
-               call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON);
+               return call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON);
        else
-               call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0);
+               return call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0);
 }
 
-static void eco_led_set(struct led_classdev *cdev,
+static int eco_led_set(struct led_classdev *cdev,
                                enum led_brightness brightness)
 {
        int curr;
 
        curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0);
        if (brightness >= LED_FULL)
-               call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON);
+               return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON);
        else
-               call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON);
+               return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON);
 }
 
 static enum led_brightness logolamp_get(struct led_classdev *cdev)
index 410741acb3c92dabe36417800f564a943c5d42ec..f46ece2ce3c4d48086c73b0e2d0c63ee1fe35893 100644 (file)
@@ -813,6 +813,7 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
                        case 8:
                        case 7:
                        case 6:
+                       case 1:
                                ideapad_input_report(priv, vpc_bit);
                                break;
                        case 5:
index 1fc0de870ff826e8b90956ab557cc83008e1ce68..361770568ad03a6e7a3bc7e6d579ccacae1725b7 100644 (file)
@@ -77,7 +77,7 @@ static int mfld_pb_probe(struct platform_device *pdev)
 
        input_set_capability(input, EV_KEY, KEY_POWER);
 
-       error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
+       error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_ONESHOT,
                                     DRIVER_NAME, input);
        if (error) {
                dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
index 97b4c3a219c0c79f3a3ed9359bc30bb13a439ce6..25f15df5c2d7b3c37b82e099f301831c403caa7d 100644 (file)
@@ -326,7 +326,7 @@ static int __init mlxplat_init(void)
        return 0;
 
 fail_platform_mux_register:
-       for (i--; i > 0 ; i--)
+       while (--i >= 0)
                platform_device_unregister(priv->pdev_mux[i]);
        platform_device_unregister(priv->pdev_i2c);
 fail_alloc:
index cbf4d83a727106ee0f7e42ca1b868616d994c0c3..25b176996cb793a789214a1a1237910b01cd3673 100644 (file)
@@ -139,7 +139,7 @@ static acpi_status s3_wmi_attach_spi_device(acpi_handle handle,
 
 static int s3_wmi_check_platform_device(struct device *dev, void *data)
 {
-       struct acpi_device *adev, *ts_adev;
+       struct acpi_device *adev, *ts_adev = NULL;
        acpi_handle handle;
        acpi_status status;
 
@@ -244,13 +244,11 @@ static int s3_wmi_remove(struct platform_device *device)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int s3_wmi_resume(struct device *dev)
+static int __maybe_unused s3_wmi_resume(struct device *dev)
 {
        s3_wmi_send_lid_state();
        return 0;
 }
-#endif
 static SIMPLE_DEV_PM_OPS(s3_wmi_pm, NULL, s3_wmi_resume);
 
 static struct platform_driver s3_wmi_driver = {
index e6a512ebeae2762812212ac5b9264f92bb8252be..a3ade9e4ef478ed90311365a4e86db0cbbc394d5 100644 (file)
@@ -272,7 +272,7 @@ static const struct regulator_desc axp806_regulators[] = {
                        64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1,
                        BIT(3)),
        AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100,
-                AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)),
+                AXP806_DCDCE_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)),
        AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
                 AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)),
        AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100,
index a43b0e8a438d305a959d3d745c7c65bf796ca9f9..988a7472c2ab568c3d1c03d1092c0713073a6d28 100644 (file)
@@ -30,9 +30,6 @@
 #include <linux/of_gpio.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/machine.h>
-#include <linux/acpi.h>
-#include <linux/property.h>
-#include <linux/gpio/consumer.h>
 
 struct fixed_voltage_data {
        struct regulator_desc desc;
@@ -97,44 +94,6 @@ of_get_fixed_voltage_config(struct device *dev,
        return config;
 }
 
-/**
- * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info
- * @dev: device requesting for fixed_voltage_config
- * @desc: regulator description
- *
- * Populates fixed_voltage_config structure by extracting data through ACPI
- * interface, returns a pointer to the populated structure of NULL if memory
- * alloc fails.
- */
-static struct fixed_voltage_config *
-acpi_get_fixed_voltage_config(struct device *dev,
-                             const struct regulator_desc *desc)
-{
-       struct fixed_voltage_config *config;
-       const char *supply_name;
-       struct gpio_desc *gpiod;
-       int ret;
-
-       config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
-       if (!config)
-               return ERR_PTR(-ENOMEM);
-
-       ret = device_property_read_string(dev, "supply-name", &supply_name);
-       if (!ret)
-               config->supply_name = supply_name;
-
-       gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
-       if (IS_ERR(gpiod))
-               return ERR_PTR(-ENODEV);
-
-       config->gpio = desc_to_gpio(gpiod);
-       config->enable_high = device_property_read_bool(dev,
-                                                       "enable-active-high");
-       gpiod_put(gpiod);
-
-       return config;
-}
-
 static struct regulator_ops fixed_voltage_ops = {
 };
 
@@ -155,11 +114,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
                                                     &drvdata->desc);
                if (IS_ERR(config))
                        return PTR_ERR(config);
-       } else if (ACPI_HANDLE(&pdev->dev)) {
-               config = acpi_get_fixed_voltage_config(&pdev->dev,
-                                                      &drvdata->desc);
-               if (IS_ERR(config))
-                       return PTR_ERR(config);
        } else {
                config = dev_get_platdata(&pdev->dev);
        }
index 4864b9d742c0f7915cc792aaacd692c2a7f305b0..716191046a70782b0007033dda6e1402c0d68ea3 100644 (file)
@@ -452,7 +452,7 @@ static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV,
                        vsel = 62;
                else if ((min_uV > 1800000) && (min_uV <= 1900000))
                        vsel = 61;
-               else if ((min_uV > 1350000) && (min_uV <= 1800000))
+               else if ((min_uV > 1500000) && (min_uV <= 1800000))
                        vsel = 60;
                else if ((min_uV > 1350000) && (min_uV <= 1500000))
                        vsel = 59;
index 9a507e77eced18cc433792f651761dd137b75d62..90b05c72186c4f9e9c37a812ec469a738d253e95 100644 (file)
@@ -396,9 +396,6 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
                        goto unwind_vring_allocations;
        }
 
-       /* track the rvdevs list reference */
-       kref_get(&rvdev->refcount);
-
        list_add_tail(&rvdev->node, &rproc->rvdevs);
 
        rproc_add_subdev(rproc, &rvdev->subdev,
@@ -889,13 +886,15 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
        /*
         * Create a copy of the resource table. When a virtio device starts
         * and calls vring_new_virtqueue() the address of the allocated vring
-        * will be stored in the table_ptr. Before the device is started,
-        * table_ptr will be copied into device memory.
+        * will be stored in the cached_table. Before the device is started,
+        * cached_table will be copied into device memory.
         */
-       rproc->table_ptr = kmemdup(table, tablesz, GFP_KERNEL);
-       if (!rproc->table_ptr)
+       rproc->cached_table = kmemdup(table, tablesz, GFP_KERNEL);
+       if (!rproc->cached_table)
                goto clean_up;
 
+       rproc->table_ptr = rproc->cached_table;
+
        /* reset max_notifyid */
        rproc->max_notifyid = -1;
 
@@ -914,16 +913,18 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
        }
 
        /*
-        * The starting device has been given the rproc->table_ptr as the
+        * The starting device has been given the rproc->cached_table as the
         * resource table. The address of the vring along with the other
-        * allocated resources (carveouts etc) is stored in table_ptr.
+        * allocated resources (carveouts etc) is stored in cached_table.
         * In order to pass this information to the remote device we must copy
         * this information to device memory. We also update the table_ptr so
         * that any subsequent changes will be applied to the loaded version.
         */
        loaded_table = rproc_find_loaded_rsc_table(rproc, fw);
-       if (loaded_table)
-               memcpy(loaded_table, rproc->table_ptr, tablesz);
+       if (loaded_table) {
+               memcpy(loaded_table, rproc->cached_table, tablesz);
+               rproc->table_ptr = loaded_table;
+       }
 
        /* power up the remote processor */
        ret = rproc->ops->start(rproc);
@@ -951,7 +952,8 @@ stop_rproc:
 clean_up_resources:
        rproc_resource_cleanup(rproc);
 clean_up:
-       kfree(rproc->table_ptr);
+       kfree(rproc->cached_table);
+       rproc->cached_table = NULL;
        rproc->table_ptr = NULL;
 
        rproc_disable_iommu(rproc);
@@ -1185,7 +1187,8 @@ void rproc_shutdown(struct rproc *rproc)
        rproc_disable_iommu(rproc);
 
        /* Free the copy of the resource table */
-       kfree(rproc->table_ptr);
+       kfree(rproc->cached_table);
+       rproc->cached_table = NULL;
        rproc->table_ptr = NULL;
 
        /* if in crash state, unlock crash handler */
index 10368ed8fd136230d1d9a13492bf557bd063a669..b6f5f1e1826c15c0e7f6db0a9af599dba39d5878 100644 (file)
@@ -163,7 +163,7 @@ int reset_control_reset(struct reset_control *rstc)
        }
 
        ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
-       if (rstc->shared && !ret)
+       if (rstc->shared && ret)
                atomic_dec(&rstc->triggered_count);
 
        return ret;
index a79cb5a9e5f22963ed56214421abc099c5949c37..1cfb775e8e82b8b391108c700abba57f92867066 100644 (file)
@@ -453,8 +453,8 @@ int rpmsg_register_device(struct rpmsg_device *rpdev)
        struct device *dev = &rpdev->dev;
        int ret;
 
-       dev_set_name(&rpdev->dev, "%s:%s",
-                    dev_name(dev->parent), rpdev->id.name);
+       dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent),
+                    rpdev->id.name, rpdev->src, rpdev->dst);
 
        rpdev->dev.bus = &rpmsg_bus;
        rpdev->dev.release = rpmsg_release_device;
index c93c5a8fba32925584dbc28c60610786328d09ff..5dc673dc948785a79da8d070954323b9357385c1 100644 (file)
@@ -1551,12 +1551,15 @@ config RTC_DRV_MPC5121
          will be called rtc-mpc5121.
 
 config RTC_DRV_JZ4740
-       bool "Ingenic JZ4740 SoC"
+       tristate "Ingenic JZ4740 SoC"
        depends on MACH_INGENIC || COMPILE_TEST
        help
          If you say yes here you get support for the Ingenic JZ47xx SoCs RTC
          controllers.
 
+         This driver can also be buillt as a module. If so, the module
+         will be called rtc-jz4740.
+
 config RTC_DRV_LPC24XX
        tristate "NXP RTC for LPC178x/18xx/408x/43xx"
        depends on ARCH_LPC18XX || COMPILE_TEST
index 72918c1ba0928d4fc78d921db621c489fafb9701..64989afffa3daada4b062321c527f18bca142bbb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
@@ -294,7 +295,7 @@ static void jz4740_rtc_power_off(void)
                             JZ_REG_RTC_RESET_COUNTER, reset_counter_ticks);
 
        jz4740_rtc_poweroff(dev_for_power_off);
-       machine_halt();
+       kernel_halt();
 }
 
 static const struct of_device_id jz4740_rtc_of_match[] = {
@@ -302,6 +303,7 @@ static const struct of_device_id jz4740_rtc_of_match[] = {
        { .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 },
        {},
 };
+MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match);
 
 static int jz4740_rtc_probe(struct platform_device *pdev)
 {
@@ -429,6 +431,7 @@ static const struct platform_device_id jz4740_rtc_ids[] = {
        { "jz4780-rtc", ID_JZ4780 },
        {}
 };
+MODULE_DEVICE_TABLE(platform, jz4740_rtc_ids);
 
 static struct platform_driver jz4740_rtc_driver = {
        .probe   = jz4740_rtc_probe,
@@ -440,4 +443,9 @@ static struct platform_driver jz4740_rtc_driver = {
        .id_table = jz4740_rtc_ids,
 };
 
-builtin_platform_driver(jz4740_rtc_driver);
+module_platform_driver(jz4740_rtc_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("RTC driver for the JZ4740 SoC\n");
+MODULE_ALIAS("platform:jz4740-rtc");
index 75f820ca17b79b0574e3afd91df18998a3438c30..27ff38f839fc1c752385f430f55020fb934ed6de 100644 (file)
@@ -1583,7 +1583,7 @@ out:
 int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
        struct zfcp_qdio *qdio = wka_port->adapter->qdio;
-       struct zfcp_fsf_req *req = NULL;
+       struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_irq(&qdio->req_q_lock);
@@ -1612,7 +1612,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
                zfcp_fsf_req_free(req);
 out:
        spin_unlock_irq(&qdio->req_q_lock);
-       if (req && !IS_ERR(req))
+       if (!retval)
                zfcp_dbf_rec_run_wka("fsowp_1", wka_port, req->req_id);
        return retval;
 }
@@ -1638,7 +1638,7 @@ static void zfcp_fsf_close_wka_port_handler(struct zfcp_fsf_req *req)
 int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
 {
        struct zfcp_qdio *qdio = wka_port->adapter->qdio;
-       struct zfcp_fsf_req *req = NULL;
+       struct zfcp_fsf_req *req;
        int retval = -EIO;
 
        spin_lock_irq(&qdio->req_q_lock);
@@ -1667,7 +1667,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
                zfcp_fsf_req_free(req);
 out:
        spin_unlock_irq(&qdio->req_q_lock);
-       if (req && !IS_ERR(req))
+       if (!retval)
                zfcp_dbf_rec_run_wka("fscwp_1", wka_port, req->req_id);
        return retval;
 }
index 639ed4e6afd19b46d1e8fb3ec5669b217da8d3c4..070c4da95f48c0e9b0dbb7b6bcf008f8d6e5972e 100644 (file)
@@ -145,6 +145,7 @@ static struct airq_info *airq_areas[MAX_AIRQ_AREAS];
 #define CCW_CMD_WRITE_CONF 0x21
 #define CCW_CMD_WRITE_STATUS 0x31
 #define CCW_CMD_READ_VQ_CONF 0x32
+#define CCW_CMD_READ_STATUS 0x72
 #define CCW_CMD_SET_IND_ADAPTER 0x73
 #define CCW_CMD_SET_VIRTIO_REV 0x83
 
@@ -160,6 +161,7 @@ static struct airq_info *airq_areas[MAX_AIRQ_AREAS];
 #define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000
 #define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000
 #define VIRTIO_CCW_DOING_SET_VIRTIO_REV 0x10000000
+#define VIRTIO_CCW_DOING_READ_STATUS 0x20000000
 #define VIRTIO_CCW_INTPARM_MASK 0xffff0000
 
 static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev)
@@ -452,7 +454,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
         * This may happen on device detach.
         */
        if (ret && (ret != -ENODEV))
-               dev_warn(&vq->vdev->dev, "Error %d while deleting queue %d",
+               dev_warn(&vq->vdev->dev, "Error %d while deleting queue %d\n",
                         ret, index);
 
        vring_del_virtqueue(vq);
@@ -892,6 +894,28 @@ out_free:
 static u8 virtio_ccw_get_status(struct virtio_device *vdev)
 {
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
+       u8 old_status = *vcdev->status;
+       struct ccw1 *ccw;
+
+       if (vcdev->revision < 1)
+               return *vcdev->status;
+
+       ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
+       if (!ccw)
+               return old_status;
+
+       ccw->cmd_code = CCW_CMD_READ_STATUS;
+       ccw->flags = 0;
+       ccw->count = sizeof(*vcdev->status);
+       ccw->cda = (__u32)(unsigned long)vcdev->status;
+       ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_STATUS);
+/*
+ * If the channel program failed (should only happen if the device
+ * was hotunplugged, and then we clean up via the machine check
+ * handler anyway), vcdev->status was not overwritten and we just
+ * return the old status, which is fine.
+*/
+       kfree(ccw);
 
        return *vcdev->status;
 }
@@ -920,7 +944,7 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
        kfree(ccw);
 }
 
-static struct virtio_config_ops virtio_ccw_config_ops = {
+static const struct virtio_config_ops virtio_ccw_config_ops = {
        .get_features = virtio_ccw_get_features,
        .finalize_features = virtio_ccw_finalize_features,
        .get = virtio_ccw_get_config,
@@ -987,6 +1011,7 @@ static void virtio_ccw_check_activity(struct virtio_ccw_device *vcdev,
                case VIRTIO_CCW_DOING_READ_CONFIG:
                case VIRTIO_CCW_DOING_WRITE_CONFIG:
                case VIRTIO_CCW_DOING_WRITE_STATUS:
+               case VIRTIO_CCW_DOING_READ_STATUS:
                case VIRTIO_CCW_DOING_SET_VQ:
                case VIRTIO_CCW_DOING_SET_IND:
                case VIRTIO_CCW_DOING_SET_CONF_IND:
index 4f56b1003cc7d9d8c56dcb98ead00b0fb5348788..5b48bedd7c385f3b73adb97d45f691d540914f42 100644 (file)
@@ -50,9 +50,13 @@ struct aac_common aac_config = {
 
 static inline int aac_is_msix_mode(struct aac_dev *dev)
 {
-       u32 status;
+       u32 status = 0;
 
-       status = src_readl(dev, MUnit.OMR);
+       if (dev->pdev->device == PMC_DEVICE_S6 ||
+               dev->pdev->device == PMC_DEVICE_S7 ||
+               dev->pdev->device == PMC_DEVICE_S8) {
+               status = src_readl(dev, MUnit.OMR);
+       }
        return (status & AAC_INT_MODE_MSIX);
 }
 
index d9e15210b110efcd3147d5a02f0e06c0673d4ad3..5caf5f3ff642282ee13776e9df9ca9a18f494536 100644 (file)
@@ -64,9 +64,9 @@ int           max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
 u32    bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
 u32    *bfi_image_cb, *bfi_image_ct, *bfi_image_ct2;
 
-#define BFAD_FW_FILE_CB                "cbfw-3.2.3.0.bin"
-#define BFAD_FW_FILE_CT                "ctfw-3.2.3.0.bin"
-#define BFAD_FW_FILE_CT2       "ct2fw-3.2.3.0.bin"
+#define BFAD_FW_FILE_CB                "cbfw-3.2.5.1.bin"
+#define BFAD_FW_FILE_CT                "ctfw-3.2.5.1.bin"
+#define BFAD_FW_FILE_CT2       "ct2fw-3.2.5.1.bin"
 
 static u32 *bfad_load_fwimg(struct pci_dev *pdev);
 static void bfad_free_fwimg(void);
index a9a00169ad91960798c35114c69b4d17f13d1039..b2e8c0dfc79cb247a30e2ec826bc9a64da489e64 100644 (file)
@@ -3363,7 +3363,7 @@ bfad_im_bsg_els_ct_request(struct bsg_job *job)
        struct bfad_fcxp    *drv_fcxp;
        struct bfa_fcs_lport_s *fcs_port;
        struct bfa_fcs_rport_s *fcs_rport;
-       struct fc_bsg_request *bsg_request = bsg_request;
+       struct fc_bsg_request *bsg_request = job->request;
        struct fc_bsg_reply *bsg_reply = job->reply;
        uint32_t command_type = bsg_request->msgcode;
        unsigned long flags;
index f9e862093a25935e601c45b4854035e98e035f03..cfcfff48e8e16e3fb2b66c0d491c0d612a8cdd38 100644 (file)
@@ -58,7 +58,7 @@
 #ifdef BFA_DRIVER_VERSION
 #define BFAD_DRIVER_VERSION    BFA_DRIVER_VERSION
 #else
-#define BFAD_DRIVER_VERSION    "3.2.25.0"
+#define BFAD_DRIVER_VERSION    "3.2.25.1"
 #endif
 
 #define BFAD_PROTO_NAME FCPI_NAME
index 9ddc9200e0a48b00632bbc441c492679786ec570..9e4b7709043e0c49620755cafce2f80b3e99df89 100644 (file)
@@ -248,6 +248,7 @@ struct fnic {
        struct completion *remove_wait; /* device remove thread blocks */
 
        atomic_t in_flight;             /* io counter */
+       bool internal_reset_inprogress;
        u32 _reserved;                  /* fill hole */
        unsigned long state_flags;      /* protected by host lock */
        enum fnic_state state;
index 2544a37ece0afdc19742d01954487f87dd4c3c5c..adb3d5871e743442e04014cd2f86eae15ab27912 100644 (file)
@@ -2581,6 +2581,19 @@ int fnic_host_reset(struct scsi_cmnd *sc)
        unsigned long wait_host_tmo;
        struct Scsi_Host *shost = sc->device->host;
        struct fc_lport *lp = shost_priv(shost);
+       struct fnic *fnic = lport_priv(lp);
+       unsigned long flags;
+
+       spin_lock_irqsave(&fnic->fnic_lock, flags);
+       if (fnic->internal_reset_inprogress == 0) {
+               fnic->internal_reset_inprogress = 1;
+       } else {
+               spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+               FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+                       "host reset in progress skipping another host reset\n");
+               return SUCCESS;
+       }
+       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 
        /*
         * If fnic_reset is successful, wait for fabric login to complete
@@ -2601,6 +2614,9 @@ int fnic_host_reset(struct scsi_cmnd *sc)
                }
        }
 
+       spin_lock_irqsave(&fnic->fnic_lock, flags);
+       fnic->internal_reset_inprogress = 0;
+       spin_unlock_irqrestore(&fnic->fnic_lock, flags);
        return ret;
 }
 
index 3d3768aaab4f2bb79ccbaf40f1f569114e4f9b30..0f807798c6245f8ba64b5ec3cced694d6a821c31 100644 (file)
@@ -46,6 +46,7 @@
 
 #define        INITIAL_SRP_LIMIT       800
 #define        DEFAULT_MAX_SECTORS     256
+#define MAX_TXU                        1024 * 1024
 
 static uint max_vdma_size = MAX_H_COPY_RDMA;
 
@@ -1391,7 +1392,7 @@ static long ibmvscsis_adapter_info(struct scsi_info *vscsi,
        }
 
        info = dma_alloc_coherent(&vscsi->dma_dev->dev, sizeof(*info), &token,
-                                 GFP_KERNEL);
+                                 GFP_ATOMIC);
        if (!info) {
                dev_err(&vscsi->dev, "bad dma_alloc_coherent %p\n",
                        iue->target);
@@ -1443,7 +1444,7 @@ static long ibmvscsis_adapter_info(struct scsi_info *vscsi,
        info->mad_version = cpu_to_be32(MAD_VERSION_1);
        info->os_type = cpu_to_be32(LINUX);
        memset(&info->port_max_txu[0], 0, sizeof(info->port_max_txu));
-       info->port_max_txu[0] = cpu_to_be32(128 * PAGE_SIZE);
+       info->port_max_txu[0] = cpu_to_be32(MAX_TXU);
 
        dma_wmb();
        rc = h_copy_rdma(sizeof(*info), vscsi->dds.window[LOCAL].liobn,
@@ -1509,7 +1510,7 @@ static int ibmvscsis_cap_mad(struct scsi_info *vscsi, struct iu_entry *iue)
        }
 
        cap = dma_alloc_coherent(&vscsi->dma_dev->dev, olen, &token,
-                                GFP_KERNEL);
+                                GFP_ATOMIC);
        if (!cap) {
                dev_err(&vscsi->dev, "bad dma_alloc_coherent %p\n",
                        iue->target);
@@ -3585,7 +3586,7 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
                               1, 1);
        if (rc) {
                pr_err("srp_transfer_data() failed: %d\n", rc);
-               return -EAGAIN;
+               return -EIO;
        }
        /*
         * We now tell TCM to add this WRITE CDB directly into the TCM storage
@@ -3815,6 +3816,7 @@ static struct configfs_attribute *ibmvscsis_tpg_attrs[] = {
 static const struct target_core_fabric_ops ibmvscsis_ops = {
        .module                         = THIS_MODULE,
        .name                           = "ibmvscsis",
+       .max_data_sg_nents              = MAX_TXU / PAGE_SIZE,
        .get_fabric_name                = ibmvscsis_get_fabric_name,
        .tpg_get_wwn                    = ibmvscsis_get_fabric_wwn,
        .tpg_get_tag                    = ibmvscsis_get_tag,
index 236e4e51d1617243d279d09089d95bb50c0a09d6..7b6bd8ed0d0bd6fc8b056052dffbe60595015cbe 100644 (file)
@@ -3590,12 +3590,14 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
                } else {
                        buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
                        lpfc_els_free_data(phba, buf_ptr1);
+                       elsiocb->context2 = NULL;
                }
        }
 
        if (elsiocb->context3) {
                buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
                lpfc_els_free_bpl(phba, buf_ptr);
+               elsiocb->context3 = NULL;
        }
        lpfc_sli_release_iocbq(phba, elsiocb);
        return 0;
index 4faa7672fc1d80add7e603e7bda066e5b98fd34b..a78a3df68f679659eb9d05b24133312a663ab812 100644 (file)
@@ -5954,18 +5954,25 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
 
  free_vfi_bmask:
        kfree(phba->sli4_hba.vfi_bmask);
+       phba->sli4_hba.vfi_bmask = NULL;
  free_xri_ids:
        kfree(phba->sli4_hba.xri_ids);
+       phba->sli4_hba.xri_ids = NULL;
  free_xri_bmask:
        kfree(phba->sli4_hba.xri_bmask);
+       phba->sli4_hba.xri_bmask = NULL;
  free_vpi_ids:
        kfree(phba->vpi_ids);
+       phba->vpi_ids = NULL;
  free_vpi_bmask:
        kfree(phba->vpi_bmask);
+       phba->vpi_bmask = NULL;
  free_rpi_ids:
        kfree(phba->sli4_hba.rpi_ids);
+       phba->sli4_hba.rpi_ids = NULL;
  free_rpi_bmask:
        kfree(phba->sli4_hba.rpi_bmask);
+       phba->sli4_hba.rpi_bmask = NULL;
  err_exit:
        return rc;
 }
index 394fe1338d0976a42f183e328dfaed02f540560f..dcb33f4fa68720624945f4bdc3f5c932e530c86f 100644 (file)
@@ -393,6 +393,7 @@ struct MPT3SAS_TARGET {
  * @eedp_enable: eedp support enable bit
  * @eedp_type: 0(type_1), 1(type_2), 2(type_3)
  * @eedp_block_length: block size
+ * @ata_command_pending: SATL passthrough outstanding for device
  */
 struct MPT3SAS_DEVICE {
        struct MPT3SAS_TARGET *sas_target;
@@ -404,6 +405,17 @@ struct MPT3SAS_DEVICE {
        u8      ignore_delay_remove;
        /* Iopriority Command Handling */
        u8      ncq_prio_enable;
+       /*
+        * Bug workaround for SATL handling: the mpt2/3sas firmware
+        * doesn't return BUSY or TASK_SET_FULL for subsequent
+        * commands while a SATL pass through is in operation as the
+        * spec requires, it simply does nothing with them until the
+        * pass through completes, causing them possibly to timeout if
+        * the passthrough is a long executing command (like format or
+        * secure erase).  This variable allows us to do the right
+        * thing while a SATL command is pending.
+        */
+       unsigned long ata_command_pending;
 
 };
 
index b5c966e319d315474b94703b93ab0343013dd973..0b5b423b1db0d19a1a1dfb6fc38e168af4559d71 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/interrupt.h>
 #include <linux/aer.h>
 #include <linux/raid_class.h>
@@ -3899,9 +3900,18 @@ _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
        }
 }
 
-static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd)
+static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
 {
-       return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16);
+       struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
+
+       if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
+               return 0;
+
+       if (pending)
+               return test_and_set_bit(0, &priv->ata_command_pending);
+
+       clear_bit(0, &priv->ata_command_pending);
+       return 0;
 }
 
 /**
@@ -3925,9 +3935,7 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
                if (!scmd)
                        continue;
                count++;
-               if (ata_12_16_cmd(scmd))
-                       scsi_internal_device_unblock(scmd->device,
-                                                       SDEV_RUNNING);
+               _scsih_set_satl_pending(scmd, false);
                mpt3sas_base_free_smid(ioc, smid);
                scsi_dma_unmap(scmd);
                if (ioc->pci_error_recovery)
@@ -4063,13 +4071,6 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
        if (ioc->logging_level & MPT_DEBUG_SCSI)
                scsi_print_command(scmd);
 
-       /*
-        * Lock the device for any subsequent command until command is
-        * done.
-        */
-       if (ata_12_16_cmd(scmd))
-               scsi_internal_device_block(scmd->device);
-
        sas_device_priv_data = scmd->device->hostdata;
        if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
                scmd->result = DID_NO_CONNECT << 16;
@@ -4083,6 +4084,19 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
                return 0;
        }
 
+       /*
+        * Bug work around for firmware SATL handling.  The loop
+        * is based on atomic operations and ensures consistency
+        * since we're lockless at this point
+        */
+       do {
+               if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
+                       scmd->result = SAM_STAT_BUSY;
+                       scmd->scsi_done(scmd);
+                       return 0;
+               }
+       } while (_scsih_set_satl_pending(scmd, true));
+
        sas_target_priv_data = sas_device_priv_data->sas_target;
 
        /* invalid device handle */
@@ -4644,14 +4658,14 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        struct MPT3SAS_DEVICE *sas_device_priv_data;
        u32 response_code = 0;
        unsigned long flags;
+       unsigned int sector_sz;
 
        mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
        scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
        if (scmd == NULL)
                return 1;
 
-       if (ata_12_16_cmd(scmd))
-               scsi_internal_device_unblock(scmd->device, SDEV_RUNNING);
+       _scsih_set_satl_pending(scmd, false);
 
        mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
 
@@ -4703,6 +4717,20 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
        }
 
        xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
+
+       /* In case of bogus fw or device, we could end up having
+        * unaligned partial completion. We can force alignment here,
+        * then scsi-ml does not need to handle this misbehavior.
+        */
+       sector_sz = scmd->device->sector_size;
+       if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz &&
+                    xfer_cnt % sector_sz)) {
+               sdev_printk(KERN_INFO, scmd->device,
+                   "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
+                           xfer_cnt, sector_sz);
+               xfer_cnt = round_down(xfer_cnt, sector_sz);
+       }
+
        scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
        if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
                log_info =  le32_to_cpu(mpi_reply->IOCLogInfo);
@@ -8734,6 +8762,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        switch (hba_mpi_version) {
        case MPI2_VERSION:
+               pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
+                       PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
                /* Use mpt2sas driver host template for SAS 2.0 HBA's */
                shost = scsi_host_alloc(&mpt2sas_driver_template,
                  sizeof(struct MPT3SAS_ADAPTER));
index 23ca8a274586746e19204f291a844e6cbc43a07f..21331453db7bd29a0c2bc8cac430b8c8bb60b9c2 100644 (file)
@@ -1,6 +1,6 @@
 config QEDI
        tristate "QLogic QEDI 25/40/100Gb iSCSI Initiator Driver Support"
-       depends on PCI && SCSI
+       depends on PCI && SCSI && UIO
        depends on QED
        select SCSI_ISCSI_ATTRS
        select QED_LL2
index 47eb4d545d13c5f9b80149f162b04756108cd654..f201f40996205c1f522cde8b53c6e0a4d02aaec9 100644 (file)
@@ -243,12 +243,15 @@ qla2x00_sysfs_read_optrom(struct file *filp, struct kobject *kobj,
        struct qla_hw_data *ha = vha->hw;
        ssize_t rval = 0;
 
+       mutex_lock(&ha->optrom_mutex);
+
        if (ha->optrom_state != QLA_SREADING)
-               return 0;
+               goto out;
 
-       mutex_lock(&ha->optrom_mutex);
        rval = memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
            ha->optrom_region_size);
+
+out:
        mutex_unlock(&ha->optrom_mutex);
 
        return rval;
@@ -263,14 +266,19 @@ qla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj,
            struct device, kobj)));
        struct qla_hw_data *ha = vha->hw;
 
-       if (ha->optrom_state != QLA_SWRITING)
+       mutex_lock(&ha->optrom_mutex);
+
+       if (ha->optrom_state != QLA_SWRITING) {
+               mutex_unlock(&ha->optrom_mutex);
                return -EINVAL;
-       if (off > ha->optrom_region_size)
+       }
+       if (off > ha->optrom_region_size) {
+               mutex_unlock(&ha->optrom_mutex);
                return -ERANGE;
+       }
        if (off + count > ha->optrom_region_size)
                count = ha->optrom_region_size - off;
 
-       mutex_lock(&ha->optrom_mutex);
        memcpy(&ha->optrom_buffer[off], buf, count);
        mutex_unlock(&ha->optrom_mutex);
 
@@ -753,7 +761,6 @@ qla2x00_issue_logo(struct file *filp, struct kobject *kobj,
        struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
            struct device, kobj)));
        int type;
-       int rval = 0;
        port_id_t did;
 
        type = simple_strtol(buf, NULL, 10);
@@ -767,7 +774,7 @@ qla2x00_issue_logo(struct file *filp, struct kobject *kobj,
 
        ql_log(ql_log_info, vha, 0x70e4, "%s: %d\n", __func__, type);
 
-       rval = qla24xx_els_dcmd_iocb(vha, ELS_DCMD_LOGO, did);
+       qla24xx_els_dcmd_iocb(vha, ELS_DCMD_LOGO, did);
        return count;
 }
 
index f7df01b76714e09dc919cbb9660b66bed603d6bc..5b1287a63c494b6edf8fcf7e8ec75a17530032db 100644 (file)
@@ -1556,7 +1556,8 @@ typedef struct {
 struct atio {
        uint8_t         entry_type;             /* Entry type. */
        uint8_t         entry_count;            /* Entry count. */
-       uint8_t         data[58];
+       __le16          attr_n_length;
+       uint8_t         data[56];
        uint32_t        signature;
 #define ATIO_PROCESSED 0xDEADDEAD              /* Signature */
 };
@@ -2732,7 +2733,7 @@ struct isp_operations {
 #define QLA_MSIX_FW_MODE(m)    (((m) & (BIT_7|BIT_8|BIT_9)) >> 7)
 #define QLA_MSIX_FW_MODE_1(m)  (QLA_MSIX_FW_MODE(m) == 1)
 
-#define QLA_MSIX_DEFAULT               0x00
+#define QLA_BASE_VECTORS       2 /* default + RSP */
 #define QLA_MSIX_RSP_Q                 0x01
 #define QLA_ATIO_VECTOR                0x02
 #define QLA_MSIX_QPAIR_MULTIQ_RSP_Q    0x03
@@ -2754,7 +2755,6 @@ struct qla_msix_entry {
        uint16_t entry;
        char name[30];
        void *handle;
-       struct irq_affinity_notify irq_notify;
        int cpuid;
 };
 
index 632d5f30386ab0ae529036c292f3c1c8e64162ca..7b6317c8c2e93bef3509c7e3d15fbae080922788 100644 (file)
@@ -1191,7 +1191,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
 
        /* Wait for soft-reset to complete. */
        RD_REG_DWORD(&reg->ctrl_status);
-       for (cnt = 0; cnt < 6000000; cnt++) {
+       for (cnt = 0; cnt < 60; cnt++) {
                barrier();
                if ((RD_REG_DWORD(&reg->ctrl_status) &
                    CSRX_ISP_SOFT_RESET) == 0)
@@ -1234,7 +1234,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
        RD_REG_DWORD(&reg->hccr);
 
        RD_REG_WORD(&reg->mailbox0);
-       for (cnt = 6000000; RD_REG_WORD(&reg->mailbox0) != 0 &&
+       for (cnt = 60; RD_REG_WORD(&reg->mailbox0) != 0 &&
            rval == QLA_SUCCESS; cnt--) {
                barrier();
                if (cnt)
index 5093ca9b02ec52c8e70674f88205941cc0967d9f..a94b0b6bd0306379b4707b29be1347d1ce89e6b8 100644 (file)
@@ -19,10 +19,6 @@ static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
 static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
 static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
        sts_entry_t *);
-static void qla_irq_affinity_notify(struct irq_affinity_notify *,
-    const cpumask_t *);
-static void qla_irq_affinity_release(struct kref *);
-
 
 /**
  * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
@@ -2496,6 +2492,10 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
        if (pkt->entry_status & RF_BUSY)
                res = DID_BUS_BUSY << 16;
 
+       if (pkt->entry_type == NOTIFY_ACK_TYPE &&
+           pkt->handle == QLA_TGT_SKIP_HANDLE)
+               return;
+
        sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
        if (sp) {
                sp->done(ha, sp, res);
@@ -2572,14 +2572,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
        if (!vha->flags.online)
                return;
 
-       if (rsp->msix && rsp->msix->cpuid != smp_processor_id()) {
-               /* if kernel does not notify qla of IRQ's CPU change,
-                * then set it here.
-                */
-               rsp->msix->cpuid = smp_processor_id();
-               ha->tgt.rspq_vector_cpuid = rsp->msix->cpuid;
-       }
-
        while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
                pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
 
@@ -3018,13 +3010,20 @@ static struct qla_init_msix_entry qla82xx_msix_entries[] = {
 static int
 qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
 {
-#define MIN_MSIX_COUNT 2
        int i, ret;
        struct qla_msix_entry *qentry;
        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+       struct irq_affinity desc = {
+               .pre_vectors = QLA_BASE_VECTORS,
+       };
+
+       if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha))
+               desc.pre_vectors++;
+
+       ret = pci_alloc_irq_vectors_affinity(ha->pdev, QLA_BASE_VECTORS,
+                       ha->msix_count, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY,
+                       &desc);
 
-       ret = pci_alloc_irq_vectors(ha->pdev, MIN_MSIX_COUNT, ha->msix_count,
-                                   PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
        if (ret < 0) {
                ql_log(ql_log_fatal, vha, 0x00c7,
                    "MSI-X: Failed to enable support, "
@@ -3069,13 +3068,10 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                qentry->have_irq = 0;
                qentry->in_use = 0;
                qentry->handle = NULL;
-               qentry->irq_notify.notify  = qla_irq_affinity_notify;
-               qentry->irq_notify.release = qla_irq_affinity_release;
-               qentry->cpuid = -1;
        }
 
        /* Enable MSI-X vectors for the base queue */
-       for (i = 0; i < (QLA_MSIX_RSP_Q + 1); i++) {
+       for (i = 0; i < QLA_BASE_VECTORS; i++) {
                qentry = &ha->msix_entries[i];
                qentry->handle = rsp;
                rsp->msix = qentry;
@@ -3093,18 +3089,6 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                        goto msix_register_fail;
                qentry->have_irq = 1;
                qentry->in_use = 1;
-
-               /* Register for CPU affinity notification. */
-               irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
-
-               /* Schedule work (ie. trigger a notification) to read cpu
-                * mask for this specific irq.
-                * kref_get is required because
-               * irq_affinity_notify() will do
-               * kref_put().
-               */
-               kref_get(&qentry->irq_notify.kref);
-               schedule_work(&qentry->irq_notify.work);
        }
 
        /*
@@ -3258,7 +3242,7 @@ qla2x00_free_irqs(scsi_qla_host_t *vha)
         * from a probe failure context.
         */
        if (!ha->rsp_q_map || !ha->rsp_q_map[0])
-               return;
+               goto free_irqs;
        rsp = ha->rsp_q_map[0];
 
        if (ha->flags.msix_enabled) {
@@ -3278,6 +3262,7 @@ qla2x00_free_irqs(scsi_qla_host_t *vha)
                free_irq(pci_irq_vector(ha->pdev, 0), rsp);
        }
 
+free_irqs:
        pci_free_irq_vectors(ha->pdev);
 }
 
@@ -3301,49 +3286,3 @@ int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
        msix->handle = qpair;
        return ret;
 }
-
-
-/* irq_set_affinity/irqbalance will trigger notification of cpu mask update */
-static void qla_irq_affinity_notify(struct irq_affinity_notify *notify,
-       const cpumask_t *mask)
-{
-       struct qla_msix_entry *e =
-               container_of(notify, struct qla_msix_entry, irq_notify);
-       struct qla_hw_data *ha;
-       struct scsi_qla_host *base_vha;
-       struct rsp_que *rsp = e->handle;
-
-       /* user is recommended to set mask to just 1 cpu */
-       e->cpuid = cpumask_first(mask);
-
-       ha = rsp->hw;
-       base_vha = pci_get_drvdata(ha->pdev);
-
-       ql_dbg(ql_dbg_init, base_vha, 0xffff,
-           "%s: host %ld : vector %d cpu %d \n", __func__,
-           base_vha->host_no, e->vector, e->cpuid);
-
-       if (e->have_irq) {
-               if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) &&
-                   (e->entry == QLA83XX_RSPQ_MSIX_ENTRY_NUMBER)) {
-                       ha->tgt.rspq_vector_cpuid = e->cpuid;
-                       ql_dbg(ql_dbg_init, base_vha, 0xffff,
-                           "%s: host%ld: rspq vector %d cpu %d  runtime change\n",
-                           __func__, base_vha->host_no, e->vector, e->cpuid);
-               }
-       }
-}
-
-static void qla_irq_affinity_release(struct kref *ref)
-{
-       struct irq_affinity_notify *notify =
-               container_of(ref, struct irq_affinity_notify, kref);
-       struct qla_msix_entry *e =
-               container_of(notify, struct qla_msix_entry, irq_notify);
-       struct rsp_que *rsp = e->handle;
-       struct scsi_qla_host *base_vha = pci_get_drvdata(rsp->hw->pdev);
-
-       ql_dbg(ql_dbg_init, base_vha, 0xffff,
-               "%s: host%ld: vector %d cpu %d\n", __func__,
-           base_vha->host_no, e->vector, e->cpuid);
-}
index 2819ceb96041e5b97b234f115c9b35d4b4251ffe..67f64db390b0cd43e2ff6166d30903712ef80938 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/delay.h>
 #include <linux/gfp.h>
 
-struct rom_cmd {
+static struct rom_cmd {
        uint16_t cmd;
 } rom_cmds[] = {
        { MBC_LOAD_RAM },
@@ -101,12 +101,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                return QLA_FUNCTION_TIMEOUT;
        }
 
-        /* if PCI error, then avoid mbx processing.*/
-        if (test_bit(PCI_ERR, &base_vha->dpc_flags)) {
+       /* if PCI error, then avoid mbx processing.*/
+       if (test_bit(PCI_ERR, &base_vha->dpc_flags)) {
                ql_log(ql_log_warn, vha, 0x1191,
                    "PCI error, exiting.\n");
                return QLA_FUNCTION_TIMEOUT;
-        }
+       }
 
        reg = ha->iobase;
        io_lock_on = base_vha->flags.init_done;
@@ -323,20 +323,33 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
                }
        } else {
 
-               uint16_t mb0;
-               uint32_t ictrl;
+               uint16_t mb[8];
+               uint32_t ictrl, host_status, hccr;
                uint16_t        w;
 
                if (IS_FWI2_CAPABLE(ha)) {
-                       mb0 = RD_REG_WORD(&reg->isp24.mailbox0);
+                       mb[0] = RD_REG_WORD(&reg->isp24.mailbox0);
+                       mb[1] = RD_REG_WORD(&reg->isp24.mailbox1);
+                       mb[2] = RD_REG_WORD(&reg->isp24.mailbox2);
+                       mb[3] = RD_REG_WORD(&reg->isp24.mailbox3);
+                       mb[7] = RD_REG_WORD(&reg->isp24.mailbox7);
                        ictrl = RD_REG_DWORD(&reg->isp24.ictrl);
+                       host_status = RD_REG_DWORD(&reg->isp24.host_status);
+                       hccr = RD_REG_DWORD(&reg->isp24.hccr);
+
+                       ql_log(ql_log_warn, vha, 0x1119,
+                           "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
+                           "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n",
+                           command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
+                           mb[7], host_status, hccr);
+
                } else {
-                       mb0 = RD_MAILBOX_REG(ha, &reg->isp, 0);
+                       mb[0] = RD_MAILBOX_REG(ha, &reg->isp, 0);
                        ictrl = RD_REG_WORD(&reg->isp.ictrl);
+                       ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
+                           "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
+                           "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
                }
-               ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
-                   "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
-                   "mb[0]=0x%x\n", command, ictrl, jiffies, mb0);
                ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
 
                /* Capture FW dump only, if PCI device active */
@@ -684,7 +697,6 @@ qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
        mbx_cmd_t       mc;
        mbx_cmd_t       *mcp = &mc;
        struct qla_hw_data *ha = vha->hw;
-       int configured_count;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111a,
            "Entered %s.\n", __func__);
@@ -707,7 +719,6 @@ qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
                /*EMPTY*/
                ql_dbg(ql_dbg_mbx, vha, 0x111b, "Failed=%x.\n", rval);
        } else {
-               configured_count = mcp->mb[11];
                ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
                    "Done %s.\n", __func__);
        }
index 54380b434b304eddde918a94ee833e18be6a35f6..0a1723cc08cfc4cbc626f988e58601eff70db5ff 100644 (file)
@@ -42,6 +42,11 @@ static int qla82xx_crb_table_initialized;
        (crb_addr_xform[QLA82XX_HW_PX_MAP_CRB_##name] = \
        QLA82XX_HW_CRB_HUB_AGT_ADR_##name << 20)
 
+const int MD_MIU_TEST_AGT_RDDATA[] = {
+       0x410000A8, 0x410000AC,
+       0x410000B8, 0x410000BC
+};
+
 static void qla82xx_crb_addr_transform_setup(void)
 {
        qla82xx_crb_addr_transform(XDMA);
index 6201dce3553bf951b5b1f770842e289ced553e95..77624eac95a4741a4e475a29a012f1217a75a72f 100644 (file)
@@ -1176,8 +1176,7 @@ struct qla82xx_md_entry_queue {
 #define MD_MIU_TEST_AGT_ADDR_LO                0x41000094
 #define MD_MIU_TEST_AGT_ADDR_HI                0x41000098
 
-static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC,
-       0x410000B8, 0x410000BC };
+extern const int MD_MIU_TEST_AGT_RDDATA[4];
 
 #define CRB_NIU_XG_PAUSE_CTL_P0        0x1
 #define CRB_NIU_XG_PAUSE_CTL_P1        0x8
index 007192d7bad85fae9711198b15f31924da9f0e3e..dc1ec9b610273956c6d7848e23882961326ecadf 100644 (file)
 
 #define TIMEOUT_100_MS 100
 
+static const uint32_t qla8044_reg_tbl[] = {
+       QLA8044_PEG_HALT_STATUS1,
+       QLA8044_PEG_HALT_STATUS2,
+       QLA8044_PEG_ALIVE_COUNTER,
+       QLA8044_CRB_DRV_ACTIVE,
+       QLA8044_CRB_DEV_STATE,
+       QLA8044_CRB_DRV_STATE,
+       QLA8044_CRB_DRV_SCRATCH,
+       QLA8044_CRB_DEV_PART_INFO1,
+       QLA8044_CRB_IDC_VER_MAJOR,
+       QLA8044_FW_VER_MAJOR,
+       QLA8044_FW_VER_MINOR,
+       QLA8044_FW_VER_SUB,
+       QLA8044_CMDPEG_STATE,
+       QLA8044_ASIC_TEMP,
+};
+
 /* 8044 Flash Read/Write functions */
 uint32_t
 qla8044_rd_reg(struct qla_hw_data *ha, ulong addr)
index 02fe3c4cdf5577f275d3a898e7d07d6e3e89592c..83c1b7e17c80f1affa2a5857118f44a6549d832a 100644 (file)
@@ -535,23 +535,6 @@ enum qla_regs {
 #define CRB_CMDPEG_CHECK_RETRY_COUNT    60
 #define CRB_CMDPEG_CHECK_DELAY          500
 
-static const uint32_t qla8044_reg_tbl[] = {
-       QLA8044_PEG_HALT_STATUS1,
-       QLA8044_PEG_HALT_STATUS2,
-       QLA8044_PEG_ALIVE_COUNTER,
-       QLA8044_CRB_DRV_ACTIVE,
-       QLA8044_CRB_DEV_STATE,
-       QLA8044_CRB_DRV_STATE,
-       QLA8044_CRB_DRV_SCRATCH,
-       QLA8044_CRB_DEV_PART_INFO1,
-       QLA8044_CRB_IDC_VER_MAJOR,
-       QLA8044_FW_VER_MAJOR,
-       QLA8044_FW_VER_MINOR,
-       QLA8044_FW_VER_SUB,
-       QLA8044_CMDPEG_STATE,
-       QLA8044_ASIC_TEMP,
-};
-
 /* MiniDump Structures */
 
 /* Driver_code is for driver to write some info about the entry
index 8521cfe302e9e3e72c7aaf1a4753ca75f953b972..40660461a4b5c3e56e61b124385ee044547a4741 100644 (file)
@@ -466,7 +466,7 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
                        continue;
 
                rsp = ha->rsp_q_map[cnt];
-               clear_bit(cnt, ha->req_qid_map);
+               clear_bit(cnt, ha->rsp_qid_map);
                ha->rsp_q_map[cnt] =  NULL;
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
                qla2x00_free_rsp_que(ha, rsp);
@@ -1616,7 +1616,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
                                /* Don't abort commands in adapter during EEH
                                 * recovery as it's not accessible/responding.
                                 */
-                               if (!ha->flags.eeh_busy) {
+                               if (GET_CMD_SP(sp) && !ha->flags.eeh_busy) {
                                        /* Get a reference to the sp and drop the lock.
                                         * The reference ensures this sp->done() call
                                         * - and not the call in qla2xxx_eh_abort() -
@@ -3662,7 +3662,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
                                sizeof(struct ct6_dsd), 0,
                                SLAB_HWCACHE_ALIGN, NULL);
                        if (!ctx_cachep)
-                               goto fail_free_gid_list;
+                               goto fail_free_srb_mempool;
                }
                ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ,
                        ctx_cachep);
@@ -3815,7 +3815,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
        ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
            GFP_KERNEL);
        if (!ha->loop_id_map)
-               goto fail_async_pd;
+               goto fail_loop_id_map;
        else {
                qla2x00_set_reserved_loop_ids(ha);
                ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123,
@@ -3824,6 +3824,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 
        return 0;
 
+fail_loop_id_map:
+       dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
 fail_async_pd:
        dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
 fail_ex_init_cb:
@@ -3851,6 +3853,10 @@ fail_free_ms_iocb:
        dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
        ha->ms_iocb = NULL;
        ha->ms_iocb_dma = 0;
+
+       if (ha->sns_cmd)
+               dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
+                   ha->sns_cmd, ha->sns_cmd_dma);
 fail_dma_pool:
        if (IS_QLA82XX(ha) || ql2xenabledif) {
                dma_pool_destroy(ha->fcp_cmnd_dma_pool);
@@ -3868,10 +3874,12 @@ fail_free_nvram:
        kfree(ha->nvram);
        ha->nvram = NULL;
 fail_free_ctx_mempool:
-       mempool_destroy(ha->ctx_mempool);
+       if (ha->ctx_mempool)
+               mempool_destroy(ha->ctx_mempool);
        ha->ctx_mempool = NULL;
 fail_free_srb_mempool:
-       mempool_destroy(ha->srb_mempool);
+       if (ha->srb_mempool)
+               mempool_destroy(ha->srb_mempool);
        ha->srb_mempool = NULL;
 fail_free_gid_list:
        dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
index bff9689f5ca94f56be0a9739af6bf769885f73bf..e4fda84b959eca2d52aa009c353cbe7f5ffc94bd 100644 (file)
@@ -668,11 +668,9 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
 {
        struct qla_hw_data *ha = vha->hw;
        struct qla_tgt_sess *sess = NULL;
-       uint32_t unpacked_lun, lun = 0;
        uint16_t loop_id;
        int res = 0;
        struct imm_ntfy_from_isp *n = (struct imm_ntfy_from_isp *)iocb;
-       struct atio_from_isp *a = (struct atio_from_isp *)iocb;
        unsigned long flags;
 
        loop_id = le16_to_cpu(n->u.isp24.nport_handle);
@@ -725,11 +723,7 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
            "loop_id %d)\n", vha->host_no, sess, sess->port_name,
            mcmd, loop_id);
 
-       lun = a->u.isp24.fcp_cmnd.lun;
-       unpacked_lun = scsilun_to_int((struct scsi_lun *)&lun);
-
-       return qlt_issue_task_mgmt(sess, unpacked_lun, mcmd,
-           iocb, QLA24XX_MGMT_SEND_NACK);
+       return qlt_issue_task_mgmt(sess, 0, mcmd, iocb, QLA24XX_MGMT_SEND_NACK);
 }
 
 /* ha->tgt.sess_lock supposed to be held on entry */
@@ -3067,7 +3061,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
 
        pkt->entry_type = NOTIFY_ACK_TYPE;
        pkt->entry_count = 1;
-       pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+       pkt->handle = QLA_TGT_SKIP_HANDLE;
 
        nack = (struct nack_to_isp *)pkt;
        nack->ox_id = ntfy->ox_id;
@@ -3110,6 +3104,9 @@ static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
 #if 0  /* Todo  */
                if (rc == -ENOMEM)
                        qlt_alloc_qfull_cmd(vha, imm, 0, 0);
+#else
+               if (rc) {
+               }
 #endif
                goto done;
        }
@@ -6457,12 +6454,29 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
        if (!vha->flags.online)
                return;
 
-       while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) {
+       while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
+           fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr)) {
                pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
                cnt = pkt->u.raw.entry_count;
 
-               qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
-                   ha_locked);
+               if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
+                       /*
+                        * This packet is corrupted. The header + payload
+                        * can not be trusted. There is no point in passing
+                        * it further up.
+                        */
+                       ql_log(ql_log_warn, vha, 0xffff,
+                           "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
+                           pkt->u.isp24.fcp_hdr.s_id,
+                           be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
+                           le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
+
+                       adjust_corrupted_atio(pkt);
+                       qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
+               } else {
+                       qlt_24xx_atio_pkt_all_vps(vha,
+                           (struct atio_from_isp *)pkt, ha_locked);
+               }
 
                for (i = 0; i < cnt; i++) {
                        ha->tgt.atio_ring_index++;
@@ -6545,6 +6559,13 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
 
                /* Disable Full Login after LIP */
                nv->host_p &= cpu_to_le32(~BIT_10);
+
+               /*
+                * clear BIT 15 explicitly as we have seen at least
+                * a couple of instances where this was set and this
+                * was causing the firmware to not be initialized.
+                */
+               nv->firmware_options_1 &= cpu_to_le32(~BIT_15);
                /* Enable target PRLI control */
                nv->firmware_options_2 |= cpu_to_le32(BIT_14);
        } else {
@@ -6560,9 +6581,6 @@ qlt_24xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_24xx *nv)
                return;
        }
 
-       /* out-of-order frames reassembly */
-       nv->firmware_options_3 |= BIT_6|BIT_9;
-
        if (ha->tgt.enable_class_2) {
                if (vha->flags.init_done)
                        fc_host_supported_classes(vha->host) =
@@ -6629,11 +6647,17 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
                /* Disable ini mode, if requested */
                if (!qla_ini_mode_enabled(vha))
                        nv->firmware_options_1 |= cpu_to_le32(BIT_5);
-
                /* Disable Full Login after LIP */
                nv->firmware_options_1 &= cpu_to_le32(~BIT_13);
                /* Enable initial LIP */
                nv->firmware_options_1 &= cpu_to_le32(~BIT_9);
+               /*
+                * clear BIT 15 explicitly as we have seen at
+                * least a couple of instances where this was set
+                * and this was causing the firmware to not be
+                * initialized.
+                */
+               nv->firmware_options_1 &= cpu_to_le32(~BIT_15);
                if (ql2xtgt_tape_enable)
                        /* Enable FC tape support */
                        nv->firmware_options_2 |= cpu_to_le32(BIT_12);
@@ -6658,9 +6682,6 @@ qlt_81xx_config_nvram_stage1(struct scsi_qla_host *vha, struct nvram_81xx *nv)
                return;
        }
 
-       /* out-of-order frames reassembly */
-       nv->firmware_options_3 |= BIT_6|BIT_9;
-
        if (ha->tgt.enable_class_2) {
                if (vha->flags.init_done)
                        fc_host_supported_classes(vha->host) =
index f26c5f60eedd27f6dcd36a835266f5924f32a6fd..0824a8164a2494361ef12892851f020ab40de6f4 100644 (file)
@@ -427,13 +427,33 @@ struct atio_from_isp {
                struct {
                        uint8_t  entry_type;    /* Entry type. */
                        uint8_t  entry_count;   /* Entry count. */
-                       uint8_t  data[58];
+                       __le16   attr_n_length;
+#define FCP_CMD_LENGTH_MASK 0x0fff
+#define FCP_CMD_LENGTH_MIN  0x38
+                       uint8_t  data[56];
                        uint32_t signature;
 #define ATIO_PROCESSED 0xDEADDEAD              /* Signature */
                } raw;
        } u;
 } __packed;
 
+static inline int fcpcmd_is_corrupted(struct atio *atio)
+{
+       if (atio->entry_type == ATIO_TYPE7 &&
+           (le16_to_cpu(atio->attr_n_length & FCP_CMD_LENGTH_MASK) <
+           FCP_CMD_LENGTH_MIN))
+               return 1;
+       else
+               return 0;
+}
+
+/* adjust corrupted atio so we won't trip over the same entry again. */
+static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
+{
+       atio->u.raw.attr_n_length = cpu_to_le16(FCP_CMD_LENGTH_MIN);
+       atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
+}
+
 #define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
 
 /*
index 36935c9ed669513195a01ba26fd1e302773b593f..8a58ef3adab4425ba69a992dd2f51bd9357f44c9 100644 (file)
@@ -433,6 +433,18 @@ qla27xx_fwdt_entry_t263(struct scsi_qla_host *vha,
                                count++;
                        }
                }
+       } else if (QLA_TGT_MODE_ENABLED() &&
+           ent->t263.queue_type == T263_QUEUE_TYPE_ATIO) {
+               struct qla_hw_data *ha = vha->hw;
+               struct atio *atr = ha->tgt.atio_ring;
+
+               if (atr || !buf) {
+                       length = ha->tgt.atio_q_length;
+                       qla27xx_insert16(0, buf, len);
+                       qla27xx_insert16(length, buf, len);
+                       qla27xx_insertbuf(atr, length * sizeof(*atr), buf, len);
+                       count++;
+               }
        } else {
                ql_dbg(ql_dbg_misc, vha, 0xd026,
                    "%s: unknown queue %x\n", __func__, ent->t263.queue_type);
@@ -676,6 +688,18 @@ qla27xx_fwdt_entry_t274(struct scsi_qla_host *vha,
                                count++;
                        }
                }
+       } else if (QLA_TGT_MODE_ENABLED() &&
+           ent->t274.queue_type == T274_QUEUE_TYPE_ATIO_SHAD) {
+               struct qla_hw_data *ha = vha->hw;
+               struct atio *atr = ha->tgt.atio_ring_ptr;
+
+               if (atr || !buf) {
+                       qla27xx_insert16(0, buf, len);
+                       qla27xx_insert16(1, buf, len);
+                       qla27xx_insert32(ha->tgt.atio_q_in ?
+                           readl(ha->tgt.atio_q_in) : 0, buf, len);
+                       count++;
+               }
        } else {
                ql_dbg(ql_dbg_misc, vha, 0xd02f,
                    "%s: unknown queue %x\n", __func__, ent->t274.queue_type);
index 6643f6fc7795bcc09fc0c3ffd79a85b907ce6d94..d925910be761dfcdc61c5c3e97bc98c4372a6cb7 100644 (file)
@@ -1800,7 +1800,7 @@ static ssize_t tcm_qla2xxx_wwn_version_show(struct config_item *item,
 {
        return sprintf(page,
            "TCM QLOGIC QLA2XXX NPIV capable fabric module %s on %s/%s on "
-           UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname,
+           UTS_RELEASE"\n", QLA2XXX_VERSION, utsname()->sysname,
            utsname()->machine);
 }
 
@@ -1906,7 +1906,7 @@ static int tcm_qla2xxx_register_configfs(void)
        int ret;
 
        pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on "
-           UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname,
+           UTS_RELEASE"\n", QLA2XXX_VERSION, utsname()->sysname,
            utsname()->machine);
 
        ret = target_register_template(&tcm_qla2xxx_ops);
index 37e026a4823d6fdeb1048dd7f419f7ca253417c0..cf8430be183b6b529d33382386c54c2acbcd828a 100644 (file)
@@ -1,7 +1,6 @@
 #include <target/target_core_base.h>
 #include <linux/btree.h>
 
-#define TCM_QLA2XXX_VERSION    "v0.1"
 /* length of ASCII WWPNs including pad */
 #define TCM_QLA2XXX_NAMELEN    32
 /*
index c35b6de4ca643297d1908341421c865c2cb93e84..78db07fd8055df135dcc5488a06c443fc4b51ac8 100644 (file)
@@ -1018,7 +1018,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb)
        count = blk_rq_map_sg(req->q, req, sdb->table.sgl);
        BUG_ON(count > sdb->table.nents);
        sdb->table.nents = count;
-       sdb->length = blk_rq_bytes(req);
+       sdb->length = blk_rq_payload_bytes(req);
        return BLKPREP_OK;
 }
 
@@ -1040,7 +1040,8 @@ int scsi_init_io(struct scsi_cmnd *cmd)
        bool is_mq = (rq->mq_ctx != NULL);
        int error;
 
-       BUG_ON(!blk_rq_nr_phys_segments(rq));
+       if (WARN_ON_ONCE(!blk_rq_nr_phys_segments(rq)))
+               return -EINVAL;
 
        error = scsi_init_sgtable(rq, &cmd->sdb);
        if (error)
@@ -2893,7 +2894,7 @@ scsi_internal_device_block(struct scsi_device *sdev)
         * request queue. 
         */
        if (q->mq_ops) {
-               blk_mq_stop_hw_queues(q);
+               blk_mq_quiesce_queue(q);
        } else {
                spin_lock_irqsave(q->queue_lock, flags);
                blk_stop_queue(q);
index b1933041da39d414f9c6e127052ba8cbaa25e65e..1f5d92a25a49dd0f928c194c5d64372fb2b071f6 100644 (file)
@@ -871,11 +871,11 @@ static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
        cmd->allowed = SD_MAX_RETRIES;
 
        /*
-        * For WRITE_SAME the data transferred in the DATA IN buffer is
+        * For WRITE SAME the data transferred via the DATA OUT buffer is
         * different from the amount of data actually written to the target.
         *
-        * We set up __data_len to the amount of data transferred from the
-        * DATA IN buffer so that blk_rq_map_sg set up the proper S/G list
+        * We set up __data_len to the amount of data transferred via the
+        * DATA OUT buffer so that blk_rq_map_sg sets up the proper S/G list
         * to transfer a single sector of data first, but then reset it to
         * the amount of data to be written right after so that the I/O path
         * knows how much to actually write.
@@ -2600,7 +2600,8 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
                if (sdp->broken_fua) {
                        sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
                        sdkp->DPOFUA = 0;
-               } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+               } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw &&
+                          !sdkp->device->use_16_for_rw) {
                        sd_first_printk(KERN_NOTICE, sdkp,
                                  "Uses READ/WRITE(6), disabling FUA\n");
                        sdkp->DPOFUA = 0;
@@ -2783,13 +2784,21 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
                queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
        }
 
-       sdkp->zoned = (buffer[8] >> 4) & 3;
-       if (sdkp->zoned == 1)
-               q->limits.zoned = BLK_ZONED_HA;
-       else if (sdkp->device->type == TYPE_ZBC)
+       if (sdkp->device->type == TYPE_ZBC) {
+               /* Host-managed */
                q->limits.zoned = BLK_ZONED_HM;
-       else
-               q->limits.zoned = BLK_ZONED_NONE;
+       } else {
+               sdkp->zoned = (buffer[8] >> 4) & 3;
+               if (sdkp->zoned == 1)
+                       /* Host-aware */
+                       q->limits.zoned = BLK_ZONED_HA;
+               else
+                       /*
+                        * Treat drive-managed devices as
+                        * regular block devices.
+                        */
+                       q->limits.zoned = BLK_ZONED_NONE;
+       }
        if (blk_queue_is_zoned(q) && sdkp->first_scan)
                sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
                      q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware");
index 8c9a35c91705e42fcbc07e3721d0522f96d496dc..50adabbb5808902aea6abfd64a39c183678a6a6f 100644 (file)
@@ -587,7 +587,7 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
 
        ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0);
 
-       if (scsi_is_sas_rphy(&sdev->sdev_gendev))
+       if (scsi_is_sas_rphy(sdev->sdev_target->dev.parent))
                efd.addr = sas_get_address(sdev);
 
        if (efd.addr) {
index dbe5b4b95df0d9d317dbdc2261914e4d8771991f..121de0aaa6adaa1e9a71376893072c1f69ddc228 100644 (file)
@@ -1753,6 +1753,10 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
                        return res;
 
                iov_iter_truncate(&i, hp->dxfer_len);
+               if (!iov_iter_count(&i)) {
+                       kfree(iov);
+                       return -EINVAL;
+               }
 
                res = blk_rq_map_user_iov(q, rq, md, &i, GFP_ATOMIC);
                kfree(iov);
index 396b32dca07464dddbf575a37fd13ad1e3f92579..7cf70aaec0ba32ce9c506a84f21fb9be39bf9e64 100644 (file)
@@ -591,6 +591,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!pool) {
                SNIC_HOST_ERR(shost, "dflt sgl pool creation failed\n");
 
+               ret = -ENOMEM;
                goto err_free_res;
        }
 
@@ -601,6 +602,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!pool) {
                SNIC_HOST_ERR(shost, "max sgl pool creation failed\n");
 
+               ret = -ENOMEM;
                goto err_free_dflt_sgl_pool;
        }
 
@@ -611,6 +613,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!pool) {
                SNIC_HOST_ERR(shost, "snic tmreq info pool creation failed.\n");
 
+               ret = -ENOMEM;
                goto err_free_max_sgl_pool;
        }
 
index ec91bd07f00a307337283cbea6f72c6e370a0170..c680d76413116c00b80193f5e7db9de2e13441b1 100644 (file)
@@ -534,7 +534,9 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
 {
        struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
        struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc);
+       unsigned long flags;
        int req_size;
+       int ret;
 
        BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
 
@@ -562,8 +564,15 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
                req_size = sizeof(cmd->req.cmd);
        }
 
-       if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0)
+       ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd));
+       if (ret == -EIO) {
+               cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
+               spin_lock_irqsave(&req_vq->vq_lock, flags);
+               virtscsi_complete_cmd(vscsi, cmd);
+               spin_unlock_irqrestore(&req_vq->vq_lock, flags);
+       } else if (ret != 0) {
                return SCSI_MLQUEUE_HOST_BUSY;
+       }
        return 0;
 }
 
index 8823cc81ae45345bd0d632436eb4ce387d456e0b..5bb376009d98b78bd0dbf6da3e8f0853f9e6528e 100644 (file)
@@ -459,6 +459,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
 
        if (IS_ERR(task)) {
                dev_err(dev, "can't create rproc_boot thread\n");
+               ret = PTR_ERR(task);
                goto err_put_rproc;
        }
 
index ec4aa252d6e8c1c761a47246851ad2645382516e..2922a9908302d84781f63d1b091ca6e4ddb2eba8 100644 (file)
@@ -378,6 +378,7 @@ config SPI_FSL_SPI
 config SPI_FSL_DSPI
        tristate "Freescale DSPI controller"
        select REGMAP_MMIO
+       depends on HAS_DMA
        depends on SOC_VF610 || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST
        help
          This enables support for the Freescale DSPI controller in master
index e89da0af45d2518ef26670f7bbd50b875692872b..0314c6b9e04415b0cb792d8e9a4048a6311fd97d 100644 (file)
@@ -800,7 +800,7 @@ static int a3700_spi_probe(struct platform_device *pdev)
        struct spi_master *master;
        struct a3700_spi *spi;
        u32 num_cs = 0;
-       int ret = 0;
+       int irq, ret = 0;
 
        master = spi_alloc_master(dev, sizeof(*spi));
        if (!master) {
@@ -825,7 +825,7 @@ static int a3700_spi_probe(struct platform_device *pdev)
        master->unprepare_message = a3700_spi_unprepare_message;
        master->set_cs = a3700_spi_set_cs;
        master->flags = SPI_MASTER_HALF_DUPLEX;
-       master->mode_bits |= (SPI_RX_DUAL | SPI_RX_DUAL |
+       master->mode_bits |= (SPI_RX_DUAL | SPI_TX_DUAL |
                              SPI_RX_QUAD | SPI_TX_QUAD);
 
        platform_set_drvdata(pdev, master);
@@ -846,12 +846,13 @@ static int a3700_spi_probe(struct platform_device *pdev)
                goto error;
        }
 
-       spi->irq = platform_get_irq(pdev, 0);
-       if (spi->irq < 0) {
-               dev_err(dev, "could not get irq: %d\n", spi->irq);
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "could not get irq: %d\n", irq);
                ret = -ENXIO;
                goto error;
        }
+       spi->irq = irq;
 
        init_completion(&spi->done);
 
index 319225d7e761b0066a062b017c6e6f2104447859..6ab4c770022882eacc338a31b345c0d80bc1b541 100644 (file)
@@ -494,7 +494,8 @@ static int spi_engine_probe(struct platform_device *pdev)
                        SPI_ENGINE_VERSION_MAJOR(version),
                        SPI_ENGINE_VERSION_MINOR(version),
                        SPI_ENGINE_VERSION_PATCH(version));
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_put_master;
        }
 
        spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
index d36c11b73a35ca656ab04e9c5ef0492f96950b32..02fb96797ac8b9ec52f41c8a13f93b290db0fc1c 100644 (file)
@@ -646,7 +646,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
                        buf = t->rx_buf;
                t->rx_dma = dma_map_single(&spi->dev, buf,
                                t->len, DMA_FROM_DEVICE);
-               if (!t->rx_dma) {
+               if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
                        ret = -EFAULT;
                        goto err_rx_map;
                }
@@ -660,7 +660,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
                        buf = (void *)t->tx_buf;
                t->tx_dma = dma_map_single(&spi->dev, buf,
                                t->len, DMA_TO_DEVICE);
-               if (!t->tx_dma) {
+               if (dma_mapping_error(&spi->dev, t->tx_dma)) {
                        ret = -EFAULT;
                        goto err_tx_map;
                }
index e31971f91475b1b3d9f1b2011e0b6e4e2ae4697b..837cb8d0bac6c9a1bd9f866192cd96950b13a68b 100644 (file)
@@ -274,11 +274,11 @@ static int mid_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
 static void mid_spi_dma_stop(struct dw_spi *dws)
 {
        if (test_bit(TX_BUSY, &dws->dma_chan_busy)) {
-               dmaengine_terminate_all(dws->txchan);
+               dmaengine_terminate_sync(dws->txchan);
                clear_bit(TX_BUSY, &dws->dma_chan_busy);
        }
        if (test_bit(RX_BUSY, &dws->dma_chan_busy)) {
-               dmaengine_terminate_all(dws->rxchan);
+               dmaengine_terminate_sync(dws->rxchan);
                clear_bit(RX_BUSY, &dws->dma_chan_busy);
        }
 }
index b715a26a91484fb695088459d9249b367b334fe1..054012f875671b995141f8c549021389f21f454f 100644 (file)
@@ -107,7 +107,10 @@ static const struct file_operations dw_spi_regs_ops = {
 
 static int dw_spi_debugfs_init(struct dw_spi *dws)
 {
-       dws->debugfs = debugfs_create_dir("dw_spi", NULL);
+       char name[128];
+
+       snprintf(name, 128, "dw_spi-%s", dev_name(&dws->master->dev));
+       dws->debugfs = debugfs_create_dir(name, NULL);
        if (!dws->debugfs)
                return -ENOMEM;
 
index dd7b5b47291d551890da8e8dfc324ca74895d66b..d6239fa718be9e251f577b9d9dd792a0e5c5ead5 100644 (file)
@@ -1690,6 +1690,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
                pxa2xx_spi_write(drv_data, SSCR1, tmp);
                tmp = SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8);
                pxa2xx_spi_write(drv_data, SSCR0, tmp);
+               break;
        default:
                tmp = SSCR1_RxTresh(RX_THRESH_DFLT) |
                      SSCR1_TxTresh(TX_THRESH_DFLT);
index 0012ad02e5696d35b547a3a698682f51a2d02819..1f00eeb0b5a3fb93ae838978dbf7815d94897378 100644 (file)
@@ -973,14 +973,16 @@ static const struct sh_msiof_chipdata r8a779x_data = {
 };
 
 static const struct of_device_id sh_msiof_match[] = {
-       { .compatible = "renesas,sh-msiof",        .data = &sh_data },
        { .compatible = "renesas,sh-mobile-msiof", .data = &sh_data },
        { .compatible = "renesas,msiof-r8a7790",   .data = &r8a779x_data },
        { .compatible = "renesas,msiof-r8a7791",   .data = &r8a779x_data },
        { .compatible = "renesas,msiof-r8a7792",   .data = &r8a779x_data },
        { .compatible = "renesas,msiof-r8a7793",   .data = &r8a779x_data },
        { .compatible = "renesas,msiof-r8a7794",   .data = &r8a779x_data },
+       { .compatible = "renesas,rcar-gen2-msiof", .data = &r8a779x_data },
        { .compatible = "renesas,msiof-r8a7796",   .data = &r8a779x_data },
+       { .compatible = "renesas,rcar-gen3-msiof", .data = &r8a779x_data },
+       { .compatible = "renesas,sh-msiof",        .data = &sh_data }, /* Deprecated */
        {},
 };
 MODULE_DEVICE_TABLE(of, sh_msiof_match);
index 113f3d6c4b3a6cdeda3fce3abe729fbc927fd9d9..27f75b17679b8f19a5f6100a769dd7b1b0f77455 100644 (file)
@@ -45,12 +45,18 @@ u32 gb_timesync_platform_get_clock_rate(void)
 
 int gb_timesync_platform_lock_bus(struct gb_timesync_svc *pdata)
 {
+       if (!arche_platform_change_state_cb)
+               return 0;
+
        return arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_TIME_SYNC,
                                              pdata);
 }
 
 void gb_timesync_platform_unlock_bus(void)
 {
+       if (!arche_platform_change_state_cb)
+               return;
+
        arche_platform_change_state_cb(ARCHE_PLATFORM_STATE_ACTIVE, NULL);
 }
 
index ee01f20d8b1110bec42a3aebf82ef69b79e63d80..9afa6bec3e6f44e22f1bf4fbcbd76e4476348fb3 100644 (file)
@@ -390,15 +390,13 @@ static int ll_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
                result = VM_FAULT_LOCKED;
                break;
        case -ENODATA:
+       case -EAGAIN:
        case -EFAULT:
                result = VM_FAULT_NOPAGE;
                break;
        case -ENOMEM:
                result = VM_FAULT_OOM;
                break;
-       case -EAGAIN:
-               result = VM_FAULT_RETRY;
-               break;
        default:
                result = VM_FAULT_SIGBUS;
                break;
index 8130dfe897451268adcea02c420d3aa61c9809aa..4971aa54756a965ccc99edc63946fee11c13d3e9 100644 (file)
@@ -770,6 +770,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
                        /* Initialize the device private structure. */
                        struct octeon_ethernet *priv = netdev_priv(dev);
 
+                       SET_NETDEV_DEV(dev, &pdev->dev);
                        dev->netdev_ops = &cvm_oct_pow_netdev_ops;
                        priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED;
                        priv->port = CVMX_PIP_NUM_INPUT_PORTS;
@@ -816,6 +817,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
                        }
 
                        /* Initialize the device private structure. */
+                       SET_NETDEV_DEV(dev, &pdev->dev);
                        priv = netdev_priv(dev);
                        priv->netdev = dev;
                        priv->of_node = cvm_oct_node_for_port(pip, interface,
index 1ebd13ef7bd333c5cbc488f7543eda58e29a2123..26929c44d70316d19a5691a400c0f87b4f63ff9d 100644 (file)
@@ -352,7 +352,15 @@ int core_enable_device_list_for_node(
                        kfree(new);
                        return -EINVAL;
                }
-               BUG_ON(orig->se_lun_acl != NULL);
+               if (orig->se_lun_acl != NULL) {
+                       pr_warn_ratelimited("Detected existing explicit"
+                               " se_lun_acl->se_lun_group reference for %s"
+                               " mapped_lun: %llu, failing\n",
+                                nacl->initiatorname, mapped_lun);
+                       mutex_unlock(&nacl->lun_entry_mutex);
+                       kfree(new);
+                       return -EINVAL;
+               }
 
                rcu_assign_pointer(new->se_lun, lun);
                rcu_assign_pointer(new->se_lun_acl, lun_acl);
index 4879e70e2eefb68ddc229effbe4a9822f369ce3f..df7b6e95c019dd91ee56671d93e03a3356fb51b9 100644 (file)
@@ -451,6 +451,7 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success,
                                             int *post_ret)
 {
        struct se_device *dev = cmd->se_dev;
+       sense_reason_t ret = TCM_NO_SENSE;
 
        /*
         * Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
@@ -458,9 +459,12 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success,
         * sent to the backend driver.
         */
        spin_lock_irq(&cmd->t_state_lock);
-       if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status) {
+       if (cmd->transport_state & CMD_T_SENT) {
                cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
                *post_ret = 1;
+
+               if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+                       ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
        spin_unlock_irq(&cmd->t_state_lock);
 
@@ -470,7 +474,7 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success,
         */
        up(&dev->caw_sem);
 
-       return TCM_NO_SENSE;
+       return ret;
 }
 
 static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success,
index 7dfefd66df93874b1359824890b4b760275ff2c6..437591bc7c0855d85102be0ca42d093531004343 100644 (file)
@@ -457,8 +457,20 @@ static void target_complete_nacl(struct kref *kref)
 {
        struct se_node_acl *nacl = container_of(kref,
                                struct se_node_acl, acl_kref);
+       struct se_portal_group *se_tpg = nacl->se_tpg;
 
-       complete(&nacl->acl_free_comp);
+       if (!nacl->dynamic_stop) {
+               complete(&nacl->acl_free_comp);
+               return;
+       }
+
+       mutex_lock(&se_tpg->acl_node_mutex);
+       list_del(&nacl->acl_list);
+       mutex_unlock(&se_tpg->acl_node_mutex);
+
+       core_tpg_wait_for_nacl_pr_ref(nacl);
+       core_free_device_list_for_node(nacl, se_tpg);
+       kfree(nacl);
 }
 
 void target_put_nacl(struct se_node_acl *nacl)
@@ -499,12 +511,39 @@ EXPORT_SYMBOL(transport_deregister_session_configfs);
 void transport_free_session(struct se_session *se_sess)
 {
        struct se_node_acl *se_nacl = se_sess->se_node_acl;
+
        /*
         * Drop the se_node_acl->nacl_kref obtained from within
         * core_tpg_get_initiator_node_acl().
         */
        if (se_nacl) {
+               struct se_portal_group *se_tpg = se_nacl->se_tpg;
+               const struct target_core_fabric_ops *se_tfo = se_tpg->se_tpg_tfo;
+               unsigned long flags;
+
                se_sess->se_node_acl = NULL;
+
+               /*
+                * Also determine if we need to drop the extra ->cmd_kref if
+                * it had been previously dynamically generated, and
+                * the endpoint is not caching dynamic ACLs.
+                */
+               mutex_lock(&se_tpg->acl_node_mutex);
+               if (se_nacl->dynamic_node_acl &&
+                   !se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
+                       spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags);
+                       if (list_empty(&se_nacl->acl_sess_list))
+                               se_nacl->dynamic_stop = true;
+                       spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags);
+
+                       if (se_nacl->dynamic_stop)
+                               list_del(&se_nacl->acl_list);
+               }
+               mutex_unlock(&se_tpg->acl_node_mutex);
+
+               if (se_nacl->dynamic_stop)
+                       target_put_nacl(se_nacl);
+
                target_put_nacl(se_nacl);
        }
        if (se_sess->sess_cmd_map) {
@@ -518,16 +557,12 @@ EXPORT_SYMBOL(transport_free_session);
 void transport_deregister_session(struct se_session *se_sess)
 {
        struct se_portal_group *se_tpg = se_sess->se_tpg;
-       const struct target_core_fabric_ops *se_tfo;
-       struct se_node_acl *se_nacl;
        unsigned long flags;
-       bool drop_nacl = false;
 
        if (!se_tpg) {
                transport_free_session(se_sess);
                return;
        }
-       se_tfo = se_tpg->se_tpg_tfo;
 
        spin_lock_irqsave(&se_tpg->session_lock, flags);
        list_del(&se_sess->sess_list);
@@ -535,33 +570,15 @@ void transport_deregister_session(struct se_session *se_sess)
        se_sess->fabric_sess_ptr = NULL;
        spin_unlock_irqrestore(&se_tpg->session_lock, flags);
 
-       /*
-        * Determine if we need to do extra work for this initiator node's
-        * struct se_node_acl if it had been previously dynamically generated.
-        */
-       se_nacl = se_sess->se_node_acl;
-
-       mutex_lock(&se_tpg->acl_node_mutex);
-       if (se_nacl && se_nacl->dynamic_node_acl) {
-               if (!se_tfo->tpg_check_demo_mode_cache(se_tpg)) {
-                       list_del(&se_nacl->acl_list);
-                       drop_nacl = true;
-               }
-       }
-       mutex_unlock(&se_tpg->acl_node_mutex);
-
-       if (drop_nacl) {
-               core_tpg_wait_for_nacl_pr_ref(se_nacl);
-               core_free_device_list_for_node(se_nacl, se_tpg);
-               se_sess->se_node_acl = NULL;
-               kfree(se_nacl);
-       }
        pr_debug("TARGET_CORE[%s]: Deregistered fabric_sess\n",
                se_tpg->se_tpg_tfo->get_fabric_name());
        /*
         * If last kref is dropping now for an explicit NodeACL, awake sleeping
         * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
         * removal context from within transport_free_session() code.
+        *
+        * For dynamic ACL, target_put_nacl() uses target_complete_nacl()
+        * to release all remaining generate_node_acl=1 created ACL resources.
         */
 
        transport_free_session(se_sess);
@@ -1693,6 +1710,10 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
        case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
        case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
+       case TCM_TOO_MANY_TARGET_DESCS:
+       case TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE:
+       case TCM_TOO_MANY_SEGMENT_DESCS:
+       case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
                break;
        case TCM_OUT_OF_RESOURCES:
                sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2808,6 +2829,26 @@ static const struct sense_info sense_info_table[] = {
                .key = ILLEGAL_REQUEST,
                .asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */
        },
+       [TCM_TOO_MANY_TARGET_DESCS] = {
+               .key = ILLEGAL_REQUEST,
+               .asc = 0x26,
+               .ascq = 0x06, /* TOO MANY TARGET DESCRIPTORS */
+       },
+       [TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE] = {
+               .key = ILLEGAL_REQUEST,
+               .asc = 0x26,
+               .ascq = 0x07, /* UNSUPPORTED TARGET DESCRIPTOR TYPE CODE */
+       },
+       [TCM_TOO_MANY_SEGMENT_DESCS] = {
+               .key = ILLEGAL_REQUEST,
+               .asc = 0x26,
+               .ascq = 0x08, /* TOO MANY SEGMENT DESCRIPTORS */
+       },
+       [TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE] = {
+               .key = ILLEGAL_REQUEST,
+               .asc = 0x26,
+               .ascq = 0x09, /* UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE */
+       },
        [TCM_PARAMETER_LIST_LENGTH_ERROR] = {
                .key = ILLEGAL_REQUEST,
                .asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */
@@ -3086,7 +3127,6 @@ static void target_tmr_work(struct work_struct *work)
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                goto check_stop;
        }
-       cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
        cmd->se_tfo->queue_tm_rsp(cmd);
@@ -3099,11 +3139,25 @@ int transport_generic_handle_tmr(
        struct se_cmd *cmd)
 {
        unsigned long flags;
+       bool aborted = false;
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
-       cmd->transport_state |= CMD_T_ACTIVE;
+       if (cmd->transport_state & CMD_T_ABORTED) {
+               aborted = true;
+       } else {
+               cmd->t_state = TRANSPORT_ISTATE_PROCESSING;
+               cmd->transport_state |= CMD_T_ACTIVE;
+       }
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
+       if (aborted) {
+               pr_warn_ratelimited("handle_tmr caught CMD_T_ABORTED TMR %d"
+                       "ref_tag: %llu tag: %llu\n", cmd->se_tmr_req->function,
+                       cmd->se_tmr_req->ref_task_tag, cmd->tag);
+               transport_cmd_check_stop_to_fabric(cmd);
+               return 0;
+       }
+
        INIT_WORK(&cmd->work, target_tmr_work);
        queue_work(cmd->se_dev->tmr_wq, &cmd->work);
        return 0;
index 37d5caebffa6b593025a28b703a54a71e7d940d3..cac5a20a4de07ba554151c6099182c9e675efbed 100644 (file)
@@ -53,18 +53,13 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
        return 0;
 }
 
-static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
-                                       bool src)
+static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn,
+                                       struct se_device **found_dev)
 {
        struct se_device *se_dev;
-       unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn;
+       unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
        int rc;
 
-       if (src)
-               dev_wwn = &xop->dst_tid_wwn[0];
-       else
-               dev_wwn = &xop->src_tid_wwn[0];
-
        mutex_lock(&g_device_mutex);
        list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
 
@@ -78,15 +73,8 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
                if (rc != 0)
                        continue;
 
-               if (src) {
-                       xop->dst_dev = se_dev;
-                       pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located"
-                               " se_dev\n", xop->dst_dev);
-               } else {
-                       xop->src_dev = se_dev;
-                       pr_debug("XCOPY 0xe4: Setting xop->src_dev: %p from located"
-                               " se_dev\n", xop->src_dev);
-               }
+               *found_dev = se_dev;
+               pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
 
                rc = target_depend_item(&se_dev->dev_group.cg_item);
                if (rc != 0) {
@@ -110,7 +98,7 @@ static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op
 }
 
 static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
-                               unsigned char *p, bool src)
+                               unsigned char *p, unsigned short cscd_index)
 {
        unsigned char *desc = p;
        unsigned short ript;
@@ -155,7 +143,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
                return -EINVAL;
        }
 
-       if (src) {
+       if (cscd_index != xop->stdi && cscd_index != xop->dtdi) {
+               pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor "
+                        "dest\n", cscd_index);
+               return 0;
+       }
+
+       if (cscd_index == xop->stdi) {
                memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
                /*
                 * Determine if the source designator matches the local device
@@ -167,10 +161,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
                        pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
                                        " received xop\n", xop->src_dev);
                }
-       } else {
+       }
+
+       if (cscd_index == xop->dtdi) {
                memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
                /*
-                * Determine if the destination designator matches the local device
+                * Determine if the destination designator matches the local
+                * device. If @cscd_index corresponds to both source (stdi) and
+                * destination (dtdi), or dtdi comes after stdi, then
+                * XCOL_DEST_RECV_OP wins.
                 */
                if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
                                XCOPY_NAA_IEEE_REGEX_LEN)) {
@@ -190,20 +189,23 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
 {
        struct se_device *local_dev = se_cmd->se_dev;
        unsigned char *desc = p;
-       int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0;
+       int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
+       unsigned short cscd_index = 0;
        unsigned short start = 0;
-       bool src = true;
 
        *sense_ret = TCM_INVALID_PARAMETER_LIST;
 
        if (offset != 0) {
                pr_err("XCOPY target descriptor list length is not"
                        " multiple of %d\n", XCOPY_TARGET_DESC_LEN);
+               *sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
                return -EINVAL;
        }
-       if (tdll > 64) {
+       if (tdll > RCR_OP_MAX_TARGET_DESC_COUNT * XCOPY_TARGET_DESC_LEN) {
                pr_err("XCOPY target descriptor supports a maximum"
                        " two src/dest descriptors, tdll: %hu too large..\n", tdll);
+               /* spc4r37 6.4.3.4 CSCD DESCRIPTOR LIST LENGTH field */
+               *sense_ret = TCM_TOO_MANY_TARGET_DESCS;
                return -EINVAL;
        }
        /*
@@ -215,37 +217,43 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
 
        while (start < tdll) {
                /*
-                * Check target descriptor identification with 0xE4 type with
-                * use VPD 0x83 WWPN matching ..
+                * Check target descriptor identification with 0xE4 type, and
+                * compare the current index with the CSCD descriptor IDs in
+                * the segment descriptor. Use VPD 0x83 WWPN matching ..
                 */
                switch (desc[0]) {
                case 0xe4:
                        rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
-                                                       &desc[0], src);
+                                                       &desc[0], cscd_index);
                        if (rc != 0)
                                goto out;
-                       /*
-                        * Assume target descriptors are in source -> destination order..
-                        */
-                       if (src)
-                               src = false;
-                       else
-                               src = true;
                        start += XCOPY_TARGET_DESC_LEN;
                        desc += XCOPY_TARGET_DESC_LEN;
-                       ret++;
+                       cscd_index++;
                        break;
                default:
                        pr_err("XCOPY unsupported descriptor type code:"
                                        " 0x%02x\n", desc[0]);
+                       *sense_ret = TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE;
                        goto out;
                }
        }
 
-       if (xop->op_origin == XCOL_SOURCE_RECV_OP)
-               rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
-       else
-               rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
+       switch (xop->op_origin) {
+       case XCOL_SOURCE_RECV_OP:
+               rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn,
+                                               &xop->dst_dev);
+               break;
+       case XCOL_DEST_RECV_OP:
+               rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn,
+                                               &xop->src_dev);
+               break;
+       default:
+               pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
+                       "stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi);
+               rc = -EINVAL;
+               break;
+       }
        /*
         * If a matching IEEE NAA 0x83 descriptor for the requested device
         * is not located on this node, return COPY_ABORTED with ASQ/ASQC
@@ -262,7 +270,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
        pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
                 xop->dst_dev, &xop->dst_tid_wwn[0]);
 
-       return ret;
+       return cscd_index;
 
 out:
        return -EINVAL;
@@ -284,6 +292,14 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
 
        xop->stdi = get_unaligned_be16(&desc[4]);
        xop->dtdi = get_unaligned_be16(&desc[6]);
+
+       if (xop->stdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX ||
+           xop->dtdi > XCOPY_CSCD_DESC_ID_LIST_OFF_MAX) {
+               pr_err("XCOPY segment desc 0x02: unsupported CSCD ID > 0x%x; stdi: %hu dtdi: %hu\n",
+                       XCOPY_CSCD_DESC_ID_LIST_OFF_MAX, xop->stdi, xop->dtdi);
+               return -EINVAL;
+       }
+
        pr_debug("XCOPY seg desc 0x02: desc_len: %hu stdi: %hu dtdi: %hu, DC: %d\n",
                desc_len, xop->stdi, xop->dtdi, dc);
 
@@ -306,15 +322,25 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
 
 static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
                                struct xcopy_op *xop, unsigned char *p,
-                               unsigned int sdll)
+                               unsigned int sdll, sense_reason_t *sense_ret)
 {
        unsigned char *desc = p;
        unsigned int start = 0;
        int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
 
+       *sense_ret = TCM_INVALID_PARAMETER_LIST;
+
        if (offset != 0) {
                pr_err("XCOPY segment descriptor list length is not"
                        " multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
+               *sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
+               return -EINVAL;
+       }
+       if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
+               pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
+                       " large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
+               /* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
+               *sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
                return -EINVAL;
        }
 
@@ -335,6 +361,7 @@ static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
                default:
                        pr_err("XCOPY unsupported segment descriptor"
                                "type: 0x%02x\n", desc[0]);
+                       *sense_ret = TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE;
                        goto out;
                }
        }
@@ -837,7 +864,7 @@ out:
                        " CHECK_CONDITION -> sending response\n", rc);
                ec_cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
        }
-       target_complete_cmd(ec_cmd, SAM_STAT_CHECK_CONDITION);
+       target_complete_cmd(ec_cmd, ec_cmd->scsi_status);
 }
 
 sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
@@ -861,6 +888,16 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
                return TCM_UNSUPPORTED_SCSI_OPCODE;
        }
 
+       if (se_cmd->data_length == 0) {
+               target_complete_cmd(se_cmd, SAM_STAT_GOOD);
+               return TCM_NO_SENSE;
+       }
+       if (se_cmd->data_length < XCOPY_HDR_LEN) {
+               pr_err("XCOPY parameter truncation: length %u < hdr_len %u\n",
+                               se_cmd->data_length, XCOPY_HDR_LEN);
+               return TCM_PARAMETER_LIST_LENGTH_ERROR;
+       }
+
        xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
        if (!xop) {
                pr_err("Unable to allocate xcopy_op\n");
@@ -883,6 +920,12 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
         */
        tdll = get_unaligned_be16(&p[2]);
        sdll = get_unaligned_be32(&p[8]);
+       if (tdll + sdll > RCR_OP_MAX_DESC_LIST_LEN) {
+               pr_err("XCOPY descriptor list length %u exceeds maximum %u\n",
+                      tdll + sdll, RCR_OP_MAX_DESC_LIST_LEN);
+               ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
+               goto out;
+       }
 
        inline_dl = get_unaligned_be32(&p[12]);
        if (inline_dl != 0) {
@@ -890,10 +933,32 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
                goto out;
        }
 
+       if (se_cmd->data_length < (XCOPY_HDR_LEN + tdll + sdll + inline_dl)) {
+               pr_err("XCOPY parameter truncation: data length %u too small "
+                       "for tdll: %hu sdll: %u inline_dl: %u\n",
+                       se_cmd->data_length, tdll, sdll, inline_dl);
+               ret = TCM_PARAMETER_LIST_LENGTH_ERROR;
+               goto out;
+       }
+
        pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
                " tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
                tdll, sdll, inline_dl);
 
+       /*
+        * skip over the target descriptors until segment descriptors
+        * have been passed - CSCD ids are needed to determine src and dest.
+        */
+       seg_desc = &p[16] + tdll;
+
+       rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
+                                                   sdll, &ret);
+       if (rc <= 0)
+               goto out;
+
+       pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
+                               rc * XCOPY_SEGMENT_DESC_LEN);
+
        rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
        if (rc <= 0)
                goto out;
@@ -911,18 +976,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
 
        pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
                                rc * XCOPY_TARGET_DESC_LEN);
-       seg_desc = &p[16];
-       seg_desc += (rc * XCOPY_TARGET_DESC_LEN);
-
-       rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, sdll);
-       if (rc <= 0) {
-               xcopy_pt_undepend_remotedev(xop);
-               goto out;
-       }
        transport_kunmap_data_sg(se_cmd);
 
-       pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
-                               rc * XCOPY_SEGMENT_DESC_LEN);
        INIT_WORK(&xop->xop_work, target_xcopy_do_work);
        queue_work(xcopy_wq, &xop->xop_work);
        return TCM_NO_SENSE;
index 4d3d4dd060f28366ebd069abb603472ae0275d5b..7c0b105cbe1b486062c40d97280059a286f59bf8 100644 (file)
@@ -1,10 +1,17 @@
 #include <target/target_core_base.h>
 
+#define XCOPY_HDR_LEN                  16
 #define XCOPY_TARGET_DESC_LEN          32
 #define XCOPY_SEGMENT_DESC_LEN         28
 #define XCOPY_NAA_IEEE_REGEX_LEN       16
 #define XCOPY_MAX_SECTORS              1024
 
+/*
+ * SPC4r37 6.4.6.1
+ * Table 150 â€” CSCD descriptor ID values
+ */
+#define XCOPY_CSCD_DESC_ID_LIST_OFF_MAX        0x07FF
+
 enum xcopy_origin_list {
        XCOL_SOURCE_RECV_OP = 0x01,
        XCOL_DEST_RECV_OP = 0x02,
index b811b0fb61b1381fba45440f963030aba9ee509a..4c779651245351ea488cf20dec87199d755eb135 100644 (file)
@@ -118,12 +118,12 @@ struct rockchip_tsadc_chip {
        void (*control)(void __iomem *reg, bool on);
 
        /* Per-sensor methods */
-       int (*get_temp)(struct chip_tsadc_table table,
+       int (*get_temp)(const struct chip_tsadc_table *table,
                        int chn, void __iomem *reg, int *temp);
-       void (*set_alarm_temp)(struct chip_tsadc_table table,
-                              int chn, void __iomem *reg, int temp);
-       void (*set_tshut_temp)(struct chip_tsadc_table table,
-                              int chn, void __iomem *reg, int temp);
+       int (*set_alarm_temp)(const struct chip_tsadc_table *table,
+                             int chn, void __iomem *reg, int temp);
+       int (*set_tshut_temp)(const struct chip_tsadc_table *table,
+                             int chn, void __iomem *reg, int temp);
        void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
 
        /* Per-table methods */
@@ -317,6 +317,7 @@ static const struct tsadc_table rk3288_code_table[] = {
        {3452, 115000},
        {3437, 120000},
        {3421, 125000},
+       {0, 125000},
 };
 
 static const struct tsadc_table rk3368_code_table[] = {
@@ -397,59 +398,80 @@ static const struct tsadc_table rk3399_code_table[] = {
        {TSADCV3_DATA_MASK, 125000},
 };
 
-static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
+static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
                                   int temp)
 {
        int high, low, mid;
-       u32 error = 0;
+       unsigned long num;
+       unsigned int denom;
+       u32 error = table->data_mask;
 
        low = 0;
-       high = table.length - 1;
+       high = (table->length - 1) - 1; /* ignore the last check for table */
        mid = (high + low) / 2;
 
        /* Return mask code data when the temp is over table range */
-       if (temp < table.id[low].temp || temp > table.id[high].temp) {
-               error = table.data_mask;
+       if (temp < table->id[low].temp || temp > table->id[high].temp)
                goto exit;
-       }
 
        while (low <= high) {
-               if (temp == table.id[mid].temp)
-                       return table.id[mid].code;
-               else if (temp < table.id[mid].temp)
+               if (temp == table->id[mid].temp)
+                       return table->id[mid].code;
+               else if (temp < table->id[mid].temp)
                        high = mid - 1;
                else
                        low = mid + 1;
                mid = (low + high) / 2;
        }
 
+       /*
+        * The conversion code granularity provided by the table. Let's
+        * assume that the relationship between temperature and
+        * analog value between 2 table entries is linear and interpolate
+        * to produce less granular result.
+        */
+       num = abs(table->id[mid + 1].code - table->id[mid].code);
+       num *= temp - table->id[mid].temp;
+       denom = table->id[mid + 1].temp - table->id[mid].temp;
+
+       switch (table->mode) {
+       case ADC_DECREMENT:
+               return table->id[mid].code - (num / denom);
+       case ADC_INCREMENT:
+               return table->id[mid].code + (num / denom);
+       default:
+               pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
+               return error;
+       }
+
 exit:
-       pr_err("Invalid the conversion, error=%d\n", error);
+       pr_err("%s: invalid temperature, temp=%d error=%d\n",
+              __func__, temp, error);
        return error;
 }
 
-static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
-                                  int *temp)
+static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table,
+                                  u32 code, int *temp)
 {
        unsigned int low = 1;
-       unsigned int high = table.length - 1;
+       unsigned int high = table->length - 1;
        unsigned int mid = (low + high) / 2;
        unsigned int num;
        unsigned long denom;
 
-       WARN_ON(table.length < 2);
+       WARN_ON(table->length < 2);
 
-       switch (table.mode) {
+       switch (table->mode) {
        case ADC_DECREMENT:
-               code &= table.data_mask;
-               if (code < table.id[high].code)
+               code &= table->data_mask;
+               if (code <= table->id[high].code)
                        return -EAGAIN;         /* Incorrect reading */
 
                while (low <= high) {
-                       if (code >= table.id[mid].code &&
-                           code < table.id[mid - 1].code)
+                       if (code >= table->id[mid].code &&
+                           code < table->id[mid - 1].code)
                                break;
-                       else if (code < table.id[mid].code)
+                       else if (code < table->id[mid].code)
                                low = mid + 1;
                        else
                                high = mid - 1;
@@ -458,15 +480,15 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
                }
                break;
        case ADC_INCREMENT:
-               code &= table.data_mask;
-               if (code < table.id[low].code)
+               code &= table->data_mask;
+               if (code < table->id[low].code)
                        return -EAGAIN;         /* Incorrect reading */
 
                while (low <= high) {
-                       if (code <= table.id[mid].code &&
-                           code > table.id[mid - 1].code)
+                       if (code <= table->id[mid].code &&
+                           code > table->id[mid - 1].code)
                                break;
-                       else if (code > table.id[mid].code)
+                       else if (code > table->id[mid].code)
                                low = mid + 1;
                        else
                                high = mid - 1;
@@ -475,7 +497,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
                }
                break;
        default:
-               pr_err("Invalid the conversion table\n");
+               pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
+               return -EINVAL;
        }
 
        /*
@@ -484,10 +507,10 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
         * temperature between 2 table entries is linear and interpolate
         * to produce less granular result.
         */
-       num = table.id[mid].temp - table.id[mid - 1].temp;
-       num *= abs(table.id[mid - 1].code - code);
-       denom = abs(table.id[mid - 1].code - table.id[mid].code);
-       *temp = table.id[mid - 1].temp + (num / denom);
+       num = table->id[mid].temp - table->id[mid - 1].temp;
+       num *= abs(table->id[mid - 1].code - code);
+       denom = abs(table->id[mid - 1].code - table->id[mid].code);
+       *temp = table->id[mid - 1].temp + (num / denom);
 
        return 0;
 }
@@ -638,7 +661,7 @@ static void rk_tsadcv3_control(void __iomem *regs, bool enable)
        writel_relaxed(val, regs + TSADCV2_AUTO_CON);
 }
 
-static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
+static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table,
                               int chn, void __iomem *regs, int *temp)
 {
        u32 val;
@@ -648,39 +671,57 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
        return rk_tsadcv2_code_to_temp(table, val, temp);
 }
 
-static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
-                                 int chn, void __iomem *regs, int temp)
+static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
+                                int chn, void __iomem *regs, int temp)
 {
-       u32 alarm_value, int_en;
+       u32 alarm_value;
+       u32 int_en, int_clr;
+
+       /*
+        * In some cases, some sensors didn't need the trip points, the
+        * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
+        * in the end, ignore this case and disable the high temperature
+        * interrupt.
+        */
+       if (temp == INT_MAX) {
+               int_clr = readl_relaxed(regs + TSADCV2_INT_EN);
+               int_clr &= ~TSADCV2_INT_SRC_EN(chn);
+               writel_relaxed(int_clr, regs + TSADCV2_INT_EN);
+               return 0;
+       }
 
        /* Make sure the value is valid */
        alarm_value = rk_tsadcv2_temp_to_code(table, temp);
-       if (alarm_value == table.data_mask)
-               return;
+       if (alarm_value == table->data_mask)
+               return -ERANGE;
 
-       writel_relaxed(alarm_value & table.data_mask,
+       writel_relaxed(alarm_value & table->data_mask,
                       regs + TSADCV2_COMP_INT(chn));
 
        int_en = readl_relaxed(regs + TSADCV2_INT_EN);
        int_en |= TSADCV2_INT_SRC_EN(chn);
        writel_relaxed(int_en, regs + TSADCV2_INT_EN);
+
+       return 0;
 }
 
-static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
-                                 int chn, void __iomem *regs, int temp)
+static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
+                                int chn, void __iomem *regs, int temp)
 {
        u32 tshut_value, val;
 
        /* Make sure the value is valid */
        tshut_value = rk_tsadcv2_temp_to_code(table, temp);
-       if (tshut_value == table.data_mask)
-               return;
+       if (tshut_value == table->data_mask)
+               return -ERANGE;
 
        writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
 
        /* TSHUT will be valid */
        val = readl_relaxed(regs + TSADCV2_AUTO_CON);
        writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
+
+       return 0;
 }
 
 static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
@@ -883,10 +924,8 @@ static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
        dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
                __func__, sensor->id, low, high);
 
-       tsadc->set_alarm_temp(tsadc->table,
-                             sensor->id, thermal->regs, high);
-
-       return 0;
+       return tsadc->set_alarm_temp(&tsadc->table,
+                                    sensor->id, thermal->regs, high);
 }
 
 static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
@@ -896,7 +935,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
        const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
        int retval;
 
-       retval = tsadc->get_temp(tsadc->table,
+       retval = tsadc->get_temp(&tsadc->table,
                                 sensor->id, thermal->regs, out_temp);
        dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
                sensor->id, *out_temp, retval);
@@ -982,8 +1021,12 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
        int error;
 
        tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
-       tsadc->set_tshut_temp(tsadc->table, id, thermal->regs,
+
+       error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
                              thermal->tshut_temp);
+       if (error)
+               dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
+                       __func__, thermal->tshut_temp, error);
 
        sensor->thermal = thermal;
        sensor->id = id;
@@ -1196,9 +1239,13 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
 
                thermal->chip->set_tshut_mode(id, thermal->regs,
                                              thermal->tshut_mode);
-               thermal->chip->set_tshut_temp(thermal->chip->table,
+
+               error = thermal->chip->set_tshut_temp(&thermal->chip->table,
                                              id, thermal->regs,
                                              thermal->tshut_temp);
+               if (error)
+                       dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
+                               __func__, thermal->tshut_temp, error);
        }
 
        thermal->chip->control(thermal->regs, true);
index 641faab6e24b50fef4d70d3334edfc49e0ab0ce3..655591316a881274a6d152801ffd19138a0dc34b 100644 (file)
@@ -799,6 +799,11 @@ static void thermal_release(struct device *dev)
        if (!strncmp(dev_name(dev), "thermal_zone",
                     sizeof("thermal_zone") - 1)) {
                tz = to_thermal_zone(dev);
+               kfree(tz->trip_type_attrs);
+               kfree(tz->trip_temp_attrs);
+               kfree(tz->trip_hyst_attrs);
+               kfree(tz->trips_attribute_group.attrs);
+               kfree(tz->device.groups);
                kfree(tz);
        } else if (!strncmp(dev_name(dev), "cooling_device",
                            sizeof("cooling_device") - 1)) {
@@ -1305,10 +1310,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 
        thermal_zone_device_set_polling(tz, 0);
 
-       kfree(tz->trip_type_attrs);
-       kfree(tz->trip_temp_attrs);
-       kfree(tz->trip_hyst_attrs);
-       kfree(tz->trips_attribute_group.attrs);
        thermal_set_governor(tz, NULL);
 
        thermal_remove_hwmon_sysfs(tz);
@@ -1316,7 +1317,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
        idr_destroy(&tz->idr);
        mutex_destroy(&tz->lock);
        device_unregister(&tz->device);
-       kfree(tz->device.groups);
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
 
index 61569a765d9ee17213052db6f0d3a1c41d4d9293..76e03a7de9cc3d790a230948f599ef2db4b93249 100644 (file)
@@ -675,7 +675,7 @@ static struct console univ8250_console = {
        .device         = uart_console_device,
        .setup          = univ8250_console_setup,
        .match          = univ8250_console_match,
-       .flags          = CON_PRINTBUFFER | CON_ANYTIME | CON_CONSDEV,
+       .flags          = CON_PRINTBUFFER | CON_ANYTIME,
        .index          = -1,
        .data           = &serial8250_reg,
 };
index aa0166b6d450dcadc85b89d3939c7ae3dd4f0cbc..116436b7fa52a96c740e025d7b5c613e1d365fa8 100644 (file)
@@ -5642,17 +5642,15 @@ static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
 static void serial8250_io_resume(struct pci_dev *dev)
 {
        struct serial_private *priv = pci_get_drvdata(dev);
-       const struct pciserial_board *board;
+       struct serial_private *new;
 
        if (!priv)
                return;
 
-       board = priv->board;
-       kfree(priv);
-       priv = pciserial_init_ports(dev, board);
-
-       if (!IS_ERR(priv)) {
-               pci_set_drvdata(dev, priv);
+       new = pciserial_init_ports(dev, priv->board);
+       if (!IS_ERR(new)) {
+               pci_set_drvdata(dev, new);
+               kfree(priv);
        }
 }
 
index fe4399b41df6cea4904edcee4749bb67532f7e18..c13fec451d03db3bfc382d77ea3b1fdf7b3d04e1 100644 (file)
@@ -1413,7 +1413,7 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p)
         * Enable previously disabled RX interrupts.
         */
        if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
-               serial8250_clear_fifos(p);
+               serial8250_clear_and_reinit_fifos(p);
 
                p->ier |= UART_IER_RLSI | UART_IER_RDI;
                serial_port_out(&p->port, UART_IER, p->ier);
index 168b10cad47b5437c2152313fcad026e2747300a..fabbe76203bb76a541775792828d3a8662c78348 100644 (file)
@@ -481,6 +481,14 @@ static void atmel_stop_tx(struct uart_port *port)
                /* disable PDC transmit */
                atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
        }
+
+       /*
+        * Disable the transmitter.
+        * This is mandatory when DMA is used, otherwise the DMA buffer
+        * is fully transmitted.
+        */
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS);
+
        /* Disable interrupts */
        atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
@@ -513,6 +521,9 @@ static void atmel_start_tx(struct uart_port *port)
 
        /* Enable interrupts */
        atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
+
+       /* re-enable the transmitter */
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
 }
 
 /*
@@ -798,6 +809,11 @@ static void atmel_complete_tx_dma(void *arg)
         */
        if (!uart_circ_empty(xmit))
                atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
+       else if ((port->rs485.flags & SER_RS485_ENABLED) &&
+                !(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
+               /* DMA done, stop TX, start RX for RS485 */
+               atmel_start_rx(port);
+       }
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -900,12 +916,6 @@ static void atmel_tx_dma(struct uart_port *port)
                desc->callback = atmel_complete_tx_dma;
                desc->callback_param = atmel_port;
                atmel_port->cookie_tx = dmaengine_submit(desc);
-
-       } else {
-               if (port->rs485.flags & SER_RS485_ENABLED) {
-                       /* DMA done, stop TX, start RX for RS485 */
-                       atmel_start_rx(port);
-               }
        }
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
index 52bbd27e93ae7a83af92489b6d27fe0309437afe..701c085bb19b8e03f67316133fa5a4be7e0b05fe 100644 (file)
@@ -946,8 +946,8 @@ static const struct input_device_id sysrq_ids[] = {
        {
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
                                INPUT_DEVICE_ID_MATCH_KEYBIT,
-               .evbit = { BIT_MASK(EV_KEY) },
-               .keybit = { BIT_MASK(KEY_LEFTALT) },
+               .evbit = { [BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY) },
+               .keybit = { [BIT_WORD(KEY_LEFTALT)] = BIT_MASK(KEY_LEFTALT) },
        },
        { },
 };
index 0aa9e7d697a5df8a8d25194c377498ddce049d87..25dbd8c7aec73345d357c2a75ff0cde26c918217 100644 (file)
@@ -239,6 +239,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
        if (ifp->desc.bNumEndpoints >= num_ep)
                goto skip_to_next_endpoint_or_interface_descriptor;
 
+       /* Check for duplicate endpoint addresses */
+       for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
+               if (ifp->endpoint[i].desc.bEndpointAddress ==
+                   d->bEndpointAddress) {
+                       dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+                           cfgno, inum, asnum, d->bEndpointAddress);
+                       goto skip_to_next_endpoint_or_interface_descriptor;
+               }
+       }
+
        endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
        ++ifp->desc.bNumEndpoints;
 
index 1fa5c0f29c647ab38367c00817518e122cf3b65a..a56c75e09786d5fa1e064a8e56e58e4095e4d716 100644 (file)
@@ -103,8 +103,7 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
 
 static void hub_release(struct kref *kref);
 static int usb_reset_and_verify_device(struct usb_device *udev);
-static void hub_usb3_port_prepare_disable(struct usb_hub *hub,
-                                         struct usb_port *port_dev);
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state);
 
 static inline char *portspeed(struct usb_hub *hub, int portstatus)
 {
@@ -902,34 +901,6 @@ static int hub_set_port_link_state(struct usb_hub *hub, int port1,
                        USB_PORT_FEAT_LINK_STATE);
 }
 
-/*
- * USB-3 does not have a similar link state as USB-2 that will avoid negotiating
- * a connection with a plugged-in cable but will signal the host when the cable
- * is unplugged. Disable remote wake and set link state to U3 for USB-3 devices
- */
-static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
-{
-       struct usb_port *port_dev = hub->ports[port1 - 1];
-       struct usb_device *hdev = hub->hdev;
-       int ret = 0;
-
-       if (!hub->error) {
-               if (hub_is_superspeed(hub->hdev)) {
-                       hub_usb3_port_prepare_disable(hub, port_dev);
-                       ret = hub_set_port_link_state(hub, port_dev->portnum,
-                                                     USB_SS_PORT_LS_U3);
-               } else {
-                       ret = usb_clear_port_feature(hdev, port1,
-                                       USB_PORT_FEAT_ENABLE);
-               }
-       }
-       if (port_dev->child && set_state)
-               usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
-       if (ret && ret != -ENODEV)
-               dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);
-       return ret;
-}
-
 /*
  * Disable a port and mark a logical connect-change event, so that some
  * time later hub_wq will disconnect() any existing usb_device on the port
@@ -4162,6 +4133,34 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
 
 #endif /* CONFIG_PM */
 
+/*
+ * USB-3 does not have a similar link state as USB-2 that will avoid negotiating
+ * a connection with a plugged-in cable but will signal the host when the cable
+ * is unplugged. Disable remote wake and set link state to U3 for USB-3 devices
+ */
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
+{
+       struct usb_port *port_dev = hub->ports[port1 - 1];
+       struct usb_device *hdev = hub->hdev;
+       int ret = 0;
+
+       if (!hub->error) {
+               if (hub_is_superspeed(hub->hdev)) {
+                       hub_usb3_port_prepare_disable(hub, port_dev);
+                       ret = hub_set_port_link_state(hub, port_dev->portnum,
+                                                     USB_SS_PORT_LS_U3);
+               } else {
+                       ret = usb_clear_port_feature(hdev, port1,
+                                       USB_PORT_FEAT_ENABLE);
+               }
+       }
+       if (port_dev->child && set_state)
+               usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
+       if (ret && ret != -ENODEV)
+               dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);
+       return ret;
+}
+
 
 /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
  *
index d2e50a27140c9254be2a80b6c6ae69bc71a93b4a..24f9f98968a5d860f83920287a5b7deb4c98bed6 100644 (file)
@@ -37,6 +37,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* CBM - Flash disk */
        { USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* WORLDE easy key (easykey.25) MIDI controller  */
+       { USB_DEVICE(0x0218, 0x0401), .driver_info =
+                       USB_QUIRK_CONFIG_INTF_STRINGS },
+
        /* HP 5300/5370C scanner */
        { USB_DEVICE(0x03f0, 0x0701), .driver_info =
                        USB_QUIRK_STRING_FETCH_255 },
index 9548d3e03453db062042600668840d5b4676e649..302b8f5f7d27d26b264bbaeb0eb9a2756362c482 100644 (file)
@@ -513,8 +513,8 @@ struct dwc2_core_params {
        /* Gadget parameters */
        bool g_dma;
        bool g_dma_desc;
-       u16 g_rx_fifo_size;
-       u16 g_np_tx_fifo_size;
+       u32 g_rx_fifo_size;
+       u32 g_np_tx_fifo_size;
        u32 g_tx_fifo_size[MAX_EPS_CHANNELS];
 };
 
index b95930f20d906dfc02d4d6db7dbe954e475d11cc..77c5fcf3a5bf7f101c51225f3c21a90fc7e59dcf 100644 (file)
@@ -3169,7 +3169,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
        /* keep other bits untouched (so e.g. forced modes are not lost) */
        usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
        usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
-               GUSBCFG_HNPCAP);
+               GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
 
        if (hsotg->params.phy_type == DWC2_PHY_TYPE_PARAM_FS &&
            (hsotg->params.speed == DWC2_SPEED_PARAM_FULL ||
@@ -3749,11 +3749,11 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
                __func__, epctrl, epctrl_reg);
 
        /* Allocate DMA descriptor chain for non-ctrl endpoints */
-       if (using_desc_dma(hsotg)) {
-               hs_ep->desc_list = dma_alloc_coherent(hsotg->dev,
+       if (using_desc_dma(hsotg) && !hs_ep->desc_list) {
+               hs_ep->desc_list = dmam_alloc_coherent(hsotg->dev,
                        MAX_DMA_DESC_NUM_GENERIC *
                        sizeof(struct dwc2_dma_desc),
-                       &hs_ep->desc_list_dma, GFP_KERNEL);
+                       &hs_ep->desc_list_dma, GFP_ATOMIC);
                if (!hs_ep->desc_list) {
                        ret = -ENOMEM;
                        goto error2;
@@ -3872,7 +3872,7 @@ error1:
 
 error2:
        if (ret && using_desc_dma(hsotg) && hs_ep->desc_list) {
-               dma_free_coherent(hsotg->dev, MAX_DMA_DESC_NUM_GENERIC *
+               dmam_free_coherent(hsotg->dev, MAX_DMA_DESC_NUM_GENERIC *
                        sizeof(struct dwc2_dma_desc),
                        hs_ep->desc_list, hs_ep->desc_list_dma);
                hs_ep->desc_list = NULL;
@@ -3902,14 +3902,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
                return -EINVAL;
        }
 
-       /* Remove DMA memory allocated for non-control Endpoints */
-       if (using_desc_dma(hsotg)) {
-               dma_free_coherent(hsotg->dev, MAX_DMA_DESC_NUM_GENERIC *
-                                 sizeof(struct dwc2_dma_desc),
-                                 hs_ep->desc_list, hs_ep->desc_list_dma);
-               hs_ep->desc_list = NULL;
-       }
-
        epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 
        spin_lock_irqsave(&hsotg->lock, flags);
@@ -4131,7 +4123,7 @@ static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
        /* keep other bits untouched (so e.g. forced modes are not lost) */
        usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
        usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
-               GUSBCFG_HNPCAP);
+               GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
 
        /* set the PLL on, remove the HNP/SRP and set the PHY */
        trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
index 911c3b36ac067028acdaa5d53bd0c9e8702f8942..46d0ad5105e40e5818e590a957072a48066c5ae0 100644 (file)
@@ -4367,6 +4367,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
        if (!HCD_HW_ACCESSIBLE(hcd))
                goto unlock;
 
+       if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
+               goto unlock;
+
        if (!hsotg->params.hibernation)
                goto skip_power_saving;
 
@@ -4489,8 +4492,8 @@ static void dwc2_dump_urb_info(struct usb_hcd *hcd, struct urb *urb,
 {
 #ifdef VERBOSE_DEBUG
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
-       char *pipetype;
-       char *speed;
+       char *pipetype = NULL;
+       char *speed = NULL;
 
        dev_vdbg(hsotg->dev, "%s, urb %p\n", fn_name, urb);
        dev_vdbg(hsotg->dev, "  Device address: %d\n",
index a786256535b6a77392018aa93f78f785daf8a1b2..bcd1e19b40768679a0cee673be38587c8fdd11b0 100644 (file)
@@ -247,8 +247,6 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
 static void dwc2_get_device_property(struct dwc2_hsotg *hsotg,
                                     char *property, u8 size, u64 *value)
 {
-       u8 val8;
-       u16 val16;
        u32 val32;
 
        switch (size) {
@@ -256,17 +254,7 @@ static void dwc2_get_device_property(struct dwc2_hsotg *hsotg,
                *value = device_property_read_bool(hsotg->dev, property);
                break;
        case 1:
-               if (device_property_read_u8(hsotg->dev, property, &val8))
-                       return;
-
-               *value = val8;
-               break;
        case 2:
-               if (device_property_read_u16(hsotg->dev, property, &val16))
-                       return;
-
-               *value = val16;
-               break;
        case 4:
                if (device_property_read_u32(hsotg->dev, property, &val32))
                        return;
@@ -397,16 +385,16 @@ static void dwc2_set_param(struct dwc2_hsotg *hsotg, void *param,
 }
 
 /**
- * dwc2_set_param_u16() - Set a u16 parameter
+ * dwc2_set_param_u32() - Set a u32 parameter
  *
  * See dwc2_set_param().
  */
-static void dwc2_set_param_u16(struct dwc2_hsotg *hsotg, u16 *param,
+static void dwc2_set_param_u32(struct dwc2_hsotg *hsotg, u32 *param,
                               bool lookup, char *property, u16 legacy,
                               u16 def, u16 min, u16 max)
 {
        dwc2_set_param(hsotg, param, lookup, property,
-                      legacy, def, min, max, 2);
+                      legacy, def, min, max, 4);
 }
 
 /**
@@ -1100,13 +1088,13 @@ static void dwc2_set_gadget_dma(struct dwc2_hsotg *hsotg)
        /* Buffer DMA */
        dwc2_set_param_bool(hsotg, &p->g_dma,
                            false, "gadget-dma",
-                           true, false,
+                           dma_capable, false,
                            dma_capable);
 
        /* DMA Descriptor */
        dwc2_set_param_bool(hsotg, &p->g_dma_desc, false,
                            "gadget-dma-desc",
-                           p->g_dma, false,
+                           !!hw->dma_desc_enable, false,
                            !!hw->dma_desc_enable);
 }
 
@@ -1130,8 +1118,14 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
 
                dwc2_set_param_bool(hsotg, &p->host_dma,
                                    false, "host-dma",
-                                   true, false,
+                                   dma_capable, false,
                                    dma_capable);
+               dwc2_set_param_host_rx_fifo_size(hsotg,
+                               params->host_rx_fifo_size);
+               dwc2_set_param_host_nperio_tx_fifo_size(hsotg,
+                               params->host_nperio_tx_fifo_size);
+               dwc2_set_param_host_perio_tx_fifo_size(hsotg,
+                               params->host_perio_tx_fifo_size);
        }
        dwc2_set_param_dma_desc_enable(hsotg, params->dma_desc_enable);
        dwc2_set_param_dma_desc_fs_enable(hsotg, params->dma_desc_fs_enable);
@@ -1140,12 +1134,6 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
                        params->host_support_fs_ls_low_power);
        dwc2_set_param_enable_dynamic_fifo(hsotg,
                        params->enable_dynamic_fifo);
-       dwc2_set_param_host_rx_fifo_size(hsotg,
-                       params->host_rx_fifo_size);
-       dwc2_set_param_host_nperio_tx_fifo_size(hsotg,
-                       params->host_nperio_tx_fifo_size);
-       dwc2_set_param_host_perio_tx_fifo_size(hsotg,
-                       params->host_perio_tx_fifo_size);
        dwc2_set_param_max_transfer_size(hsotg,
                        params->max_transfer_size);
        dwc2_set_param_max_packet_count(hsotg,
@@ -1190,12 +1178,12 @@ static void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
                 * auto-detect if the hardware does not support the
                 * default.
                 */
-               dwc2_set_param_u16(hsotg, &p->g_rx_fifo_size,
+               dwc2_set_param_u32(hsotg, &p->g_rx_fifo_size,
                                   true, "g-rx-fifo-size", 2048,
                                   hw->rx_fifo_size,
                                   16, hw->rx_fifo_size);
 
-               dwc2_set_param_u16(hsotg, &p->g_np_tx_fifo_size,
+               dwc2_set_param_u32(hsotg, &p->g_np_tx_fifo_size,
                                   true, "g-np-tx-fifo-size", 1024,
                                   hw->dev_nperio_tx_fifo_size,
                                   16, hw->dev_nperio_tx_fifo_size);
index de5a8570be04213cd3fd39c774662c9173907e34..14b760209680920e65e92fbbb75a14c3bd4a3b18 100644 (file)
@@ -45,9 +45,7 @@
 #define DWC3_XHCI_RESOURCES_NUM        2
 
 #define DWC3_SCRATCHBUF_SIZE   4096    /* each buffer is assumed to be 4KiB */
-#define DWC3_EVENT_SIZE                4       /* bytes */
-#define DWC3_EVENT_MAX_NUM     64      /* 2 events/endpoint */
-#define DWC3_EVENT_BUFFERS_SIZE        (DWC3_EVENT_SIZE * DWC3_EVENT_MAX_NUM)
+#define DWC3_EVENT_BUFFERS_SIZE        4096
 #define DWC3_EVENT_TYPE_MASK   0xfe
 
 #define DWC3_EVENT_TYPE_DEV    0
 #define DWC3_DCFG_SUPERSPEED_PLUS (5 << 0)  /* DWC_usb31 only */
 #define DWC3_DCFG_SUPERSPEED   (4 << 0)
 #define DWC3_DCFG_HIGHSPEED    (0 << 0)
-#define DWC3_DCFG_FULLSPEED2   (1 << 0)
+#define DWC3_DCFG_FULLSPEED    (1 << 0)
 #define DWC3_DCFG_LOWSPEED     (2 << 0)
-#define DWC3_DCFG_FULLSPEED1   (3 << 0)
 
 #define DWC3_DCFG_NUMP_SHIFT   17
 #define DWC3_DCFG_NUMP(n)      (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f)
 #define DWC3_DSTS_SUPERSPEED_PLUS      (5 << 0) /* DWC_usb31 only */
 #define DWC3_DSTS_SUPERSPEED           (4 << 0)
 #define DWC3_DSTS_HIGHSPEED            (0 << 0)
-#define DWC3_DSTS_FULLSPEED2           (1 << 0)
+#define DWC3_DSTS_FULLSPEED            (1 << 0)
 #define DWC3_DSTS_LOWSPEED             (2 << 0)
-#define DWC3_DSTS_FULLSPEED1           (3 << 0)
 
 /* Device Generic Command Register */
 #define DWC3_DGCMD_SET_LMP             0x01
index e27899bb57064b94811fae851587b06b743128ff..e956306d9b0f834e52632f09fe2af5f2ae913bc0 100644 (file)
@@ -138,7 +138,8 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
                exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
                if (IS_ERR(exynos->axius_clk)) {
                        dev_err(dev, "no AXI UpScaler clk specified\n");
-                       return -ENODEV;
+                       ret = -ENODEV;
+                       goto axius_clk_err;
                }
                clk_prepare_enable(exynos->axius_clk);
        } else {
@@ -196,6 +197,7 @@ err3:
        regulator_disable(exynos->vdd33);
 err2:
        clk_disable_unprepare(exynos->axius_clk);
+axius_clk_err:
        clk_disable_unprepare(exynos->susp_clk);
        clk_disable_unprepare(exynos->clk);
        return ret;
index 29e80cc9b634aab72f59e73c71667dfef9f86a45..eb1b9cb3f9d1df29bb4c6d8fe2b8d4b3ebf7897b 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/dwc3-omap.h>
@@ -510,7 +511,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
        /* check the DMA Status */
        reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
-
+       irq_set_status_flags(omap->irq, IRQ_NOAUTOEN);
        ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
                                        dwc3_omap_interrupt_thread, IRQF_SHARED,
                                        "dwc3-omap", omap);
@@ -531,7 +532,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
        }
 
        dwc3_omap_enable_irqs(omap);
-
+       enable_irq(omap->irq);
        return 0;
 
 err2:
@@ -552,6 +553,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
        extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
        extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
        dwc3_omap_disable_irqs(omap);
+       disable_irq(omap->irq);
        of_platform_depopulate(omap->dev);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
index 2b73339f286ba109d74e465aa55189bf84463398..cce0a220b6b0437f23102da3fa56f4f7373f9082 100644 (file)
@@ -38,6 +38,7 @@
 #define PCI_DEVICE_ID_INTEL_BXT_M              0x1aaa
 #define PCI_DEVICE_ID_INTEL_APL                        0x5aaa
 #define PCI_DEVICE_ID_INTEL_KBP                        0xa2b0
+#define PCI_DEVICE_ID_INTEL_GLK                        0x31aa
 
 #define PCI_INTEL_BXT_DSM_UUID         "732b85d5-b7a7-4a1b-9ba0-4bbd00ffd511"
 #define PCI_INTEL_BXT_FUNC_PMU_PWR     4
@@ -73,16 +74,6 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
 {
        struct platform_device          *dwc3 = dwc->dwc3;
        struct pci_dev                  *pdev = dwc->pci;
-       int                             ret;
-
-       struct property_entry sysdev_property[] = {
-               PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
-               { },
-       };
-
-       ret = platform_device_add_properties(dwc3, sysdev_property);
-       if (ret)
-               return ret;
 
        if (pdev->vendor == PCI_VENDOR_ID_AMD &&
            pdev->device == PCI_DEVICE_ID_AMD_NL_USB) {
@@ -105,6 +96,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
                        PROPERTY_ENTRY_BOOL("snps,disable_scramble_quirk"),
                        PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
                        PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
+                       PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
                        { },
                };
 
@@ -115,7 +107,8 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
                int ret;
 
                struct property_entry properties[] = {
-                       PROPERTY_ENTRY_STRING("dr-mode", "peripheral"),
+                       PROPERTY_ENTRY_STRING("dr_mode", "peripheral"),
+                       PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
                        { }
                };
 
@@ -167,6 +160,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc)
                        PROPERTY_ENTRY_BOOL("snps,usb3_lpm_capable"),
                        PROPERTY_ENTRY_BOOL("snps,has-lpm-erratum"),
                        PROPERTY_ENTRY_BOOL("snps,dis_enblslpm_quirk"),
+                       PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
                        { },
                };
 
@@ -274,6 +268,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BXT_M), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_APL), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBP), },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GLK), },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB), },
        {  }    /* Terminating Entry */
 };
index 4878d187c7d4a4b3b3851c29624ff04bb32df020..9bb1f8526f3ed4d5413e008b2ec24b4565f3f619 100644 (file)
@@ -39,18 +39,13 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
 static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                struct dwc3_ep *dep, struct dwc3_request *req);
 
-static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
-               u32 len, u32 type, bool chain)
+static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum,
+               dma_addr_t buf_dma, u32 len, u32 type, bool chain)
 {
-       struct dwc3_gadget_ep_cmd_params params;
        struct dwc3_trb                 *trb;
        struct dwc3_ep                  *dep;
 
-       int                             ret;
-
        dep = dwc->eps[epnum];
-       if (dep->flags & DWC3_EP_BUSY)
-               return 0;
 
        trb = &dwc->ep0_trb[dep->trb_enqueue];
 
@@ -71,15 +66,23 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
                trb->ctrl |= (DWC3_TRB_CTRL_IOC
                                | DWC3_TRB_CTRL_LST);
 
-       if (chain)
+       trace_dwc3_prepare_trb(dep, trb);
+}
+
+static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum)
+{
+       struct dwc3_gadget_ep_cmd_params params;
+       struct dwc3_ep                  *dep;
+       int                             ret;
+
+       dep = dwc->eps[epnum];
+       if (dep->flags & DWC3_EP_BUSY)
                return 0;
 
        memset(&params, 0, sizeof(params));
        params.param0 = upper_32_bits(dwc->ep0_trb_addr);
        params.param1 = lower_32_bits(dwc->ep0_trb_addr);
 
-       trace_dwc3_prepare_trb(dep, trb);
-
        ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, &params);
        if (ret < 0)
                return ret;
@@ -280,8 +283,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
 
        complete(&dwc->ep0_in_setup);
 
-       ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
+       dwc3_ep0_prepare_one_trb(dwc, 0, dwc->ctrl_req_addr, 8,
                        DWC3_TRBCTL_CONTROL_SETUP, false);
+       ret = dwc3_ep0_start_trans(dwc, 0);
        WARN_ON(ret < 0);
 }
 
@@ -912,9 +916,9 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 
                        dwc->ep0_next_event = DWC3_EP0_COMPLETE;
 
-                       ret = dwc3_ep0_start_trans(dwc, epnum,
-                                       dwc->ctrl_req_addr, 0,
-                                       DWC3_TRBCTL_CONTROL_DATA, false);
+                       dwc3_ep0_prepare_one_trb(dwc, epnum, dwc->ctrl_req_addr,
+                                       0, DWC3_TRBCTL_CONTROL_DATA, false);
+                       ret = dwc3_ep0_start_trans(dwc, epnum);
                        WARN_ON(ret < 0);
                }
        }
@@ -993,9 +997,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
        req->direction = !!dep->number;
 
        if (req->request.length == 0) {
-               ret = dwc3_ep0_start_trans(dwc, dep->number,
+               dwc3_ep0_prepare_one_trb(dwc, dep->number,
                                dwc->ctrl_req_addr, 0,
                                DWC3_TRBCTL_CONTROL_DATA, false);
+               ret = dwc3_ep0_start_trans(dwc, dep->number);
        } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
                        && (dep->number == 0)) {
                u32     transfer_size = 0;
@@ -1011,7 +1016,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
                        transfer_size = ALIGN(req->request.length - maxpacket,
                                              maxpacket);
-                       ret = dwc3_ep0_start_trans(dwc, dep->number,
+                       dwc3_ep0_prepare_one_trb(dwc, dep->number,
                                                   req->request.dma,
                                                   transfer_size,
                                                   DWC3_TRBCTL_CONTROL_DATA,
@@ -1023,18 +1028,20 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 
                dwc->ep0_bounced = true;
 
-               ret = dwc3_ep0_start_trans(dwc, dep->number,
+               dwc3_ep0_prepare_one_trb(dwc, dep->number,
                                dwc->ep0_bounce_addr, transfer_size,
                                DWC3_TRBCTL_CONTROL_DATA, false);
+               ret = dwc3_ep0_start_trans(dwc, dep->number);
        } else {
                ret = usb_gadget_map_request_by_dev(dwc->sysdev,
                                &req->request, dep->number);
                if (ret)
                        return;
 
-               ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
+               dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma,
                                req->request.length, DWC3_TRBCTL_CONTROL_DATA,
                                false);
+               ret = dwc3_ep0_start_trans(dwc, dep->number);
        }
 
        WARN_ON(ret < 0);
@@ -1048,8 +1055,9 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
        type = dwc->three_stage_setup ? DWC3_TRBCTL_CONTROL_STATUS3
                : DWC3_TRBCTL_CONTROL_STATUS2;
 
-       return dwc3_ep0_start_trans(dwc, dep->number,
+       dwc3_ep0_prepare_one_trb(dwc, dep->number,
                        dwc->ctrl_req_addr, 0, type, false);
+       return dwc3_ep0_start_trans(dwc, dep->number);
 }
 
 static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
index efddaf5d11d12639867ce8cb7c9a24ae2c7333c9..204c754cc647072d4caffbe06a4c1a8b869ca51a 100644 (file)
@@ -180,11 +180,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
 
-       if (dwc->ep0_bounced && dep->number == 0)
+       if (dwc->ep0_bounced && dep->number <= 1)
                dwc->ep0_bounced = false;
-       else
-               usb_gadget_unmap_request_by_dev(dwc->sysdev,
-                               &req->request, req->direction);
+
+       usb_gadget_unmap_request_by_dev(dwc->sysdev,
+                       &req->request, req->direction);
 
        trace_dwc3_gadget_giveback(req);
 
@@ -1720,7 +1720,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
                        reg |= DWC3_DCFG_LOWSPEED;
                        break;
                case USB_SPEED_FULL:
-                       reg |= DWC3_DCFG_FULLSPEED1;
+                       reg |= DWC3_DCFG_FULLSPEED;
                        break;
                case USB_SPEED_HIGH:
                        reg |= DWC3_DCFG_HIGHSPEED;
@@ -2232,9 +2232,14 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 
        dep = dwc->eps[epnum];
 
-       if (!(dep->flags & DWC3_EP_ENABLED) &&
-           !(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
-               return;
+       if (!(dep->flags & DWC3_EP_ENABLED)) {
+               if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+                       return;
+
+               /* Handle only EPCMDCMPLT when EP disabled */
+               if (event->endpoint_event != DWC3_DEPEVT_EPCMDCMPLT)
+                       return;
+       }
 
        if (epnum == 0 || epnum == 1) {
                dwc3_ep0_interrupt(dwc, event);
@@ -2531,8 +2536,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
                dwc->gadget.ep0->maxpacket = 64;
                dwc->gadget.speed = USB_SPEED_HIGH;
                break;
-       case DWC3_DSTS_FULLSPEED2:
-       case DWC3_DSTS_FULLSPEED1:
+       case DWC3_DSTS_FULLSPEED:
                dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(64);
                dwc->gadget.ep0->maxpacket = 64;
                dwc->gadget.speed = USB_SPEED_FULL;
index 41ab61f9b6e0b24be1dd950afdae9f4f3a179d50..49d685ad0da90d1a1282dd9d25f31ad64db22087 100644 (file)
@@ -1694,9 +1694,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                value = min(w_length, (u16) 1);
                break;
 
-       /* function drivers must handle get/set altsetting; if there's
-        * no get() method, we know only altsetting zero works.
-        */
+       /* function drivers must handle get/set altsetting */
        case USB_REQ_SET_INTERFACE:
                if (ctrl->bRequestType != USB_RECIP_INTERFACE)
                        goto unknown;
@@ -1705,7 +1703,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                f = cdev->config->interface[intf];
                if (!f)
                        break;
-               if (w_value && !f->set_alt)
+
+               /*
+                * If there's no get_alt() method, we know only altsetting zero
+                * works. There is no need to check if set_alt() is not NULL
+                * as we check this in usb_add_function().
+                */
+               if (w_value && !f->get_alt)
                        break;
                value = f->set_alt(f, w_index, w_value);
                if (value == USB_GADGET_DELAYED_STATUS) {
@@ -2143,7 +2147,7 @@ int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
        cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL);
        if (!cdev->os_desc_req->buf) {
                ret = -ENOMEM;
-               kfree(cdev->os_desc_req);
+               usb_ep_free_request(ep0, cdev->os_desc_req);
                goto end;
        }
        cdev->os_desc_req->context = cdev;
index aab3fc1dbb94c44f0287990e89aa98fc8bf3da3a..fd80c1b9c8234cf4de8371c7ca4e528bc4712fc3 100644 (file)
@@ -1806,7 +1806,7 @@ static void ffs_func_eps_disable(struct ffs_function *func)
        unsigned long flags;
 
        spin_lock_irqsave(&func->ffs->eps_lock, flags);
-       do {
+       while (count--) {
                /* pending requests get nuked */
                if (likely(ep->ep))
                        usb_ep_disable(ep->ep);
@@ -1817,7 +1817,7 @@ static void ffs_func_eps_disable(struct ffs_function *func)
                        __ffs_epfile_read_buffer_free(epfile);
                        ++epfile;
                }
-       } while (--count);
+       }
        spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 }
 
@@ -1831,7 +1831,7 @@ static int ffs_func_eps_enable(struct ffs_function *func)
        int ret = 0;
 
        spin_lock_irqsave(&func->ffs->eps_lock, flags);
-       do {
+       while(count--) {
                struct usb_endpoint_descriptor *ds;
                int desc_idx;
 
@@ -1867,7 +1867,7 @@ static int ffs_func_eps_enable(struct ffs_function *func)
 
                ++ep;
                ++epfile;
-       } while (--count);
+       }
        spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
 
        return ret;
@@ -2091,8 +2091,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
 
        case FFS_STRING:
                /*
-                * Strings are indexed from 1 (0 is magic ;) reserved
-                * for languages list or some such)
+                * Strings are indexed from 1 (0 is reserved
+                * for languages list)
                 */
                if (*valuep > helper->ffs->strings_count)
                        helper->ffs->strings_count = *valuep;
@@ -2252,7 +2252,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
 
                if (len < sizeof(*d) ||
                    d->bFirstInterfaceNumber >= ffs->interfaces_count ||
-                   !d->Reserved1)
+                   d->Reserved1)
                        return -EINVAL;
                for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
                        if (d->Reserved2[i])
@@ -2269,6 +2269,8 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
                if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
                        return -EINVAL;
                length = le32_to_cpu(d->dwSize);
+               if (len < length)
+                       return -EINVAL;
                type = le32_to_cpu(d->dwPropertyDataType);
                if (type < USB_EXT_PROP_UNICODE ||
                    type > USB_EXT_PROP_UNICODE_MULTI) {
@@ -2277,6 +2279,11 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
                        return -EINVAL;
                }
                pnl = le16_to_cpu(d->wPropertyNameLength);
+               if (length < 14 + pnl) {
+                       pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n",
+                                 length, pnl, type);
+                       return -EINVAL;
+               }
                pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
                if (length != 14 + pnl + pdl) {
                        pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
@@ -2363,6 +2370,9 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
                }
        }
        if (flags & (1 << i)) {
+               if (len < 4) {
+                       goto error;
+               }
                os_descs_count = get_unaligned_le32(data);
                data += 4;
                len -= 4;
@@ -2435,7 +2445,8 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
 
        ENTER();
 
-       if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
+       if (unlikely(len < 16 ||
+                    get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
                     get_unaligned_le32(data + 4) != len))
                goto error;
        str_count  = get_unaligned_le32(data + 8);
@@ -3448,12 +3459,12 @@ static void ffs_func_unbind(struct usb_configuration *c,
 
        /* cleanup after autoconfig */
        spin_lock_irqsave(&func->ffs->eps_lock, flags);
-       do {
+       while (count--) {
                if (ep->ep && ep->req)
                        usb_ep_free_request(ep->ep, ep->req);
                ep->req = NULL;
                ++ep;
-       } while (--count);
+       }
        spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
        kfree(func->eps);
        func->eps = NULL;
@@ -3666,6 +3677,7 @@ static void ffs_closed(struct ffs_data *ffs)
 {
        struct ffs_dev *ffs_obj;
        struct f_fs_opts *opts;
+       struct config_item *ci;
 
        ENTER();
        ffs_dev_lock();
@@ -3689,8 +3701,11 @@ static void ffs_closed(struct ffs_data *ffs)
            || !atomic_read(&opts->func_inst.group.cg_item.ci_kref.refcount))
                goto done;
 
-       unregister_gadget_item(ffs_obj->opts->
-                              func_inst.group.cg_item.ci_parent->ci_parent);
+       ci = opts->func_inst.group.cg_item.ci_parent->ci_parent;
+       ffs_dev_unlock();
+
+       unregister_gadget_item(ci);
+       return;
 done:
        ffs_dev_unlock();
 }
index 3151d2a0fe594b516841ae8c653878ad45899e2e..5f8139b8e601808414407e88a94a53a60892ae55 100644 (file)
@@ -593,7 +593,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                }
                status = usb_ep_enable(hidg->out_ep);
                if (status < 0) {
-                       ERROR(cdev, "Enable IN endpoint FAILED!\n");
+                       ERROR(cdev, "Enable OUT endpoint FAILED!\n");
                        goto fail;
                }
                hidg->out_ep->driver_data = hidg;
index e8f4102d19df54fa1983578f8f773067ee317d92..6bde4396927c997b686419cbc4fb15997b0e304f 100644 (file)
@@ -1126,7 +1126,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        /* data and/or status stage for control request */
        } else if (dev->state == STATE_DEV_SETUP) {
 
-               /* IN DATA+STATUS caller makes len <= wLength */
+               len = min_t(size_t, len, dev->setup_wLength);
                if (dev->setup_in) {
                        retval = setup_req (dev->gadget->ep0, dev->req, len);
                        if (retval == 0) {
@@ -1734,10 +1734,12 @@ static struct usb_gadget_driver gadgetfs_driver = {
  * such as configuration notifications.
  */
 
-static int is_valid_config (struct usb_config_descriptor *config)
+static int is_valid_config(struct usb_config_descriptor *config,
+               unsigned int total)
 {
        return config->bDescriptorType == USB_DT_CONFIG
                && config->bLength == USB_DT_CONFIG_SIZE
+               && total >= USB_DT_CONFIG_SIZE
                && config->bConfigurationValue != 0
                && (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
                && (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
@@ -1762,7 +1764,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        }
        spin_unlock_irq(&dev->lock);
 
-       if (len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4))
+       if ((len < (USB_DT_CONFIG_SIZE + USB_DT_DEVICE_SIZE + 4)) ||
+           (len > PAGE_SIZE * 4))
                return -EINVAL;
 
        /* we might need to change message format someday */
@@ -1786,7 +1789,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        /* full or low speed config */
        dev->config = (void *) kbuf;
        total = le16_to_cpu(dev->config->wTotalLength);
-       if (!is_valid_config (dev->config) || total >= length)
+       if (!is_valid_config(dev->config, total) ||
+                       total > length - USB_DT_DEVICE_SIZE)
                goto fail;
        kbuf += total;
        length -= total;
@@ -1795,10 +1799,13 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        if (kbuf [1] == USB_DT_CONFIG) {
                dev->hs_config = (void *) kbuf;
                total = le16_to_cpu(dev->hs_config->wTotalLength);
-               if (!is_valid_config (dev->hs_config) || total >= length)
+               if (!is_valid_config(dev->hs_config, total) ||
+                               total > length - USB_DT_DEVICE_SIZE)
                        goto fail;
                kbuf += total;
                length -= total;
+       } else {
+               dev->hs_config = NULL;
        }
 
        /* could support multiple configs, using another encoding! */
@@ -1811,7 +1818,6 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                        || dev->dev->bDescriptorType != USB_DT_DEVICE
                        || dev->dev->bNumConfigurations != 1)
                goto fail;
-       dev->dev->bNumConfigurations = 1;
        dev->dev->bcdUSB = cpu_to_le16 (0x0200);
 
        /* triggers gadgetfs_bind(); then we can enumerate. */
index f3212db9bc37bf1889c482e86c9c679720766b1f..12c7687216e62f3b88dc47546ec12d5d52efdff5 100644 (file)
@@ -1978,7 +1978,8 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
                        dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
                        goto err;
                }
-               ep->ep.name = kasprintf(GFP_KERNEL, "ep%d", ep->index);
+               sprintf(ep->name, "ep%d", ep->index);
+               ep->ep.name = ep->name;
 
                ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
                ep->dma_regs = udc->regs + USBA_DMA_BASE(i);
index 3e1c9d589dfa34ade18fffa7e300a4c9dfcc1563..b03b2ebfc53a3cdc2e5e7c1731beb9221ea7ea4c 100644 (file)
@@ -280,6 +280,7 @@ struct usba_ep {
        void __iomem                            *ep_regs;
        void __iomem                            *dma_regs;
        void __iomem                            *fifo;
+       char                                    name[8];
        struct usb_ep                           ep;
        struct usba_udc                         *udc;
 
index 9483489080f66230370db44a2326a152a3f3eb47..0402177f93cdde2346586ff95b392256e17f84ce 100644 (file)
@@ -1317,7 +1317,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
                        if (!ret)
                                break;
                }
-               if (!ret && !udc->driver)
+               if (ret)
+                       ret = -ENODEV;
+               else if (udc->driver)
+                       ret = -EBUSY;
+               else
                        goto found;
        } else {
                list_for_each_entry(udc, &udc_list, list) {
index 02b14e91ae6c5a586417dec05d558dbe1cace35a..c60abe3a68f9cf48c21831d40bc32c4e9390b892 100644 (file)
@@ -330,7 +330,7 @@ static void nuke(struct dummy *dum, struct dummy_ep *ep)
 /* caller must hold lock */
 static void stop_activity(struct dummy *dum)
 {
-       struct dummy_ep *ep;
+       int i;
 
        /* prevent any more requests */
        dum->address = 0;
@@ -338,8 +338,8 @@ static void stop_activity(struct dummy *dum)
        /* The timer is left running so that outstanding URBs can fail */
 
        /* nuke any pending requests first, so driver i/o is quiesced */
-       list_for_each_entry(ep, &dum->gadget.ep_list, ep.ep_list)
-               nuke(dum, ep);
+       for (i = 0; i < DUMMY_ENDPOINTS; ++i)
+               nuke(dum, &dum->ep[i]);
 
        /* driver now does any non-usb quiescing necessary */
 }
index be9e6383688111fe8d2c53d3e679758f36fd9873..414e3c376dbbd59587dc3398f4a90872a5aae19c 100644 (file)
@@ -43,7 +43,6 @@ struct at91_usbh_data {
        struct gpio_desc *overcurrent_pin[AT91_MAX_USBH_PORTS];
        u8 ports;                               /* number of ports on root hub */
        u8 overcurrent_supported;
-       u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
        u8 overcurrent_status[AT91_MAX_USBH_PORTS];
        u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
 };
@@ -266,8 +265,7 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int
        if (!valid_port(port))
                return;
 
-       gpiod_set_value(pdata->vbus_pin[port],
-                       pdata->vbus_pin_active_low[port] ^ enable);
+       gpiod_set_value(pdata->vbus_pin[port], enable);
 }
 
 static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
@@ -275,8 +273,7 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
        if (!valid_port(port))
                return -EINVAL;
 
-       return gpiod_get_value(pdata->vbus_pin[port]) ^
-              pdata->vbus_pin_active_low[port];
+       return gpiod_get_value(pdata->vbus_pin[port]);
 }
 
 /*
@@ -533,18 +530,17 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
                pdata->ports = ports;
 
        at91_for_each_port(i) {
-               pdata->vbus_pin[i] = devm_gpiod_get_optional(&pdev->dev,
-                                                            "atmel,vbus-gpio",
-                                                            GPIOD_IN);
+               if (i >= pdata->ports)
+                       break;
+
+               pdata->vbus_pin[i] =
+                       devm_gpiod_get_index_optional(&pdev->dev, "atmel,vbus",
+                                                     i, GPIOD_OUT_HIGH);
                if (IS_ERR(pdata->vbus_pin[i])) {
                        err = PTR_ERR(pdata->vbus_pin[i]);
                        dev_err(&pdev->dev, "unable to claim gpio \"vbus\": %d\n", err);
                        continue;
                }
-
-               pdata->vbus_pin_active_low[i] = gpiod_get_value(pdata->vbus_pin[i]);
-
-               ohci_at91_usb_set_power(pdata, i, 1);
        }
 
        at91_for_each_port(i) {
@@ -552,8 +548,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
                        break;
 
                pdata->overcurrent_pin[i] =
-                       devm_gpiod_get_optional(&pdev->dev,
-                                               "atmel,oc-gpio", GPIOD_IN);
+                       devm_gpiod_get_index_optional(&pdev->dev, "atmel,oc",
+                                                     i, GPIOD_IN);
                if (IS_ERR(pdata->overcurrent_pin[i])) {
                        err = PTR_ERR(pdata->overcurrent_pin[i]);
                        dev_err(&pdev->dev, "unable to claim gpio \"overcurrent\": %d\n", err);
index 321de2e0161b4a3ef825489ab59a96e6250b1cd9..8414ed2a02de98b08ccadbe375d75b93da59cd35 100644 (file)
@@ -979,6 +979,40 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
        xhci->devs[slot_id] = NULL;
 }
 
+/*
+ * Free a virt_device structure.
+ * If the virt_device added a tt_info (a hub) and has children pointing to
+ * that tt_info, then free the child first. Recursive.
+ * We can't rely on udev at this point to find child-parent relationships.
+ */
+void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id)
+{
+       struct xhci_virt_device *vdev;
+       struct list_head *tt_list_head;
+       struct xhci_tt_bw_info *tt_info, *next;
+       int i;
+
+       vdev = xhci->devs[slot_id];
+       if (!vdev)
+               return;
+
+       tt_list_head = &(xhci->rh_bw[vdev->real_port - 1].tts);
+       list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) {
+               /* is this a hub device that added a tt_info to the tts list */
+               if (tt_info->slot_id == slot_id) {
+                       /* are any devices using this tt_info? */
+                       for (i = 1; i < HCS_MAX_SLOTS(xhci->hcs_params1); i++) {
+                               vdev = xhci->devs[i];
+                               if (vdev && (vdev->tt_info == tt_info))
+                                       xhci_free_virt_devices_depth_first(
+                                               xhci, i);
+                       }
+               }
+       }
+       /* we are now at a leaf device */
+       xhci_free_virt_device(xhci, slot_id);
+}
+
 int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
                struct usb_device *udev, gfp_t flags)
 {
@@ -1795,7 +1829,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        int size;
        int i, j, num_ports;
 
-       del_timer_sync(&xhci->cmd_timer);
+       cancel_delayed_work_sync(&xhci->cmd_timer);
 
        /* Free the Event Ring Segment Table and the actual Event Ring */
        size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
@@ -1828,8 +1862,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
                }
        }
 
-       for (i = 1; i < MAX_HC_SLOTS; ++i)
-               xhci_free_virt_device(xhci, i);
+       for (i = HCS_MAX_SLOTS(xhci->hcs_params1); i > 0; i--)
+               xhci_free_virt_devices_depth_first(xhci, i);
 
        dma_pool_destroy(xhci->segment_pool);
        xhci->segment_pool = NULL;
@@ -2342,9 +2376,9 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
        INIT_LIST_HEAD(&xhci->cmd_list);
 
-       /* init command timeout timer */
-       setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
-                   (unsigned long)xhci);
+       /* init command timeout work */
+       INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);
+       init_completion(&xhci->cmd_ring_stop_completion);
 
        page_size = readl(&xhci->op_regs->page_size);
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
index 1094ebd2838ff95a5834f7a680e4a2c0aa13301c..bac961cd24ad62b649da486f62c519ab0b51661d 100644 (file)
@@ -579,8 +579,10 @@ static int xhci_mtk_probe(struct platform_device *pdev)
                goto disable_ldos;
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
+       if (irq < 0) {
+               ret = irq;
                goto disable_clk;
+       }
 
        /* Initialize dma_mask and coherent_dma_mask to 32-bits */
        ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
index e96ae80d107e94fd8db8c33cae52ff9153f14730..954abfd5014d281d537e11353cb6093b9b7a0bdd 100644 (file)
@@ -165,7 +165,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI ||
-                pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI)) {
+                pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI)) {
                xhci->quirks |= XHCI_PME_STUCK_QUIRK;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
index ddfab301e36658adccde76b9a47141b39a3508c7..e5834dd9bcdedb246a51be1b35fa70c9ed920b61 100644 (file)
@@ -165,7 +165,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
                return -ENODEV;
 
        /* Try to set 64-bit DMA first */
-       if (WARN_ON(!pdev->dev.dma_mask))
+       if (!pdev->dev.dma_mask)
                /* Platform did not initialize dma_mask */
                ret = dma_coerce_mask_and_coherent(&pdev->dev,
                                                   DMA_BIT_MASK(64));
index bdf6b13d9b6755a0504a15ba10fcfe1d06b5bc73..e32029a31ca4d2ed5856c18e6e10b4b40de1132a 100644 (file)
@@ -279,23 +279,76 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci)
        readl(&xhci->dba->doorbell[0]);
 }
 
-static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
+static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci, unsigned long delay)
+{
+       return mod_delayed_work(system_wq, &xhci->cmd_timer, delay);
+}
+
+static struct xhci_command *xhci_next_queued_cmd(struct xhci_hcd *xhci)
+{
+       return list_first_entry_or_null(&xhci->cmd_list, struct xhci_command,
+                                       cmd_list);
+}
+
+/*
+ * Turn all commands on command ring with status set to "aborted" to no-op trbs.
+ * If there are other commands waiting then restart the ring and kick the timer.
+ * This must be called with command ring stopped and xhci->lock held.
+ */
+static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
+                                        struct xhci_command *cur_cmd)
+{
+       struct xhci_command *i_cmd;
+       u32 cycle_state;
+
+       /* Turn all aborted commands in list to no-ops, then restart */
+       list_for_each_entry(i_cmd, &xhci->cmd_list, cmd_list) {
+
+               if (i_cmd->status != COMP_CMD_ABORT)
+                       continue;
+
+               i_cmd->status = COMP_CMD_STOP;
+
+               xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
+                        i_cmd->command_trb);
+               /* get cycle state from the original cmd trb */
+               cycle_state = le32_to_cpu(
+                       i_cmd->command_trb->generic.field[3]) & TRB_CYCLE;
+               /* modify the command trb to no-op command */
+               i_cmd->command_trb->generic.field[0] = 0;
+               i_cmd->command_trb->generic.field[1] = 0;
+               i_cmd->command_trb->generic.field[2] = 0;
+               i_cmd->command_trb->generic.field[3] = cpu_to_le32(
+                       TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
+
+               /*
+                * caller waiting for completion is called when command
+                *  completion event is received for these no-op commands
+                */
+       }
+
+       xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+
+       /* ring command ring doorbell to restart the command ring */
+       if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
+           !(xhci->xhc_state & XHCI_STATE_DYING)) {
+               xhci->current_cmd = cur_cmd;
+               xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
+               xhci_ring_cmd_db(xhci);
+       }
+}
+
+/* Must be called with xhci->lock held, releases and aquires lock back */
+static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
 {
        u64 temp_64;
        int ret;
 
        xhci_dbg(xhci, "Abort command ring\n");
 
-       temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
-       xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
+       reinit_completion(&xhci->cmd_ring_stop_completion);
 
-       /*
-        * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
-        * however on some host hw the CMD_RING_RUNNING bit is correctly cleared
-        * but the completion event in never sent. Use the cmd timeout timer to
-        * handle those cases. Use twice the time to cover the bit polling retry
-        */
-       mod_timer(&xhci->cmd_timer, jiffies + (2 * XHCI_CMD_DEFAULT_TIMEOUT));
+       temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
                        &xhci->op_regs->cmd_ring);
 
@@ -315,17 +368,30 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
                udelay(1000);
                ret = xhci_handshake(&xhci->op_regs->cmd_ring,
                                     CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
-               if (ret == 0)
-                       return 0;
-
-               xhci_err(xhci, "Stopped the command ring failed, "
-                               "maybe the host is dead\n");
-               del_timer(&xhci->cmd_timer);
-               xhci->xhc_state |= XHCI_STATE_DYING;
-               xhci_halt(xhci);
-               return -ESHUTDOWN;
+               if (ret < 0) {
+                       xhci_err(xhci, "Stopped the command ring failed, "
+                                "maybe the host is dead\n");
+                       xhci->xhc_state |= XHCI_STATE_DYING;
+                       xhci_halt(xhci);
+                       return -ESHUTDOWN;
+               }
+       }
+       /*
+        * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
+        * however on some host hw the CMD_RING_RUNNING bit is correctly cleared
+        * but the completion event in never sent. Wait 2 secs (arbitrary
+        * number) to handle those cases after negation of CMD_RING_RUNNING.
+        */
+       spin_unlock_irqrestore(&xhci->lock, flags);
+       ret = wait_for_completion_timeout(&xhci->cmd_ring_stop_completion,
+                                         msecs_to_jiffies(2000));
+       spin_lock_irqsave(&xhci->lock, flags);
+       if (!ret) {
+               xhci_dbg(xhci, "No stop event for abort, ring start fail?\n");
+               xhci_cleanup_command_queue(xhci);
+       } else {
+               xhci_handle_stopped_cmd_ring(xhci, xhci_next_queued_cmd(xhci));
        }
-
        return 0;
 }
 
@@ -847,17 +913,6 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
        spin_lock_irqsave(&xhci->lock, flags);
 
        ep->stop_cmds_pending--;
-       if (xhci->xhc_state & XHCI_STATE_REMOVING) {
-               spin_unlock_irqrestore(&xhci->lock, flags);
-               return;
-       }
-       if (xhci->xhc_state & XHCI_STATE_DYING) {
-               xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-                               "Stop EP timer ran, but another timer marked "
-                               "xHCI as DYING, exiting.");
-               spin_unlock_irqrestore(&xhci->lock, flags);
-               return;
-       }
        if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
                                "Stop EP timer ran, but no command pending, "
@@ -1207,101 +1262,62 @@ void xhci_cleanup_command_queue(struct xhci_hcd *xhci)
                xhci_complete_del_and_free_cmd(cur_cmd, COMP_CMD_ABORT);
 }
 
-/*
- * Turn all commands on command ring with status set to "aborted" to no-op trbs.
- * If there are other commands waiting then restart the ring and kick the timer.
- * This must be called with command ring stopped and xhci->lock held.
- */
-static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
-                                        struct xhci_command *cur_cmd)
-{
-       struct xhci_command *i_cmd, *tmp_cmd;
-       u32 cycle_state;
-
-       /* Turn all aborted commands in list to no-ops, then restart */
-       list_for_each_entry_safe(i_cmd, tmp_cmd, &xhci->cmd_list,
-                                cmd_list) {
-
-               if (i_cmd->status != COMP_CMD_ABORT)
-                       continue;
-
-               i_cmd->status = COMP_CMD_STOP;
-
-               xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
-                        i_cmd->command_trb);
-               /* get cycle state from the original cmd trb */
-               cycle_state = le32_to_cpu(
-                       i_cmd->command_trb->generic.field[3]) & TRB_CYCLE;
-               /* modify the command trb to no-op command */
-               i_cmd->command_trb->generic.field[0] = 0;
-               i_cmd->command_trb->generic.field[1] = 0;
-               i_cmd->command_trb->generic.field[2] = 0;
-               i_cmd->command_trb->generic.field[3] = cpu_to_le32(
-                       TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
-
-               /*
-                * caller waiting for completion is called when command
-                *  completion event is received for these no-op commands
-                */
-       }
-
-       xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
-
-       /* ring command ring doorbell to restart the command ring */
-       if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
-           !(xhci->xhc_state & XHCI_STATE_DYING)) {
-               xhci->current_cmd = cur_cmd;
-               mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
-               xhci_ring_cmd_db(xhci);
-       }
-       return;
-}
-
-
-void xhci_handle_command_timeout(unsigned long data)
+void xhci_handle_command_timeout(struct work_struct *work)
 {
        struct xhci_hcd *xhci;
        int ret;
        unsigned long flags;
        u64 hw_ring_state;
-       bool second_timeout = false;
-       xhci = (struct xhci_hcd *) data;
 
-       /* mark this command to be cancelled */
+       xhci = container_of(to_delayed_work(work), struct xhci_hcd, cmd_timer);
+
        spin_lock_irqsave(&xhci->lock, flags);
-       if (xhci->current_cmd) {
-               if (xhci->current_cmd->status == COMP_CMD_ABORT)
-                       second_timeout = true;
-               xhci->current_cmd->status = COMP_CMD_ABORT;
+
+       /*
+        * If timeout work is pending, or current_cmd is NULL, it means we
+        * raced with command completion. Command is handled so just return.
+        */
+       if (!xhci->current_cmd || delayed_work_pending(&xhci->cmd_timer)) {
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               return;
        }
+       /* mark this command to be cancelled */
+       xhci->current_cmd->status = COMP_CMD_ABORT;
 
        /* Make sure command ring is running before aborting it */
        hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
            (hw_ring_state & CMD_RING_RUNNING))  {
-               spin_unlock_irqrestore(&xhci->lock, flags);
+               /* Prevent new doorbell, and start command abort */
+               xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
                xhci_dbg(xhci, "Command timeout\n");
-               ret = xhci_abort_cmd_ring(xhci);
+               ret = xhci_abort_cmd_ring(xhci, flags);
                if (unlikely(ret == -ESHUTDOWN)) {
                        xhci_err(xhci, "Abort command ring failed\n");
                        xhci_cleanup_command_queue(xhci);
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
                        xhci_dbg(xhci, "xHCI host controller is dead.\n");
+
+                       return;
                }
-               return;
+
+               goto time_out_completed;
        }
 
-       /* command ring failed to restart, or host removed. Bail out */
-       if (second_timeout || xhci->xhc_state & XHCI_STATE_REMOVING) {
-               spin_unlock_irqrestore(&xhci->lock, flags);
-               xhci_dbg(xhci, "command timed out twice, ring start fail?\n");
+       /* host removed. Bail out */
+       if (xhci->xhc_state & XHCI_STATE_REMOVING) {
+               xhci_dbg(xhci, "host removed, ring start fail?\n");
                xhci_cleanup_command_queue(xhci);
-               return;
+
+               goto time_out_completed;
        }
 
        /* command timeout on stopped ring, ring can't be aborted */
        xhci_dbg(xhci, "Command timeout on stopped ring\n");
        xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
+
+time_out_completed:
        spin_unlock_irqrestore(&xhci->lock, flags);
        return;
 }
@@ -1333,7 +1349,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 
        cmd = list_entry(xhci->cmd_list.next, struct xhci_command, cmd_list);
 
-       del_timer(&xhci->cmd_timer);
+       cancel_delayed_work(&xhci->cmd_timer);
 
        trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
@@ -1341,7 +1357,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 
        /* If CMD ring stopped we own the trbs between enqueue and dequeue */
        if (cmd_comp_code == COMP_CMD_STOP) {
-               xhci_handle_stopped_cmd_ring(xhci, cmd);
+               complete_all(&xhci->cmd_ring_stop_completion);
                return;
        }
 
@@ -1359,8 +1375,11 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
         */
        if (cmd_comp_code == COMP_CMD_ABORT) {
                xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
-               if (cmd->status == COMP_CMD_ABORT)
+               if (cmd->status == COMP_CMD_ABORT) {
+                       if (xhci->current_cmd == cmd)
+                               xhci->current_cmd = NULL;
                        goto event_handled;
+               }
        }
 
        cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3]));
@@ -1421,7 +1440,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
        if (cmd->cmd_list.next != &xhci->cmd_list) {
                xhci->current_cmd = list_entry(cmd->cmd_list.next,
                                               struct xhci_command, cmd_list);
-               mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+               xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
+       } else if (xhci->current_cmd == cmd) {
+               xhci->current_cmd = NULL;
        }
 
 event_handled:
@@ -1939,8 +1960,9 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
        struct xhci_ep_ctx *ep_ctx;
        u32 trb_comp_code;
        u32 remaining, requested;
-       bool on_data_stage;
+       u32 trb_type;
 
+       trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(ep_trb->generic.field[3]));
        slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
        xdev = xhci->devs[slot_id];
        ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
@@ -1950,14 +1972,11 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
        requested = td->urb->transfer_buffer_length;
        remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 
-       /* not setup (dequeue), or status stage means we are at data stage */
-       on_data_stage = (ep_trb != ep_ring->dequeue && ep_trb != td->last_trb);
-
        switch (trb_comp_code) {
        case COMP_SUCCESS:
-               if (ep_trb != td->last_trb) {
+               if (trb_type != TRB_STATUS) {
                        xhci_warn(xhci, "WARN: Success on ctrl %s TRB without IOC set?\n",
-                                 on_data_stage ? "data" : "setup");
+                                 (trb_type == TRB_DATA) ? "data" : "setup");
                        *status = -ESHUTDOWN;
                        break;
                }
@@ -1967,15 +1986,25 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                *status = 0;
                break;
        case COMP_STOP_SHORT:
-               if (on_data_stage)
+               if (trb_type == TRB_DATA || trb_type == TRB_NORMAL)
                        td->urb->actual_length = remaining;
                else
                        xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n");
                goto finish_td;
        case COMP_STOP:
-               if (on_data_stage)
+               switch (trb_type) {
+               case TRB_SETUP:
+                       td->urb->actual_length = 0;
+                       goto finish_td;
+               case TRB_DATA:
+               case TRB_NORMAL:
                        td->urb->actual_length = requested - remaining;
-               goto finish_td;
+                       goto finish_td;
+               default:
+                       xhci_warn(xhci, "WARN: unexpected TRB Type %d\n",
+                                 trb_type);
+                       goto finish_td;
+               }
        case COMP_STOP_INVAL:
                goto finish_td;
        default:
@@ -1987,7 +2016,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                /* else fall through */
        case COMP_STALL:
                /* Did we transfer part of the data (middle) phase? */
-               if (on_data_stage)
+               if (trb_type == TRB_DATA || trb_type == TRB_NORMAL)
                        td->urb->actual_length = requested - remaining;
                else if (!td->urb_length_set)
                        td->urb->actual_length = 0;
@@ -1995,14 +2024,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
        }
 
        /* stopped at setup stage, no data transferred */
-       if (ep_trb == ep_ring->dequeue)
+       if (trb_type == TRB_SETUP)
                goto finish_td;
 
        /*
         * if on data stage then update the actual_length of the URB and flag it
         * as set, so it won't be overwritten in the event for the last TRB.
         */
-       if (on_data_stage) {
+       if (trb_type == TRB_DATA ||
+               trb_type == TRB_NORMAL) {
                td->urb_length_set = true;
                td->urb->actual_length = requested - remaining;
                xhci_dbg(xhci, "Waiting for status stage event\n");
@@ -3790,9 +3820,9 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
 
        /* if there are no other commands queued we start the timeout timer */
        if (xhci->cmd_list.next == &cmd->cmd_list &&
-           !timer_pending(&xhci->cmd_timer)) {
+           !delayed_work_pending(&xhci->cmd_timer)) {
                xhci->current_cmd = cmd;
-               mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+               xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
        }
 
        queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
index 1cd56417cbec455b6db7605d3b3e20aa20a0998d..9a0ec116654acd27740d497c76ba1a6bb6ab6dd9 100644 (file)
@@ -1534,19 +1534,6 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                xhci_urb_free_priv(urb_priv);
                return ret;
        }
-       if ((xhci->xhc_state & XHCI_STATE_DYING) ||
-                       (xhci->xhc_state & XHCI_STATE_HALTED)) {
-               xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-                               "Ep 0x%x: URB %p to be canceled on "
-                               "non-responsive xHCI host.",
-                               urb->ep->desc.bEndpointAddress, urb);
-               /* Let the stop endpoint command watchdog timer (which set this
-                * state) finish cleaning up the endpoint TD lists.  We must
-                * have caught it in the middle of dropping a lock and giving
-                * back an URB.
-                */
-               goto done;
-       }
 
        ep_index = xhci_get_endpoint_index(&urb->ep->desc);
        ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];
@@ -3787,8 +3774,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 
        mutex_lock(&xhci->mutex);
 
-       if (xhci->xhc_state)    /* dying, removing or halted */
+       if (xhci->xhc_state) {  /* dying, removing or halted */
+               ret = -ESHUTDOWN;
                goto out;
+       }
 
        if (!udev->slot_id) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_address,
index 8ccc11a974b8a62ee0afe18808babb0603071efa..2d7b6374b58d0c092528dff89e761716552735d2 100644 (file)
@@ -1568,7 +1568,8 @@ struct xhci_hcd {
 #define CMD_RING_STATE_STOPPED         (1 << 2)
        struct list_head        cmd_list;
        unsigned int            cmd_ring_reserved_trbs;
-       struct timer_list       cmd_timer;
+       struct delayed_work     cmd_timer;
+       struct completion       cmd_ring_stop_completion;
        struct xhci_command     *current_cmd;
        struct xhci_ring        *event_ring;
        struct xhci_erst        erst;
@@ -1934,7 +1935,7 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
                unsigned int slot_id, unsigned int ep_index,
                struct xhci_dequeue_state *deq_state);
 void xhci_stop_endpoint_command_watchdog(unsigned long arg);
-void xhci_handle_command_timeout(unsigned long data);
+void xhci_handle_command_timeout(struct work_struct *work);
 
 void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id,
                unsigned int ep_index, unsigned int stream_id);
index 310238c6b5cd699bcd89ef101b926feba5d60a8c..8967980718170d5119d6331ed8395dfa2f4fa970 100644 (file)
@@ -469,6 +469,7 @@ static const struct musb_platform_ops bfin_ops = {
        .init           = bfin_musb_init,
        .exit           = bfin_musb_exit,
 
+       .fifo_offset    = bfin_fifo_offset,
        .readb          = bfin_readb,
        .writeb         = bfin_writeb,
        .readw          = bfin_readw,
index 9e226468a13eb07af0bf5a6407d81cd304436369..772f1582124255d749ab470a42394498af8f9741 100644 (file)
@@ -594,11 +594,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                                                | MUSB_PORT_STAT_RESUME;
                                musb->rh_timer = jiffies
                                        + msecs_to_jiffies(USB_RESUME_TIMEOUT);
-                               musb->need_finish_resume = 1;
-
                                musb->xceiv->otg->state = OTG_STATE_A_HOST;
                                musb->is_active = 1;
                                musb_host_resume_root_hub(musb);
+                               schedule_delayed_work(&musb->finish_resume_work,
+                                       msecs_to_jiffies(USB_RESUME_TIMEOUT));
                                break;
                        case OTG_STATE_B_WAIT_ACON:
                                musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL;
@@ -1925,6 +1925,14 @@ static void musb_pm_runtime_check_session(struct musb *musb)
 static void musb_irq_work(struct work_struct *data)
 {
        struct musb *musb = container_of(data, struct musb, irq_work.work);
+       int error;
+
+       error = pm_runtime_get_sync(musb->controller);
+       if (error < 0) {
+               dev_err(musb->controller, "Could not enable: %i\n", error);
+
+               return;
+       }
 
        musb_pm_runtime_check_session(musb);
 
@@ -1932,6 +1940,9 @@ static void musb_irq_work(struct work_struct *data)
                musb->xceiv_old_state = musb->xceiv->otg->state;
                sysfs_notify(&musb->controller->kobj, NULL, "mode");
        }
+
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
 }
 
 static void musb_recover_from_babble(struct musb *musb)
@@ -2050,6 +2061,7 @@ struct musb_pending_work {
        struct list_head node;
 };
 
+#ifdef CONFIG_PM
 /*
  * Called from musb_runtime_resume(), musb_resume(), and
  * musb_queue_resume_work(). Callers must take musb->lock.
@@ -2077,6 +2089,7 @@ static int musb_run_resume_work(struct musb *musb)
 
        return error;
 }
+#endif
 
 /*
  * Called to run work if device is active or else queue the work to happen
@@ -2708,11 +2721,6 @@ static int musb_resume(struct device *dev)
        mask = MUSB_DEVCTL_BDEVICE | MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV;
        if ((devctl & mask) != (musb->context.devctl & mask))
                musb->port1_status = 0;
-       if (musb->need_finish_resume) {
-               musb->need_finish_resume = 0;
-               schedule_delayed_work(&musb->finish_resume_work,
-                                     msecs_to_jiffies(USB_RESUME_TIMEOUT));
-       }
 
        /*
         * The USB HUB code expects the device to be in RPM_ACTIVE once it came
@@ -2764,12 +2772,6 @@ static int musb_runtime_resume(struct device *dev)
 
        musb_restore_context(musb);
 
-       if (musb->need_finish_resume) {
-               musb->need_finish_resume = 0;
-               schedule_delayed_work(&musb->finish_resume_work,
-                               msecs_to_jiffies(USB_RESUME_TIMEOUT));
-       }
-
        spin_lock_irqsave(&musb->lock, flags);
        error = musb_run_resume_work(musb);
        if (error)
index a611e2f67bdc9e3233e4d6efde27d8ce18fe0a67..ce5a18c98c6d1134231a29fa9229cf6804a0ae6e 100644 (file)
@@ -216,6 +216,7 @@ struct musb_platform_ops {
        void    (*pre_root_reset_end)(struct musb *musb);
        void    (*post_root_reset_end)(struct musb *musb);
        int     (*phy_callback)(enum musb_vbus_id_status status);
+       void    (*clear_ep_rxintr)(struct musb *musb, int epnum);
 };
 
 /*
@@ -409,7 +410,6 @@ struct musb {
 
        /* is_suspended means USB B_PERIPHERAL suspend */
        unsigned                is_suspended:1;
-       unsigned                need_finish_resume :1;
 
        /* may_wakeup means remote wakeup is enabled */
        unsigned                may_wakeup:1;
@@ -626,6 +626,12 @@ static inline void musb_platform_post_root_reset_end(struct musb *musb)
                musb->ops->post_root_reset_end(musb);
 }
 
+static inline void musb_platform_clear_ep_rxintr(struct musb *musb, int epnum)
+{
+       if (musb->ops->clear_ep_rxintr)
+               musb->ops->clear_ep_rxintr(musb, epnum);
+}
+
 /*
  * gets the "dr_mode" property from DT and converts it into musb_mode
  * if the property is not found or not recognized returns MUSB_OTG
index 4fef50e5c8c1295364aca0a28ba9cf8da005ac21..dd70c88419d20798b738c3da2df009887fdfec7f 100644 (file)
@@ -114,6 +114,7 @@ static int musb_regdump_show(struct seq_file *s, void *unused)
        unsigned                i;
 
        seq_printf(s, "MUSB (M)HDRC Register Dump\n");
+       pm_runtime_get_sync(musb->controller);
 
        for (i = 0; i < ARRAY_SIZE(musb_regmap); i++) {
                switch (musb_regmap[i].size) {
@@ -132,6 +133,8 @@ static int musb_regdump_show(struct seq_file *s, void *unused)
                }
        }
 
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
        return 0;
 }
 
@@ -145,7 +148,10 @@ static int musb_test_mode_show(struct seq_file *s, void *unused)
        struct musb             *musb = s->private;
        unsigned                test;
 
+       pm_runtime_get_sync(musb->controller);
        test = musb_readb(musb->mregs, MUSB_TESTMODE);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
 
        if (test & MUSB_TEST_FORCE_HOST)
                seq_printf(s, "force host\n");
@@ -194,11 +200,12 @@ static ssize_t musb_test_mode_write(struct file *file,
        u8                      test;
        char                    buf[18];
 
+       pm_runtime_get_sync(musb->controller);
        test = musb_readb(musb->mregs, MUSB_TESTMODE);
        if (test) {
                dev_err(musb->controller, "Error: test mode is already set. "
                        "Please do USB Bus Reset to start a new test.\n");
-               return count;
+               goto ret;
        }
 
        memset(buf, 0x00, sizeof(buf));
@@ -234,6 +241,9 @@ static ssize_t musb_test_mode_write(struct file *file,
 
        musb_writeb(musb->mregs, MUSB_TESTMODE, test);
 
+ret:
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
        return count;
 }
 
@@ -254,8 +264,13 @@ static int musb_softconnect_show(struct seq_file *s, void *unused)
        switch (musb->xceiv->otg->state) {
        case OTG_STATE_A_HOST:
        case OTG_STATE_A_WAIT_BCON:
+               pm_runtime_get_sync(musb->controller);
+
                reg = musb_readb(musb->mregs, MUSB_DEVCTL);
                connect = reg & MUSB_DEVCTL_SESSION ? 1 : 0;
+
+               pm_runtime_mark_last_busy(musb->controller);
+               pm_runtime_put_autosuspend(musb->controller);
                break;
        default:
                connect = -1;
@@ -284,6 +299,7 @@ static ssize_t musb_softconnect_write(struct file *file,
        if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
                return -EFAULT;
 
+       pm_runtime_get_sync(musb->controller);
        if (!strncmp(buf, "0", 1)) {
                switch (musb->xceiv->otg->state) {
                case OTG_STATE_A_HOST:
@@ -314,6 +330,8 @@ static ssize_t musb_softconnect_write(struct file *file,
                }
        }
 
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
        return count;
 }
 
index feae1561b9abb6924d2fe2fc6f1222dfac9d2be7..9f125e179acd444ca43c73a1a5d263b8e5c8893d 100644 (file)
@@ -267,6 +267,17 @@ static void otg_timer(unsigned long _musb)
        pm_runtime_put_autosuspend(dev);
 }
 
+void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum)
+{
+       u32 epintr;
+       struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
+       const struct dsps_musb_wrapper *wrp = glue->wrp;
+
+       /* musb->lock might already been held */
+       epintr = (1 << epnum) << wrp->rxep_shift;
+       musb_writel(musb->ctrl_base, wrp->epintr_status, epintr);
+}
+
 static irqreturn_t dsps_interrupt(int irq, void *hci)
 {
        struct musb  *musb = hci;
@@ -622,6 +633,7 @@ static struct musb_platform_ops dsps_ops = {
 
        .set_mode       = dsps_musb_set_mode,
        .recover        = dsps_musb_recover,
+       .clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
 };
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
index f6cdbad00daceb5837a8cfcdec37438389aae800..ac3a4952abb4b290b019ac59fbddd7004b50d949 100644 (file)
@@ -2374,12 +2374,11 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
        int                     is_in = usb_pipein(urb->pipe);
        int                     status = 0;
        u16                     csr;
+       struct dma_channel      *dma = NULL;
 
        musb_ep_select(regs, hw_end);
 
        if (is_dma_capable()) {
-               struct dma_channel      *dma;
-
                dma = is_in ? ep->rx_channel : ep->tx_channel;
                if (dma) {
                        status = ep->musb->dma_controller->channel_abort(dma);
@@ -2395,10 +2394,9 @@ static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
                /* giveback saves bulk toggle */
                csr = musb_h_flush_rxfifo(ep, 0);
 
-               /* REVISIT we still get an irq; should likely clear the
-                * endpoint's irq status here to avoid bogus irqs.
-                * clearing that status is platform-specific...
-                */
+               /* clear the endpoint's irq status here to avoid bogus irqs */
+               if (is_dma_capable() && dma)
+                       musb_platform_clear_ep_rxintr(musb, ep->epnum);
        } else if (ep->epnum) {
                musb_h_tx_flush_fifo(ep);
                csr = musb_readw(epio, MUSB_TXCSR);
index f7b13fd252574f848e7984905cbaef4478c2e90a..a3dcbd55e43609b3140979d971a43426a1ce3db0 100644 (file)
@@ -157,5 +157,5 @@ struct musb_dma_controller {
        void __iomem                    *base;
        u8                              channel_count;
        u8                              used_channels;
-       u8                              irq;
+       int                             irq;
 };
index 2597b83a8ae254d0eff28b2d2d124ff51c196248..95aa5233726cf86166ae5aad2ea88c446e894d13 100644 (file)
@@ -95,6 +95,7 @@ struct ch341_private {
        unsigned baud_rate; /* set baud rate */
        u8 line_control; /* set line control value RTS/DTR */
        u8 line_status; /* active status of modem control inputs */
+       u8 lcr;
 };
 
 static void ch341_set_termios(struct tty_struct *tty,
@@ -112,6 +113,8 @@ static int ch341_control_out(struct usb_device *dev, u8 request,
        r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
                            USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
                            value, index, NULL, 0, DEFAULT_TIMEOUT);
+       if (r < 0)
+               dev_err(&dev->dev, "failed to send control message: %d\n", r);
 
        return r;
 }
@@ -129,11 +132,24 @@ static int ch341_control_in(struct usb_device *dev,
        r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request,
                            USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                            value, index, buf, bufsize, DEFAULT_TIMEOUT);
-       return r;
+       if (r < bufsize) {
+               if (r >= 0) {
+                       dev_err(&dev->dev,
+                               "short control message received (%d < %u)\n",
+                               r, bufsize);
+                       r = -EIO;
+               }
+
+               dev_err(&dev->dev, "failed to receive control message: %d\n",
+                       r);
+               return r;
+       }
+
+       return 0;
 }
 
-static int ch341_init_set_baudrate(struct usb_device *dev,
-                                  struct ch341_private *priv, unsigned ctrl)
+static int ch341_set_baudrate_lcr(struct usb_device *dev,
+                                 struct ch341_private *priv, u8 lcr)
 {
        short a;
        int r;
@@ -156,9 +172,19 @@ static int ch341_init_set_baudrate(struct usb_device *dev,
        factor = 0x10000 - factor;
        a = (factor & 0xff00) | divisor;
 
-       /* 0x9c is "enable SFR_UART Control register and timer" */
-       r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT,
-                             0x9c | (ctrl << 8), a | 0x80);
+       /*
+        * CH341A buffers data until a full endpoint-size packet (32 bytes)
+        * has been received unless bit 7 is set.
+        */
+       a |= BIT(7);
+
+       r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x1312, a);
+       if (r)
+               return r;
+
+       r = ch341_control_out(dev, CH341_REQ_WRITE_REG, 0x2518, lcr);
+       if (r)
+               return r;
 
        return r;
 }
@@ -170,9 +196,9 @@ static int ch341_set_handshake(struct usb_device *dev, u8 control)
 
 static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
 {
+       const unsigned int size = 2;
        char *buffer;
        int r;
-       const unsigned size = 8;
        unsigned long flags;
 
        buffer = kmalloc(size, GFP_KERNEL);
@@ -183,14 +209,9 @@ static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
        if (r < 0)
                goto out;
 
-       /* setup the private status if available */
-       if (r == 2) {
-               r = 0;
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
-               spin_unlock_irqrestore(&priv->lock, flags);
-       } else
-               r = -EPROTO;
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
+       spin_unlock_irqrestore(&priv->lock, flags);
 
 out:   kfree(buffer);
        return r;
@@ -200,9 +221,9 @@ out:        kfree(buffer);
 
 static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
 {
+       const unsigned int size = 2;
        char *buffer;
        int r;
-       const unsigned size = 8;
 
        buffer = kmalloc(size, GFP_KERNEL);
        if (!buffer)
@@ -232,7 +253,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
        if (r < 0)
                goto out;
 
-       r = ch341_init_set_baudrate(dev, priv, 0);
+       r = ch341_set_baudrate_lcr(dev, priv, priv->lcr);
        if (r < 0)
                goto out;
 
@@ -258,7 +279,6 @@ static int ch341_port_probe(struct usb_serial_port *port)
 
        spin_lock_init(&priv->lock);
        priv->baud_rate = DEFAULT_BAUD_RATE;
-       priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
        r = ch341_configure(port->serial->dev, priv);
        if (r < 0)
@@ -320,7 +340,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
 
        r = ch341_configure(serial->dev, priv);
        if (r)
-               goto out;
+               return r;
 
        if (tty)
                ch341_set_termios(tty, port, NULL);
@@ -330,12 +350,19 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
        if (r) {
                dev_err(&port->dev, "%s - failed to submit interrupt urb: %d\n",
                        __func__, r);
-               goto out;
+               return r;
        }
 
        r = usb_serial_generic_open(tty, port);
+       if (r)
+               goto err_kill_interrupt_urb;
+
+       return 0;
+
+err_kill_interrupt_urb:
+       usb_kill_urb(port->interrupt_in_urb);
 
-out:   return r;
+       return r;
 }
 
 /* Old_termios contains the original termios settings and
@@ -356,7 +383,6 @@ static void ch341_set_termios(struct tty_struct *tty,
 
        baud_rate = tty_get_baud_rate(tty);
 
-       priv->baud_rate = baud_rate;
        ctrl = CH341_LCR_ENABLE_RX | CH341_LCR_ENABLE_TX;
 
        switch (C_CSIZE(tty)) {
@@ -386,22 +412,25 @@ static void ch341_set_termios(struct tty_struct *tty,
                ctrl |= CH341_LCR_STOP_BITS_2;
 
        if (baud_rate) {
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
-               spin_unlock_irqrestore(&priv->lock, flags);
-               r = ch341_init_set_baudrate(port->serial->dev, priv, ctrl);
+               priv->baud_rate = baud_rate;
+
+               r = ch341_set_baudrate_lcr(port->serial->dev, priv, ctrl);
                if (r < 0 && old_termios) {
                        priv->baud_rate = tty_termios_baud_rate(old_termios);
                        tty_termios_copy_hw(&tty->termios, old_termios);
+               } else if (r == 0) {
+                       priv->lcr = ctrl;
                }
-       } else {
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
-               spin_unlock_irqrestore(&priv->lock, flags);
        }
 
-       ch341_set_handshake(port->serial->dev, priv->line_control);
+       spin_lock_irqsave(&priv->lock, flags);
+       if (C_BAUD(tty) == B0)
+               priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
+       else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
+               priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
+       ch341_set_handshake(port->serial->dev, priv->line_control);
 }
 
 static void ch341_break_ctl(struct tty_struct *tty, int break_state)
@@ -576,14 +605,23 @@ static int ch341_tiocmget(struct tty_struct *tty)
 
 static int ch341_reset_resume(struct usb_serial *serial)
 {
-       struct ch341_private *priv;
-
-       priv = usb_get_serial_port_data(serial->port[0]);
+       struct usb_serial_port *port = serial->port[0];
+       struct ch341_private *priv = usb_get_serial_port_data(port);
+       int ret;
 
        /* reconfigure ch341 serial port after bus-reset */
        ch341_configure(serial->dev, priv);
 
-       return 0;
+       if (tty_port_initialized(&port->port)) {
+               ret = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+               if (ret) {
+                       dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       return usb_serial_generic_resume(serial);
 }
 
 static struct usb_serial_driver ch341_device = {
index 5f17a3b9916d79ea28c82b04755e23d5680d4b2d..80260b08398b2e55833c65d21e0be70cc43ccf01 100644 (file)
@@ -50,6 +50,7 @@
 #define CYBERJACK_PRODUCT_ID   0x0100
 
 /* Function prototypes */
+static int cyberjack_attach(struct usb_serial *serial);
 static int cyberjack_port_probe(struct usb_serial_port *port);
 static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
@@ -77,6 +78,7 @@ static struct usb_serial_driver cyberjack_device = {
        .description =          "Reiner SCT Cyberjack USB card reader",
        .id_table =             id_table,
        .num_ports =            1,
+       .attach =               cyberjack_attach,
        .port_probe =           cyberjack_port_probe,
        .port_remove =          cyberjack_port_remove,
        .open =                 cyberjack_open,
@@ -100,6 +102,14 @@ struct cyberjack_private {
        short           wrsent;         /* Data already sent */
 };
 
+static int cyberjack_attach(struct usb_serial *serial)
+{
+       if (serial->num_bulk_out < serial->num_ports)
+               return -ENODEV;
+
+       return 0;
+}
+
 static int cyberjack_port_probe(struct usb_serial_port *port)
 {
        struct cyberjack_private *priv;
index 8282a6a18fee83f6f1838b2f6f55b37a0ec4d409..22f23a429a95cb6a1cdeaca445a92035fd3e98e8 100644 (file)
@@ -1237,6 +1237,7 @@ static int f81534_attach(struct usb_serial *serial)
 static int f81534_port_probe(struct usb_serial_port *port)
 {
        struct f81534_port_private *port_priv;
+       int ret;
 
        port_priv = devm_kzalloc(&port->dev, sizeof(*port_priv), GFP_KERNEL);
        if (!port_priv)
@@ -1246,10 +1247,11 @@ static int f81534_port_probe(struct usb_serial_port *port)
        mutex_init(&port_priv->mcr_mutex);
 
        /* Assign logic-to-phy mapping */
-       port_priv->phy_num = f81534_logic_to_phy_port(port->serial, port);
-       if (port_priv->phy_num < 0 || port_priv->phy_num >= F81534_NUM_PORT)
-               return -ENODEV;
+       ret = f81534_logic_to_phy_port(port->serial, port);
+       if (ret < 0)
+               return ret;
 
+       port_priv->phy_num = ret;
        usb_set_serial_port_data(port, port_priv);
        dev_dbg(&port->dev, "%s: port_number: %d, phy_num: %d\n", __func__,
                        port->port_number, port_priv->phy_num);
index 97cabf803c2fa91a134c957dba74c4f77b97c712..b2f2e87aed945d7aceac24c99cf2f7c401beb5b2 100644 (file)
@@ -1043,6 +1043,7 @@ static int garmin_write_bulk(struct usb_serial_port *port,
                   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
                                __func__, status);
                count = status;
+               kfree(buffer);
        }
 
        /* we are done with this urb, so let the host driver
index dcc0c58aaad5adaf89bdd535d4cd9699445de3ac..d50e5773483f5494be90ff42633cff70012079cc 100644 (file)
@@ -2751,6 +2751,11 @@ static int edge_startup(struct usb_serial *serial)
                                        EDGE_COMPATIBILITY_MASK1,
                                        EDGE_COMPATIBILITY_MASK2 };
 
+       if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
        dev = serial->dev;
 
        /* create our private serial structure */
index c339163698eb9960f8cc71735d8ed1cf24905e75..9a0db2965fbb45df5fd6b67f5eddb9d90969869c 100644 (file)
@@ -1499,8 +1499,7 @@ static int do_boot_mode(struct edgeport_serial *serial,
 
                dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__);
 
-               /* return an error on purpose */
-               return -ENODEV;
+               return 1;
        }
 
 stayinbootmode:
@@ -1508,7 +1507,7 @@ stayinbootmode:
        dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__);
        serial->product_info.TiMode = TI_MODE_BOOT;
 
-       return 0;
+       return 1;
 }
 
 static int ti_do_config(struct edgeport_port *port, int feature, int on)
@@ -2546,6 +2545,13 @@ static int edge_startup(struct usb_serial *serial)
        int status;
        u16 product_id;
 
+       /* Make sure we have the required endpoints when in download mode. */
+       if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) {
+               if (serial->num_bulk_in < serial->num_ports ||
+                               serial->num_bulk_out < serial->num_ports)
+                       return -ENODEV;
+       }
+
        /* create our private serial structure */
        edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
        if (!edge_serial)
@@ -2553,14 +2559,18 @@ static int edge_startup(struct usb_serial *serial)
 
        mutex_init(&edge_serial->es_lock);
        edge_serial->serial = serial;
+       INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
        usb_set_serial_data(serial, edge_serial);
 
        status = download_fw(edge_serial);
-       if (status) {
+       if (status < 0) {
                kfree(edge_serial);
                return status;
        }
 
+       if (status > 0)
+               return 1;       /* bind but do not register any ports */
+
        product_id = le16_to_cpu(
                        edge_serial->serial->dev->descriptor.idProduct);
 
@@ -2572,7 +2582,6 @@ static int edge_startup(struct usb_serial *serial)
                }
        }
 
-       INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
        edge_heartbeat_schedule(edge_serial);
 
        return 0;
@@ -2580,6 +2589,9 @@ static int edge_startup(struct usb_serial *serial)
 
 static void edge_disconnect(struct usb_serial *serial)
 {
+       struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+       cancel_delayed_work_sync(&edge_serial->heartbeat_work);
 }
 
 static void edge_release(struct usb_serial *serial)
index 344b4eea4bd59c4da0590f538323f37b5ed74074..d57fb51992182afec68a28fce42a242a4cd46ff2 100644 (file)
@@ -68,6 +68,16 @@ struct iuu_private {
        u32 clk;
 };
 
+static int iuu_attach(struct usb_serial *serial)
+{
+       unsigned char num_ports = serial->num_ports;
+
+       if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports)
+               return -ENODEV;
+
+       return 0;
+}
+
 static int iuu_port_probe(struct usb_serial_port *port)
 {
        struct iuu_private *priv;
@@ -1196,6 +1206,7 @@ static struct usb_serial_driver iuu_device = {
        .tiocmset = iuu_tiocmset,
        .set_termios = iuu_set_termios,
        .init_termios = iuu_init_termios,
+       .attach = iuu_attach,
        .port_probe = iuu_port_probe,
        .port_remove = iuu_port_remove,
 };
index e49ad0c63ad8b54c61995965445054e34cda6869..83523fcf6fb9d6a75bfba7738362e1c8bbfa01c9 100644 (file)
@@ -699,6 +699,19 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
 MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
 #endif
 
+static int keyspan_pda_attach(struct usb_serial *serial)
+{
+       unsigned char num_ports = serial->num_ports;
+
+       if (serial->num_bulk_out < num_ports ||
+                       serial->num_interrupt_in < num_ports) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 static int keyspan_pda_port_probe(struct usb_serial_port *port)
 {
 
@@ -776,6 +789,7 @@ static struct usb_serial_driver keyspan_pda_device = {
        .break_ctl =            keyspan_pda_break_ctl,
        .tiocmget =             keyspan_pda_tiocmget,
        .tiocmset =             keyspan_pda_tiocmset,
+       .attach =               keyspan_pda_attach,
        .port_probe =           keyspan_pda_port_probe,
        .port_remove =          keyspan_pda_port_remove,
 };
index 0ee190fc1bf8ce7154a4a4eac7023a377aa03365..6cb45757818fae2222383358b4d38d7c87b2dbf4 100644 (file)
@@ -192,10 +192,11 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
                             status_buf, KLSI_STATUSBUF_LEN,
                             10000
                             );
-       if (rc < 0)
-               dev_err(&port->dev, "Reading line status failed (error = %d)\n",
-                       rc);
-       else {
+       if (rc != KLSI_STATUSBUF_LEN) {
+               dev_err(&port->dev, "reading line status failed: %d\n", rc);
+               if (rc >= 0)
+                       rc = -EIO;
+       } else {
                status = get_unaligned_le16(status_buf);
 
                dev_info(&port->serial->dev->dev, "read status %x %x\n",
index 2363654cafc9b79de61a30bcc00b7f875c470b60..813035f51fe73a4e0de69ce76e6c3329ba4d376c 100644 (file)
@@ -51,6 +51,7 @@
 
 
 /* Function prototypes */
+static int kobil_attach(struct usb_serial *serial);
 static int kobil_port_probe(struct usb_serial_port *probe);
 static int kobil_port_remove(struct usb_serial_port *probe);
 static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
@@ -86,6 +87,7 @@ static struct usb_serial_driver kobil_device = {
        .description =          "KOBIL USB smart card terminal",
        .id_table =             id_table,
        .num_ports =            1,
+       .attach =               kobil_attach,
        .port_probe =           kobil_port_probe,
        .port_remove =          kobil_port_remove,
        .ioctl =                kobil_ioctl,
@@ -113,6 +115,16 @@ struct kobil_private {
 };
 
 
+static int kobil_attach(struct usb_serial *serial)
+{
+       if (serial->num_interrupt_out < serial->num_ports) {
+               dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 static int kobil_port_probe(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
index d52caa03679c6cbc5886316cb27d471d0c4b7bc4..91bc170b408a08a59c49786e2cb5753149ce2425 100644 (file)
@@ -65,8 +65,6 @@ struct moschip_port {
        struct urb              *write_urb_pool[NUM_URBS];
 };
 
-static struct usb_serial_driver moschip7720_2port_driver;
-
 #define USB_VENDOR_ID_MOSCHIP          0x9710
 #define MOSCHIP_DEVICE_ID_7720         0x7720
 #define MOSCHIP_DEVICE_ID_7715         0x7715
@@ -970,25 +968,6 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
                tty_port_tty_wakeup(&mos7720_port->port->port);
 }
 
-/*
- * mos77xx_probe
- *     this function installs the appropriate read interrupt endpoint callback
- *     depending on whether the device is a 7720 or 7715, thus avoiding costly
- *     run-time checks in the high-frequency callback routine itself.
- */
-static int mos77xx_probe(struct usb_serial *serial,
-                        const struct usb_device_id *id)
-{
-       if (id->idProduct == MOSCHIP_DEVICE_ID_7715)
-               moschip7720_2port_driver.read_int_callback =
-                       mos7715_interrupt_callback;
-       else
-               moschip7720_2port_driver.read_int_callback =
-                       mos7720_interrupt_callback;
-
-       return 0;
-}
-
 static int mos77xx_calc_num_ports(struct usb_serial *serial)
 {
        u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
@@ -1917,6 +1896,11 @@ static int mos7720_startup(struct usb_serial *serial)
        u16 product;
        int ret_val;
 
+       if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) {
+               dev_err(&serial->interface->dev, "missing bulk endpoints\n");
+               return -ENODEV;
+       }
+
        product = le16_to_cpu(serial->dev->descriptor.idProduct);
        dev = serial->dev;
 
@@ -1941,19 +1925,18 @@ static int mos7720_startup(struct usb_serial *serial)
                        tmp->interrupt_in_endpointAddress;
                serial->port[1]->interrupt_in_urb = NULL;
                serial->port[1]->interrupt_in_buffer = NULL;
+
+               if (serial->port[0]->interrupt_in_urb) {
+                       struct urb *urb = serial->port[0]->interrupt_in_urb;
+
+                       urb->complete = mos7715_interrupt_callback;
+               }
        }
 
        /* setting configuration feature to one */
        usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                        (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000);
 
-       /* start the interrupt urb */
-       ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
-       if (ret_val)
-               dev_err(&dev->dev,
-                       "%s - Error %d submitting control urb\n",
-                       __func__, ret_val);
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
        if (product == MOSCHIP_DEVICE_ID_7715) {
                ret_val = mos7715_parport_init(serial);
@@ -1961,6 +1944,13 @@ static int mos7720_startup(struct usb_serial *serial)
                        return ret_val;
        }
 #endif
+       /* start the interrupt urb */
+       ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL);
+       if (ret_val) {
+               dev_err(&dev->dev, "failed to submit interrupt urb: %d\n",
+                       ret_val);
+       }
+
        /* LSR For Port 1 */
        read_mos_reg(serial, 0, MOS7720_LSR, &data);
        dev_dbg(&dev->dev, "LSR:%x\n", data);
@@ -1970,6 +1960,8 @@ static int mos7720_startup(struct usb_serial *serial)
 
 static void mos7720_release(struct usb_serial *serial)
 {
+       usb_kill_urb(serial->port[0]->interrupt_in_urb);
+
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
        /* close the parallel port */
 
@@ -2019,11 +2011,6 @@ static int mos7720_port_probe(struct usb_serial_port *port)
        if (!mos7720_port)
                return -ENOMEM;
 
-       /* Initialize all port interrupt end point to port 0 int endpoint.
-        * Our device has only one interrupt endpoint common to all ports.
-        */
-       port->interrupt_in_endpointAddress =
-               port->serial->port[0]->interrupt_in_endpointAddress;
        mos7720_port->port = port;
 
        usb_set_serial_port_data(port, mos7720_port);
@@ -2053,7 +2040,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .close                  = mos7720_close,
        .throttle               = mos7720_throttle,
        .unthrottle             = mos7720_unthrottle,
-       .probe                  = mos77xx_probe,
        .attach                 = mos7720_startup,
        .release                = mos7720_release,
        .port_probe             = mos7720_port_probe,
@@ -2067,7 +2053,7 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .chars_in_buffer        = mos7720_chars_in_buffer,
        .break_ctl              = mos7720_break,
        .read_bulk_callback     = mos7720_bulk_in_callback,
-       .read_int_callback      = NULL  /* dynamically assigned in probe() */
+       .read_int_callback      = mos7720_interrupt_callback,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 9a220b8e810f161be985d9655ec6d9dee90147dc..ea27fb23967a13dd3e3c47d31fdaab52c38028eb 100644 (file)
@@ -214,7 +214,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 struct moschip_port {
        int port_num;           /*Actual port number in the device(1,2,etc) */
-       struct urb *write_urb;  /* write URB for this port */
        struct urb *read_urb;   /* read URB for this port */
        __u8 shadowLCR;         /* last LCR value received */
        __u8 shadowMCR;         /* last MCR value received */
@@ -1037,9 +1036,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
                                serial,
                                serial->port[0]->interrupt_in_urb->interval);
 
-                       /* start interrupt read for mos7840               *
-                        * will continue as long as mos7840 is connected  */
-
+                       /* start interrupt read for mos7840 */
                        response =
                            usb_submit_urb(serial->port[0]->interrupt_in_urb,
                                           GFP_KERNEL);
@@ -1186,7 +1183,6 @@ static void mos7840_close(struct usb_serial_port *port)
                }
        }
 
-       usb_kill_urb(mos7840_port->write_urb);
        usb_kill_urb(mos7840_port->read_urb);
        mos7840_port->read_urb_busy = false;
 
@@ -1199,12 +1195,6 @@ static void mos7840_close(struct usb_serial_port *port)
                }
        }
 
-       if (mos7840_port->write_urb) {
-               /* if this urb had a transfer buffer already (old tx) free it */
-               kfree(mos7840_port->write_urb->transfer_buffer);
-               usb_free_urb(mos7840_port->write_urb);
-       }
-
        Data = 0x0;
        mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
 
@@ -2113,6 +2103,17 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
        return mos7840_num_ports;
 }
 
+static int mos7840_attach(struct usb_serial *serial)
+{
+       if (serial->num_bulk_in < serial->num_ports ||
+                       serial->num_bulk_out < serial->num_ports) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 static int mos7840_port_probe(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
@@ -2388,6 +2389,7 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .tiocmset = mos7840_tiocmset,
        .tiocmiwait = usb_serial_generic_tiocmiwait,
        .get_icount = usb_serial_generic_get_icount,
+       .attach = mos7840_attach,
        .port_probe = mos7840_port_probe,
        .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
index f6c6900bccf01c87c88734b2a7417db9f0fade8d..a180b17d24323b074aee19e33bf0f497ad271d8a 100644 (file)
@@ -38,6 +38,7 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                                const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
+static int omninet_attach(struct usb_serial *serial);
 static int omninet_port_probe(struct usb_serial_port *port);
 static int omninet_port_remove(struct usb_serial_port *port);
 
@@ -56,6 +57,7 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .description =          "ZyXEL - omni.net lcd plus usb",
        .id_table =             id_table,
        .num_ports =            1,
+       .attach =               omninet_attach,
        .port_probe =           omninet_port_probe,
        .port_remove =          omninet_port_remove,
        .open =                 omninet_open,
@@ -104,6 +106,17 @@ struct omninet_data {
        __u8    od_outseq;      /* Sequence number for bulk_out URBs */
 };
 
+static int omninet_attach(struct usb_serial *serial)
+{
+       /* The second bulk-out endpoint is used for writing. */
+       if (serial->num_bulk_out < 2) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 static int omninet_port_probe(struct usb_serial_port *port)
 {
        struct omninet_data *od;
index 7ce31a4c7e7fd3d186e8e05b20b9a3ca52700b6c..42cc72e54c051b2115c358bcee8bfc534258d206 100644 (file)
@@ -2007,6 +2007,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index a4b88bc038b6d0a943b76457714e65a9449881b2..b8bf52bf7a944d5fddd6976f90a63db3cd6807e5 100644 (file)
@@ -134,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
                                unsigned int set, unsigned int clear);
+static int oti6858_attach(struct usb_serial *serial);
 static int oti6858_port_probe(struct usb_serial_port *port);
 static int oti6858_port_remove(struct usb_serial_port *port);
 
@@ -158,6 +159,7 @@ static struct usb_serial_driver oti6858_device = {
        .write_bulk_callback =  oti6858_write_bulk_callback,
        .write_room =           oti6858_write_room,
        .chars_in_buffer =      oti6858_chars_in_buffer,
+       .attach =               oti6858_attach,
        .port_probe =           oti6858_port_probe,
        .port_remove =          oti6858_port_remove,
 };
@@ -324,6 +326,20 @@ static void send_data(struct work_struct *work)
        usb_serial_port_softint(port);
 }
 
+static int oti6858_attach(struct usb_serial *serial)
+{
+       unsigned char num_ports = serial->num_ports;
+
+       if (serial->num_bulk_in < num_ports ||
+                       serial->num_bulk_out < num_ports ||
+                       serial->num_interrupt_in < num_ports) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 static int oti6858_port_probe(struct usb_serial_port *port)
 {
        struct oti6858_private *priv;
index ae682e4eeaef575a23c90a8dda15407e862d42e1..1db4b61bdf7bd710d7be6e3ff81b97102d76fbe9 100644 (file)
@@ -49,6 +49,7 @@ static const struct usb_device_id id_table[] = {
        { 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) },
+       { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID2) },
        { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
        { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
        { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID_UCSGT) },
@@ -220,9 +221,17 @@ static int pl2303_probe(struct usb_serial *serial,
 static int pl2303_startup(struct usb_serial *serial)
 {
        struct pl2303_serial_private *spriv;
+       unsigned char num_ports = serial->num_ports;
        enum pl2303_type type = TYPE_01;
        unsigned char *buf;
 
+       if (serial->num_bulk_in < num_ports ||
+                       serial->num_bulk_out < num_ports ||
+                       serial->num_interrupt_in < num_ports) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
        spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
        if (!spriv)
                return -ENOMEM;
index e3b7af8adfb73ccefa92d4ba3c2c927a044dfa43..09d9be88209e1ce6b1f53dc052a53c5e4c491336 100644 (file)
@@ -27,6 +27,7 @@
 #define ATEN_VENDOR_ID         0x0557
 #define ATEN_VENDOR_ID2                0x0547
 #define ATEN_PRODUCT_ID                0x2008
+#define ATEN_PRODUCT_ID2       0x2118
 
 #define IODATA_VENDOR_ID       0x04bb
 #define IODATA_PRODUCT_ID      0x0a03
index 1bc6089b90083a05e0ef3e4ff71c0ef752e3831a..696458db7e3c45e661a9825d05df0fe25dc0a832 100644 (file)
@@ -124,6 +124,7 @@ static const struct usb_device_id id_table[] = {
        {USB_DEVICE(0x1410, 0xa021)},   /* Novatel Gobi 3000 Composite */
        {USB_DEVICE(0x413c, 0x8193)},   /* Dell Gobi 3000 QDL */
        {USB_DEVICE(0x413c, 0x8194)},   /* Dell Gobi 3000 Composite */
+       {USB_DEVICE(0x413c, 0x81a6)},   /* Dell DW5570 QDL (MC8805) */
        {USB_DEVICE(0x1199, 0x68a4)},   /* Sierra Wireless QDL */
        {USB_DEVICE(0x1199, 0x68a5)},   /* Sierra Wireless Modem */
        {USB_DEVICE(0x1199, 0x68a8)},   /* Sierra Wireless QDL */
index 659cb8606bd953a7585a013beeb3dc3989400a14..5709cc93b0837a0b73a8acec627caa05e27c9b64 100644 (file)
@@ -408,16 +408,12 @@ static void qt2_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial;
        struct qt2_port_private *port_priv;
-       unsigned long flags;
        int i;
 
        serial = port->serial;
        port_priv = usb_get_serial_port_data(port);
 
-       spin_lock_irqsave(&port_priv->urb_lock, flags);
        usb_kill_urb(port_priv->write_urb);
-       port_priv->urb_in_use = false;
-       spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
index ef0dbf0703c574eb62d1e2ce3be49e5186258aee..475e6c31b266b013ed4749b482c0477eda4a3904 100644 (file)
@@ -154,6 +154,19 @@ static int spcp8x5_probe(struct usb_serial *serial,
        return 0;
 }
 
+static int spcp8x5_attach(struct usb_serial *serial)
+{
+       unsigned char num_ports = serial->num_ports;
+
+       if (serial->num_bulk_in < num_ports ||
+                       serial->num_bulk_out < num_ports) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
        const struct usb_device_id *id = usb_get_serial_data(port->serial);
@@ -477,6 +490,7 @@ static struct usb_serial_driver spcp8x5_device = {
        .tiocmget               = spcp8x5_tiocmget,
        .tiocmset               = spcp8x5_tiocmset,
        .probe                  = spcp8x5_probe,
+       .attach                 = spcp8x5_attach,
        .port_probe             = spcp8x5_port_probe,
        .port_remove            = spcp8x5_port_remove,
 };
index 8db9d071d9409a9f6e85ce6b23a1515f90f11157..64b85b8dedf33c9af7ea5faf68b7ea1a97335903 100644 (file)
@@ -579,6 +579,13 @@ static int ti_startup(struct usb_serial *serial)
                goto free_tdev;
        }
 
+       if (serial->num_bulk_in < serial->num_ports ||
+                       serial->num_bulk_out < serial->num_ports) {
+               dev_err(&serial->interface->dev, "missing endpoints\n");
+               status = -ENODEV;
+               goto free_tdev;
+       }
+
        return 0;
 
 free_tdev:
index af3c7eecff91d4a49fb1b49cdfce7b7d4c9b11fe..16cc18369111d039ffededa7559075a869638708 100644 (file)
@@ -2109,6 +2109,13 @@ UNUSUAL_DEV(  0x152d, 0x2566, 0x0114, 0x0114,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_BROKEN_FUA ),
 
+/* Reported-by George Cherian <george.cherian@cavium.com> */
+UNUSUAL_DEV(0x152d, 0x9561, 0x0000, 0x9999,
+               "JMicron",
+               "JMS56x",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_REPORT_OPCODES),
+
 /*
  * Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI)
  * and Mac USB Dock USB-SCSI */
index 79451f7ef1b76301cc881379ad28ce12e4b4dc33..062c205f00469faf1f7226e152f61d920d71f27b 100644 (file)
@@ -216,7 +216,6 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
        struct scatterlist sg[4], sg_dst;
        void *dst_buf;
        size_t dst_size;
-       const u8 bzero[16] = { 0 };
        u8 iv[crypto_skcipher_ivsize(tfm_cbc)];
        size_t zero_padding;
 
@@ -261,7 +260,7 @@ static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc,
        sg_set_buf(&sg[1], &scratch->b1, sizeof(scratch->b1));
        sg_set_buf(&sg[2], b, blen);
        /* 0 if well behaved :) */
-       sg_set_buf(&sg[3], bzero, zero_padding);
+       sg_set_page(&sg[3], ZERO_PAGE(0), zero_padding, 0);
        sg_init_one(&sg_dst, dst_buf, dst_size);
 
        skcipher_request_set_tfm(req, tfm_cbc);
index be1ee89ee9172f4408eab231c9b1e6a52a253c88..36d75c367d2215c4761f72d40b6c34eaf54bec02 100644 (file)
@@ -27,6 +27,45 @@ static LIST_HEAD(parent_list);
 static DEFINE_MUTEX(parent_list_lock);
 static struct class_compat *mdev_bus_compat_class;
 
+static LIST_HEAD(mdev_list);
+static DEFINE_MUTEX(mdev_list_lock);
+
+struct device *mdev_parent_dev(struct mdev_device *mdev)
+{
+       return mdev->parent->dev;
+}
+EXPORT_SYMBOL(mdev_parent_dev);
+
+void *mdev_get_drvdata(struct mdev_device *mdev)
+{
+       return mdev->driver_data;
+}
+EXPORT_SYMBOL(mdev_get_drvdata);
+
+void mdev_set_drvdata(struct mdev_device *mdev, void *data)
+{
+       mdev->driver_data = data;
+}
+EXPORT_SYMBOL(mdev_set_drvdata);
+
+struct device *mdev_dev(struct mdev_device *mdev)
+{
+       return &mdev->dev;
+}
+EXPORT_SYMBOL(mdev_dev);
+
+struct mdev_device *mdev_from_dev(struct device *dev)
+{
+       return dev_is_mdev(dev) ? to_mdev_device(dev) : NULL;
+}
+EXPORT_SYMBOL(mdev_from_dev);
+
+uuid_le mdev_uuid(struct mdev_device *mdev)
+{
+       return mdev->uuid;
+}
+EXPORT_SYMBOL(mdev_uuid);
+
 static int _find_mdev_device(struct device *dev, void *data)
 {
        struct mdev_device *mdev;
@@ -42,7 +81,7 @@ static int _find_mdev_device(struct device *dev, void *data)
        return 0;
 }
 
-static bool mdev_device_exist(struct parent_device *parent, uuid_le uuid)
+static bool mdev_device_exist(struct mdev_parent *parent, uuid_le uuid)
 {
        struct device *dev;
 
@@ -56,9 +95,9 @@ static bool mdev_device_exist(struct parent_device *parent, uuid_le uuid)
 }
 
 /* Should be called holding parent_list_lock */
-static struct parent_device *__find_parent_device(struct device *dev)
+static struct mdev_parent *__find_parent_device(struct device *dev)
 {
-       struct parent_device *parent;
+       struct mdev_parent *parent;
 
        list_for_each_entry(parent, &parent_list, next) {
                if (parent->dev == dev)
@@ -69,8 +108,8 @@ static struct parent_device *__find_parent_device(struct device *dev)
 
 static void mdev_release_parent(struct kref *kref)
 {
-       struct parent_device *parent = container_of(kref, struct parent_device,
-                                                   ref);
+       struct mdev_parent *parent = container_of(kref, struct mdev_parent,
+                                                 ref);
        struct device *dev = parent->dev;
 
        kfree(parent);
@@ -78,7 +117,7 @@ static void mdev_release_parent(struct kref *kref)
 }
 
 static
-inline struct parent_device *mdev_get_parent(struct parent_device *parent)
+inline struct mdev_parent *mdev_get_parent(struct mdev_parent *parent)
 {
        if (parent)
                kref_get(&parent->ref);
@@ -86,7 +125,7 @@ inline struct parent_device *mdev_get_parent(struct parent_device *parent)
        return parent;
 }
 
-static inline void mdev_put_parent(struct parent_device *parent)
+static inline void mdev_put_parent(struct mdev_parent *parent)
 {
        if (parent)
                kref_put(&parent->ref, mdev_release_parent);
@@ -95,7 +134,7 @@ static inline void mdev_put_parent(struct parent_device *parent)
 static int mdev_device_create_ops(struct kobject *kobj,
                                  struct mdev_device *mdev)
 {
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
        int ret;
 
        ret = parent->ops->create(kobj, mdev);
@@ -122,7 +161,7 @@ static int mdev_device_create_ops(struct kobject *kobj,
  */
 static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove)
 {
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
        int ret;
 
        /*
@@ -153,10 +192,10 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
  * Add device to list of registered parent devices.
  * Returns a negative value on error, otherwise 0.
  */
-int mdev_register_device(struct device *dev, const struct parent_ops *ops)
+int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
 {
        int ret;
-       struct parent_device *parent;
+       struct mdev_parent *parent;
 
        /* check for mandatory ops */
        if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups)
@@ -229,7 +268,7 @@ EXPORT_SYMBOL(mdev_register_device);
 
 void mdev_unregister_device(struct device *dev)
 {
-       struct parent_device *parent;
+       struct mdev_parent *parent;
        bool force_remove = true;
 
        mutex_lock(&parent_list_lock);
@@ -266,7 +305,7 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
 {
        int ret;
        struct mdev_device *mdev;
-       struct parent_device *parent;
+       struct mdev_parent *parent;
        struct mdev_type *type = to_mdev_type(kobj);
 
        parent = mdev_get_parent(type->parent);
@@ -316,6 +355,11 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
        dev_dbg(&mdev->dev, "MDEV: created\n");
 
        mutex_unlock(&parent->lock);
+
+       mutex_lock(&mdev_list_lock);
+       list_add(&mdev->next, &mdev_list);
+       mutex_unlock(&mdev_list_lock);
+
        return ret;
 
 create_failed:
@@ -329,12 +373,30 @@ create_err:
 
 int mdev_device_remove(struct device *dev, bool force_remove)
 {
-       struct mdev_device *mdev;
-       struct parent_device *parent;
+       struct mdev_device *mdev, *tmp;
+       struct mdev_parent *parent;
        struct mdev_type *type;
        int ret;
+       bool found = false;
 
        mdev = to_mdev_device(dev);
+
+       mutex_lock(&mdev_list_lock);
+       list_for_each_entry(tmp, &mdev_list, next) {
+               if (tmp == mdev) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (found)
+               list_del(&mdev->next);
+
+       mutex_unlock(&mdev_list_lock);
+
+       if (!found)
+               return -ENODEV;
+
        type = to_mdev_type(mdev->type_kobj);
        parent = mdev->parent;
        mutex_lock(&parent->lock);
@@ -342,6 +404,11 @@ int mdev_device_remove(struct device *dev, bool force_remove)
        ret = mdev_device_remove_ops(mdev, force_remove);
        if (ret) {
                mutex_unlock(&parent->lock);
+
+               mutex_lock(&mdev_list_lock);
+               list_add(&mdev->next, &mdev_list);
+               mutex_unlock(&mdev_list_lock);
+
                return ret;
        }
 
@@ -349,7 +416,8 @@ int mdev_device_remove(struct device *dev, bool force_remove)
        device_unregister(dev);
        mutex_unlock(&parent->lock);
        mdev_put_parent(parent);
-       return ret;
+
+       return 0;
 }
 
 static int __init mdev_init(void)
index d35097cbf3d755c027b7a98a8e6daed835754117..a9cefd70a7050a45d88b77dfd17efeffd5d3e95f 100644 (file)
 int  mdev_bus_register(void);
 void mdev_bus_unregister(void);
 
+struct mdev_parent {
+       struct device *dev;
+       const struct mdev_parent_ops *ops;
+       struct kref ref;
+       struct mutex lock;
+       struct list_head next;
+       struct kset *mdev_types_kset;
+       struct list_head type_list;
+};
+
+struct mdev_device {
+       struct device dev;
+       struct mdev_parent *parent;
+       uuid_le uuid;
+       void *driver_data;
+       struct kref ref;
+       struct list_head next;
+       struct kobject *type_kobj;
+};
+
+#define to_mdev_device(dev)    container_of(dev, struct mdev_device, dev)
+#define dev_is_mdev(d)         ((d)->bus == &mdev_bus_type)
+
 struct mdev_type {
        struct kobject kobj;
        struct kobject *devices_kobj;
-       struct parent_device *parent;
+       struct mdev_parent *parent;
        struct list_head next;
        struct attribute_group *group;
 };
@@ -29,8 +52,8 @@ struct mdev_type {
 #define to_mdev_type(_kobj)            \
        container_of(_kobj, struct mdev_type, kobj)
 
-int  parent_create_sysfs_files(struct parent_device *parent);
-void parent_remove_sysfs_files(struct parent_device *parent);
+int  parent_create_sysfs_files(struct mdev_parent *parent);
+void parent_remove_sysfs_files(struct mdev_parent *parent);
 
 int  mdev_create_sysfs_files(struct device *dev, struct mdev_type *type);
 void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type);
index 1a53deb2ee102b677f92d7388eb340a6e0204ffd..802df210929ba5d52924c102867cbe55ba365963 100644 (file)
@@ -92,7 +92,7 @@ static struct kobj_type mdev_type_ktype = {
        .release = mdev_type_release,
 };
 
-struct mdev_type *add_mdev_supported_type(struct parent_device *parent,
+struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
                                          struct attribute_group *group)
 {
        struct mdev_type *type;
@@ -158,7 +158,7 @@ static void remove_mdev_supported_type(struct mdev_type *type)
        kobject_put(&type->kobj);
 }
 
-static int add_mdev_supported_type_groups(struct parent_device *parent)
+static int add_mdev_supported_type_groups(struct mdev_parent *parent)
 {
        int i;
 
@@ -183,7 +183,7 @@ static int add_mdev_supported_type_groups(struct parent_device *parent)
 }
 
 /* mdev sysfs functions */
-void parent_remove_sysfs_files(struct parent_device *parent)
+void parent_remove_sysfs_files(struct mdev_parent *parent)
 {
        struct mdev_type *type, *tmp;
 
@@ -196,7 +196,7 @@ void parent_remove_sysfs_files(struct parent_device *parent)
        kset_unregister(parent->mdev_types_kset);
 }
 
-int parent_create_sysfs_files(struct parent_device *parent)
+int parent_create_sysfs_files(struct mdev_parent *parent)
 {
        int ret;
 
index ffc36758cb84c08ce1b2c4d516bd73b0c18d52d1..fa848a701b8b4ed921ae56248eac3ef0fdc7d5a3 100644 (file)
@@ -27,7 +27,7 @@
 static int vfio_mdev_open(void *device_data)
 {
        struct mdev_device *mdev = device_data;
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
        int ret;
 
        if (unlikely(!parent->ops->open))
@@ -46,7 +46,7 @@ static int vfio_mdev_open(void *device_data)
 static void vfio_mdev_release(void *device_data)
 {
        struct mdev_device *mdev = device_data;
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
 
        if (likely(parent->ops->release))
                parent->ops->release(mdev);
@@ -58,7 +58,7 @@ static long vfio_mdev_unlocked_ioctl(void *device_data,
                                     unsigned int cmd, unsigned long arg)
 {
        struct mdev_device *mdev = device_data;
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->ioctl))
                return -EINVAL;
@@ -70,7 +70,7 @@ static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
                              size_t count, loff_t *ppos)
 {
        struct mdev_device *mdev = device_data;
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->read))
                return -EINVAL;
@@ -82,7 +82,7 @@ static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
                               size_t count, loff_t *ppos)
 {
        struct mdev_device *mdev = device_data;
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->write))
                return -EINVAL;
@@ -93,7 +93,7 @@ static ssize_t vfio_mdev_write(void *device_data, const char __user *buf,
 static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma)
 {
        struct mdev_device *mdev = device_data;
-       struct parent_device *parent = mdev->parent;
+       struct mdev_parent *parent = mdev->parent;
 
        if (unlikely(!parent->ops->mmap))
                return -EINVAL;
index dcd7c2a9961830b7fd1ff4155d5c302cd55fd809..324c52e3a1a47736a819826eea2d1974e47c7a87 100644 (file)
@@ -1142,6 +1142,10 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
                        return ret;
 
                vdev->barmap[index] = pci_iomap(pdev, index, 0);
+               if (!vdev->barmap[index]) {
+                       pci_release_selected_regions(pdev, 1 << index);
+                       return -ENOMEM;
+               }
        }
 
        vma->vm_private_data = vdev;
index 5ffd1d9ad4bdf8111a35a9b6b0c217109d238ebf..357243d76f108fe184d2079736726e89a0ad0846 100644 (file)
@@ -193,7 +193,10 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
        if (!vdev->has_vga)
                return -EINVAL;
 
-       switch (pos) {
+       if (pos > 0xbfffful)
+               return -EINVAL;
+
+       switch ((u32)pos) {
        case 0xa0000 ... 0xbffff:
                count = min(count, (size_t)(0xc0000 - pos));
                iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1);
index c8823578a1b2afd3ae7a36c2f526fd071116876b..59b3f62a2d64ebd85be990630e09a48c7c7f2f1c 100644 (file)
@@ -1123,12 +1123,11 @@ static long tce_iommu_ioctl(void *iommu_data,
                mutex_lock(&container->lock);
 
                ret = tce_iommu_create_default_window(container);
-               if (ret)
-                       return ret;
-
-               ret = tce_iommu_create_window(container, create.page_shift,
-                               create.window_size, create.levels,
-                               &create.start_addr);
+               if (!ret)
+                       ret = tce_iommu_create_window(container,
+                                       create.page_shift,
+                                       create.window_size, create.levels,
+                                       &create.start_addr);
 
                mutex_unlock(&container->lock);
 
@@ -1246,6 +1245,8 @@ static void tce_iommu_release_ownership_ddw(struct tce_container *container,
 static long tce_iommu_take_ownership_ddw(struct tce_container *container,
                struct iommu_table_group *table_group)
 {
+       long i, ret = 0;
+
        if (!table_group->ops->create_table || !table_group->ops->set_window ||
                        !table_group->ops->release_ownership) {
                WARN_ON_ONCE(1);
@@ -1254,7 +1255,27 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container,
 
        table_group->ops->take_ownership(table_group);
 
+       /* Set all windows to the new group */
+       for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
+               struct iommu_table *tbl = container->tables[i];
+
+               if (!tbl)
+                       continue;
+
+               ret = table_group->ops->set_window(table_group, i, tbl);
+               if (ret)
+                       goto release_exit;
+       }
+
        return 0;
+
+release_exit:
+       for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i)
+               table_group->ops->unset_window(table_group, i);
+
+       table_group->ops->release_ownership(table_group);
+
+       return ret;
 }
 
 static int tce_iommu_attach_group(void *iommu_data,
@@ -1270,6 +1291,10 @@ static int tce_iommu_attach_group(void *iommu_data,
        /* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n",
                        iommu_group_id(iommu_group), iommu_group); */
        table_group = iommu_group_get_iommudata(iommu_group);
+       if (!table_group) {
+               ret = -ENODEV;
+               goto unlock_exit;
+       }
 
        if (tce_groups_attached(container) && (!table_group->ops ||
                        !table_group->ops->take_ownership ||
index f3726ba12aa6ceccff8a0c96523aa683537be8f4..b3cc33fa6d26a69f44dc013b7bee55f6bd7682ab 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/uaccess.h>
 #include <linux/vfio.h>
 #include <linux/workqueue.h>
-#include <linux/pid_namespace.h>
 #include <linux/mdev.h>
 #include <linux/notifier.h>
 
@@ -268,28 +267,38 @@ static void vfio_lock_acct(struct task_struct *task, long npage)
 {
        struct vwork *vwork;
        struct mm_struct *mm;
+       bool is_current;
 
        if (!npage)
                return;
 
-       mm = get_task_mm(task);
+       is_current = (task->mm == current->mm);
+
+       mm = is_current ? task->mm : get_task_mm(task);
        if (!mm)
-               return; /* process exited or nothing to do */
+               return; /* process exited */
 
        if (down_write_trylock(&mm->mmap_sem)) {
                mm->locked_vm += npage;
                up_write(&mm->mmap_sem);
-               mmput(mm);
+               if (!is_current)
+                       mmput(mm);
                return;
        }
 
+       if (is_current) {
+               mm = get_task_mm(task);
+               if (!mm)
+                       return;
+       }
+
        /*
         * Couldn't get mmap_sem lock, so must setup to update
         * mm->locked_vm later. If locked_vm were atomic, we
         * wouldn't need this silliness
         */
        vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
-       if (!vwork) {
+       if (WARN_ON(!vwork)) {
                mmput(mm);
                return;
        }
@@ -393,77 +402,71 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
 static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
                                  long npage, unsigned long *pfn_base)
 {
-       unsigned long limit;
-       bool lock_cap = ns_capable(task_active_pid_ns(dma->task)->user_ns,
-                                  CAP_IPC_LOCK);
-       struct mm_struct *mm;
-       long ret, i = 0, lock_acct = 0;
+       unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+       bool lock_cap = capable(CAP_IPC_LOCK);
+       long ret, pinned = 0, lock_acct = 0;
        bool rsvd;
        dma_addr_t iova = vaddr - dma->vaddr + dma->iova;
 
-       mm = get_task_mm(dma->task);
-       if (!mm)
+       /* This code path is only user initiated */
+       if (!current->mm)
                return -ENODEV;
 
-       ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
+       ret = vaddr_get_pfn(current->mm, vaddr, dma->prot, pfn_base);
        if (ret)
-               goto pin_pg_remote_exit;
+               return ret;
 
+       pinned++;
        rsvd = is_invalid_reserved_pfn(*pfn_base);
-       limit = task_rlimit(dma->task, RLIMIT_MEMLOCK) >> PAGE_SHIFT;
 
        /*
         * Reserved pages aren't counted against the user, externally pinned
         * pages are already counted against the user.
         */
        if (!rsvd && !vfio_find_vpfn(dma, iova)) {
-               if (!lock_cap && mm->locked_vm + 1 > limit) {
+               if (!lock_cap && current->mm->locked_vm + 1 > limit) {
                        put_pfn(*pfn_base, dma->prot);
                        pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__,
                                        limit << PAGE_SHIFT);
-                       ret = -ENOMEM;
-                       goto pin_pg_remote_exit;
+                       return -ENOMEM;
                }
                lock_acct++;
        }
 
-       i++;
-       if (likely(!disable_hugepages)) {
-               /* Lock all the consecutive pages from pfn_base */
-               for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; i < npage;
-                    i++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) {
-                       unsigned long pfn = 0;
+       if (unlikely(disable_hugepages))
+               goto out;
 
-                       ret = vaddr_get_pfn(mm, vaddr, dma->prot, &pfn);
-                       if (ret)
-                               break;
+       /* Lock all the consecutive pages from pfn_base */
+       for (vaddr += PAGE_SIZE, iova += PAGE_SIZE; pinned < npage;
+            pinned++, vaddr += PAGE_SIZE, iova += PAGE_SIZE) {
+               unsigned long pfn = 0;
 
-                       if (pfn != *pfn_base + i ||
-                           rsvd != is_invalid_reserved_pfn(pfn)) {
+               ret = vaddr_get_pfn(current->mm, vaddr, dma->prot, &pfn);
+               if (ret)
+                       break;
+
+               if (pfn != *pfn_base + pinned ||
+                   rsvd != is_invalid_reserved_pfn(pfn)) {
+                       put_pfn(pfn, dma->prot);
+                       break;
+               }
+
+               if (!rsvd && !vfio_find_vpfn(dma, iova)) {
+                       if (!lock_cap &&
+                           current->mm->locked_vm + lock_acct + 1 > limit) {
                                put_pfn(pfn, dma->prot);
+                               pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
+                                       __func__, limit << PAGE_SHIFT);
                                break;
                        }
-
-                       if (!rsvd && !vfio_find_vpfn(dma, iova)) {
-                               if (!lock_cap &&
-                                   mm->locked_vm + lock_acct + 1 > limit) {
-                                       put_pfn(pfn, dma->prot);
-                                       pr_warn("%s: RLIMIT_MEMLOCK (%ld) "
-                                               "exceeded\n", __func__,
-                                               limit << PAGE_SHIFT);
-                                       break;
-                               }
-                               lock_acct++;
-                       }
+                       lock_acct++;
                }
        }
 
-       vfio_lock_acct(dma->task, lock_acct);
-       ret = i;
+out:
+       vfio_lock_acct(current, lock_acct);
 
-pin_pg_remote_exit:
-       mmput(mm);
-       return ret;
+       return pinned;
 }
 
 static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova,
@@ -473,10 +476,10 @@ static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova,
        long unlocked = 0, locked = 0;
        long i;
 
-       for (i = 0; i < npage; i++) {
+       for (i = 0; i < npage; i++, iova += PAGE_SIZE) {
                if (put_pfn(pfn++, dma->prot)) {
                        unlocked++;
-                       if (vfio_find_vpfn(dma, iova + (i << PAGE_SHIFT)))
+                       if (vfio_find_vpfn(dma, iova))
                                locked++;
                }
        }
@@ -491,8 +494,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
                                  unsigned long *pfn_base, bool do_accounting)
 {
        unsigned long limit;
-       bool lock_cap = ns_capable(task_active_pid_ns(dma->task)->user_ns,
-                                  CAP_IPC_LOCK);
+       bool lock_cap = has_capability(dma->task, CAP_IPC_LOCK);
        struct mm_struct *mm;
        int ret;
        bool rsvd;
index 253310cdaacabc25d67aa997e45033bf7137b3b9..fd6c8b66f06fd97734bfdad5917c7f65de70265d 100644 (file)
@@ -843,7 +843,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
        struct iov_iter out_iter, in_iter, prot_iter, data_iter;
        u64 tag;
        u32 exp_data_len, data_direction;
-       unsigned out, in;
+       unsigned int out = 0, in = 0;
        int head, ret, prot_bytes;
        size_t req_size, rsp_size = sizeof(struct virtio_scsi_cmd_resp);
        size_t out_size, in_size;
@@ -2087,7 +2087,7 @@ static struct configfs_attribute *vhost_scsi_wwn_attrs[] = {
        NULL,
 };
 
-static struct target_core_fabric_ops vhost_scsi_ops = {
+static const struct target_core_fabric_ops vhost_scsi_ops = {
        .module                         = THIS_MODULE,
        .name                           = "vhost",
        .get_fabric_name                = vhost_scsi_get_fabric_name,
index d6432603880c1343ea2451eba6df1973e6d61822..8f99fe08de02e7b48725a99d682055c03056b82a 100644 (file)
@@ -130,14 +130,14 @@ static long vhost_get_vring_endian(struct vhost_virtqueue *vq, u32 idx,
 
 static void vhost_init_is_le(struct vhost_virtqueue *vq)
 {
-       if (vhost_has_feature(vq, VIRTIO_F_VERSION_1))
-               vq->is_le = true;
+       vq->is_le = vhost_has_feature(vq, VIRTIO_F_VERSION_1)
+               || virtio_legacy_is_little_endian();
 }
 #endif /* CONFIG_VHOST_CROSS_ENDIAN_LEGACY */
 
 static void vhost_reset_is_le(struct vhost_virtqueue *vq)
 {
-       vq->is_le = virtio_legacy_is_little_endian();
+       vhost_init_is_le(vq);
 }
 
 struct vhost_flush_struct {
@@ -1714,10 +1714,8 @@ int vhost_vq_init_access(struct vhost_virtqueue *vq)
        int r;
        bool is_le = vq->is_le;
 
-       if (!vq->private_data) {
-               vhost_reset_is_le(vq);
+       if (!vq->private_data)
                return 0;
-       }
 
        vhost_init_is_le(vq);
 
index bbbf588540ed71d82ed63deb355b77736a2a9628..ce5e63d2c66aac7d019c422ec294cab025e94e5e 100644 (file)
@@ -373,6 +373,7 @@ static void vhost_vsock_handle_rx_kick(struct vhost_work *work)
 
 static int vhost_vsock_start(struct vhost_vsock *vsock)
 {
+       struct vhost_virtqueue *vq;
        size_t i;
        int ret;
 
@@ -383,19 +384,20 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
                goto err;
 
        for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
-               struct vhost_virtqueue *vq = &vsock->vqs[i];
+               vq = &vsock->vqs[i];
 
                mutex_lock(&vq->mutex);
 
                if (!vhost_vq_access_ok(vq)) {
                        ret = -EFAULT;
-                       mutex_unlock(&vq->mutex);
                        goto err_vq;
                }
 
                if (!vq->private_data) {
                        vq->private_data = vsock;
-                       vhost_vq_init_access(vq);
+                       ret = vhost_vq_init_access(vq);
+                       if (ret)
+                               goto err_vq;
                }
 
                mutex_unlock(&vq->mutex);
@@ -405,8 +407,11 @@ static int vhost_vsock_start(struct vhost_vsock *vsock)
        return 0;
 
 err_vq:
+       vq->private_data = NULL;
+       mutex_unlock(&vq->mutex);
+
        for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
-               struct vhost_virtqueue *vq = &vsock->vqs[i];
+               vq = &vsock->vqs[i];
 
                mutex_lock(&vq->mutex);
                vq->private_data = NULL;
index f89245b8ba8e9a28483c4ff5edb03b80a1a9b2e3..68a113594808f220aa818424cd6e342897806a74 100644 (file)
@@ -163,17 +163,18 @@ void fb_dealloc_cmap(struct fb_cmap *cmap)
 
 int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
 {
-       int tooff = 0, fromoff = 0;
-       int size;
+       unsigned int tooff = 0, fromoff = 0;
+       size_t size;
 
        if (to->start > from->start)
                fromoff = to->start - from->start;
        else
                tooff = from->start - to->start;
-       size = to->len - tooff;
-       if (size > (int) (from->len - fromoff))
-               size = from->len - fromoff;
-       if (size <= 0)
+       if (fromoff >= from->len || tooff >= to->len)
+               return -EINVAL;
+
+       size = min_t(size_t, to->len - tooff, from->len - fromoff);
+       if (size == 0)
                return -EINVAL;
        size *= sizeof(u16);
 
@@ -187,17 +188,18 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
 
 int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
 {
-       int tooff = 0, fromoff = 0;
-       int size;
+       unsigned int tooff = 0, fromoff = 0;
+       size_t size;
 
        if (to->start > from->start)
                fromoff = to->start - from->start;
        else
                tooff = from->start - to->start;
-       size = to->len - tooff;
-       if (size > (int) (from->len - fromoff))
-               size = from->len - fromoff;
-       if (size <= 0)
+       if (fromoff >= from->len || tooff >= to->len)
+               return -EINVAL;
+
+       size = min_t(size_t, to->len - tooff, from->len - fromoff);
+       if (size == 0)
                return -EINVAL;
        size *= sizeof(u16);
 
index d47a2fcef818f3cea1ce7f09160061b3c8d2f0a6..c71fde5fe835c48d1ce4611b29108f8cf7fb44f3 100644 (file)
@@ -59,6 +59,7 @@
 #define pr_fmt(fmt) "virtio-mmio: " fmt
 
 #include <linux/acpi.h>
+#include <linux/dma-mapping.h>
 #include <linux/highmem.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -498,6 +499,7 @@ static int virtio_mmio_probe(struct platform_device *pdev)
        struct virtio_mmio_device *vm_dev;
        struct resource *mem;
        unsigned long magic;
+       int rc;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem)
@@ -547,9 +549,25 @@ static int virtio_mmio_probe(struct platform_device *pdev)
        }
        vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
 
-       if (vm_dev->version == 1)
+       if (vm_dev->version == 1) {
                writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
 
+               rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+               /*
+                * In the legacy case, ensure our coherently-allocated virtio
+                * ring will be at an address expressable as a 32-bit PFN.
+                */
+               if (!rc)
+                       dma_set_coherent_mask(&pdev->dev,
+                                             DMA_BIT_MASK(32 + PAGE_SHIFT));
+       } else {
+               rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+       }
+       if (rc)
+               rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (rc)
+               dev_warn(&pdev->dev, "Failed to enable 64-bit or 32-bit DMA.  Trying to continue, but this might not work.\n");
+
        platform_set_drvdata(pdev, vm_dev);
 
        return register_virtio_device(&vm_dev->vdev);
index 6b5ee896af6318e9b50c384fcf3e062d24d89c47..7cc51223db1cbe8e905307850b7bd42b6c739279 100644 (file)
@@ -464,7 +464,7 @@ static int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled,
        vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
        pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
 
-       *pci_base = (dma_addr_t)vme_base + pci_offset;
+       *pci_base = (dma_addr_t)*vme_base + pci_offset;
        *size = (unsigned long long)((vme_bound - *vme_base) + granularity);
 
        *enabled = 0;
index 778acf80aacbf81042a3debc4ca1e90d58037f6c..85dd20e0572678581ffa03a8ff6b734773230d1e 100644 (file)
@@ -58,9 +58,13 @@ static int xen_map_device_mmio(const struct resource *resources,
        xen_pfn_t *gpfns;
        xen_ulong_t *idxs;
        int *errs;
-       struct xen_add_to_physmap_range xatp;
 
        for (i = 0; i < count; i++) {
+               struct xen_add_to_physmap_range xatp = {
+                       .domid = DOMID_SELF,
+                       .space = XENMAPSPACE_dev_mmio
+               };
+
                r = &resources[i];
                nr = DIV_ROUND_UP(resource_size(r), XEN_PAGE_SIZE);
                if ((resource_type(r) != IORESOURCE_MEM) || (nr == 0))
@@ -87,9 +91,7 @@ static int xen_map_device_mmio(const struct resource *resources,
                        idxs[j] = XEN_PFN_DOWN(r->start) + j;
                }
 
-               xatp.domid = DOMID_SELF;
                xatp.size = nr;
-               xatp.space = XENMAPSPACE_dev_mmio;
 
                set_xen_guest_handle(xatp.gpfns, gpfns);
                set_xen_guest_handle(xatp.idxs, idxs);
index c03f9c86c7e37d580032d1553e829a6f14ef2014..3c41470c7fc4f123b845bc611bb6ea1d48aabc92 100644 (file)
@@ -369,8 +369,7 @@ static void evtchn_fifo_resume(void)
                }
 
                ret = init_control_block(cpu, control_block);
-               if (ret < 0)
-                       BUG();
+               BUG_ON(ret < 0);
        }
 
        /*
index e8c7f09d01be8a483df94db111faec580beb032a..6890897a6f30edab0c0d87926942463f9b481aa9 100644 (file)
@@ -125,7 +125,7 @@ static int add_evtchn(struct per_user_data *u, struct user_evtchn *evtchn)
        while (*new) {
                struct user_evtchn *this;
 
-               this = container_of(*new, struct user_evtchn, node);
+               this = rb_entry(*new, struct user_evtchn, node);
 
                parent = *new;
                if (this->port < evtchn->port)
@@ -157,7 +157,7 @@ static struct user_evtchn *find_evtchn(struct per_user_data *u, unsigned port)
        while (node) {
                struct user_evtchn *evtchn;
 
-               evtchn = container_of(node, struct user_evtchn, node);
+               evtchn = rb_entry(node, struct user_evtchn, node);
 
                if (evtchn->port < port)
                        node = node->rb_left;
index 112ce422dc2268f25d7266e42797d6ddfa1a8fe4..2a165cc8a43cd6768529ffe48126c172e5b9f7df 100644 (file)
@@ -42,6 +42,7 @@
 static unsigned long platform_mmio;
 static unsigned long platform_mmio_alloc;
 static unsigned long platform_mmiolen;
+static uint64_t callback_via;
 
 static unsigned long alloc_xen_mmio(unsigned long len)
 {
@@ -54,6 +55,51 @@ static unsigned long alloc_xen_mmio(unsigned long len)
        return addr;
 }
 
+static uint64_t get_callback_via(struct pci_dev *pdev)
+{
+       u8 pin;
+       int irq;
+
+       irq = pdev->irq;
+       if (irq < 16)
+               return irq; /* ISA IRQ */
+
+       pin = pdev->pin;
+
+       /* We don't know the GSI. Specify the PCI INTx line instead. */
+       return ((uint64_t)0x01 << HVM_CALLBACK_VIA_TYPE_SHIFT) | /* PCI INTx identifier */
+               ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
+               ((uint64_t)pdev->bus->number << 16) |
+               ((uint64_t)(pdev->devfn & 0xff) << 8) |
+               ((uint64_t)(pin - 1) & 3);
+}
+
+static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id)
+{
+       xen_hvm_evtchn_do_upcall();
+       return IRQ_HANDLED;
+}
+
+static int xen_allocate_irq(struct pci_dev *pdev)
+{
+       return request_irq(pdev->irq, do_hvm_evtchn_intr,
+                       IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+                       "xen-platform-pci", pdev);
+}
+
+static int platform_pci_resume(struct pci_dev *pdev)
+{
+       int err;
+       if (!xen_pv_domain())
+               return 0;
+       err = xen_set_callback_via(callback_via);
+       if (err) {
+               dev_err(&pdev->dev, "platform_pci_resume failure!\n");
+               return err;
+       }
+       return 0;
+}
+
 static int platform_pci_probe(struct pci_dev *pdev,
                              const struct pci_device_id *ent)
 {
@@ -92,6 +138,28 @@ static int platform_pci_probe(struct pci_dev *pdev,
        platform_mmio = mmio_addr;
        platform_mmiolen = mmio_len;
 
+       /* 
+        * Xen HVM guests always use the vector callback mechanism.
+        * L1 Dom0 in a nested Xen environment is a PV guest inside in an
+        * HVM environment. It needs the platform-pci driver to get
+        * notifications from L0 Xen, but it cannot use the vector callback
+        * as it is not exported by L1 Xen.
+        */
+       if (xen_pv_domain()) {
+               ret = xen_allocate_irq(pdev);
+               if (ret) {
+                       dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret);
+                       goto out;
+               }
+               callback_via = get_callback_via(pdev);
+               ret = xen_set_callback_via(callback_via);
+               if (ret) {
+                       dev_warn(&pdev->dev, "Unable to set the evtchn callback "
+                                        "err=%d\n", ret);
+                       goto out;
+               }
+       }
+
        max_nr_gframes = gnttab_max_grant_frames();
        grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes);
        ret = gnttab_setup_auto_xlat_frames(grant_frames);
@@ -123,6 +191,9 @@ static struct pci_driver platform_driver = {
        .name =           DRV_NAME,
        .probe =          platform_pci_probe,
        .id_table =       platform_pci_tbl,
+#ifdef CONFIG_PM
+       .resume_early =   platform_pci_resume,
+#endif
 };
 
 builtin_pci_driver(platform_driver);
index 478fb91e3df2b8a9f8c75d8538668465feb59462..f8afc6dcc29f2769694308092a4b543e5e0bed49 100644 (file)
@@ -275,6 +275,10 @@ retry:
                rc = 0;
        } else
                rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs);
+
+       if (!rc)
+               swiotlb_set_max_segment(PAGE_SIZE);
+
        return rc;
 error:
        if (repeat--) {
@@ -392,7 +396,7 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
        if (dma_capable(dev, dev_addr, size) &&
            !range_straddles_page_boundary(phys, size) &&
                !xen_arch_need_swiotlb(dev, phys, dev_addr) &&
-               !swiotlb_force) {
+               (swiotlb_force != SWIOTLB_FORCE)) {
                /* we are not interested in the dma_addr returned by
                 * xen_dma_map_page, only in the potential cache flushes executed
                 * by the function. */
@@ -410,9 +414,9 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
        if (map == SWIOTLB_MAP_ERROR)
                return DMA_ERROR_CODE;
 
+       dev_addr = xen_phys_to_bus(map);
        xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT),
                                        dev_addr, map & ~PAGE_MASK, size, dir, attrs);
-       dev_addr = xen_phys_to_bus(map);
 
        /*
         * Ensure that the address returned is DMA'ble
@@ -552,7 +556,7 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
                phys_addr_t paddr = sg_phys(sg);
                dma_addr_t dev_addr = xen_phys_to_bus(paddr);
 
-               if (swiotlb_force ||
+               if (swiotlb_force == SWIOTLB_FORCE ||
                    xen_arch_need_swiotlb(hwdev, paddr, dev_addr) ||
                    !dma_capable(hwdev, dev_addr, sg->length) ||
                    range_straddles_page_boundary(paddr, sg->length)) {
@@ -571,13 +575,14 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
                                sg_dma_len(sgl) = 0;
                                return 0;
                        }
+                       dev_addr = xen_phys_to_bus(map);
                        xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
                                                dev_addr,
                                                map & ~PAGE_MASK,
                                                sg->length,
                                                dir,
                                                attrs);
-                       sg->dma_address = xen_phys_to_bus(map);
+                       sg->dma_address = dev_addr;
                } else {
                        /* we are not interested in the dma_addr returned by
                         * xen_dma_map_page, only in the potential cache flushes executed
index e74f9c1fbd80a9fe4c6cfbba0176785b005c06fd..867a2e4252086531bcd682367838f4c4c169427d 100644 (file)
@@ -42,7 +42,6 @@ int xb_write(const void *data, unsigned len);
 int xb_read(void *data, unsigned len);
 int xb_data_to_read(void);
 int xb_wait_for_data_to_read(void);
-int xs_input_avail(void);
 extern struct xenstore_domain_interface *xen_store_interface;
 extern int xen_store_evtchn;
 extern enum xenstore_init xen_store_domain_type;
index 6c0ead4be784340019e69942a8d704ab088ea202..79130b31024754dc7560f60732545a8f28c103b1 100644 (file)
@@ -302,6 +302,29 @@ static void watch_fired(struct xenbus_watch *watch,
        mutex_unlock(&adap->dev_data->reply_mutex);
 }
 
+static int xenbus_command_reply(struct xenbus_file_priv *u,
+                               unsigned int msg_type, const char *reply)
+{
+       struct {
+               struct xsd_sockmsg hdr;
+               const char body[16];
+       } msg;
+       int rc;
+
+       msg.hdr = u->u.msg;
+       msg.hdr.type = msg_type;
+       msg.hdr.len = strlen(reply) + 1;
+       if (msg.hdr.len > sizeof(msg.body))
+               return -E2BIG;
+
+       mutex_lock(&u->reply_mutex);
+       rc = queue_reply(&u->read_buffers, &msg, sizeof(msg.hdr) + msg.hdr.len);
+       wake_up(&u->read_waitq);
+       mutex_unlock(&u->reply_mutex);
+
+       return rc;
+}
+
 static int xenbus_write_transaction(unsigned msg_type,
                                    struct xenbus_file_priv *u)
 {
@@ -316,12 +339,12 @@ static int xenbus_write_transaction(unsigned msg_type,
                        rc = -ENOMEM;
                        goto out;
                }
-       } else if (msg_type == XS_TRANSACTION_END) {
+       } else if (u->u.msg.tx_id != 0) {
                list_for_each_entry(trans, &u->transactions, list)
                        if (trans->handle.id == u->u.msg.tx_id)
                                break;
                if (&trans->list == &u->transactions)
-                       return -ESRCH;
+                       return xenbus_command_reply(u, XS_ERROR, "ENOENT");
        }
 
        reply = xenbus_dev_request_and_reply(&u->u.msg);
@@ -372,12 +395,12 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
        path = u->u.buffer + sizeof(u->u.msg);
        token = memchr(path, 0, u->u.msg.len);
        if (token == NULL) {
-               rc = -EILSEQ;
+               rc = xenbus_command_reply(u, XS_ERROR, "EINVAL");
                goto out;
        }
        token++;
        if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) {
-               rc = -EILSEQ;
+               rc = xenbus_command_reply(u, XS_ERROR, "EINVAL");
                goto out;
        }
 
@@ -411,23 +434,7 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u)
        }
 
        /* Success.  Synthesize a reply to say all is OK. */
-       {
-               struct {
-                       struct xsd_sockmsg hdr;
-                       char body[3];
-               } __packed reply = {
-                       {
-                               .type = msg_type,
-                               .len = sizeof(reply.body)
-                       },
-                       "OK"
-               };
-
-               mutex_lock(&u->reply_mutex);
-               rc = queue_reply(&u->read_buffers, &reply, sizeof(reply));
-               wake_up(&u->read_waitq);
-               mutex_unlock(&u->reply_mutex);
-       }
+       rc = xenbus_command_reply(u, msg_type, "OK");
 
 out:
        return rc;
index c2a377cdda2b03d6efe8768e4ef7894a06ebe853..83eab52fb3f69a75aa06a9f2a31760a384508f41 100644 (file)
@@ -38,6 +38,7 @@ config FS_DAX
        bool "Direct Access (DAX) support"
        depends on MMU
        depends on !(ARM || MIPS || SPARC)
+       select FS_IOMAP
        help
          Direct Access (DAX) can be used on memory-backed block devices.
          If the block device supports DAX and the filesystem supports DAX,
index 4ab67e8cb776ac18fd12bfec2fa7816800f3f5fa..873b4ca82ccbcde4c108a2592fbd7f46b88273a0 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1085,7 +1085,8 @@ static void aio_complete(struct kiocb *kiocb, long res, long res2)
                 * Tell lockdep we inherited freeze protection from submission
                 * thread.
                 */
-               __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+               if (S_ISREG(file_inode(file)->i_mode))
+                       __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
                file_end_write(file);
        }
 
@@ -1525,7 +1526,8 @@ static ssize_t aio_write(struct kiocb *req, struct iocb *iocb, bool vectored,
                 * by telling it the lock got released so that it doesn't
                 * complain about held lock when we return to userspace.
                 */
-               __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+               if (S_ISREG(file_inode(file)->i_mode))
+                       __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
        }
        kfree(iovec);
        return ret;
index 29a02daf08a97896c600e88317e646dbf3ab3c9b..422370293cfd8cfc9b0f527f73498ce7c28244be 100644 (file)
@@ -2298,6 +2298,7 @@ static int elf_core_dump(struct coredump_params *cprm)
                                goto end_coredump;
                }
        }
+       dump_truncate(cprm);
 
        if (!elf_core_write_extra_data(cprm))
                goto end_coredump;
index 5db5d1340d69eccf475f0feac7f85665bd6aceb5..3c47614a4b32c75c4d5cf75d436389305c145288 100644 (file)
@@ -331,7 +331,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        struct blk_plug plug;
        struct blkdev_dio *dio;
        struct bio *bio;
-       bool is_read = (iov_iter_rw(iter) == READ);
+       bool is_read = (iov_iter_rw(iter) == READ), is_sync;
        loff_t pos = iocb->ki_pos;
        blk_qc_t qc = BLK_QC_T_NONE;
        int ret;
@@ -344,7 +344,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        bio_get(bio); /* extra ref for the completion handler */
 
        dio = container_of(bio, struct blkdev_dio, bio);
-       dio->is_sync = is_sync_kiocb(iocb);
+       dio->is_sync = is_sync = is_sync_kiocb(iocb);
        if (dio->is_sync)
                dio->waiter = current;
        else
@@ -398,7 +398,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
        }
        blk_finish_plug(&plug);
 
-       if (!dio->is_sync)
+       if (!is_sync)
                return -EIOCBQUEUED;
 
        for (;;) {
index 63d197724519b30d8392546f9a8ba9855feaf5aa..ff0b0be92d6122402f02c039eed8e4599fdce4df 100644 (file)
@@ -273,6 +273,8 @@ static void run_ordered_work(struct __btrfs_workqueue *wq)
        unsigned long flags;
 
        while (1) {
+               void *wtag;
+
                spin_lock_irqsave(lock, flags);
                if (list_empty(list))
                        break;
@@ -299,11 +301,13 @@ static void run_ordered_work(struct __btrfs_workqueue *wq)
                spin_unlock_irqrestore(lock, flags);
 
                /*
-                * we don't want to call the ordered free functions
-                * with the lock held though
+                * We don't want to call the ordered free functions with the
+                * lock held though. Save the work as tag for the trace event,
+                * because the callback could free the structure.
                 */
+               wtag = work;
                work->ordered_free(work);
-               trace_btrfs_all_work_done(work);
+               trace_btrfs_all_work_done(wq->fs_info, wtag);
        }
        spin_unlock_irqrestore(lock, flags);
 }
@@ -311,6 +315,7 @@ static void run_ordered_work(struct __btrfs_workqueue *wq)
 static void normal_work_helper(struct btrfs_work *work)
 {
        struct __btrfs_workqueue *wq;
+       void *wtag;
        int need_order = 0;
 
        /*
@@ -324,6 +329,8 @@ static void normal_work_helper(struct btrfs_work *work)
        if (work->ordered_func)
                need_order = 1;
        wq = work->wq;
+       /* Safe for tracepoints in case work gets freed by the callback */
+       wtag = work;
 
        trace_btrfs_work_sched(work);
        thresh_exec_hook(wq);
@@ -333,7 +340,7 @@ static void normal_work_helper(struct btrfs_work *work)
                run_ordered_work(wq);
        }
        if (!need_order)
-               trace_btrfs_all_work_done(work);
+               trace_btrfs_all_work_done(wq->fs_info, wtag);
 }
 
 void btrfs_init_work(struct btrfs_work *work, btrfs_work_func_t uniq_func,
index 7f390849343b3e42b9399c2ac58b948c87944902..c4444d6f439f676cee59a20322d0f88fcb3cc4a3 100644 (file)
@@ -1024,6 +1024,7 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
        unsigned long buf_offset;
        unsigned long current_buf_start;
        unsigned long start_byte;
+       unsigned long prev_start_byte;
        unsigned long working_bytes = total_out - buf_start;
        unsigned long bytes;
        char *kaddr;
@@ -1071,26 +1072,34 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
                if (!bio->bi_iter.bi_size)
                        return 0;
                bvec = bio_iter_iovec(bio, bio->bi_iter);
-
+               prev_start_byte = start_byte;
                start_byte = page_offset(bvec.bv_page) - disk_start;
 
                /*
-                * make sure our new page is covered by this
-                * working buffer
+                * We need to make sure we're only adjusting
+                * our offset into compression working buffer when
+                * we're switching pages.  Otherwise we can incorrectly
+                * keep copying when we were actually done.
                 */
-               if (total_out <= start_byte)
-                       return 1;
+               if (start_byte != prev_start_byte) {
+                       /*
+                        * make sure our new page is covered by this
+                        * working buffer
+                        */
+                       if (total_out <= start_byte)
+                               return 1;
 
-               /*
-                * the next page in the biovec might not be adjacent
-                * to the last page, but it might still be found
-                * inside this working buffer. bump our offset pointer
-                */
-               if (total_out > start_byte &&
-                   current_buf_start < start_byte) {
-                       buf_offset = start_byte - buf_start;
-                       working_bytes = total_out - start_byte;
-                       current_buf_start = buf_start + buf_offset;
+                       /*
+                        * the next page in the biovec might not be adjacent
+                        * to the last page, but it might still be found
+                        * inside this working buffer. bump our offset pointer
+                        */
+                       if (total_out > start_byte &&
+                           current_buf_start < start_byte) {
+                               buf_offset = start_byte - buf_start;
+                               working_bytes = total_out - start_byte;
+                               current_buf_start = buf_start + buf_offset;
+                       }
                }
        }
 
index e97302f437a16db24db7d2aa6ae202cde3309fb6..dcd2e798767e57a80e7f50ff791a675e394a62c0 100644 (file)
@@ -2522,11 +2522,11 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                if (ref && ref->seq &&
                    btrfs_check_delayed_seq(fs_info, delayed_refs, ref->seq)) {
                        spin_unlock(&locked_ref->lock);
-                       btrfs_delayed_ref_unlock(locked_ref);
                        spin_lock(&delayed_refs->lock);
                        locked_ref->processing = 0;
                        delayed_refs->num_heads_ready++;
                        spin_unlock(&delayed_refs->lock);
+                       btrfs_delayed_ref_unlock(locked_ref);
                        locked_ref = NULL;
                        cond_resched();
                        count++;
@@ -2572,7 +2572,10 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                                         */
                                        if (must_insert_reserved)
                                                locked_ref->must_insert_reserved = 1;
+                                       spin_lock(&delayed_refs->lock);
                                        locked_ref->processing = 0;
+                                       delayed_refs->num_heads_ready++;
+                                       spin_unlock(&delayed_refs->lock);
                                        btrfs_debug(fs_info,
                                                    "run_delayed_extent_op returned %d",
                                                    ret);
@@ -7384,7 +7387,8 @@ btrfs_lock_cluster(struct btrfs_block_group_cache *block_group,
 
                spin_unlock(&cluster->refill_lock);
 
-               down_read(&used_bg->data_rwsem);
+               /* We should only have one-level nested. */
+               down_read_nested(&used_bg->data_rwsem, SINGLE_DEPTH_NESTING);
 
                spin_lock(&cluster->refill_lock);
                if (used_bg == cluster->block_group)
index f2b281ad7af6b9db26b48c6d4f072a850c19d58a..1e861a063721e7c173a770cd68d0fea484cb75b3 100644 (file)
@@ -3835,10 +3835,7 @@ cache_acl:
                break;
        case S_IFDIR:
                inode->i_fop = &btrfs_dir_file_operations;
-               if (root == fs_info->tree_root)
-                       inode->i_op = &btrfs_dir_ro_inode_operations;
-               else
-                       inode->i_op = &btrfs_dir_inode_operations;
+               inode->i_op = &btrfs_dir_inode_operations;
                break;
        case S_IFLNK:
                inode->i_op = &btrfs_symlink_inode_operations;
@@ -4505,8 +4502,19 @@ search_again:
                if (found_type > min_type) {
                        del_item = 1;
                } else {
-                       if (item_end < new_size)
+                       if (item_end < new_size) {
+                               /*
+                                * With NO_HOLES mode, for the following mapping
+                                *
+                                * [0-4k][hole][8k-12k]
+                                *
+                                * if truncating isize down to 6k, it ends up
+                                * isize being 8k.
+                                */
+                               if (btrfs_fs_incompat(root->fs_info, NO_HOLES))
+                                       last_size = new_size;
                                break;
+                       }
                        if (found_key.offset >= new_size)
                                del_item = 1;
                        else
@@ -5710,6 +5718,7 @@ static struct inode *new_simple_dir(struct super_block *s,
 
        inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID;
        inode->i_op = &btrfs_dir_ro_inode_operations;
+       inode->i_opflags &= ~IOP_XATTR;
        inode->i_fop = &simple_dir_operations;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
        inode->i_mtime = current_time(inode);
@@ -7059,7 +7068,7 @@ insert:
        write_unlock(&em_tree->lock);
 out:
 
-       trace_btrfs_get_extent(root, em);
+       trace_btrfs_get_extent(root, inode, em);
 
        btrfs_free_path(path);
        if (trans) {
@@ -7215,7 +7224,6 @@ static struct extent_map *btrfs_create_dio_extent(struct inode *inode,
        struct extent_map *em = NULL;
        int ret;
 
-       down_read(&BTRFS_I(inode)->dio_sem);
        if (type != BTRFS_ORDERED_NOCOW) {
                em = create_pinned_em(inode, start, len, orig_start,
                                      block_start, block_len, orig_block_len,
@@ -7234,7 +7242,6 @@ static struct extent_map *btrfs_create_dio_extent(struct inode *inode,
                em = ERR_PTR(ret);
        }
  out:
-       up_read(&BTRFS_I(inode)->dio_sem);
 
        return em;
 }
@@ -7623,11 +7630,18 @@ static void adjust_dio_outstanding_extents(struct inode *inode,
         * within our reservation, otherwise we need to adjust our inode
         * counter appropriately.
         */
-       if (dio_data->outstanding_extents) {
+       if (dio_data->outstanding_extents >= num_extents) {
                dio_data->outstanding_extents -= num_extents;
        } else {
+               /*
+                * If dio write length has been split due to no large enough
+                * contiguous space, we need to compensate our inode counter
+                * appropriately.
+                */
+               u64 num_needed = num_extents - dio_data->outstanding_extents;
+
                spin_lock(&BTRFS_I(inode)->lock);
-               BTRFS_I(inode)->outstanding_extents += num_extents;
+               BTRFS_I(inode)->outstanding_extents += num_needed;
                spin_unlock(&BTRFS_I(inode)->lock);
        }
 }
@@ -8685,6 +8699,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                dio_data.unsubmitted_oe_range_start = (u64)offset;
                dio_data.unsubmitted_oe_range_end = (u64)offset;
                current->journal_info = &dio_data;
+               down_read(&BTRFS_I(inode)->dio_sem);
        } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
                                     &BTRFS_I(inode)->runtime_flags)) {
                inode_dio_end(inode);
@@ -8697,6 +8712,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                                   iter, btrfs_get_blocks_direct, NULL,
                                   btrfs_submit_direct, flags);
        if (iov_iter_rw(iter) == WRITE) {
+               up_read(&BTRFS_I(inode)->dio_sem);
                current->journal_info = NULL;
                if (ret < 0 && ret != -EIOCBQUEUED) {
                        if (dio_data.reserve)
@@ -9205,6 +9221,7 @@ static int btrfs_truncate(struct inode *inode)
                        break;
                }
 
+               btrfs_block_rsv_release(fs_info, rsv, -1);
                ret = btrfs_block_rsv_migrate(&fs_info->trans_block_rsv,
                                              rsv, min_size, 0);
                BUG_ON(ret);    /* shouldn't happen */
@@ -10572,8 +10589,6 @@ static const struct inode_operations btrfs_dir_inode_operations = {
 static const struct inode_operations btrfs_dir_ro_inode_operations = {
        .lookup         = btrfs_lookup,
        .permission     = btrfs_permission,
-       .get_acl        = btrfs_get_acl,
-       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
 };
 
index 33f967d30b2ad1d555015baea2bccc5eba05d1d5..21e51b0ba188a37be6b71cab9218a8b9457b86f8 100644 (file)
@@ -5653,6 +5653,10 @@ long btrfs_ioctl(struct file *file, unsigned int
 #ifdef CONFIG_COMPAT
 long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
+       /*
+        * These all access 32-bit values anyway so no further
+        * handling is necessary.
+        */
        switch (cmd) {
        case FS_IOC32_GETFLAGS:
                cmd = FS_IOC_GETFLAGS;
@@ -5663,8 +5667,6 @@ long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FS_IOC32_GETVERSION:
                cmd = FS_IOC_GETVERSION;
                break;
-       default:
-               return -ENOIOCTLCMD;
        }
 
        return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
index f10bf5213ed8a48b95a8cf3cf51dc3c2c81b8463..eeffff84f280958cfd117e860055d7b9fc683377 100644 (file)
@@ -37,6 +37,7 @@
  */
 #define LOG_INODE_ALL 0
 #define LOG_INODE_EXISTS 1
+#define LOG_OTHER_INODE 2
 
 /*
  * directory trouble cases
@@ -4641,7 +4642,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
        if (S_ISDIR(inode->i_mode) ||
            (!test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
                       &BTRFS_I(inode)->runtime_flags) &&
-            inode_only == LOG_INODE_EXISTS))
+            inode_only >= LOG_INODE_EXISTS))
                max_key.type = BTRFS_XATTR_ITEM_KEY;
        else
                max_key.type = (u8)-1;
@@ -4665,7 +4666,13 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                return ret;
        }
 
-       mutex_lock(&BTRFS_I(inode)->log_mutex);
+       if (inode_only == LOG_OTHER_INODE) {
+               inode_only = LOG_INODE_EXISTS;
+               mutex_lock_nested(&BTRFS_I(inode)->log_mutex,
+                                 SINGLE_DEPTH_NESTING);
+       } else {
+               mutex_lock(&BTRFS_I(inode)->log_mutex);
+       }
 
        /*
         * a brute force approach to making sure we get the most uptodate
@@ -4817,7 +4824,7 @@ again:
                                 * unpin it.
                                 */
                                err = btrfs_log_inode(trans, root, other_inode,
-                                                     LOG_INODE_EXISTS,
+                                                     LOG_OTHER_INODE,
                                                      0, LLONG_MAX, ctx);
                                iput(other_inode);
                                if (err)
index 161342b73ce50256bd2cba63b0d1c5ece503f599..726f928238d0c86a931cd58613799e59cc35fdf8 100644 (file)
@@ -352,7 +352,5 @@ skip:
 
 out:
        btrfs_free_path(path);
-       if (ret)
-               btrfs_warn(fs_info, "btrfs_uuid_tree_iterate failed %d", ret);
-       return 0;
+       return ret;
 }
index 9cd0c0ea7cdbd5b683ab035927636f9f56b751d3..e4b066cd912ad9ea249c3c88f81026a68186095c 100644 (file)
@@ -502,9 +502,9 @@ static struct ceph_snap_context *get_oldest_context(struct inode *inode,
                dout(" head snapc %p has %d dirty pages\n",
                     snapc, ci->i_wrbuffer_ref_head);
                if (truncate_size)
-                       *truncate_size = capsnap->truncate_size;
+                       *truncate_size = ci->i_truncate_size;
                if (truncate_seq)
-                       *truncate_seq = capsnap->truncate_seq;
+                       *truncate_seq = ci->i_truncate_seq;
        }
        spin_unlock(&ci->i_ceph_lock);
        return snapc;
index baea866a6751facf4c1f18dda23e71582978dffe..94fd76d04683d88103b42ff71a02490201a9783f 100644 (file)
@@ -2591,8 +2591,13 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
                        add_wait_queue(&ci->i_cap_wq, &wait);
 
                        while (!try_get_cap_refs(ci, need, want, endoff,
-                                                true, &_got, &err))
+                                                true, &_got, &err)) {
+                               if (signal_pending(current)) {
+                                       ret = -ERESTARTSYS;
+                                       break;
+                               }
                                wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+                       }
 
                        remove_wait_queue(&ci->i_cap_wq, &wait);
 
index d7a93696663b66b9183a9ae1559c2119b3fc3f98..8ab1fdf0bd49b74f380a578aea92ce738393403d 100644 (file)
@@ -1230,7 +1230,8 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
                struct ceph_mds_client *mdsc =
                        ceph_sb_to_client(dir->i_sb)->mdsc;
                struct ceph_mds_request *req;
-               int op, mask, err;
+               int op, err;
+               u32 mask;
 
                if (flags & LOOKUP_RCU)
                        return -ECHILD;
@@ -1245,7 +1246,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
                        mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED;
                        if (ceph_security_xattr_wanted(dir))
                                mask |= CEPH_CAP_XATTR_SHARED;
-                       req->r_args.getattr.mask = mask;
+                       req->r_args.getattr.mask = cpu_to_le32(mask);
 
                        err = ceph_mdsc_do_request(mdsc, NULL, req);
                        switch (err) {
index 398e5328b30952410cc503e7e4d20918d3bdc671..5e659d054b40ae6faac23af26c5321c5af6ff69b 100644 (file)
@@ -305,7 +305,8 @@ static int frag_tree_split_cmp(const void *l, const void *r)
 {
        struct ceph_frag_tree_split *ls = (struct ceph_frag_tree_split*)l;
        struct ceph_frag_tree_split *rs = (struct ceph_frag_tree_split*)r;
-       return ceph_frag_compare(ls->frag, rs->frag);
+       return ceph_frag_compare(le32_to_cpu(ls->frag),
+                                le32_to_cpu(rs->frag));
 }
 
 static bool is_frag_child(u32 f, struct ceph_inode_frag *frag)
index 4f49253387a0a59d238a041b1ec8fc9fd7185c40..c9d2e553a6c487f01bd11ed4c7a2c15ddfcd058d 100644 (file)
@@ -288,12 +288,13 @@ static int parse_reply_info_extra(void **p, void *end,
                                  struct ceph_mds_reply_info_parsed *info,
                                  u64 features)
 {
-       if (info->head->op == CEPH_MDS_OP_GETFILELOCK)
+       u32 op = le32_to_cpu(info->head->op);
+
+       if (op == CEPH_MDS_OP_GETFILELOCK)
                return parse_reply_info_filelock(p, end, info, features);
-       else if (info->head->op == CEPH_MDS_OP_READDIR ||
-                info->head->op == CEPH_MDS_OP_LSSNAP)
+       else if (op == CEPH_MDS_OP_READDIR || op == CEPH_MDS_OP_LSSNAP)
                return parse_reply_info_dir(p, end, info, features);
-       else if (info->head->op == CEPH_MDS_OP_CREATE)
+       else if (op == CEPH_MDS_OP_CREATE)
                return parse_reply_info_create(p, end, info, features);
        else
                return -EIO;
@@ -2106,6 +2107,11 @@ static int __do_request(struct ceph_mds_client *mdsc,
                        dout("do_request mdsmap err %d\n", err);
                        goto finish;
                }
+               if (mdsc->mdsmap->m_epoch == 0) {
+                       dout("do_request no mdsmap, waiting for map\n");
+                       list_add(&req->r_wait, &mdsc->waiting_for_map);
+                       goto finish;
+               }
                if (!(mdsc->fsc->mount_options->flags &
                      CEPH_MOUNT_OPT_MOUNTWAIT) &&
                    !ceph_mdsmap_is_cluster_available(mdsc->mdsmap)) {
index 8f6a2a5863b9d9275bfb6afb00fc16b867101275..a27fc8791551cc86ca14d2d65e7870990a393f1e 100644 (file)
@@ -285,6 +285,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file)
                        rc = -ENOMEM;
                        goto error_exit;
                }
+               spin_lock_init(&cifsFile->file_info_lock);
                file->private_data = cifsFile;
                cifsFile->tlink = cifs_get_tlink(tlink);
                tcon = tlink_tcon(tlink);
index e525b6017cdf863fd811425fb603070be40420b2..ae6b05629ca174d714bbdb3db477bee8f0d8bff8 100644 (file)
@@ -833,3 +833,21 @@ int dump_align(struct coredump_params *cprm, int align)
        return mod ? dump_skip(cprm, align - mod) : 1;
 }
 EXPORT_SYMBOL(dump_align);
+
+/*
+ * Ensures that file size is big enough to contain the current file
+ * postion. This prevents gdb from complaining about a truncated file
+ * if the last "write" to the file was dump_skip.
+ */
+void dump_truncate(struct coredump_params *cprm)
+{
+       struct file *file = cprm->file;
+       loff_t offset;
+
+       if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+               offset = file->f_op->llseek(file, 0, SEEK_CUR);
+               if (i_size_read(file->f_mapping->host) < offset)
+                       do_truncate(file->f_path.dentry, offset, 0, file);
+       }
+}
+EXPORT_SYMBOL(dump_truncate);
index 5c74f60d0a5094dc0a27f27ae0acd41667414332..c45598b912e14c981fdeb002b01c1535218c0ff2 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -691,8 +691,8 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
                                      pgoff_t index, unsigned long pfn)
 {
        struct vm_area_struct *vma;
-       pte_t *ptep;
-       pte_t pte;
+       pte_t pte, *ptep = NULL;
+       pmd_t *pmdp = NULL;
        spinlock_t *ptl;
        bool changed;
 
@@ -707,21 +707,42 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
 
                address = pgoff_address(index, vma);
                changed = false;
-               if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
+               if (follow_pte_pmd(vma->vm_mm, address, &ptep, &pmdp, &ptl))
                        continue;
-               if (pfn != pte_pfn(*ptep))
-                       goto unlock;
-               if (!pte_dirty(*ptep) && !pte_write(*ptep))
-                       goto unlock;
 
-               flush_cache_page(vma, address, pfn);
-               pte = ptep_clear_flush(vma, address, ptep);
-               pte = pte_wrprotect(pte);
-               pte = pte_mkclean(pte);
-               set_pte_at(vma->vm_mm, address, ptep, pte);
-               changed = true;
-unlock:
-               pte_unmap_unlock(ptep, ptl);
+               if (pmdp) {
+#ifdef CONFIG_FS_DAX_PMD
+                       pmd_t pmd;
+
+                       if (pfn != pmd_pfn(*pmdp))
+                               goto unlock_pmd;
+                       if (!pmd_dirty(*pmdp) && !pmd_write(*pmdp))
+                               goto unlock_pmd;
+
+                       flush_cache_page(vma, address, pfn);
+                       pmd = pmdp_huge_clear_flush(vma, address, pmdp);
+                       pmd = pmd_wrprotect(pmd);
+                       pmd = pmd_mkclean(pmd);
+                       set_pmd_at(vma->vm_mm, address, pmdp, pmd);
+                       changed = true;
+unlock_pmd:
+                       spin_unlock(ptl);
+#endif
+               } else {
+                       if (pfn != pte_pfn(*ptep))
+                               goto unlock_pte;
+                       if (!pte_dirty(*ptep) && !pte_write(*ptep))
+                               goto unlock_pte;
+
+                       flush_cache_page(vma, address, pfn);
+                       pte = ptep_clear_flush(vma, address, ptep);
+                       pte = pte_wrprotect(pte);
+                       pte = pte_mkclean(pte);
+                       set_pte_at(vma->vm_mm, address, ptep, pte);
+                       changed = true;
+unlock_pte:
+                       pte_unmap_unlock(ptep, ptl);
+               }
 
                if (changed)
                        mmu_notifier_invalidate_page(vma->vm_mm, address);
@@ -969,7 +990,6 @@ int __dax_zero_page_range(struct block_device *bdev, sector_t sector,
 }
 EXPORT_SYMBOL_GPL(__dax_zero_page_range);
 
-#ifdef CONFIG_FS_IOMAP
 static sector_t dax_iomap_sector(struct iomap *iomap, loff_t pos)
 {
        return iomap->blkno + (((pos & PAGE_MASK) - iomap->offset) >> 9);
@@ -1011,6 +1031,11 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
                struct blk_dax_ctl dax = { 0 };
                ssize_t map_len;
 
+               if (fatal_signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+
                dax.sector = dax_iomap_sector(iomap, pos);
                dax.size = (length + offset + PAGE_SIZE - 1) & PAGE_MASK;
                map_len = dax_map_atomic(iomap->bdev, &dax);
@@ -1407,4 +1432,3 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
 }
 EXPORT_SYMBOL_GPL(dax_iomap_pmd_fault);
 #endif /* CONFIG_FS_DAX_PMD */
-#endif /* CONFIG_FS_IOMAP */
index 769903dbc19df53199b4aca2e79607145e179c98..95d71eda81420a506c5a1f4a4f5283b31310d5e4 100644 (file)
@@ -1336,8 +1336,11 @@ int d_set_mounted(struct dentry *dentry)
        }
        spin_lock(&dentry->d_lock);
        if (!d_unlinked(dentry)) {
-               dentry->d_flags |= DCACHE_MOUNTED;
-               ret = 0;
+               ret = -EBUSY;
+               if (!d_mountpoint(dentry)) {
+                       dentry->d_flags |= DCACHE_MOUNTED;
+                       ret = 0;
+               }
        }
        spin_unlock(&dentry->d_lock);
 out:
index aeae8c06345155e35e6f9d1567d004c6d073ea66..c87bae4376b848f4204c06016eeb223f675dc7db 100644 (file)
@@ -906,6 +906,7 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
                        struct buffer_head *map_bh)
 {
        const unsigned blkbits = sdio->blkbits;
+       const unsigned i_blkbits = blkbits + sdio->blkfactor;
        int ret = 0;
 
        while (sdio->block_in_file < sdio->final_block_in_request) {
@@ -949,7 +950,7 @@ static int do_direct_IO(struct dio *dio, struct dio_submit *sdio,
                                        clean_bdev_aliases(
                                                map_bh->b_bdev,
                                                map_bh->b_blocknr,
-                                               map_bh->b_size >> blkbits);
+                                               map_bh->b_size >> i_blkbits);
                                }
 
                                if (!sdio->blkfactor)
index 36bea5adcabaa735056b20290ce23cdc7dfc0851..c634874e12d969fbd0b00ad8da745553168876e6 100644 (file)
@@ -1,6 +1,5 @@
 config EXT2_FS
        tristate "Second extended fs support"
-       select FS_IOMAP if FS_DAX
        help
          Ext2 is a standard Linux file system for hard disks.
 
index 7b90691e98c4f5fdd3b2d162285b00e71ac51b63..e38039fd96ff59ab59ce17407abcf26de4c5a950 100644 (file)
@@ -37,7 +37,6 @@ config EXT4_FS
        select CRC16
        select CRYPTO
        select CRYPTO_CRC32C
-       select FS_IOMAP if FS_DAX
        help
          This is the next generation of the ext3 filesystem.
 
index 0738f48293ccbfe0fd528ededfd6a4a08fe4251d..0d880245375890058602437d3c709bfedd3945b8 100644 (file)
@@ -713,8 +713,8 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
        }
        sector = SECTOR_FROM_BLOCK(blkstart);
 
-       if (sector & (bdev_zone_size(bdev) - 1) ||
-                               nr_sects != bdev_zone_size(bdev)) {
+       if (sector & (bdev_zone_sectors(bdev) - 1) ||
+           nr_sects != bdev_zone_sectors(bdev)) {
                f2fs_msg(sbi->sb, KERN_INFO,
                        "(%d) %s: Unaligned discard attempted (block %x + %x)",
                        devi, sbi->s_ndevs ? FDEV(devi).path: "",
index 702638e21c7621a4804a8c84fefc7635785ff42d..46fd30d8af7763c93244092b6673e3cc2ff5f05f 100644 (file)
@@ -1553,16 +1553,16 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
                return 0;
 
        if (sbi->blocks_per_blkz && sbi->blocks_per_blkz !=
-                               SECTOR_TO_BLOCK(bdev_zone_size(bdev)))
+                               SECTOR_TO_BLOCK(bdev_zone_sectors(bdev)))
                return -EINVAL;
-       sbi->blocks_per_blkz = SECTOR_TO_BLOCK(bdev_zone_size(bdev));
+       sbi->blocks_per_blkz = SECTOR_TO_BLOCK(bdev_zone_sectors(bdev));
        if (sbi->log_blocks_per_blkz && sbi->log_blocks_per_blkz !=
                                __ilog2_u32(sbi->blocks_per_blkz))
                return -EINVAL;
        sbi->log_blocks_per_blkz = __ilog2_u32(sbi->blocks_per_blkz);
        FDEV(devi).nr_blkz = SECTOR_TO_BLOCK(nr_sectors) >>
                                        sbi->log_blocks_per_blkz;
-       if (nr_sectors & (bdev_zone_size(bdev) - 1))
+       if (nr_sectors & (bdev_zone_sectors(bdev) - 1))
                FDEV(devi).nr_blkz++;
 
        FDEV(devi).blkz_type = kmalloc(FDEV(devi).nr_blkz, GFP_KERNEL);
index 4304072161aa08c14d24291bf24eb2481c567874..40d61077bead88e39abff93bcdb185941462bfcb 100644 (file)
@@ -542,6 +542,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
                hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
                        if (invalidate)
                                set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
+                       clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
                        fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
                }
        } else {
@@ -560,6 +561,10 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
                wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
                                 TASK_UNINTERRUPTIBLE);
 
+       /* Make sure any pending writes are cancelled. */
+       if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX)
+               fscache_invalidate_writes(cookie);
+
        /* Reset the cookie state if it wasn't relinquished */
        if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
                atomic_inc(&cookie->n_active);
index 9b28649df3a1fdc6f0f0c23b58b03db94dd69eb2..a8aa00be44442f59d6cf08516ab7403d0c02ab9e 100644 (file)
@@ -48,6 +48,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
        cookie->flags           = 1 << FSCACHE_COOKIE_ENABLED;
 
        spin_lock_init(&cookie->lock);
+       spin_lock_init(&cookie->stores_lock);
        INIT_HLIST_HEAD(&cookie->backing_objects);
 
        /* check the netfs type is not already present */
index 9e792e30f4db47b38c6db644487c440a2e12febb..7a182c87f37805f1a5fa6719f5cc06cf3dd38552 100644 (file)
@@ -30,6 +30,7 @@ static const struct fscache_state *fscache_look_up_object(struct fscache_object
 static const struct fscache_state *fscache_object_available(struct fscache_object *, int);
 static const struct fscache_state *fscache_parent_ready(struct fscache_object *, int);
 static const struct fscache_state *fscache_update_object(struct fscache_object *, int);
+static const struct fscache_state *fscache_object_dead(struct fscache_object *, int);
 
 #define __STATE_NAME(n) fscache_osm_##n
 #define STATE(n) (&__STATE_NAME(n))
@@ -91,7 +92,7 @@ static WORK_STATE(LOOKUP_FAILURE,     "LCFL", fscache_lookup_failure);
 static WORK_STATE(KILL_OBJECT,         "KILL", fscache_kill_object);
 static WORK_STATE(KILL_DEPENDENTS,     "KDEP", fscache_kill_dependents);
 static WORK_STATE(DROP_OBJECT,         "DROP", fscache_drop_object);
-static WORK_STATE(OBJECT_DEAD,         "DEAD", (void*)2UL);
+static WORK_STATE(OBJECT_DEAD,         "DEAD", fscache_object_dead);
 
 static WAIT_STATE(WAIT_FOR_INIT,       "?INI",
                  TRANSIT_TO(INIT_OBJECT,       1 << FSCACHE_OBJECT_EV_NEW_CHILD));
@@ -229,6 +230,10 @@ execute_work_state:
        event = -1;
        if (new_state == NO_TRANSIT) {
                _debug("{OBJ%x} %s notrans", object->debug_id, state->name);
+               if (unlikely(state == STATE(OBJECT_DEAD))) {
+                       _leave(" [dead]");
+                       return;
+               }
                fscache_enqueue_object(object);
                event_mask = object->oob_event_mask;
                goto unmask_events;
@@ -239,7 +244,7 @@ execute_work_state:
        object->state = state = new_state;
 
        if (state->work) {
-               if (unlikely(state->work == ((void *)2UL))) {
+               if (unlikely(state == STATE(OBJECT_DEAD))) {
                        _leave(" [dead]");
                        return;
                }
@@ -645,6 +650,12 @@ static const struct fscache_state *fscache_kill_object(struct fscache_object *ob
        fscache_mark_object_dead(object);
        object->oob_event_mask = 0;
 
+       if (test_bit(FSCACHE_OBJECT_RETIRED, &object->flags)) {
+               /* Reject any new read/write ops and abort any that are pending. */
+               clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
+               fscache_cancel_all_ops(object);
+       }
+
        if (list_empty(&object->dependents) &&
            object->n_ops == 0 &&
            object->n_children == 0)
@@ -1077,3 +1088,20 @@ void fscache_object_mark_killed(struct fscache_object *object,
        }
 }
 EXPORT_SYMBOL(fscache_object_mark_killed);
+
+/*
+ * The object is dead.  We can get here if an object gets queued by an event
+ * that would lead to its death (such as EV_KILL) when the dispatcher is
+ * already running (and so can be requeued) but hasn't yet cleared the event
+ * mask.
+ */
+static const struct fscache_state *fscache_object_dead(struct fscache_object *object,
+                                                      int event)
+{
+       if (!test_and_set_bit(FSCACHE_OBJECT_RUN_AFTER_DEAD,
+                             &object->flags))
+               return NO_TRANSIT;
+
+       WARN(true, "FS-Cache object redispatched after death");
+       return NO_TRANSIT;
+}
index 70ea57c7b6bb2b48ecf47d8cc9bd211cfc430a61..f11792672977d2280ec7fc301f81e9b1b1ba7741 100644 (file)
@@ -399,6 +399,10 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
 {
        spin_lock(&fiq->waitq.lock);
+       if (test_bit(FR_FINISHED, &req->flags)) {
+               spin_unlock(&fiq->waitq.lock);
+               return;
+       }
        if (list_empty(&req->intr_entry)) {
                list_add_tail(&req->intr_entry, &fiq->interrupts);
                wake_up_locked(&fiq->waitq);
@@ -1372,6 +1376,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
                 * code can Oops if the buffer persists after module unload.
                 */
                bufs[page_nr].ops = &nosteal_pipe_buf_ops;
+               bufs[page_nr].flags = 0;
                ret = add_to_pipe(pipe, &bufs[page_nr++]);
                if (unlikely(ret < 0))
                        break;
@@ -2025,7 +2030,6 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
                struct fuse_req *req;
                req = list_entry(head->next, struct fuse_req, list);
                req->out.h.error = -ECONNABORTED;
-               clear_bit(FR_PENDING, &req->flags);
                clear_bit(FR_SENT, &req->flags);
                list_del_init(&req->list);
                request_end(fc, req);
@@ -2103,6 +2107,8 @@ void fuse_abort_conn(struct fuse_conn *fc)
                spin_lock(&fiq->waitq.lock);
                fiq->connected = 0;
                list_splice_init(&fiq->pending, &to_end2);
+               list_for_each_entry(req, &to_end2, list)
+                       clear_bit(FR_PENDING, &req->flags);
                while (forget_pending(fiq))
                        kfree(dequeue_forget(fiq, 1, NULL));
                wake_up_all_locked(&fiq->waitq);
index 1f7c732f32b07f1bab9e4961f16cb52ee9f09f70..811fd8929a18c1e330316202fd40ac58857ec3c7 100644 (file)
@@ -68,7 +68,7 @@ static u64 time_to_jiffies(u64 sec, u32 nsec)
        if (sec || nsec) {
                struct timespec64 ts = {
                        sec,
-                       max_t(u32, nsec, NSEC_PER_SEC - 1)
+                       min_t(u32, nsec, NSEC_PER_SEC - 1)
                };
 
                return get_jiffies_64() + timespec64_to_jiffies(&ts);
index 354a123f170e534a016f74ca7006458e3b823ef8..a51cb4c07d4d8cd3a09715361c84126cecae2ca2 100644 (file)
@@ -114,6 +114,9 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
 
        BUG_ON(pos + len > iomap->offset + iomap->length);
 
+       if (fatal_signal_pending(current))
+               return -EINTR;
+
        page = grab_cache_page_write_begin(inode->i_mapping, index, flags);
        if (!page)
                return -ENOMEM;
index e973cd51f12632eff2c17929c85d1e8b2e955730..28d6f35feed62855e26ede0073b3bcaf6b6564a9 100644 (file)
@@ -245,7 +245,8 @@ struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
        struct inode *root;
        struct qstr d_name = QSTR_INIT(name, strlen(name));
 
-       s = sget(fs_type, NULL, set_anon_super, MS_NOUSER, NULL);
+       s = sget_userns(fs_type, NULL, set_anon_super, MS_KERNMOUNT|MS_NOUSER,
+                       &init_user_ns, NULL);
        if (IS_ERR(s))
                return ERR_CAST(s);
 
index b5b1259e064f8d9661110ba1f1f73d1a0ff19d51..487ba30bb5c67a8f66bdaadb5b13e8240c937f7a 100644 (file)
@@ -742,26 +742,50 @@ static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
        return NULL;
 }
 
-static struct mountpoint *new_mountpoint(struct dentry *dentry)
+static struct mountpoint *get_mountpoint(struct dentry *dentry)
 {
-       struct hlist_head *chain = mp_hash(dentry);
-       struct mountpoint *mp;
+       struct mountpoint *mp, *new = NULL;
        int ret;
 
-       mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
-       if (!mp)
+       if (d_mountpoint(dentry)) {
+mountpoint:
+               read_seqlock_excl(&mount_lock);
+               mp = lookup_mountpoint(dentry);
+               read_sequnlock_excl(&mount_lock);
+               if (mp)
+                       goto done;
+       }
+
+       if (!new)
+               new = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+       if (!new)
                return ERR_PTR(-ENOMEM);
 
+
+       /* Exactly one processes may set d_mounted */
        ret = d_set_mounted(dentry);
-       if (ret) {
-               kfree(mp);
-               return ERR_PTR(ret);
-       }
 
-       mp->m_dentry = dentry;
-       mp->m_count = 1;
-       hlist_add_head(&mp->m_hash, chain);
-       INIT_HLIST_HEAD(&mp->m_list);
+       /* Someone else set d_mounted? */
+       if (ret == -EBUSY)
+               goto mountpoint;
+
+       /* The dentry is not available as a mountpoint? */
+       mp = ERR_PTR(ret);
+       if (ret)
+               goto done;
+
+       /* Add the new mountpoint to the hash table */
+       read_seqlock_excl(&mount_lock);
+       new->m_dentry = dentry;
+       new->m_count = 1;
+       hlist_add_head(&new->m_hash, mp_hash(dentry));
+       INIT_HLIST_HEAD(&new->m_list);
+       read_sequnlock_excl(&mount_lock);
+
+       mp = new;
+       new = NULL;
+done:
+       kfree(new);
        return mp;
 }
 
@@ -1595,11 +1619,11 @@ void __detach_mounts(struct dentry *dentry)
        struct mount *mnt;
 
        namespace_lock();
+       lock_mount_hash();
        mp = lookup_mountpoint(dentry);
        if (IS_ERR_OR_NULL(mp))
                goto out_unlock;
 
-       lock_mount_hash();
        event++;
        while (!hlist_empty(&mp->m_list)) {
                mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
@@ -1609,9 +1633,9 @@ void __detach_mounts(struct dentry *dentry)
                }
                else umount_tree(mnt, UMOUNT_CONNECTED);
        }
-       unlock_mount_hash();
        put_mountpoint(mp);
 out_unlock:
+       unlock_mount_hash();
        namespace_unlock();
 }
 
@@ -2038,9 +2062,7 @@ retry:
        namespace_lock();
        mnt = lookup_mnt(path);
        if (likely(!mnt)) {
-               struct mountpoint *mp = lookup_mountpoint(dentry);
-               if (!mp)
-                       mp = new_mountpoint(dentry);
+               struct mountpoint *mp = get_mountpoint(dentry);
                if (IS_ERR(mp)) {
                        namespace_unlock();
                        inode_unlock(dentry->d_inode);
@@ -2059,7 +2081,11 @@ retry:
 static void unlock_mount(struct mountpoint *where)
 {
        struct dentry *dentry = where->m_dentry;
+
+       read_seqlock_excl(&mount_lock);
        put_mountpoint(where);
+       read_sequnlock_excl(&mount_lock);
+
        namespace_unlock();
        inode_unlock(dentry->d_inode);
 }
@@ -3135,9 +3161,9 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
        touch_mnt_namespace(current->nsproxy->mnt_ns);
        /* A moved mount should not expire automatically */
        list_del_init(&new_mnt->mnt_expire);
+       put_mountpoint(root_mp);
        unlock_mount_hash();
        chroot_fs_refs(&root, &new);
-       put_mountpoint(root_mp);
        error = 0;
 out4:
        unlock_mount(old_mp);
index 6dcbc5defb7a8dd670b63995eb553c379e47a0d4..0a0eaecf967683f66461874408a1f572c4b154f1 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/file.h>
 #include <linux/string.h>
 #include <linux/ratelimit.h>
 #include <linux/printk.h>
@@ -1083,7 +1082,8 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
        return nfs4_call_sync_sequence(clnt, server, msg, args, res);
 }
 
-static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
+static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
+               unsigned long timestamp)
 {
        struct nfs_inode *nfsi = NFS_I(dir);
 
@@ -1099,6 +1099,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
                                NFS_INO_INVALID_ACL;
        }
        dir->i_version = cinfo->after;
+       nfsi->read_cache_jiffies = timestamp;
        nfsi->attr_gencount = nfs_inc_attr_generation_counter();
        nfs_fscache_invalidate(dir);
        spin_unlock(&dir->i_lock);
@@ -2391,11 +2392,13 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
        nfs_fattr_map_and_free_names(server, &data->f_attr);
 
        if (o_arg->open_flags & O_CREAT) {
-               update_changeattr(dir, &o_res->cinfo);
                if (o_arg->open_flags & O_EXCL)
                        data->file_created = 1;
                else if (o_res->cinfo.before != o_res->cinfo.after)
                        data->file_created = 1;
+               if (data->file_created || dir->i_version != o_res->cinfo.after)
+                       update_changeattr(dir, &o_res->cinfo,
+                                       o_res->f_attr->time_start);
        }
        if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
                server->caps &= ~NFS_CAP_POSIX_LOCK;
@@ -2697,7 +2700,8 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata,
                sattr->ia_valid |= ATTR_MTIME;
 
        /* Except MODE, it seems harmless of setting twice. */
-       if ((attrset[1] & FATTR4_WORD1_MODE))
+       if (opendata->o_arg.createmode != NFS4_CREATE_EXCLUSIVE &&
+               attrset[1] & FATTR4_WORD1_MODE)
                sattr->ia_valid &= ~ATTR_MODE;
 
        if (attrset[2] & FATTR4_WORD2_SECURITY_LABEL)
@@ -4073,11 +4077,12 @@ static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
+       unsigned long timestamp = jiffies;
        int status;
 
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
        if (status == 0)
-               update_changeattr(dir, &res.cinfo);
+               update_changeattr(dir, &res.cinfo, timestamp);
        return status;
 }
 
@@ -4125,7 +4130,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        if (nfs4_async_handle_error(task, res->server, NULL,
                                    &data->timeout) == -EAGAIN)
                return 0;
-       update_changeattr(dir, &res->cinfo);
+       if (task->tk_status == 0)
+               update_changeattr(dir, &res->cinfo, res->dir_attr->time_start);
        return 1;
 }
 
@@ -4159,8 +4165,11 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
        if (nfs4_async_handle_error(task, res->server, NULL, &data->timeout) == -EAGAIN)
                return 0;
 
-       update_changeattr(old_dir, &res->old_cinfo);
-       update_changeattr(new_dir, &res->new_cinfo);
+       if (task->tk_status == 0) {
+               update_changeattr(old_dir, &res->old_cinfo, res->old_fattr->time_start);
+               if (new_dir != old_dir)
+                       update_changeattr(new_dir, &res->new_cinfo, res->new_fattr->time_start);
+       }
        return 1;
 }
 
@@ -4197,7 +4206,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
 
        status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
        if (!status) {
-               update_changeattr(dir, &res.cinfo);
+               update_changeattr(dir, &res.cinfo, res.fattr->time_start);
                status = nfs_post_op_update_inode(inode, res.fattr);
                if (!status)
                        nfs_setsecurity(inode, res.fattr, res.label);
@@ -4272,7 +4281,8 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
        int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
                                    &data->arg.seq_args, &data->res.seq_res, 1);
        if (status == 0) {
-               update_changeattr(dir, &data->res.dir_cinfo);
+               update_changeattr(dir, &data->res.dir_cinfo,
+                               data->res.fattr->time_start);
                status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
        }
        return status;
@@ -6127,7 +6137,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
        p->server = server;
        atomic_inc(&lsp->ls_count);
        p->ctx = get_nfs_open_context(ctx);
-       get_file(fl->fl_file);
        memcpy(&p->fl, fl, sizeof(p->fl));
        return p;
 out_free_seqid:
@@ -6240,7 +6249,6 @@ static void nfs4_lock_release(void *calldata)
                nfs_free_seqid(data->arg.lock_seqid);
        nfs4_put_lock_state(data->lsp);
        put_nfs_open_context(data->ctx);
-       fput(data->fl.fl_file);
        kfree(data);
        dprintk("%s: done!\n", __func__);
 }
@@ -8483,6 +8491,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
                goto out;
        }
 
+       nfs4_sequence_free_slot(&lgp->res.seq_res);
        err = nfs4_handle_exception(server, nfs4err, exception);
        if (!status) {
                if (exception->retry)
index 1d152f4470cd6f6b0bcc6f73fd572e331b18778b..daeb94e3acd49bd6553601bd15adb8f72236825b 100644 (file)
@@ -1091,6 +1091,7 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
                case -NFS4ERR_BADXDR:
                case -NFS4ERR_RESOURCE:
                case -NFS4ERR_NOFILEHANDLE:
+               case -NFS4ERR_MOVED:
                        /* Non-seqid mutating errors */
                        return;
        };
@@ -1729,7 +1730,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                        break;
                case -NFS4ERR_STALE_CLIENTID:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-                       nfs4_state_clear_reclaim_reboot(clp);
                        nfs4_state_start_reclaim_reboot(clp);
                        break;
                case -NFS4ERR_EXPIRED:
index 59554f3adf2948a10dd945b5f8441c236f53e9f2..dd042498ce7c67df24b4919c2e98dc8f48db13ca 100644 (file)
@@ -1200,10 +1200,10 @@ _pnfs_return_layout(struct inode *ino)
 
        send = pnfs_prepare_layoutreturn(lo, &stateid, NULL);
        spin_unlock(&ino->i_lock);
-       pnfs_free_lseg_list(&tmp_list);
        if (send)
                status = pnfs_send_layoutreturn(lo, &stateid, IOMODE_ANY, true);
 out_put_layout_hdr:
+       pnfs_free_lseg_list(&tmp_list);
        pnfs_put_layout_hdr(lo);
 out:
        dprintk("<-- %s status: %d\n", __func__, status);
index 596205d939a1f43f1faa292d31680377045a8589..1fc07a9c70e9c6028342e8c97d183dfe914a343b 100644 (file)
@@ -223,10 +223,11 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate,
        struct nfs4_layout_stateid *ls;
        struct nfs4_stid *stp;
 
-       stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache);
+       stp = nfs4_alloc_stid(cstate->clp, nfs4_layout_stateid_cache,
+                                       nfsd4_free_layout_stateid);
        if (!stp)
                return NULL;
-       stp->sc_free = nfsd4_free_layout_stateid;
+
        get_nfs4_file(fp);
        stp->sc_file = fp;
 
index 4b4beaaa4eaac01233f874c7dfdb8d1a6d7cd3d6..a0dee8ae9f97f16a18e40ba19f8e84a45ad1a02b 100644 (file)
@@ -633,8 +633,8 @@ out:
        return co;
 }
 
-struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
-                                        struct kmem_cache *slab)
+struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
+                                 void (*sc_free)(struct nfs4_stid *))
 {
        struct nfs4_stid *stid;
        int new_id;
@@ -650,6 +650,8 @@ struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
        idr_preload_end();
        if (new_id < 0)
                goto out_free;
+
+       stid->sc_free = sc_free;
        stid->sc_client = cl;
        stid->sc_stateid.si_opaque.so_id = new_id;
        stid->sc_stateid.si_opaque.so_clid = cl->cl_clientid;
@@ -675,15 +677,12 @@ out_free:
 static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp)
 {
        struct nfs4_stid *stid;
-       struct nfs4_ol_stateid *stp;
 
-       stid = nfs4_alloc_stid(clp, stateid_slab);
+       stid = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_ol_stateid);
        if (!stid)
                return NULL;
 
-       stp = openlockstateid(stid);
-       stp->st_stid.sc_free = nfs4_free_ol_stateid;
-       return stp;
+       return openlockstateid(stid);
 }
 
 static void nfs4_free_deleg(struct nfs4_stid *stid)
@@ -781,11 +780,10 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh,
                goto out_dec;
        if (delegation_blocked(&current_fh->fh_handle))
                goto out_dec;
-       dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab));
+       dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab, nfs4_free_deleg));
        if (dp == NULL)
                goto out_dec;
 
-       dp->dl_stid.sc_free = nfs4_free_deleg;
        /*
         * delegation seqid's are never incremented.  The 4.1 special
         * meaning of seqid 0 isn't meaningful, really, but let's avoid
@@ -5580,7 +5578,6 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
        stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
        get_nfs4_file(fp);
        stp->st_stid.sc_file = fp;
-       stp->st_stid.sc_free = nfs4_free_lock_stateid;
        stp->st_access_bmap = 0;
        stp->st_deny_bmap = open_stp->st_deny_bmap;
        stp->st_openstp = open_stp;
@@ -5623,7 +5620,7 @@ find_or_create_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fi,
        lst = find_lock_stateid(lo, fi);
        if (lst == NULL) {
                spin_unlock(&clp->cl_lock);
-               ns = nfs4_alloc_stid(clp, stateid_slab);
+               ns = nfs4_alloc_stid(clp, stateid_slab, nfs4_free_lock_stateid);
                if (ns == NULL)
                        return NULL;
 
index 7ecf16be4a444ec250678e89ad210c7f19cbbc18..8fae53ce21d16c8406ff01425d924eb044edee34 100644 (file)
@@ -2440,7 +2440,9 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
        p++;                /* to be backfilled later */
 
        if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
-               u32 *supp = nfsd_suppattrs[minorversion];
+               u32 supp[3];
+
+               memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
 
                if (!IS_POSIXACL(dentry->d_inode))
                        supp[0] &= ~FATTR4_WORD0_ACL;
index c9399366f9dfc73b343d079fbad2dc2127927aae..4516e8b7d776305d94fb89f86256ee3fc54dec27 100644 (file)
@@ -603,8 +603,8 @@ extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
 __be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
                     stateid_t *stateid, unsigned char typemask,
                     struct nfs4_stid **s, struct nfsd_net *nn);
-struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
-               struct kmem_cache *slab);
+struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct kmem_cache *slab,
+                                 void (*sc_free)(struct nfs4_stid *));
 void nfs4_unhash_stid(struct nfs4_stid *s);
 void nfs4_put_stid(struct nfs4_stid *s);
 void nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid);
index d3fea0bd89e2cbedcea630ba3e966963720f725a..6043306e8e21518daeb945ebf2569d19fe9edbbf 100644 (file)
@@ -510,18 +510,6 @@ void fsnotify_detach_group_marks(struct fsnotify_group *group)
        }
 }
 
-void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old)
-{
-       assert_spin_locked(&old->lock);
-       new->inode = old->inode;
-       new->mnt = old->mnt;
-       if (old->group)
-               fsnotify_get_group(old->group);
-       new->group = old->group;
-       new->mask = old->mask;
-       new->free_mark = old->free_mark;
-}
-
 /*
  * Nothing fancy, just initialize lists and locks and counters.
  */
index 83d576f6a287b13939a7dd70622ae4d89b5031f8..77d1632e905d8b1ec249cf86c7ece183c38f2746 100644 (file)
@@ -3303,6 +3303,16 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
        mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name,
             lockres->l_level, new_level);
 
+       /*
+        * On DLM_LKF_VALBLK, fsdlm behaves differently with o2cb. It always
+        * expects DLM_LKF_VALBLK being set if the LKB has LVB, so that
+        * we can recover correctly from node failure. Otherwise, we may get
+        * invalid LVB in LKB, but without DLM_SBF_VALNOTVALID being set.
+        */
+       if (!ocfs2_is_o2cb_active() &&
+           lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
+               lvb = 1;
+
        if (lvb)
                dlm_flags |= DLM_LKF_VALBLK;
 
index 52c07346bea3f8960399184c0e6aead7545a25f2..820359096c7aa8df5b76e2a0c1404ce7f9d0337d 100644 (file)
@@ -48,6 +48,12 @@ static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";
  */
 static struct ocfs2_stack_plugin *active_stack;
 
+inline int ocfs2_is_o2cb_active(void)
+{
+       return !strcmp(active_stack->sp_name, OCFS2_STACK_PLUGIN_O2CB);
+}
+EXPORT_SYMBOL_GPL(ocfs2_is_o2cb_active);
+
 static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
 {
        struct ocfs2_stack_plugin *p;
index f2dce10fae543c254dcb4e6628d357b60a3ac16c..e3036e1790e86da7b4e13dcb0b8c88e3f19b6d50 100644 (file)
@@ -298,6 +298,9 @@ void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_p
 int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin);
 void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin);
 
+/* In ocfs2_downconvert_lock(), we need to know which stack we are using */
+int ocfs2_is_o2cb_active(void);
+
 extern struct kset *ocfs2_kset;
 
 #endif  /* STACKGLUE_H */
index 9ad48d9202a99a6c63ccb07b9b31476f5ee524af..023bb0b03352f4440d893b4e713d7d9ed937a771 100644 (file)
@@ -154,29 +154,38 @@ out_err:
 static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
                            struct dentry **ret)
 {
-       const char *s = d->name.name;
+       /* Counting down from the end, since the prefix can change */
+       size_t rem = d->name.len - 1;
        struct dentry *dentry = NULL;
        int err;
 
-       if (*s != '/')
+       if (d->name.name[0] != '/')
                return ovl_lookup_single(base, d, d->name.name, d->name.len,
                                         0, "", ret);
 
-       while (*s++ == '/' && !IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
+       while (!IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
+               const char *s = d->name.name + d->name.len - rem;
                const char *next = strchrnul(s, '/');
-               size_t slen = strlen(s);
+               size_t thislen = next - s;
+               bool end = !next[0];
 
-               if (WARN_ON(slen > d->name.len) ||
-                   WARN_ON(strcmp(d->name.name + d->name.len - slen, s)))
+               /* Verify we did not go off the rails */
+               if (WARN_ON(s[-1] != '/'))
                        return -EIO;
 
-               err = ovl_lookup_single(base, d, s, next - s,
-                                       d->name.len - slen, next, &base);
+               err = ovl_lookup_single(base, d, s, thislen,
+                                       d->name.len - rem, next, &base);
                dput(dentry);
                if (err)
                        return err;
                dentry = base;
-               s = next;
+               if (end)
+                       break;
+
+               rem -= thislen + 1;
+
+               if (WARN_ON(rem >= d->name.len))
+                       return -EIO;
        }
        *ret = dentry;
        return 0;
index 595522022aca04beeeabd3d2ed4e73992f268296..c9d48dc784953fa4af62f9af58dfbb56ed2faa70 100644 (file)
@@ -922,11 +922,10 @@ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        int error;
 
        if (type == ACL_TYPE_ACCESS) {
-               error = posix_acl_equiv_mode(acl, &inode->i_mode);
-               if (error < 0)
-                       return 0;
-               if (error == 0)
-                       acl = NULL;
+               error = posix_acl_update_mode(inode,
+                               &inode->i_mode, &acl);
+               if (error)
+                       return error;
        }
 
        inode->i_ctime = current_time(inode);
index 8e7e61b28f31c037961c081d09a7be5f818013ef..87c9a9aacda3601e2686e239243f447728137943 100644 (file)
@@ -3179,6 +3179,8 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
             iter.tgid += 1, iter = next_tgid(ns, iter)) {
                char name[PROC_NUMBUF];
                int len;
+
+               cond_resched();
                if (!has_pid_permissions(ns, iter.task, 2))
                        continue;
 
index a2066e6dee9058ac41b3c51cfcad83f0796e0598..2726536489b19a30394226a27e7a0183690e6b4c 100644 (file)
@@ -173,7 +173,8 @@ u64 stable_page_flags(struct page *page)
        u |= kpf_copy_bit(k, KPF_ACTIVE,        PG_active);
        u |= kpf_copy_bit(k, KPF_RECLAIM,       PG_reclaim);
 
-       u |= kpf_copy_bit(k, KPF_SWAPCACHE,     PG_swapcache);
+       if (PageSwapCache(page))
+               u |= 1 << KPF_SWAPCACHE;
        u |= kpf_copy_bit(k, KPF_SWAPBACKED,    PG_swapbacked);
 
        u |= kpf_copy_bit(k, KPF_UNEVICTABLE,   PG_unevictable);
index 55313d9948954bbe4bff5769e487eb78012776db..d4e37acd48217dcb1090a1ee68bb4ec4cb7226e5 100644 (file)
@@ -709,7 +709,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
        ctl_dir = container_of(head, struct ctl_dir, header);
 
        if (!dir_emit_dots(file, ctx))
-               return 0;
+               goto out;
 
        pos = 2;
 
@@ -719,6 +719,7 @@ static int proc_sys_readdir(struct file *file, struct dir_context *ctx)
                        break;
                }
        }
+out:
        sysctl_head_finish(head);
        return 0;
 }
index 27c059e1760a8918a0dde19cb884c5ff4563606c..1d887efaaf718c497a233b63286914cd9a498a00 100644 (file)
@@ -280,7 +280,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
                                           1, id, type, PSTORE_TYPE_PMSG, 0);
 
        /* ftrace is last since it may want to dynamically allocate memory. */
-       if (!prz_ok(prz)) {
+       if (!prz_ok(prz) && cxt->fprzs) {
                if (!(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)) {
                        prz = ramoops_get_next_prz(cxt->fprzs,
                                        &cxt->ftrace_read_cnt, 1, id, type,
index d0f8a38dfafacd8f3d524d1ff69ae8f621eea278..0186fe6d39f3b4d2e77497d4d34a7691204ae9fa 100644 (file)
@@ -74,6 +74,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/uaccess.h>
+#include <linux/major.h>
 #include "internal.h"
 
 static struct kmem_cache *romfs_inode_cachep;
@@ -416,7 +417,22 @@ static void romfs_destroy_inode(struct inode *inode)
 static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
-       u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
+       u64 id = 0;
+
+       /* When calling huge_encode_dev(),
+        * use sb->s_bdev->bd_dev when,
+        *   - CONFIG_ROMFS_ON_BLOCK defined
+        * use sb->s_dev when,
+        *   - CONFIG_ROMFS_ON_BLOCK undefined and
+        *   - CONFIG_ROMFS_ON_MTD defined
+        * leave id as 0 when,
+        *   - CONFIG_ROMFS_ON_BLOCK undefined and
+        *   - CONFIG_ROMFS_ON_MTD undefined
+        */
+       if (sb->s_bdev)
+               id = huge_encode_dev(sb->s_bdev->bd_dev);
+       else if (sb->s_dev)
+               id = huge_encode_dev(sb->s_dev);
 
        buf->f_type = ROMFS_MAGIC;
        buf->f_namelen = ROMFS_MAXFN;
@@ -489,6 +505,11 @@ static int romfs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_flags |= MS_RDONLY | MS_NOATIME;
        sb->s_op = &romfs_super_ops;
 
+#ifdef CONFIG_ROMFS_ON_MTD
+       /* Use same dev ID from the underlying mtdblock device */
+       if (sb->s_mtd)
+               sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
+#endif
        /* read the image superblock and check it */
        rsb = kmalloc(512, GFP_KERNEL);
        if (!rsb)
index 873d83104e79aed14a24c417f211e38ae4038122..4ef78aa8ef61e8d0f091fe4088bc7c28035b5ef1 100644 (file)
@@ -204,6 +204,7 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
                buf->len = spd->partial[page_nr].len;
                buf->private = spd->partial[page_nr].private;
                buf->ops = spd->ops;
+               buf->flags = 0;
 
                pipe->nrbufs++;
                page_nr++;
index 0a908ae7af1382d46efa5c8073300db4680ce7e2..b0d0623c83ed88eae3afa31f079dfd2486767d07 100644 (file)
@@ -53,7 +53,7 @@ config UBIFS_ATIME_SUPPORT
 
 config UBIFS_FS_ENCRYPTION
        bool "UBIFS Encryption"
-       depends on UBIFS_FS
+       depends on UBIFS_FS && BLOCK
        select FS_ENCRYPTION
        default n
        help
index 1c5331ac9614040016019aca78c1338133ea4e11..528369f3e472087fe39e0b9e716cb4a70016cee7 100644 (file)
@@ -390,16 +390,6 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
        dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
                dentry, mode, dir->i_ino);
 
-       if (ubifs_crypt_is_encrypted(dir)) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       return err;
-
-               if (!fscrypt_has_encryption_key(dir)) {
-                       return -EPERM;
-               }
-       }
-
        err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
        if (err)
                return err;
@@ -741,17 +731,9 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
        ubifs_assert(inode_is_locked(dir));
        ubifs_assert(inode_is_locked(inode));
 
-       if (ubifs_crypt_is_encrypted(dir)) {
-               if (!fscrypt_has_permitted_context(dir, inode))
-                       return -EPERM;
-
-               err = fscrypt_get_encryption_info(inode);
-               if (err)
-                       return err;
-
-               if (!fscrypt_has_encryption_key(inode))
-                       return -EPERM;
-       }
+       if (ubifs_crypt_is_encrypted(dir) &&
+           !fscrypt_has_permitted_context(dir, inode))
+               return -EPERM;
 
        err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
        if (err)
@@ -1000,17 +982,6 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        if (err)
                return err;
 
-       if (ubifs_crypt_is_encrypted(dir)) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       goto out_budg;
-
-               if (!fscrypt_has_encryption_key(dir)) {
-                       err = -EPERM;
-                       goto out_budg;
-               }
-       }
-
        err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
        if (err)
                goto out_budg;
@@ -1096,17 +1067,6 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
                return err;
        }
 
-       if (ubifs_crypt_is_encrypted(dir)) {
-               err = fscrypt_get_encryption_info(dir);
-               if (err)
-                       goto out_budg;
-
-               if (!fscrypt_has_encryption_key(dir)) {
-                       err = -EPERM;
-                       goto out_budg;
-               }
-       }
-
        err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
        if (err)
                goto out_budg;
@@ -1231,18 +1191,6 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
                        goto out_inode;
                }
 
-               err = fscrypt_get_encryption_info(inode);
-               if (err) {
-                       kfree(sd);
-                       goto out_inode;
-               }
-
-               if (!fscrypt_has_encryption_key(inode)) {
-                       kfree(sd);
-                       err = -EPERM;
-                       goto out_inode;
-               }
-
                ostr.name = sd->encrypted_path;
                ostr.len = disk_link.len;
 
index 78d713644df3c00cf5f3be6ae51b742a47345417..da519ba205f614fb7a5ea9d3eb72b4c58b4504e9 100644 (file)
@@ -217,6 +217,9 @@ long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FS_IOC32_SETFLAGS:
                cmd = FS_IOC_SETFLAGS;
                break;
+       case FS_IOC_SET_ENCRYPTION_POLICY:
+       case FS_IOC_GET_ENCRYPTION_POLICY:
+               break;
        default:
                return -ENOIOCTLCMD;
        }
index a459211a1c21059ff8739566d873b2093285b495..294519b98874058ef7ac7e089361733adb9f26de 100644 (file)
@@ -744,6 +744,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 
        } else {
                data->compr_size = 0;
+               out_len = compr_len;
        }
 
        dlen = UBIFS_DATA_NODE_SZ + out_len;
@@ -1319,6 +1320,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
        dn->compr_type = cpu_to_le16(compr_type);
        dn->size = cpu_to_le32(*new_len);
        *new_len = UBIFS_DATA_NODE_SZ + out_len;
+       err = 0;
 out:
        kfree(buf);
        return err;
index 74ae2de949df68b5918a3656840eb5ab22c8cda1..709aa098dd46e48e34a9627cd0af85d136737fab 100644 (file)
 #include <linux/slab.h>
 #include "ubifs.h"
 
+static int try_read_node(const struct ubifs_info *c, void *buf, int type,
+                        int len, int lnum, int offs);
+static int fallible_read_node(struct ubifs_info *c, const union ubifs_key *key,
+                             struct ubifs_zbranch *zbr, void *node);
+
 /*
  * Returned codes of 'matches_name()' and 'fallible_matches_name()' functions.
  * @NAME_LESS: name corresponding to the first argument is less than second
@@ -402,7 +407,19 @@ static int tnc_read_hashed_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
                return 0;
        }
 
-       err = ubifs_tnc_read_node(c, zbr, node);
+       if (c->replaying) {
+               err = fallible_read_node(c, &zbr->key, zbr, node);
+               /*
+                * When the node was not found, return -ENOENT, 0 otherwise.
+                * Negative return codes stay as-is.
+                */
+               if (err == 0)
+                       err = -ENOENT;
+               else if (err == 1)
+                       err = 0;
+       } else {
+               err = ubifs_tnc_read_node(c, zbr, node);
+       }
        if (err)
                return err;
 
@@ -2857,7 +2874,11 @@ struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,
        if (fname_len(nm) > 0) {
                if (err) {
                        /* Handle collisions */
-                       err = resolve_collision(c, key, &znode, &n, nm);
+                       if (c->replaying)
+                               err = fallible_resolve_collision(c, key, &znode, &n,
+                                                        nm, 0);
+                       else
+                               err = resolve_collision(c, key, &znode, &n, nm);
                        dbg_tnc("rc returned %d, znode %p, n %d",
                                err, znode, n);
                        if (unlikely(err < 0))
index d96e2f30084bcfab552ffe3005af090abfe319c9..43953e03c35682723c6658dfe9b8cceed9de22ef 100644 (file)
@@ -63,6 +63,7 @@ struct userfaultfd_wait_queue {
        struct uffd_msg msg;
        wait_queue_t wq;
        struct userfaultfd_ctx *ctx;
+       bool waken;
 };
 
 struct userfaultfd_wake_range {
@@ -86,6 +87,12 @@ static int userfaultfd_wake_function(wait_queue_t *wq, unsigned mode,
        if (len && (start > uwq->msg.arg.pagefault.address ||
                    start + len <= uwq->msg.arg.pagefault.address))
                goto out;
+       WRITE_ONCE(uwq->waken, true);
+       /*
+        * The implicit smp_mb__before_spinlock in try_to_wake_up()
+        * renders uwq->waken visible to other CPUs before the task is
+        * waken.
+        */
        ret = wake_up_state(wq->private, mode);
        if (ret)
                /*
@@ -264,6 +271,7 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
        struct userfaultfd_wait_queue uwq;
        int ret;
        bool must_wait, return_to_userland;
+       long blocking_state;
 
        BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
 
@@ -334,10 +342,13 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
        uwq.wq.private = current;
        uwq.msg = userfault_msg(vmf->address, vmf->flags, reason);
        uwq.ctx = ctx;
+       uwq.waken = false;
 
        return_to_userland =
                (vmf->flags & (FAULT_FLAG_USER|FAULT_FLAG_KILLABLE)) ==
                (FAULT_FLAG_USER|FAULT_FLAG_KILLABLE);
+       blocking_state = return_to_userland ? TASK_INTERRUPTIBLE :
+                        TASK_KILLABLE;
 
        spin_lock(&ctx->fault_pending_wqh.lock);
        /*
@@ -350,8 +361,7 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
         * following the spin_unlock to happen before the list_add in
         * __add_wait_queue.
         */
-       set_current_state(return_to_userland ? TASK_INTERRUPTIBLE :
-                         TASK_KILLABLE);
+       set_current_state(blocking_state);
        spin_unlock(&ctx->fault_pending_wqh.lock);
 
        must_wait = userfaultfd_must_wait(ctx, vmf->address, vmf->flags,
@@ -364,6 +374,29 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
                wake_up_poll(&ctx->fd_wqh, POLLIN);
                schedule();
                ret |= VM_FAULT_MAJOR;
+
+               /*
+                * False wakeups can orginate even from rwsem before
+                * up_read() however userfaults will wait either for a
+                * targeted wakeup on the specific uwq waitqueue from
+                * wake_userfault() or for signals or for uffd
+                * release.
+                */
+               while (!READ_ONCE(uwq.waken)) {
+                       /*
+                        * This needs the full smp_store_mb()
+                        * guarantee as the state write must be
+                        * visible to other CPUs before reading
+                        * uwq.waken from other CPUs.
+                        */
+                       set_current_state(blocking_state);
+                       if (READ_ONCE(uwq.waken) ||
+                           READ_ONCE(ctx->released) ||
+                           (return_to_userland ? signal_pending(current) :
+                            fatal_signal_pending(current)))
+                               break;
+                       schedule();
+               }
        }
 
        __set_current_state(TASK_RUNNING);
index d346d42c54d1590250040f0b36c05367287e7bf5..33db69be4832c7bb702f34589d715956d7a871fe 100644 (file)
@@ -39,6 +39,7 @@
 #include "xfs_rmap_btree.h"
 #include "xfs_btree.h"
 #include "xfs_refcount_btree.h"
+#include "xfs_ialloc_btree.h"
 
 /*
  * Per-AG Block Reservations
@@ -200,22 +201,30 @@ __xfs_ag_resv_init(
        struct xfs_mount                *mp = pag->pag_mount;
        struct xfs_ag_resv              *resv;
        int                             error;
+       xfs_extlen_t                    reserved;
 
-       resv = xfs_perag_resv(pag, type);
        if (used > ask)
                ask = used;
-       resv->ar_asked = ask;
-       resv->ar_reserved = resv->ar_orig_reserved = ask - used;
-       mp->m_ag_max_usable -= ask;
+       reserved = ask - used;
 
-       trace_xfs_ag_resv_init(pag, type, ask);
-
-       error = xfs_mod_fdblocks(mp, -(int64_t)resv->ar_reserved, true);
-       if (error)
+       error = xfs_mod_fdblocks(mp, -(int64_t)reserved, true);
+       if (error) {
                trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno,
                                error, _RET_IP_);
+               xfs_warn(mp,
+"Per-AG reservation for AG %u failed.  Filesystem may run out of space.",
+                               pag->pag_agno);
+               return error;
+       }
 
-       return error;
+       mp->m_ag_max_usable -= ask;
+
+       resv = xfs_perag_resv(pag, type);
+       resv->ar_asked = ask;
+       resv->ar_reserved = resv->ar_orig_reserved = reserved;
+
+       trace_xfs_ag_resv_init(pag, type, ask);
+       return 0;
 }
 
 /* Create a per-AG block reservation. */
@@ -223,6 +232,8 @@ int
 xfs_ag_resv_init(
        struct xfs_perag                *pag)
 {
+       struct xfs_mount                *mp = pag->pag_mount;
+       xfs_agnumber_t                  agno = pag->pag_agno;
        xfs_extlen_t                    ask;
        xfs_extlen_t                    used;
        int                             error = 0;
@@ -231,23 +242,45 @@ xfs_ag_resv_init(
        if (pag->pag_meta_resv.ar_asked == 0) {
                ask = used = 0;
 
-               error = xfs_refcountbt_calc_reserves(pag->pag_mount,
-                               pag->pag_agno, &ask, &used);
+               error = xfs_refcountbt_calc_reserves(mp, agno, &ask, &used);
                if (error)
                        goto out;
 
-               error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA,
-                               ask, used);
+               error = xfs_finobt_calc_reserves(mp, agno, &ask, &used);
                if (error)
                        goto out;
+
+               error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA,
+                               ask, used);
+               if (error) {
+                       /*
+                        * Because we didn't have per-AG reservations when the
+                        * finobt feature was added we might not be able to
+                        * reserve all needed blocks.  Warn and fall back to the
+                        * old and potentially buggy code in that case, but
+                        * ensure we do have the reservation for the refcountbt.
+                        */
+                       ask = used = 0;
+
+                       mp->m_inotbt_nores = true;
+
+                       error = xfs_refcountbt_calc_reserves(mp, agno, &ask,
+                                       &used);
+                       if (error)
+                               goto out;
+
+                       error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA,
+                                       ask, used);
+                       if (error)
+                               goto out;
+               }
        }
 
        /* Create the AGFL metadata reservation */
        if (pag->pag_agfl_resv.ar_asked == 0) {
                ask = used = 0;
 
-               error = xfs_rmapbt_calc_reserves(pag->pag_mount, pag->pag_agno,
-                               &ask, &used);
+               error = xfs_rmapbt_calc_reserves(mp, agno, &ask, &used);
                if (error)
                        goto out;
 
@@ -256,9 +289,16 @@ xfs_ag_resv_init(
                        goto out;
        }
 
+#ifdef DEBUG
+       /* need to read in the AGF for the ASSERT below to work */
+       error = xfs_alloc_pagf_init(pag->pag_mount, NULL, pag->pag_agno, 0);
+       if (error)
+               return error;
+
        ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
               xfs_perag_resv(pag, XFS_AG_RESV_AGFL)->ar_reserved <=
               pag->pagf_freeblks + pag->pagf_flcount);
+#endif
 out:
        return error;
 }
index 5050056a0b06445a93845987a52ec8356c499f80..9f06a211e1570549cb8df3cdba2de2d01a79f890 100644 (file)
@@ -95,10 +95,7 @@ unsigned int
 xfs_alloc_set_aside(
        struct xfs_mount        *mp)
 {
-       unsigned int            blocks;
-
-       blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE);
-       return blocks;
+       return mp->m_sb.sb_agcount * (XFS_ALLOC_AGFL_RESERVE + 4);
 }
 
 /*
@@ -365,35 +362,11 @@ xfs_alloc_fix_len(
                return;
        ASSERT(rlen >= args->minlen && rlen <= args->maxlen);
        ASSERT(rlen % args->prod == args->mod);
+       ASSERT(args->pag->pagf_freeblks + args->pag->pagf_flcount >=
+               rlen + args->minleft);
        args->len = rlen;
 }
 
-/*
- * Fix up length if there is too little space left in the a.g.
- * Return 1 if ok, 0 if too little, should give up.
- */
-STATIC int
-xfs_alloc_fix_minleft(
-       xfs_alloc_arg_t *args)          /* allocation argument structure */
-{
-       xfs_agf_t       *agf;           /* a.g. freelist header */
-       int             diff;           /* free space difference */
-
-       if (args->minleft == 0)
-               return 1;
-       agf = XFS_BUF_TO_AGF(args->agbp);
-       diff = be32_to_cpu(agf->agf_freeblks)
-               - args->len - args->minleft;
-       if (diff >= 0)
-               return 1;
-       args->len += diff;              /* shrink the allocated space */
-       /* casts to (int) catch length underflows */
-       if ((int)args->len >= (int)args->minlen)
-               return 1;
-       args->agbno = NULLAGBLOCK;
-       return 0;
-}
-
 /*
  * Update the two btrees, logically removing from freespace the extent
  * starting at rbno, rlen blocks.  The extent is contained within the
@@ -689,8 +662,6 @@ xfs_alloc_ag_vextent(
        xfs_alloc_arg_t *args)  /* argument structure for allocation */
 {
        int             error=0;
-       xfs_extlen_t    reservation;
-       xfs_extlen_t    oldmax;
 
        ASSERT(args->minlen > 0);
        ASSERT(args->maxlen > 0);
@@ -698,20 +669,6 @@ xfs_alloc_ag_vextent(
        ASSERT(args->mod < args->prod);
        ASSERT(args->alignment > 0);
 
-       /*
-        * Clamp maxlen to the amount of free space minus any reservations
-        * that have been made.
-        */
-       oldmax = args->maxlen;
-       reservation = xfs_ag_resv_needed(args->pag, args->resv);
-       if (args->maxlen > args->pag->pagf_freeblks - reservation)
-               args->maxlen = args->pag->pagf_freeblks - reservation;
-       if (args->maxlen == 0) {
-               args->agbno = NULLAGBLOCK;
-               args->maxlen = oldmax;
-               return 0;
-       }
-
        /*
         * Branch to correct routine based on the type.
         */
@@ -731,8 +688,6 @@ xfs_alloc_ag_vextent(
                /* NOTREACHED */
        }
 
-       args->maxlen = oldmax;
-
        if (error || args->agbno == NULLAGBLOCK)
                return error;
 
@@ -841,9 +796,6 @@ xfs_alloc_ag_vextent_exact(
        args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen)
                                                - args->agbno;
        xfs_alloc_fix_len(args);
-       if (!xfs_alloc_fix_minleft(args))
-               goto not_found;
-
        ASSERT(args->agbno + args->len <= tend);
 
        /*
@@ -1149,12 +1101,7 @@ restart:
                XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
                args->len = blen;
-               if (!xfs_alloc_fix_minleft(args)) {
-                       xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
-                       trace_xfs_alloc_near_nominleft(args);
-                       return 0;
-               }
-               blen = args->len;
+
                /*
                 * We are allocating starting at bnew for blen blocks.
                 */
@@ -1346,12 +1293,6 @@ restart:
         */
        args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
        xfs_alloc_fix_len(args);
-       if (!xfs_alloc_fix_minleft(args)) {
-               trace_xfs_alloc_near_nominleft(args);
-               xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
-               xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
-               return 0;
-       }
        rlen = args->len;
        (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment,
                                     args->datatype, ltbnoa, ltlena, &ltnew);
@@ -1553,8 +1494,6 @@ restart:
        }
        xfs_alloc_fix_len(args);
 
-       if (!xfs_alloc_fix_minleft(args))
-               goto out_nominleft;
        rlen = args->len;
        XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0);
        /*
@@ -2056,7 +1995,7 @@ xfs_alloc_space_available(
        int                     flags)
 {
        struct xfs_perag        *pag = args->pag;
-       xfs_extlen_t            longest;
+       xfs_extlen_t            alloc_len, longest;
        xfs_extlen_t            reservation; /* blocks that are still reserved */
        int                     available;
 
@@ -2066,17 +2005,28 @@ xfs_alloc_space_available(
        reservation = xfs_ag_resv_needed(pag, args->resv);
 
        /* do we have enough contiguous free space for the allocation? */
+       alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop;
        longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free,
                        reservation);
-       if ((args->minlen + args->alignment + args->minalignslop - 1) > longest)
+       if (longest < alloc_len)
                return false;
 
        /* do we have enough free space remaining for the allocation? */
        available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
-                         reservation - min_free - args->total);
-       if (available < (int)args->minleft || available <= 0)
+                         reservation - min_free - args->minleft);
+       if (available < (int)max(args->total, alloc_len))
                return false;
 
+       /*
+        * Clamp maxlen to the amount of free space available for the actual
+        * extent allocation.
+        */
+       if (available < (int)args->maxlen && !(flags & XFS_ALLOC_FLAG_CHECK)) {
+               args->maxlen = available;
+               ASSERT(args->maxlen > 0);
+               ASSERT(args->maxlen >= args->minlen);
+       }
+
        return true;
 }
 
@@ -2122,7 +2072,8 @@ xfs_alloc_fix_freelist(
        }
 
        need = xfs_alloc_min_freelist(mp, pag);
-       if (!xfs_alloc_space_available(args, need, flags))
+       if (!xfs_alloc_space_available(args, need, flags |
+                       XFS_ALLOC_FLAG_CHECK))
                goto out_agbp_relse;
 
        /*
@@ -2638,12 +2589,10 @@ xfs_alloc_vextent(
        xfs_agblock_t   agsize; /* allocation group size */
        int             error;
        int             flags;  /* XFS_ALLOC_FLAG_... locking flags */
-       xfs_extlen_t    minleft;/* minimum left value, temp copy */
        xfs_mount_t     *mp;    /* mount structure pointer */
        xfs_agnumber_t  sagno;  /* starting allocation group number */
        xfs_alloctype_t type;   /* input allocation type */
        int             bump_rotor = 0;
-       int             no_min = 0;
        xfs_agnumber_t  rotorstep = xfs_rotorstep; /* inode32 agf stepper */
 
        mp = args->mp;
@@ -2672,7 +2621,6 @@ xfs_alloc_vextent(
                trace_xfs_alloc_vextent_badargs(args);
                return 0;
        }
-       minleft = args->minleft;
 
        switch (type) {
        case XFS_ALLOCTYPE_THIS_AG:
@@ -2683,9 +2631,7 @@ xfs_alloc_vextent(
                 */
                args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
                args->pag = xfs_perag_get(mp, args->agno);
-               args->minleft = 0;
                error = xfs_alloc_fix_freelist(args, 0);
-               args->minleft = minleft;
                if (error) {
                        trace_xfs_alloc_vextent_nofix(args);
                        goto error0;
@@ -2750,9 +2696,7 @@ xfs_alloc_vextent(
                 */
                for (;;) {
                        args->pag = xfs_perag_get(mp, args->agno);
-                       if (no_min) args->minleft = 0;
                        error = xfs_alloc_fix_freelist(args, flags);
-                       args->minleft = minleft;
                        if (error) {
                                trace_xfs_alloc_vextent_nofix(args);
                                goto error0;
@@ -2792,20 +2736,17 @@ xfs_alloc_vextent(
                         * or switch to non-trylock mode.
                         */
                        if (args->agno == sagno) {
-                               if (no_min == 1) {
+                               if (flags == 0) {
                                        args->agbno = NULLAGBLOCK;
                                        trace_xfs_alloc_vextent_allfailed(args);
                                        break;
                                }
-                               if (flags == 0) {
-                                       no_min = 1;
-                               } else {
-                                       flags = 0;
-                                       if (type == XFS_ALLOCTYPE_START_BNO) {
-                                               args->agbno = XFS_FSB_TO_AGBNO(mp,
-                                                       args->fsbno);
-                                               args->type = XFS_ALLOCTYPE_NEAR_BNO;
-                                       }
+
+                               flags = 0;
+                               if (type == XFS_ALLOCTYPE_START_BNO) {
+                                       args->agbno = XFS_FSB_TO_AGBNO(mp,
+                                               args->fsbno);
+                                       args->type = XFS_ALLOCTYPE_NEAR_BNO;
                                }
                        }
                        xfs_perag_put(args->pag);
index 7c404a6b0ae32292cf9a6eb39efd15026e8e76ed..1d0f48a501a3d6e9575b634ac022f30a91a2f309 100644 (file)
@@ -56,7 +56,7 @@ typedef unsigned int xfs_alloctype_t;
 #define        XFS_ALLOC_FLAG_FREEING  0x00000002  /* indicate caller is freeing extents*/
 #define        XFS_ALLOC_FLAG_NORMAP   0x00000004  /* don't modify the rmapbt */
 #define        XFS_ALLOC_FLAG_NOSHRINK 0x00000008  /* don't shrink the freelist */
-
+#define        XFS_ALLOC_FLAG_CHECK    0x00000010  /* test only, don't modify args */
 
 /*
  * Argument structure for xfs_alloc routines.
index af1ecb19121e9e8569c0ee907652405575d882c8..6622d46ddec3890c0356dab26fbff448436584d7 100644 (file)
@@ -131,9 +131,6 @@ xfs_attr_get(
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                return -EIO;
 
-       if (!xfs_inode_hasattr(ip))
-               return -ENOATTR;
-
        error = xfs_attr_args_init(&args, ip, name, flags);
        if (error)
                return error;
@@ -392,9 +389,6 @@ xfs_attr_remove(
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
                return -EIO;
 
-       if (!xfs_inode_hasattr(dp))
-               return -ENOATTR;
-
        error = xfs_attr_args_init(&args, dp, name, flags);
        if (error)
                return error;
index 2760bc3b2536c46eedd63c66e127e953dab9ce55..bfc00de5c6f17a75c7addae26e709ee6cbfde3a9 100644 (file)
@@ -3629,7 +3629,7 @@ xfs_bmap_btalloc(
                align = xfs_get_cowextsz_hint(ap->ip);
        else if (xfs_alloc_is_userdata(ap->datatype))
                align = xfs_get_extsz_hint(ap->ip);
-       if (unlikely(align)) {
+       if (align) {
                error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
                                                align, 0, ap->eof, 0, ap->conv,
                                                &ap->offset, &ap->length);
@@ -3701,7 +3701,7 @@ xfs_bmap_btalloc(
                args.minlen = ap->minlen;
        }
        /* apply extent size hints if obtained earlier */
-       if (unlikely(align)) {
+       if (align) {
                args.prod = align;
                if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
                        args.mod = (xfs_extlen_t)(args.prod - args.mod);
@@ -3812,7 +3812,6 @@ xfs_bmap_btalloc(
                args.fsbno = 0;
                args.type = XFS_ALLOCTYPE_FIRST_AG;
                args.total = ap->minlen;
-               args.minleft = 0;
                if ((error = xfs_alloc_vextent(&args)))
                        return error;
                ap->dfops->dop_low = true;
@@ -4344,8 +4343,6 @@ xfs_bmapi_allocate(
        if (error)
                return error;
 
-       if (bma->dfops->dop_low)
-               bma->minleft = 0;
        if (bma->cur)
                bma->cur->bc_private.b.firstblock = *bma->firstblock;
        if (bma->blkno == NULLFSBLOCK)
@@ -4517,8 +4514,6 @@ xfs_bmapi_write(
        int                     n;              /* current extent index */
        xfs_fileoff_t           obno;           /* old block number (offset) */
        int                     whichfork;      /* data or attr fork */
-       char                    inhole;         /* current location is hole in file */
-       char                    wasdelay;       /* old extent was delayed */
 
 #ifdef DEBUG
        xfs_fileoff_t           orig_bno;       /* original block number value */
@@ -4606,22 +4601,44 @@ xfs_bmapi_write(
        bma.firstblock = firstblock;
 
        while (bno < end && n < *nmap) {
-               inhole = eof || bma.got.br_startoff > bno;
-               wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
+               bool                    need_alloc = false, wasdelay = false;
 
-               /*
-                * Make sure we only reflink into a hole.
-                */
-               if (flags & XFS_BMAPI_REMAP)
-                       ASSERT(inhole);
-               if (flags & XFS_BMAPI_COWFORK)
-                       ASSERT(!inhole);
+               /* in hole or beyoned EOF? */
+               if (eof || bma.got.br_startoff > bno) {
+                       if (flags & XFS_BMAPI_DELALLOC) {
+                               /*
+                                * For the COW fork we can reasonably get a
+                                * request for converting an extent that races
+                                * with other threads already having converted
+                                * part of it, as there converting COW to
+                                * regular blocks is not protected using the
+                                * IOLOCK.
+                                */
+                               ASSERT(flags & XFS_BMAPI_COWFORK);
+                               if (!(flags & XFS_BMAPI_COWFORK)) {
+                                       error = -EIO;
+                                       goto error0;
+                               }
+
+                               if (eof || bno >= end)
+                                       break;
+                       } else {
+                               need_alloc = true;
+                       }
+               } else {
+                       /*
+                        * Make sure we only reflink into a hole.
+                        */
+                       ASSERT(!(flags & XFS_BMAPI_REMAP));
+                       if (isnullstartblock(bma.got.br_startblock))
+                               wasdelay = true;
+               }
 
                /*
                 * First, deal with the hole before the allocated space
                 * that we found, if any.
                 */
-               if (inhole || wasdelay) {
+               if (need_alloc || wasdelay) {
                        bma.eof = eof;
                        bma.conv = !!(flags & XFS_BMAPI_CONVERT);
                        bma.wasdel = wasdelay;
index cecd094404cc53d821567be873bafdbba98880fa..cdef87db5262bdc2f43b17f5a1e76fb45a107233 100644 (file)
@@ -110,6 +110,9 @@ struct xfs_extent_free_item
 /* Map something in the CoW fork. */
 #define XFS_BMAPI_COWFORK      0x200
 
+/* Only convert delalloc space, don't allocate entirely new extents */
+#define XFS_BMAPI_DELALLOC     0x400
+
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
        { XFS_BMAPI_METADATA,   "METADATA" }, \
@@ -120,7 +123,8 @@ struct xfs_extent_free_item
        { XFS_BMAPI_CONVERT,    "CONVERT" }, \
        { XFS_BMAPI_ZERO,       "ZERO" }, \
        { XFS_BMAPI_REMAP,      "REMAP" }, \
-       { XFS_BMAPI_COWFORK,    "COWFORK" }
+       { XFS_BMAPI_COWFORK,    "COWFORK" }, \
+       { XFS_BMAPI_DELALLOC,   "DELALLOC" }
 
 
 static inline int xfs_bmapi_aflag(int w)
index d6330c297ca0a4858666403f513f43ce4e16d1a0..d9be241fc86fb39207e725d28bdcdccf943a393d 100644 (file)
@@ -502,12 +502,11 @@ try_another_ag:
        if (args.fsbno == NULLFSBLOCK && args.minleft) {
                /*
                 * Could not find an AG with enough free space to satisfy
-                * a full btree split.  Try again without minleft and if
+                * a full btree split.  Try again and if
                 * successful activate the lowspace algorithm.
                 */
                args.fsbno = 0;
                args.type = XFS_ALLOCTYPE_FIRST_AG;
-               args.minleft = 0;
                error = xfs_alloc_vextent(&args);
                if (error)
                        goto error0;
index c58d72c220f58593cd05b90b3227f1ecb4f2d06f..2f389d366e93324c3f481d8c7b0773475b423d83 100644 (file)
 struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
 
 /*
- * @mode, if set, indicates that the type field needs to be set up.
- * This uses the transformation from file mode to DT_* as defined in linux/fs.h
- * for file type specification. This will be propagated into the directory
- * structure if appropriate for the given operation and filesystem config.
+ * Convert inode mode to directory entry filetype
  */
-const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
-       [0]                     = XFS_DIR3_FT_UNKNOWN,
-       [S_IFREG >> S_SHIFT]    = XFS_DIR3_FT_REG_FILE,
-       [S_IFDIR >> S_SHIFT]    = XFS_DIR3_FT_DIR,
-       [S_IFCHR >> S_SHIFT]    = XFS_DIR3_FT_CHRDEV,
-       [S_IFBLK >> S_SHIFT]    = XFS_DIR3_FT_BLKDEV,
-       [S_IFIFO >> S_SHIFT]    = XFS_DIR3_FT_FIFO,
-       [S_IFSOCK >> S_SHIFT]   = XFS_DIR3_FT_SOCK,
-       [S_IFLNK >> S_SHIFT]    = XFS_DIR3_FT_SYMLINK,
-};
+unsigned char xfs_mode_to_ftype(int mode)
+{
+       switch (mode & S_IFMT) {
+       case S_IFREG:
+               return XFS_DIR3_FT_REG_FILE;
+       case S_IFDIR:
+               return XFS_DIR3_FT_DIR;
+       case S_IFCHR:
+               return XFS_DIR3_FT_CHRDEV;
+       case S_IFBLK:
+               return XFS_DIR3_FT_BLKDEV;
+       case S_IFIFO:
+               return XFS_DIR3_FT_FIFO;
+       case S_IFSOCK:
+               return XFS_DIR3_FT_SOCK;
+       case S_IFLNK:
+               return XFS_DIR3_FT_SYMLINK;
+       default:
+               return XFS_DIR3_FT_UNKNOWN;
+       }
+}
 
 /*
  * ASCII case-insensitive (ie. A-Z) support for directories that was
@@ -631,7 +639,8 @@ xfs_dir2_isblock(
        if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
                return rval;
        rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
-       ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize);
+       if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
+               return -EFSCORRUPTED;
        *vp = rval;
        return 0;
 }
index 0197590fa7d7c0a3d97d68dccdcfb3bd0709964b..d6e6d9d16f6c30d90e88f742c077782bc678b86f 100644 (file)
@@ -18,6 +18,9 @@
 #ifndef __XFS_DIR2_H__
 #define __XFS_DIR2_H__
 
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+
 struct xfs_defer_ops;
 struct xfs_da_args;
 struct xfs_inode;
@@ -32,10 +35,9 @@ struct xfs_dir2_data_unused;
 extern struct xfs_name xfs_name_dotdot;
 
 /*
- * directory filetype conversion tables.
+ * Convert inode mode to directory entry filetype
  */
-#define S_SHIFT 12
-extern const unsigned char xfs_mode_to_ftype[];
+extern unsigned char xfs_mode_to_ftype(int mode);
 
 /*
  * directory operations vector for encode/decode routines
index 0fd086d03d4156cde3fc2851533d910cee046c1c..7c471881c9a67482bd6bf88df59bd6f2e63a57a7 100644 (file)
@@ -82,11 +82,12 @@ xfs_finobt_set_root(
 }
 
 STATIC int
-xfs_inobt_alloc_block(
+__xfs_inobt_alloc_block(
        struct xfs_btree_cur    *cur,
        union xfs_btree_ptr     *start,
        union xfs_btree_ptr     *new,
-       int                     *stat)
+       int                     *stat,
+       enum xfs_ag_resv_type   resv)
 {
        xfs_alloc_arg_t         args;           /* block allocation args */
        int                     error;          /* error return value */
@@ -103,6 +104,7 @@ xfs_inobt_alloc_block(
        args.maxlen = 1;
        args.prod = 1;
        args.type = XFS_ALLOCTYPE_NEAR_BNO;
+       args.resv = resv;
 
        error = xfs_alloc_vextent(&args);
        if (error) {
@@ -122,6 +124,27 @@ xfs_inobt_alloc_block(
        return 0;
 }
 
+STATIC int
+xfs_inobt_alloc_block(
+       struct xfs_btree_cur    *cur,
+       union xfs_btree_ptr     *start,
+       union xfs_btree_ptr     *new,
+       int                     *stat)
+{
+       return __xfs_inobt_alloc_block(cur, start, new, stat, XFS_AG_RESV_NONE);
+}
+
+STATIC int
+xfs_finobt_alloc_block(
+       struct xfs_btree_cur    *cur,
+       union xfs_btree_ptr     *start,
+       union xfs_btree_ptr     *new,
+       int                     *stat)
+{
+       return __xfs_inobt_alloc_block(cur, start, new, stat,
+                       XFS_AG_RESV_METADATA);
+}
+
 STATIC int
 xfs_inobt_free_block(
        struct xfs_btree_cur    *cur,
@@ -328,7 +351,7 @@ static const struct xfs_btree_ops xfs_finobt_ops = {
 
        .dup_cursor             = xfs_inobt_dup_cursor,
        .set_root               = xfs_finobt_set_root,
-       .alloc_block            = xfs_inobt_alloc_block,
+       .alloc_block            = xfs_finobt_alloc_block,
        .free_block             = xfs_inobt_free_block,
        .get_minrecs            = xfs_inobt_get_minrecs,
        .get_maxrecs            = xfs_inobt_get_maxrecs,
@@ -480,3 +503,64 @@ xfs_inobt_rec_check_count(
        return 0;
 }
 #endif /* DEBUG */
+
+static xfs_extlen_t
+xfs_inobt_max_size(
+       struct xfs_mount        *mp)
+{
+       /* Bail out if we're uninitialized, which can happen in mkfs. */
+       if (mp->m_inobt_mxr[0] == 0)
+               return 0;
+
+       return xfs_btree_calc_size(mp, mp->m_inobt_mnr,
+               (uint64_t)mp->m_sb.sb_agblocks * mp->m_sb.sb_inopblock /
+                               XFS_INODES_PER_CHUNK);
+}
+
+static int
+xfs_inobt_count_blocks(
+       struct xfs_mount        *mp,
+       xfs_agnumber_t          agno,
+       xfs_btnum_t             btnum,
+       xfs_extlen_t            *tree_blocks)
+{
+       struct xfs_buf          *agbp;
+       struct xfs_btree_cur    *cur;
+       int                     error;
+
+       error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
+       if (error)
+               return error;
+
+       cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno, btnum);
+       error = xfs_btree_count_blocks(cur, tree_blocks);
+       xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+       xfs_buf_relse(agbp);
+
+       return error;
+}
+
+/*
+ * Figure out how many blocks to reserve and how many are used by this btree.
+ */
+int
+xfs_finobt_calc_reserves(
+       struct xfs_mount        *mp,
+       xfs_agnumber_t          agno,
+       xfs_extlen_t            *ask,
+       xfs_extlen_t            *used)
+{
+       xfs_extlen_t            tree_len = 0;
+       int                     error;
+
+       if (!xfs_sb_version_hasfinobt(&mp->m_sb))
+               return 0;
+
+       error = xfs_inobt_count_blocks(mp, agno, XFS_BTNUM_FINO, &tree_len);
+       if (error)
+               return error;
+
+       *ask += xfs_inobt_max_size(mp);
+       *used += tree_len;
+       return 0;
+}
index bd88453217ceca0466fbd07e409707ab7e9354b3..aa81e2e63f3f95da8434798e8b2bf6501491eac3 100644 (file)
@@ -72,4 +72,7 @@ int xfs_inobt_rec_check_count(struct xfs_mount *,
 #define xfs_inobt_rec_check_count(mp, rec)     0
 #endif /* DEBUG */
 
+int xfs_finobt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno,
+               xfs_extlen_t *ask, xfs_extlen_t *used);
+
 #endif /* __XFS_IALLOC_BTREE_H__ */
index dd483e2767f7a38a4dfef5c063148430364b4aaf..d93f9d918cfc11ada2ded50d21e0eb9226381f93 100644 (file)
@@ -29,6 +29,7 @@
 #include "xfs_icache.h"
 #include "xfs_trans.h"
 #include "xfs_ialloc.h"
+#include "xfs_dir2.h"
 
 /*
  * Check that none of the inode's in the buffer have a next
@@ -386,6 +387,7 @@ xfs_dinode_verify(
        xfs_ino_t               ino,
        struct xfs_dinode       *dip)
 {
+       uint16_t                mode;
        uint16_t                flags;
        uint64_t                flags2;
 
@@ -396,8 +398,12 @@ xfs_dinode_verify(
        if (be64_to_cpu(dip->di_size) & (1ULL << 63))
                return false;
 
-       /* No zero-length symlinks. */
-       if (S_ISLNK(be16_to_cpu(dip->di_mode)) && dip->di_size == 0)
+       mode = be16_to_cpu(dip->di_mode);
+       if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
+               return false;
+
+       /* No zero-length symlinks/dirs. */
+       if ((S_ISLNK(mode) || S_ISDIR(mode)) && dip->di_size == 0)
                return false;
 
        /* only version 3 or greater inodes are extensively verified here */
index 2580262e4ea00c3dc728b041dca125f4f7078373..584ec896a53374f81da05906d517fba717686504 100644 (file)
@@ -242,7 +242,7 @@ xfs_mount_validate_sb(
            sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG                    ||
            sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG                    ||
            sbp->sb_blocksize != (1 << sbp->sb_blocklog)                ||
-           sbp->sb_dirblklog > XFS_MAX_BLOCKSIZE_LOG                   ||
+           sbp->sb_dirblklog + sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
            sbp->sb_inodesize < XFS_DINODE_MIN_SIZE                     ||
            sbp->sb_inodesize > XFS_DINODE_MAX_SIZE                     ||
            sbp->sb_inodelog < XFS_DINODE_MIN_LOG                       ||
index 0f56fcd3a5d51517b93c391bb3d97a58f205a544..631e7c0e0a29ae51eba5f7e25d8dfc96dc93c61e 100644 (file)
@@ -1152,19 +1152,22 @@ xfs_vm_releasepage(
         * block_invalidatepage() can send pages that are still marked dirty
         * but otherwise have invalidated buffers.
         *
-        * We've historically freed buffers on the latter. Instead, quietly
-        * filter out all dirty pages to avoid spurious buffer state warnings.
-        * This can likely be removed once shrink_active_list() is fixed.
+        * We want to release the latter to avoid unnecessary buildup of the
+        * LRU, skip the former and warn if we've left any lingering
+        * delalloc/unwritten buffers on clean pages. Skip pages with delalloc
+        * or unwritten buffers and warn if the page is not dirty. Otherwise
+        * try to release the buffers.
         */
-       if (PageDirty(page))
-               return 0;
-
        xfs_count_page_state(page, &delalloc, &unwritten);
 
-       if (WARN_ON_ONCE(delalloc))
+       if (delalloc) {
+               WARN_ON_ONCE(!PageDirty(page));
                return 0;
-       if (WARN_ON_ONCE(unwritten))
+       }
+       if (unwritten) {
+               WARN_ON_ONCE(!PageDirty(page));
                return 0;
+       }
 
        return try_to_free_buffers(page);
 }
index b9abce524c33b1af8581e8d52d032685fb767747..c1417919ab0a67eb61e97b77746d71c90c392776 100644 (file)
@@ -528,7 +528,6 @@ xfs_getbmap(
        xfs_bmbt_irec_t         *map;           /* buffer for user's data */
        xfs_mount_t             *mp;            /* file system mount point */
        int                     nex;            /* # of user extents can do */
-       int                     nexleft;        /* # of user extents left */
        int                     subnex;         /* # of bmapi's can do */
        int                     nmap;           /* number of map entries */
        struct getbmapx         *out;           /* output structure */
@@ -686,10 +685,8 @@ xfs_getbmap(
                goto out_free_map;
        }
 
-       nexleft = nex;
-
        do {
-               nmap = (nexleft > subnex) ? subnex : nexleft;
+               nmap = (nex> subnex) ? subnex : nex;
                error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
                                       XFS_BB_TO_FSB(mp, bmv->bmv_length),
                                       map, &nmap, bmapi_flags);
@@ -697,8 +694,8 @@ xfs_getbmap(
                        goto out_free_map;
                ASSERT(nmap <= subnex);
 
-               for (i = 0; i < nmap && nexleft && bmv->bmv_length &&
-                               cur_ext < bmv->bmv_count; i++) {
+               for (i = 0; i < nmap && bmv->bmv_length &&
+                               cur_ext < bmv->bmv_count - 1; i++) {
                        out[cur_ext].bmv_oflags = 0;
                        if (map[i].br_state == XFS_EXT_UNWRITTEN)
                                out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
@@ -760,16 +757,27 @@ xfs_getbmap(
                                continue;
                        }
 
+                       /*
+                        * In order to report shared extents accurately,
+                        * we report each distinct shared/unshared part
+                        * of a single bmbt record using multiple bmap
+                        * extents.  To make that happen, we iterate the
+                        * same map array item multiple times, each
+                        * time trimming out the subextent that we just
+                        * reported.
+                        *
+                        * Because of this, we must check the out array
+                        * index (cur_ext) directly against bmv_count-1
+                        * to avoid overflows.
+                        */
                        if (inject_map.br_startblock != NULLFSBLOCK) {
                                map[i] = inject_map;
                                i--;
-                       } else
-                               nexleft--;
+                       }
                        bmv->bmv_entries++;
                        cur_ext++;
                }
-       } while (nmap && nexleft && bmv->bmv_length &&
-                cur_ext < bmv->bmv_count);
+       } while (nmap && bmv->bmv_length && cur_ext < bmv->bmv_count - 1);
 
  out_free_map:
        kmem_free(map);
index 7f0a01f7b592d20932649d1f8a705a836d86ca02..ac3b4db519df8ee5c03fc759295028d6316f474e 100644 (file)
@@ -422,6 +422,7 @@ retry:
 out_free_pages:
        for (i = 0; i < bp->b_page_count; i++)
                __free_page(bp->b_pages[i]);
+       bp->b_flags &= ~_XBF_PAGES;
        return error;
 }
 
index 7a30b8f11db7a26f8a82ded531e8a5170ea03ad5..9d06cc30e875e147a5560bad24e5a55aedb65cf0 100644 (file)
@@ -710,6 +710,10 @@ xfs_dq_get_next_id(
        /* Simple advance */
        next_id = *id + 1;
 
+       /* If we'd wrap past the max ID, stop */
+       if (next_id < *id)
+               return -ENOENT;
+
        /* If new ID is within the current chunk, advancing it sufficed */
        if (next_id % mp->m_quotainfo->qi_dqperchunk) {
                *id = next_id;
index b9557795eb74d4249b34ffd97db6faf0354f8be0..de32f0fe47c8e00d3163b808ebec9c42edefb70b 100644 (file)
@@ -1792,22 +1792,23 @@ xfs_inactive_ifree(
        int                     error;
 
        /*
-        * The ifree transaction might need to allocate blocks for record
-        * insertion to the finobt. We don't want to fail here at ENOSPC, so
-        * allow ifree to dip into the reserved block pool if necessary.
-        *
-        * Freeing large sets of inodes generally means freeing inode chunks,
-        * directory and file data blocks, so this should be relatively safe.
-        * Only under severe circumstances should it be possible to free enough
-        * inodes to exhaust the reserve block pool via finobt expansion while
-        * at the same time not creating free space in the filesystem.
+        * We try to use a per-AG reservation for any block needed by the finobt
+        * tree, but as the finobt feature predates the per-AG reservation
+        * support a degraded file system might not have enough space for the
+        * reservation at mount time.  In that case try to dip into the reserved
+        * pool and pray.
         *
         * Send a warning if the reservation does happen to fail, as the inode
         * now remains allocated and sits on the unlinked list until the fs is
         * repaired.
         */
-       error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree,
-                       XFS_IFREE_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
+       if (unlikely(mp->m_inotbt_nores)) {
+               error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree,
+                               XFS_IFREE_SPACE_RES(mp), 0, XFS_TRANS_RESERVE,
+                               &tp);
+       } else {
+               error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ifree, 0, 0, 0, &tp);
+       }
        if (error) {
                if (error == -ENOSPC) {
                        xfs_warn_ratelimited(mp,
index 0d147428971e0c21c88aa90e2628001cf582971c..1aa3abd67b36670f60b9daf7672c243307c77438 100644 (file)
@@ -681,7 +681,7 @@ xfs_iomap_write_allocate(
        xfs_trans_t     *tp;
        int             nimaps;
        int             error = 0;
-       int             flags = 0;
+       int             flags = XFS_BMAPI_DELALLOC;
        int             nres;
 
        if (whichfork == XFS_COW_FORK)
index 308bebb6dfd266f85ae225ef0c235128bb7b36ba..22c16155f1b42a1380f85935fa43706cd60e2b40 100644 (file)
@@ -97,13 +97,28 @@ xfs_init_security(
 
 static void
 xfs_dentry_to_name(
+       struct xfs_name *namep,
+       struct dentry   *dentry)
+{
+       namep->name = dentry->d_name.name;
+       namep->len = dentry->d_name.len;
+       namep->type = XFS_DIR3_FT_UNKNOWN;
+}
+
+static int
+xfs_dentry_mode_to_name(
        struct xfs_name *namep,
        struct dentry   *dentry,
        int             mode)
 {
        namep->name = dentry->d_name.name;
        namep->len = dentry->d_name.len;
-       namep->type = xfs_mode_to_ftype[(mode & S_IFMT) >> S_SHIFT];
+       namep->type = xfs_mode_to_ftype(mode);
+
+       if (unlikely(namep->type == XFS_DIR3_FT_UNKNOWN))
+               return -EFSCORRUPTED;
+
+       return 0;
 }
 
 STATIC void
@@ -119,7 +134,7 @@ xfs_cleanup_inode(
         * xfs_init_security we must back out.
         * ENOSPC can hit here, among other things.
         */
-       xfs_dentry_to_name(&teardown, dentry, 0);
+       xfs_dentry_to_name(&teardown, dentry);
 
        xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
 }
@@ -154,8 +169,12 @@ xfs_generic_create(
        if (error)
                return error;
 
+       /* Verify mode is valid also for tmpfile case */
+       error = xfs_dentry_mode_to_name(&name, dentry, mode);
+       if (unlikely(error))
+               goto out_free_acl;
+
        if (!tmpfile) {
-               xfs_dentry_to_name(&name, dentry, mode);
                error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
        } else {
                error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip);
@@ -248,7 +267,7 @@ xfs_vn_lookup(
        if (dentry->d_name.len >= MAXNAMELEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       xfs_dentry_to_name(&name, dentry, 0);
+       xfs_dentry_to_name(&name, dentry);
        error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
        if (unlikely(error)) {
                if (unlikely(error != -ENOENT))
@@ -275,7 +294,7 @@ xfs_vn_ci_lookup(
        if (dentry->d_name.len >= MAXNAMELEN)
                return ERR_PTR(-ENAMETOOLONG);
 
-       xfs_dentry_to_name(&xname, dentry, 0);
+       xfs_dentry_to_name(&xname, dentry);
        error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name);
        if (unlikely(error)) {
                if (unlikely(error != -ENOENT))
@@ -310,7 +329,9 @@ xfs_vn_link(
        struct xfs_name name;
        int             error;
 
-       xfs_dentry_to_name(&name, dentry, inode->i_mode);
+       error = xfs_dentry_mode_to_name(&name, dentry, inode->i_mode);
+       if (unlikely(error))
+               return error;
 
        error = xfs_link(XFS_I(dir), XFS_I(inode), &name);
        if (unlikely(error))
@@ -329,7 +350,7 @@ xfs_vn_unlink(
        struct xfs_name name;
        int             error;
 
-       xfs_dentry_to_name(&name, dentry, 0);
+       xfs_dentry_to_name(&name, dentry);
 
        error = xfs_remove(XFS_I(dir), &name, XFS_I(d_inode(dentry)));
        if (error)
@@ -359,7 +380,9 @@ xfs_vn_symlink(
 
        mode = S_IFLNK |
                (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
-       xfs_dentry_to_name(&name, dentry, mode);
+       error = xfs_dentry_mode_to_name(&name, dentry, mode);
+       if (unlikely(error))
+               goto out;
 
        error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip);
        if (unlikely(error))
@@ -395,6 +418,7 @@ xfs_vn_rename(
 {
        struct inode    *new_inode = d_inode(ndentry);
        int             omode = 0;
+       int             error;
        struct xfs_name oname;
        struct xfs_name nname;
 
@@ -405,8 +429,14 @@ xfs_vn_rename(
        if (flags & RENAME_EXCHANGE)
                omode = d_inode(ndentry)->i_mode;
 
-       xfs_dentry_to_name(&oname, odentry, omode);
-       xfs_dentry_to_name(&nname, ndentry, d_inode(odentry)->i_mode);
+       error = xfs_dentry_mode_to_name(&oname, odentry, omode);
+       if (omode && unlikely(error))
+               return error;
+
+       error = xfs_dentry_mode_to_name(&nname, ndentry,
+                                       d_inode(odentry)->i_mode);
+       if (unlikely(error))
+               return error;
 
        return xfs_rename(XFS_I(odir), &oname, XFS_I(d_inode(odentry)),
                          XFS_I(ndir), &nname,
index e467218c0098323d41e55caf4a660862d39463a8..7a989de224f4b77477e88e74e23d1be4272682be 100644 (file)
@@ -331,11 +331,11 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
 }
 
 #define ASSERT_ALWAYS(expr)    \
-       (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+       (likely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
 
 #ifdef DEBUG
 #define ASSERT(expr)   \
-       (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+       (likely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
 
 #ifndef STATIC
 # define STATIC noinline
@@ -346,7 +346,7 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
 #ifdef XFS_WARN
 
 #define ASSERT(expr)   \
-       (unlikely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__))
+       (likely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__))
 
 #ifndef STATIC
 # define STATIC static noinline
index c39ac14ff54009ba33a4a7313612bd2afb95117c..b1469f0a91a6c04329cb2fff2dc6e9953485a071 100644 (file)
@@ -3317,12 +3317,8 @@ xfs_log_force(
        xfs_mount_t     *mp,
        uint            flags)
 {
-       int     error;
-
        trace_xfs_log_force(mp, 0, _RET_IP_);
-       error = _xfs_log_force(mp, flags, NULL);
-       if (error)
-               xfs_warn(mp, "%s: error %d returned.", __func__, error);
+       _xfs_log_force(mp, flags, NULL);
 }
 
 /*
@@ -3466,12 +3462,8 @@ xfs_log_force_lsn(
        xfs_lsn_t       lsn,
        uint            flags)
 {
-       int     error;
-
        trace_xfs_log_force(mp, lsn, _RET_IP_);
-       error = _xfs_log_force_lsn(mp, lsn, flags, NULL);
-       if (error)
-               xfs_warn(mp, "%s: error %d returned.", __func__, error);
+       _xfs_log_force_lsn(mp, lsn, flags, NULL);
 }
 
 /*
index 84f785218907434276d12e6926d8e85974a14477..7f351f706b7a2938292680801c9fa0bf51458c1c 100644 (file)
@@ -140,6 +140,7 @@ typedef struct xfs_mount {
        int                     m_fixedfsid[2]; /* unchanged for life of FS */
        uint                    m_dmevmask;     /* DMI events for this FS */
        __uint64_t              m_flags;        /* global mount flags */
+       bool                    m_inotbt_nores; /* no per-AG finobt resv. */
        int                     m_ialloc_inos;  /* inodes in inode allocation */
        int                     m_ialloc_blks;  /* blocks in inode allocation */
        int                     m_ialloc_min_blks;/* min blocks in sparse inode
index 45e50ea90769f15d80e3da57e9a6d1721d12a21a..b669b123287bb115e561a6ea1c0be8ae4db359db 100644 (file)
@@ -1177,7 +1177,8 @@ xfs_qm_dqusage_adjust(
         * the case in all other instances. It's OK that we do this because
         * quotacheck is done only at mount time.
         */
-       error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip);
+       error = xfs_iget(mp, NULL, ino, XFS_IGET_DONTCACHE, XFS_ILOCK_EXCL,
+                        &ip);
        if (error) {
                *res = BULKSTAT_RV_NOTHING;
                return error;
index df13637e4017342ac427894ec5c342123b77339e..939869c772b17a07a9776e323e1a253dba1f92d2 100644 (file)
@@ -1,7 +1,13 @@
 #include <linux/bitops.h>
+#undef __memset
 extern void *__memset(void *, int, __kernel_size_t);
+#undef __memcpy
 extern void *__memcpy(void *, const void *, __kernel_size_t);
+#undef __memmove
 extern void *__memmove(void *, const void *, __kernel_size_t);
+#undef memset
 extern void *memset(void *, int, __kernel_size_t);
+#undef memcpy
 extern void *memcpy(void *, const void *, __kernel_size_t);
+#undef memmove
 extern void *memmove(void *, const void *, __kernel_size_t);
index 63554e9f6e0c68595943e27d2734ad4fa8271007..719db1968d8177a91028fd5e8bd6068f5d71c491 100644 (file)
@@ -9,18 +9,15 @@
 #ifndef KSYM_ALIGN
 #define KSYM_ALIGN 8
 #endif
-#ifndef KCRC_ALIGN
-#define KCRC_ALIGN 8
-#endif
 #else
 #define __put .long
 #ifndef KSYM_ALIGN
 #define KSYM_ALIGN 4
 #endif
+#endif
 #ifndef KCRC_ALIGN
 #define KCRC_ALIGN 4
 #endif
-#endif
 
 #ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
 #define KSYM(name) _##name
@@ -52,7 +49,11 @@ KSYM(__kstrtab_\name):
        .section ___kcrctab\sec+\name,"a"
        .balign KCRC_ALIGN
 KSYM(__kcrctab_\name):
-       __put KSYM(__crc_\name)
+#if defined(CONFIG_MODULE_REL_CRCS)
+       .long KSYM(__crc_\name) - .
+#else
+       .long KSYM(__crc_\name)
+#endif
        .weak KSYM(__crc_\name)
        .previous
 #endif
index 192016e2b5183c7a22fd13fd21372de5862f44d8..9c4ee144b5f6b799baf92a9722cddcaee3eb2b4f 100644 (file)
@@ -517,6 +517,7 @@ struct drm_device {
        struct drm_minor *control;              /**< Control node */
        struct drm_minor *primary;              /**< Primary node */
        struct drm_minor *render;               /**< Render node */
+       bool registered;
 
        /* currently active master for this device. Protected by master_mutex */
        struct drm_master *master;
index d6d241f63b9f8e4c3a9310008f17b9439f7fa2ed..56814e8ae7ea91a4c9aeed59a2c6f9d2263fb2e4 100644 (file)
@@ -144,7 +144,7 @@ struct __drm_crtcs_state {
        struct drm_crtc *ptr;
        struct drm_crtc_state *state;
        struct drm_crtc_commit *commit;
-       s64 __user *out_fence_ptr;
+       s32 __user *out_fence_ptr;
 };
 
 struct __drm_connnectors_state {
index a9b95246e26efcf3d44cd5afc85f7031f0fa77fe..045a97cbeba24f44eb1b1d5582b4145801fcafdd 100644 (file)
@@ -381,6 +381,8 @@ struct drm_connector_funcs {
         * core drm connector interfaces. Everything added from this callback
         * should be unregistered in the early_unregister callback.
         *
+        * This is called while holding drm_connector->mutex.
+        *
         * Returns:
         *
         * 0 on success, or a negative error code on failure.
@@ -395,6 +397,8 @@ struct drm_connector_funcs {
         * late_register(). It is called from drm_connector_unregister(),
         * early in the driver unload sequence to disable userspace access
         * before data structures are torndown.
+        *
+        * This is called while holding drm_connector->mutex.
         */
        void (*early_unregister)(struct drm_connector *connector);
 
@@ -559,7 +563,6 @@ struct drm_cmdline_mode {
  * @interlace_allowed: can this connector handle interlaced modes?
  * @doublescan_allowed: can this connector handle doublescan?
  * @stereo_allowed: can this connector handle stereo modes?
- * @registered: is this connector exposed (registered) with userspace?
  * @modes: modes available on this connector (from fill_modes() + user)
  * @status: one of the drm_connector_status enums (connected, not, or unknown)
  * @probed_modes: list of modes derived directly from the display
@@ -607,6 +610,13 @@ struct drm_connector {
 
        char *name;
 
+       /**
+        * @mutex: Lock for general connector state, but currently only protects
+        * @registered. Most of the connector state is still protected by the
+        * mutex in &drm_mode_config.
+        */
+       struct mutex mutex;
+
        /**
         * @index: Compacted connector index, which matches the position inside
         * the mode_config.list for drivers not supporting hot-add/removing. Can
@@ -620,6 +630,10 @@ struct drm_connector {
        bool interlace_allowed;
        bool doublescan_allowed;
        bool stereo_allowed;
+       /**
+        * @registered: Is this connector exposed (registered) with userspace?
+        * Protected by @mutex.
+        */
        bool registered;
        struct list_head modes; /* list of modes on this connector */
 
index bf9991b20611a666d05445152d587446c5a834f5..137432386310aa8a9449d28f655a60b78bdd654a 100644 (file)
@@ -488,7 +488,7 @@ struct drm_mode_config {
        /**
         * @prop_out_fence_ptr: Sync File fd pointer representing the
         * outgoing fences for a CRTC. Userspace should provide a pointer to a
-        * value of type s64, and then cast that pointer to u64.
+        * value of type s32, and then cast that pointer to u64.
         */
        struct drm_property *prop_out_fence_ptr;
        /**
diff --git a/include/dt-bindings/mfd/tps65217.h b/include/dt-bindings/mfd/tps65217.h
deleted file mode 100644 (file)
index cafb9e6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This header provides macros for TI TPS65217 DT bindings.
- *
- * Copyright (C) 2016 Texas Instruments
- *
- * 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.
- *
- * 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/>.
- */
-
-#ifndef __DT_BINDINGS_TPS65217_H__
-#define __DT_BINDINGS_TPS65217_H__
-
-#define TPS65217_IRQ_USB       0
-#define TPS65217_IRQ_AC                1
-#define TPS65217_IRQ_PB                2
-
-#endif
index b717ed9d2b755255cfafa76553b3823449f594c2..5c970ce6794977a73e8c69181b5fe715191927b5 100644 (file)
@@ -76,4 +76,5 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
 
 void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
 
+void kvm_timer_init_vhe(void);
 #endif
index 83695641bd5ec272551857c448cc9b4f354898b8..1ca8e8fd10789d0fff1aa0b21ede64b72075e094 100644 (file)
@@ -739,7 +739,7 @@ static inline bool blk_queue_is_zoned(struct request_queue *q)
        }
 }
 
-static inline unsigned int blk_queue_zone_size(struct request_queue *q)
+static inline unsigned int blk_queue_zone_sectors(struct request_queue *q)
 {
        return blk_queue_is_zoned(q) ? q->limits.chunk_sectors : 0;
 }
@@ -1000,6 +1000,19 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq)
        return blk_rq_cur_bytes(rq) >> 9;
 }
 
+/*
+ * Some commands like WRITE SAME have a payload or data transfer size which
+ * is different from the size of the request.  Any driver that supports such
+ * commands using the RQF_SPECIAL_PAYLOAD flag needs to use this helper to
+ * calculate the data transfer size.
+ */
+static inline unsigned int blk_rq_payload_bytes(struct request *rq)
+{
+       if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
+               return rq->special_vec.bv_len;
+       return blk_rq_bytes(rq);
+}
+
 static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
                                                     int op)
 {
@@ -1536,12 +1549,12 @@ static inline bool bdev_is_zoned(struct block_device *bdev)
        return false;
 }
 
-static inline unsigned int bdev_zone_size(struct block_device *bdev)
+static inline unsigned int bdev_zone_sectors(struct block_device *bdev)
 {
        struct request_queue *q = bdev_get_queue(bdev);
 
        if (q)
-               return blk_queue_zone_size(q);
+               return blk_queue_zone_sectors(q);
 
        return 0;
 }
index 92bc89ae7e20733c28f6130cf00314a42aa0c580..c970a25d2a49b34325aa6ae3e386b9ed93743c14 100644 (file)
@@ -21,20 +21,19 @@ struct cgroup_bpf {
         */
        struct bpf_prog *prog[MAX_BPF_ATTACH_TYPE];
        struct bpf_prog __rcu *effective[MAX_BPF_ATTACH_TYPE];
+       bool disallow_override[MAX_BPF_ATTACH_TYPE];
 };
 
 void cgroup_bpf_put(struct cgroup *cgrp);
 void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent);
 
-void __cgroup_bpf_update(struct cgroup *cgrp,
-                        struct cgroup *parent,
-                        struct bpf_prog *prog,
-                        enum bpf_attach_type type);
+int __cgroup_bpf_update(struct cgroup *cgrp, struct cgroup *parent,
+                       struct bpf_prog *prog, enum bpf_attach_type type,
+                       bool overridable);
 
 /* Wrapper for __cgroup_bpf_update() protected by cgroup_mutex */
-void cgroup_bpf_update(struct cgroup *cgrp,
-                      struct bpf_prog *prog,
-                      enum bpf_attach_type type);
+int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog,
+                     enum bpf_attach_type type, bool overridable);
 
 int __cgroup_bpf_run_filter_skb(struct sock *sk,
                                struct sk_buff *skb,
index f74ae68086dc69b3c02ced58a13f6daed0b4cd77..3ed1f3b1d594b67f1fab991492e5d73e10b81606 100644 (file)
@@ -216,7 +216,7 @@ u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5);
 u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
 
 bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp);
-int bpf_prog_calc_digest(struct bpf_prog *fp);
+int bpf_prog_calc_tag(struct bpf_prog *fp);
 
 const struct bpf_func_proto *bpf_get_trace_printk_proto(void);
 
@@ -247,6 +247,8 @@ struct bpf_map * __must_check bpf_map_inc(struct bpf_map *map, bool uref);
 void bpf_map_put_with_uref(struct bpf_map *map);
 void bpf_map_put(struct bpf_map *map);
 int bpf_map_precharge_memlock(u32 pages);
+void *bpf_map_area_alloc(size_t size);
+void bpf_map_area_free(void *base);
 
 extern int sysctl_unprivileged_bpf_disabled;
 
index d67ab83823adc81234b0380feca85877996817db..79591c3660cc1dc61e1e3f4b501c470161c41eb9 100644 (file)
@@ -243,12 +243,10 @@ static inline int block_page_mkwrite_return(int err)
 {
        if (err == 0)
                return VM_FAULT_LOCKED;
-       if (err == -EFAULT)
+       if (err == -EFAULT || err == -EAGAIN)
                return VM_FAULT_NOPAGE;
        if (err == -ENOMEM)
                return VM_FAULT_OOM;
-       if (err == -EAGAIN)
-               return VM_FAULT_RETRY;
        /* -ENOSPC, -EDQUOT, -EIO ... */
        return VM_FAULT_SIGBUS;
 }
index a0875001b13c84ad70a9b2909654e9ffb6824c58..df08a41d5be5f26cfa4cdc74935f5eae7fa51385 100644 (file)
@@ -45,10 +45,9 @@ struct can_proto {
 extern int  can_proto_register(const struct can_proto *cp);
 extern void can_proto_unregister(const struct can_proto *cp);
 
-extern int  can_rx_register(struct net_device *dev, canid_t can_id,
-                           canid_t mask,
-                           void (*func)(struct sk_buff *, void *),
-                           void *data, char *ident);
+int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
+                   void (*func)(struct sk_buff *, void *),
+                   void *data, char *ident, struct sock *sk);
 
 extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
                              canid_t mask,
index d016a121a8c46492bd6feea5b093dcea9bf27933..28ffa94aed6b85d10531e7dc11864f9ebc8701f4 100644 (file)
@@ -14,6 +14,7 @@ struct coredump_params;
 extern int dump_skip(struct coredump_params *cprm, size_t nr);
 extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
 extern int dump_align(struct coredump_params *cprm, int align);
+extern void dump_truncate(struct coredump_params *cprm);
 #ifdef CONFIG_COREDUMP
 extern void do_coredump(const siginfo_t *siginfo);
 #else
index 20bfefbe75941627c25c30621d4d9b09606c720c..921acaaa16017979df0722fb9803b204d77c0be0 100644 (file)
@@ -8,9 +8,7 @@ enum cpuhp_state {
        CPUHP_CREATE_THREADS,
        CPUHP_PERF_PREPARE,
        CPUHP_PERF_X86_PREPARE,
-       CPUHP_PERF_X86_UNCORE_PREP,
        CPUHP_PERF_X86_AMD_UNCORE_PREP,
-       CPUHP_PERF_X86_RAPL_PREP,
        CPUHP_PERF_BFIN,
        CPUHP_PERF_POWER,
        CPUHP_PERF_SUPERH,
@@ -74,6 +72,8 @@ enum cpuhp_state {
        CPUHP_ZCOMP_PREPARE,
        CPUHP_TIMERS_DEAD,
        CPUHP_MIPS_SOC_PREPARE,
+       CPUHP_BP_PREPARE_DYN,
+       CPUHP_BP_PREPARE_DYN_END                = CPUHP_BP_PREPARE_DYN + 20,
        CPUHP_BRINGUP_CPU,
        CPUHP_AP_IDLE_DEAD,
        CPUHP_AP_OFFLINE,
@@ -84,7 +84,6 @@ enum cpuhp_state {
        CPUHP_AP_IRQ_ARMADA_XP_STARTING,
        CPUHP_AP_IRQ_BCM2836_STARTING,
        CPUHP_AP_ARM_MVEBU_COHERENCY,
-       CPUHP_AP_PERF_X86_UNCORE_STARTING,
        CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
        CPUHP_AP_PERF_X86_STARTING,
        CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
index c717f5ea88cb7e7f04471f34ac14bcf9bc75a4d1..b3d2c1a89ac48fb8257c32cf070e551f1cc22c4e 100644 (file)
@@ -560,7 +560,7 @@ static inline void cpumask_copy(struct cpumask *dstp,
 static inline int cpumask_parse_user(const char __user *buf, int len,
                                     struct cpumask *dstp)
 {
-       return bitmap_parse_user(buf, len, cpumask_bits(dstp), nr_cpu_ids);
+       return bitmap_parse_user(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
@@ -575,7 +575,7 @@ static inline int cpumask_parselist_user(const char __user *buf, int len,
                                     struct cpumask *dstp)
 {
        return bitmap_parselist_user(buf, len, cpumask_bits(dstp),
-                                    nr_cpu_ids);
+                                    nr_cpumask_bits);
 }
 
 /**
@@ -590,7 +590,7 @@ static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
        char *nl = strchr(buf, '\n');
        unsigned int len = nl ? (unsigned int)(nl - buf) : strlen(buf);
 
-       return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpu_ids);
+       return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
@@ -602,7 +602,7 @@ static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
  */
 static inline int cpulist_parse(const char *buf, struct cpumask *dstp)
 {
-       return bitmap_parselist(buf, cpumask_bits(dstp), nr_cpu_ids);
+       return bitmap_parselist(buf, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
index a07a476178cd1b4c59295ba2c1ee420c1bbb696e..5b1af30ece55828e655b2bf02a149fd71354f3eb 100644 (file)
@@ -103,6 +103,7 @@ typedef     struct {
 
 #define EFI_PAGE_SHIFT         12
 #define EFI_PAGE_SIZE          (1UL << EFI_PAGE_SHIFT)
+#define EFI_PAGES_MAX          (U64_MAX >> EFI_PAGE_SHIFT)
 
 typedef struct {
        u32 type;
@@ -950,6 +951,7 @@ static inline efi_status_t efi_query_variable_store(u32 attributes,
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
 
+extern phys_addr_t __init efi_memmap_alloc(unsigned int num_entries);
 extern int __init efi_memmap_init_early(struct efi_memory_map_data *data);
 extern int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size);
 extern void __init efi_memmap_unmap(void);
index 2a0f61fbc7310e61f5927c31250e208d217c3e26..1a1dfdb2a5c6d8806d11e2cd58722e304f293054 100644 (file)
@@ -43,12 +43,19 @@ extern struct module __this_module;
 #ifdef CONFIG_MODVERSIONS
 /* Mark the CRC weak since genksyms apparently decides not to
  * generate a checksums for some symbols */
+#if defined(CONFIG_MODULE_REL_CRCS)
 #define __CRC_SYMBOL(sym, sec)                                         \
-       extern __visible void *__crc_##sym __attribute__((weak));       \
-       static const unsigned long __kcrctab_##sym                      \
-       __used                                                          \
-       __attribute__((section("___kcrctab" sec "+" #sym), used))       \
-       = (unsigned long) &__crc_##sym;
+       asm("   .section \"___kcrctab" sec "+" #sym "\", \"a\"  \n"     \
+           "   .weak   " VMLINUX_SYMBOL_STR(__crc_##sym) "     \n"     \
+           "   .long   " VMLINUX_SYMBOL_STR(__crc_##sym) " - . \n"     \
+           "   .previous                                       \n");
+#else
+#define __CRC_SYMBOL(sym, sec)                                         \
+       asm("   .section \"___kcrctab" sec "+" #sym "\", \"a\"  \n"     \
+           "   .weak   " VMLINUX_SYMBOL_STR(__crc_##sym) "     \n"     \
+           "   .long   " VMLINUX_SYMBOL_STR(__crc_##sym) "     \n"     \
+           "   .previous                                       \n");
+#endif
 #else
 #define __CRC_SYMBOL(sym, sec)
 #endif
index a0934e6c9babf8436a18b28f4dea285894e5dca5..e4eb2546339afbf2764f5ba335e1e66947fc5af3 100644 (file)
@@ -57,6 +57,8 @@ struct bpf_prog_aux;
 /* BPF program can access up to 512 bytes of stack space. */
 #define MAX_BPF_STACK  512
 
+#define BPF_TAG_SIZE   8
+
 /* Helper macros for filter block array initializers. */
 
 /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
@@ -408,7 +410,7 @@ struct bpf_prog {
        kmemcheck_bitfield_end(meta);
        enum bpf_prog_type      type;           /* Type of BPF program */
        u32                     len;            /* Number of filter blocks */
-       u32                     digest[SHA_DIGEST_WORDS]; /* Program digest */
+       u8                      tag[BPF_TAG_SIZE];
        struct bpf_prog_aux     *aux;           /* Auxiliary fields */
        struct sock_fprog_kern  *orig_prog;     /* Original BPF program */
        unsigned int            (*bpf_func)(const void *ctx,
@@ -519,7 +521,7 @@ static inline u32 bpf_prog_insn_size(const struct bpf_prog *prog)
        return prog->len * sizeof(struct bpf_insn);
 }
 
-static inline u32 bpf_prog_digest_scratch_size(const struct bpf_prog *prog)
+static inline u32 bpf_prog_tag_scratch_size(const struct bpf_prog *prog)
 {
        return round_up(bpf_prog_insn_size(prog) +
                        sizeof(__be64) + 1, SHA_MESSAGE_BYTES);
index 13ba552e6c094e82ee8b952b26d9f0bf5eeebc39..4c467ef50159db533ecb567a86eeaf6e1e81e632 100644 (file)
@@ -360,6 +360,7 @@ struct fscache_object {
 #define FSCACHE_OBJECT_IS_AVAILABLE    5       /* T if object has become active */
 #define FSCACHE_OBJECT_RETIRED         6       /* T if object was retired on relinquishment */
 #define FSCACHE_OBJECT_KILLED_BY_CACHE 7       /* T if object was killed by the cache */
+#define FSCACHE_OBJECT_RUN_AFTER_DEAD  8       /* T if object has been dispatched after death */
 
        struct list_head        cache_link;     /* link in cache->object_list */
        struct hlist_node       cookie_link;    /* link in cookie->backing_objects */
index 0cf34d6cc253853c459e60908aa06128b4a8cf45..487246546ebebb63da20fde2eb12bd9a2914040c 100644 (file)
@@ -323,8 +323,6 @@ extern void fsnotify_init_mark(struct fsnotify_mark *mark, void (*free_mark)(str
 extern struct fsnotify_mark *fsnotify_find_inode_mark(struct fsnotify_group *group, struct inode *inode);
 /* find (and take a reference) to a mark associated with group and vfsmount */
 extern struct fsnotify_mark *fsnotify_find_vfsmount_mark(struct fsnotify_group *group, struct vfsmount *mnt);
-/* copy the values from old into new */
-extern void fsnotify_duplicate_mark(struct fsnotify_mark *new, struct fsnotify_mark *old);
 /* set the ignored_mask of a mark */
 extern void fsnotify_set_mark_ignored_mask_locked(struct fsnotify_mark *mark, __u32 mask);
 /* set the mask of a mark (might pin the object into memory */
index 4175dca4ac39dd7848e3abcda5eb163865ab2734..0fe0b6295ab58edfe6745467487fe19beba0d723 100644 (file)
@@ -38,9 +38,8 @@ struct vm_area_struct;
 #define ___GFP_ACCOUNT         0x100000u
 #define ___GFP_NOTRACK         0x200000u
 #define ___GFP_DIRECT_RECLAIM  0x400000u
-#define ___GFP_OTHER_NODE      0x800000u
-#define ___GFP_WRITE           0x1000000u
-#define ___GFP_KSWAPD_RECLAIM  0x2000000u
+#define ___GFP_WRITE           0x800000u
+#define ___GFP_KSWAPD_RECLAIM  0x1000000u
 /* If the above are modified, __GFP_BITS_SHIFT may need updating */
 
 /*
@@ -172,11 +171,6 @@ struct vm_area_struct;
  * __GFP_NOTRACK_FALSE_POSITIVE is an alias of __GFP_NOTRACK. It's a means of
  *   distinguishing in the source between false positives and allocations that
  *   cannot be supported (e.g. page tables).
- *
- * __GFP_OTHER_NODE is for allocations that are on a remote node but that
- *   should not be accounted for as a remote allocation in vmstat. A
- *   typical user would be khugepaged collapsing a huge page on a remote
- *   node.
  */
 #define __GFP_COLD     ((__force gfp_t)___GFP_COLD)
 #define __GFP_NOWARN   ((__force gfp_t)___GFP_NOWARN)
@@ -184,10 +178,9 @@ struct vm_area_struct;
 #define __GFP_ZERO     ((__force gfp_t)___GFP_ZERO)
 #define __GFP_NOTRACK  ((__force gfp_t)___GFP_NOTRACK)
 #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
-#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE)
 
 /* Room for N __GFP_FOO bits */
-#define __GFP_BITS_SHIFT 26
+#define __GFP_BITS_SHIFT 25
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /*
@@ -506,11 +499,10 @@ extern void free_hot_cold_page(struct page *page, bool cold);
 extern void free_hot_cold_page_list(struct list_head *list, bool cold);
 
 struct page_frag_cache;
-extern void __page_frag_drain(struct page *page, unsigned int order,
-                             unsigned int count);
-extern void *__alloc_page_frag(struct page_frag_cache *nc,
-                              unsigned int fragsz, gfp_t gfp_mask);
-extern void __free_page_frag(void *addr);
+extern void __page_frag_cache_drain(struct page *page, unsigned int count);
+extern void *page_frag_alloc(struct page_frag_cache *nc,
+                            unsigned int fragsz, gfp_t gfp_mask);
+extern void page_frag_free(void *addr);
 
 #define __free_page(page) __free_pages((page), 0)
 #define free_page(addr) free_pages((addr), 0)
index c2748accea71aa006268afebe65898fcc9f6d033..e973faba69dc5c90586aa97511d860178f31ff2e 100644 (file)
@@ -274,37 +274,67 @@ void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
                struct irq_chip *irqchip,
                int parent_irq);
 
-int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
+int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
+                            struct irq_chip *irqchip,
+                            unsigned int first_irq,
+                            irq_flow_handler_t handler,
+                            unsigned int type,
+                            bool nested,
+                            struct lock_class_key *lock_key);
+
+#ifdef CONFIG_LOCKDEP
+
+/*
+ * Lockdep requires that each irqchip instance be created with a
+ * unique key so as to avoid unnecessary warnings. This upfront
+ * boilerplate static inlines provides such a key for each
+ * unique instance.
+ */
+static inline int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
+                                      struct irq_chip *irqchip,
+                                      unsigned int first_irq,
+                                      irq_flow_handler_t handler,
+                                      unsigned int type)
+{
+       static struct lock_class_key key;
+
+       return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq,
+                                       handler, type, false, &key);
+}
+
+static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,
                          struct irq_chip *irqchip,
                          unsigned int first_irq,
                          irq_flow_handler_t handler,
-                         unsigned int type,
-                         bool nested,
-                         struct lock_class_key *lock_key);
+                         unsigned int type)
+{
+
+       static struct lock_class_key key;
+
+       return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq,
+                                       handler, type, true, &key);
+}
+#else
+static inline int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
+                                      struct irq_chip *irqchip,
+                                      unsigned int first_irq,
+                                      irq_flow_handler_t handler,
+                                      unsigned int type)
+{
+       return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq,
+                                       handler, type, false, NULL);
+}
 
-/* FIXME: I assume threaded IRQchips do not have the lockdep problem */
 static inline int gpiochip_irqchip_add_nested(struct gpio_chip *gpiochip,
                          struct irq_chip *irqchip,
                          unsigned int first_irq,
                          irq_flow_handler_t handler,
                          unsigned int type)
 {
-       return _gpiochip_irqchip_add(gpiochip, irqchip, first_irq,
-                                    handler, type, true, NULL);
+       return gpiochip_irqchip_add_key(gpiochip, irqchip, first_irq,
+                                       handler, type, true, NULL);
 }
-
-#ifdef CONFIG_LOCKDEP
-#define gpiochip_irqchip_add(...)                              \
-(                                                              \
-       ({                                                      \
-               static struct lock_class_key _key;              \
-               _gpiochip_irqchip_add(__VA_ARGS__, false, &_key); \
-       })                                                      \
-)
-#else
-#define gpiochip_irqchip_add(...)                              \
-       _gpiochip_irqchip_add(__VA_ARGS__, false, NULL)
-#endif
+#endif /* CONFIG_LOCKDEP */
 
 #endif /* CONFIG_GPIOLIB_IRQCHIP */
 
index 42fe43fb0c80605f9553c746f04310f43914f683..183efde54269e18c5d4d1eda7dc448717fe85800 100644 (file)
@@ -128,6 +128,7 @@ struct hv_ring_buffer_info {
        u32 ring_data_startoffset;
        u32 priv_write_index;
        u32 priv_read_index;
+       u32 cached_read_index;
 };
 
 /*
@@ -180,6 +181,19 @@ static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
        return write;
 }
 
+static inline u32 hv_get_cached_bytes_to_write(
+       const struct hv_ring_buffer_info *rbi)
+{
+       u32 read_loc, write_loc, dsize, write;
+
+       dsize = rbi->ring_datasize;
+       read_loc = rbi->cached_read_index;
+       write_loc = rbi->ring_buffer->write_index;
+
+       write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
+               read_loc - write_loc;
+       return write;
+}
 /*
  * VMBUS version is 32 bit entity broken up into
  * two 16 bit quantities: major_number. minor_number.
@@ -1488,7 +1502,7 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
 
 static inline  void hv_signal_on_read(struct vmbus_channel *channel)
 {
-       u32 cur_write_sz;
+       u32 cur_write_sz, cached_write_sz;
        u32 pending_sz;
        struct hv_ring_buffer_info *rbi = &channel->inbound;
 
@@ -1512,12 +1526,24 @@ static inline  void hv_signal_on_read(struct vmbus_channel *channel)
 
        cur_write_sz = hv_get_bytes_to_write(rbi);
 
-       if (cur_write_sz >= pending_sz)
+       if (cur_write_sz < pending_sz)
+               return;
+
+       cached_write_sz = hv_get_cached_bytes_to_write(rbi);
+       if (cached_write_sz < pending_sz)
                vmbus_setevent(channel);
 
        return;
 }
 
+static inline void
+init_cached_read_index(struct vmbus_channel *channel)
+{
+       struct hv_ring_buffer_info *rbi = &channel->inbound;
+
+       rbi->cached_read_index = rbi->ring_buffer->read_index;
+}
+
 /*
  * An API to support in-place processing of incoming VMBUS packets.
  */
@@ -1569,6 +1595,8 @@ static inline void put_pkt_raw(struct vmbus_channel *channel,
  * This call commits the read index and potentially signals the host.
  * Here is the pattern for using the "in-place" consumption APIs:
  *
+ * init_cached_read_index();
+ *
  * while (get_next_pkt_raw() {
  *     process the packet "in-place";
  *     put_pkt_raw();
index b2109c522dec0726d6e6e390358a79be4bcdf891..4b45ec46161fd66d6e7fd32f53dd71b8ac1cab42 100644 (file)
@@ -665,6 +665,7 @@ i2c_unlock_adapter(struct i2c_adapter *adapter)
 #define I2C_CLIENT_TEN         0x10    /* we have a ten bit chip address */
                                        /* Must equal I2C_M_TEN below */
 #define I2C_CLIENT_SLAVE       0x20    /* we are the slave */
+#define I2C_CLIENT_HOST_NOTIFY 0x40    /* We want to use I2C host notify */
 #define I2C_CLIENT_WAKE                0x80    /* for board_info; true iff can wake */
 #define I2C_CLIENT_SCCB                0x9000  /* Use Omnivision SCCB protocol */
                                        /* Must match I2C_M_STOP|IGNORE_NAK */
index 228bd44efa4c6efecd3af2e3ec16be8bd02d3d1b..497f2b3a5a62c8da6f87107de16519b176cc9f1f 100644 (file)
@@ -115,6 +115,16 @@ struct st_sensor_bdu {
        u8 mask;
 };
 
+/**
+ * struct st_sensor_das - ST sensor device data alignment selection
+ * @addr: address of the register.
+ * @mask: mask to write the das flag for left alignment.
+ */
+struct st_sensor_das {
+       u8 addr;
+       u8 mask;
+};
+
 /**
  * struct st_sensor_data_ready_irq - ST sensor device data-ready interrupt
  * @addr: address of the register.
@@ -185,6 +195,7 @@ struct st_sensor_transfer_function {
  * @enable_axis: Enable one or more axis of the sensor.
  * @fs: Full scale register and full scale list available.
  * @bdu: Block data update register.
+ * @das: Data Alignment Selection register.
  * @drdy_irq: Data ready register of the sensor.
  * @multi_read_bit: Use or not particular bit for [I2C/SPI] multi-read.
  * @bootime: samples to discard when sensor passing from power-down to power-up.
@@ -200,6 +211,7 @@ struct st_sensor_settings {
        struct st_sensor_axis enable_axis;
        struct st_sensor_fullscale fs;
        struct st_sensor_bdu bdu;
+       struct st_sensor_das das;
        struct st_sensor_data_ready_irq drdy_irq;
        bool multi_read_bit;
        unsigned int bootime;
index e79875574b393f33ed183fdc8f44277a49c26ba8..39e3254e5769d7da1d0f74cdfdf90bd9b40cfc8a 100644 (file)
@@ -184,6 +184,7 @@ struct irq_data {
  *
  * IRQD_TRIGGER_MASK           - Mask for the trigger type bits
  * IRQD_SETAFFINITY_PENDING    - Affinity setting is pending
+ * IRQD_ACTIVATED              - Interrupt has already been activated
  * IRQD_NO_BALANCING           - Balancing disabled for this IRQ
  * IRQD_PER_CPU                        - Interrupt is per cpu
  * IRQD_AFFINITY_SET           - Interrupt affinity was set
@@ -202,6 +203,7 @@ struct irq_data {
 enum {
        IRQD_TRIGGER_MASK               = 0xf,
        IRQD_SETAFFINITY_PENDING        = (1 <<  8),
+       IRQD_ACTIVATED                  = (1 <<  9),
        IRQD_NO_BALANCING               = (1 << 10),
        IRQD_PER_CPU                    = (1 << 11),
        IRQD_AFFINITY_SET               = (1 << 12),
@@ -312,6 +314,21 @@ static inline bool irqd_affinity_is_managed(struct irq_data *d)
        return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED;
 }
 
+static inline bool irqd_is_activated(struct irq_data *d)
+{
+       return __irqd_to_state(d) & IRQD_ACTIVATED;
+}
+
+static inline void irqd_set_activated(struct irq_data *d)
+{
+       __irqd_to_state(d) |= IRQD_ACTIVATED;
+}
+
+static inline void irqd_clr_activated(struct irq_data *d)
+{
+       __irqd_to_state(d) &= ~IRQD_ACTIVATED;
+}
+
 #undef __irqd_to_state
 
 static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
index 089f70f83e97c9a1adf1087f10d095a02bd3e152..23da3af459fe7af7b5e5c2eabccbda350122e88b 100644 (file)
@@ -14,6 +14,7 @@ struct static_key_deferred {
 
 #ifdef HAVE_JUMP_LABEL
 extern void static_key_slow_dec_deferred(struct static_key_deferred *key);
+extern void static_key_deferred_flush(struct static_key_deferred *key);
 extern void
 jump_label_rate_limit(struct static_key_deferred *key, unsigned long rl);
 
@@ -26,6 +27,10 @@ static inline void static_key_slow_dec_deferred(struct static_key_deferred *key)
        STATIC_KEY_CHECK_USE();
        static_key_slow_dec(&key->key);
 }
+static inline void static_key_deferred_flush(struct static_key_deferred *key)
+{
+       STATIC_KEY_CHECK_USE();
+}
 static inline void
 jump_label_rate_limit(struct static_key_deferred *key,
                unsigned long rl)
index 56aec84237ad5b7b55c3a43eb04a882f9eb24d5e..cb09238f6d32be355a9b7e2347e48746de7eae77 100644 (file)
@@ -514,8 +514,8 @@ extern enum system_states {
 #define TAINT_FLAGS_COUNT              16
 
 struct taint_flag {
-       char true;      /* character printed when tainted */
-       char false;     /* character printed when not tainted */
+       char c_true;    /* character printed when tainted */
+       char c_false;   /* character printed when not tainted */
        bool module;    /* also show as a per-module taint flag */
 };
 
index fd7ff3d91e6a920ff084beca09d10b5b9abba981..ef3d4f67118ce0f60789e6e749a4773754e01e87 100644 (file)
@@ -203,6 +203,17 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
  *  ... and so on.
  */
 
-#define order_base_2(n) ilog2(roundup_pow_of_two(n))
+static inline __attribute_const__
+int __order_base_2(unsigned long n)
+{
+       return n > 1 ? ilog2(n - 1) + 1 : 0;
+}
 
+#define order_base_2(n)                                \
+(                                              \
+       __builtin_constant_p(n) ? (             \
+               ((n) == 0 || (n) == 1) ? 0 :    \
+               ilog2((n) - 1) + 1) :           \
+       __order_base_2(n)                       \
+)
 #endif /* _LINUX_LOG2_H */
index ec819e9a115af492a8e57d2fe67384accb925436..b6e048e1045f99868642b920a005d2382e6dc316 100644 (file)
 #ifndef MDEV_H
 #define MDEV_H
 
-/* Parent device */
-struct parent_device {
-       struct device           *dev;
-       const struct parent_ops *ops;
-
-       /* internal */
-       struct kref             ref;
-       struct mutex            lock;
-       struct list_head        next;
-       struct kset             *mdev_types_kset;
-       struct list_head        type_list;
-};
-
-/* Mediated device */
-struct mdev_device {
-       struct device           dev;
-       struct parent_device    *parent;
-       uuid_le                 uuid;
-       void                    *driver_data;
-
-       /* internal */
-       struct kref             ref;
-       struct list_head        next;
-       struct kobject          *type_kobj;
-};
+struct mdev_device;
 
 /**
- * struct parent_ops - Structure to be registered for each parent device to
+ * struct mdev_parent_ops - Structure to be registered for each parent device to
  * register the device to mdev module.
  *
  * @owner:             The module owner.
@@ -86,10 +62,9 @@ struct mdev_device {
  *                     @mdev: mediated device structure
  *                     @vma: vma structure
  * Parent device that support mediated device should be registered with mdev
- * module with parent_ops structure.
+ * module with mdev_parent_ops structure.
  **/
-
-struct parent_ops {
+struct mdev_parent_ops {
        struct module   *owner;
        const struct attribute_group **dev_attr_groups;
        const struct attribute_group **mdev_attr_groups;
@@ -103,7 +78,7 @@ struct parent_ops {
                        size_t count, loff_t *ppos);
        ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
                         size_t count, loff_t *ppos);
-       ssize_t (*ioctl)(struct mdev_device *mdev, unsigned int cmd,
+       long    (*ioctl)(struct mdev_device *mdev, unsigned int cmd,
                         unsigned long arg);
        int     (*mmap)(struct mdev_device *mdev, struct vm_area_struct *vma);
 };
@@ -142,27 +117,22 @@ struct mdev_driver {
 };
 
 #define to_mdev_driver(drv)    container_of(drv, struct mdev_driver, driver)
-#define to_mdev_device(dev)    container_of(dev, struct mdev_device, dev)
-
-static inline void *mdev_get_drvdata(struct mdev_device *mdev)
-{
-       return mdev->driver_data;
-}
 
-static inline void mdev_set_drvdata(struct mdev_device *mdev, void *data)
-{
-       mdev->driver_data = data;
-}
+extern void *mdev_get_drvdata(struct mdev_device *mdev);
+extern void mdev_set_drvdata(struct mdev_device *mdev, void *data);
+extern uuid_le mdev_uuid(struct mdev_device *mdev);
 
 extern struct bus_type mdev_bus_type;
 
-#define dev_is_mdev(d) ((d)->bus == &mdev_bus_type)
-
 extern int  mdev_register_device(struct device *dev,
-                                const struct parent_ops *ops);
+                                const struct mdev_parent_ops *ops);
 extern void mdev_unregister_device(struct device *dev);
 
 extern int  mdev_register_driver(struct mdev_driver *drv, struct module *owner);
 extern void mdev_unregister_driver(struct mdev_driver *drv);
 
+extern struct device *mdev_parent_dev(struct mdev_device *mdev);
+extern struct device *mdev_dev(struct mdev_device *mdev);
+extern struct mdev_device *mdev_from_dev(struct device *dev);
+
 #endif /* MDEV_H */
index 61d20c17f3b7e40ba706a49da463c2f9eabd7d93..254698856b8fc2723dae61e3dd20b6c8176129e7 100644 (file)
@@ -120,7 +120,7 @@ struct mem_cgroup_reclaim_iter {
  */
 struct mem_cgroup_per_node {
        struct lruvec           lruvec;
-       unsigned long           lru_size[NR_LRU_LISTS];
+       unsigned long           lru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS];
 
        struct mem_cgroup_reclaim_iter  iter[DEF_PRIORITY + 1];
 
@@ -432,7 +432,7 @@ static inline bool mem_cgroup_online(struct mem_cgroup *memcg)
 int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
 
 void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
-               int nr_pages);
+               int zid, int nr_pages);
 
 unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
                                           int nid, unsigned int lru_mask);
@@ -441,9 +441,23 @@ static inline
 unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)
 {
        struct mem_cgroup_per_node *mz;
+       unsigned long nr_pages = 0;
+       int zid;
 
        mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
-       return mz->lru_size[lru];
+       for (zid = 0; zid < MAX_NR_ZONES; zid++)
+               nr_pages += mz->lru_zone_size[zid][lru];
+       return nr_pages;
+}
+
+static inline
+unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
+               enum lru_list lru, int zone_idx)
+{
+       struct mem_cgroup_per_node *mz;
+
+       mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
+       return mz->lru_zone_size[zone_idx][lru];
 }
 
 void mem_cgroup_handle_over_high(void);
@@ -671,6 +685,12 @@ mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)
 {
        return 0;
 }
+static inline
+unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
+               enum lru_list lru, int zone_idx)
+{
+       return 0;
+}
 
 static inline unsigned long
 mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
index 01033fadea4766d5e6efddc78ca595d68c021464..134a2f69c21abf7921181af0adff033bb459edc5 100644 (file)
@@ -85,7 +85,8 @@ extern int zone_grow_waitqueues(struct zone *zone, unsigned long nr_pages);
 extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
 /* VM interface that may be used by firmware interface */
 extern int online_pages(unsigned long, unsigned long, int);
-extern int test_pages_in_a_zone(unsigned long, unsigned long);
+extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
+       unsigned long *valid_start, unsigned long *valid_end);
 extern void __offline_isolated_pages(unsigned long, unsigned long);
 
 typedef void (*online_page_callback_t)(struct page *page);
@@ -284,7 +285,7 @@ extern void sparse_remove_one_section(struct zone *zone, struct mem_section *ms,
                unsigned long map_offset);
 extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
                                          unsigned long pnum);
-extern int zone_can_shift(unsigned long pfn, unsigned long nr_pages,
-                         enum zone_type target);
+extern bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
+                         enum zone_type target, int *zone_shift);
 
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
index 257173e0095ebdb22e1684fbd56ce05a8971ee1d..f541da68d1e7c50f1bb543c05e57a73001c86d28 100644 (file)
@@ -35,6 +35,8 @@
 #define PHY_ID_KSZ886X         0x00221430
 #define PHY_ID_KSZ8863         0x00221435
 
+#define PHY_ID_KSZ8795         0x00221550
+
 /* struct phy_device dev_flags definitions */
 #define MICREL_PHY_50MHZ_CLK   0x00000001
 #define MICREL_PHY_FXEN                0x00000002
index fe6b4036664a9a7c82fe4a22be93288928eceac1..b84615b0f64c294eebb72095cc8dbc874b4ae22b 100644 (file)
@@ -1210,8 +1210,8 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
                        struct vm_area_struct *vma);
 void unmap_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen, int even_cows);
-int follow_pte(struct mm_struct *mm, unsigned long address, pte_t **ptepp,
-              spinlock_t **ptlp);
+int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
+                            pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
        unsigned long *pfn);
 int follow_phys(struct vm_area_struct *vma, unsigned long address,
index 71613e8a720f99b6870f1e3f8957d2761a6ac1a0..41d376e7116dccae22d9881312cfb660cd9fd58e 100644 (file)
@@ -39,7 +39,7 @@ static __always_inline void update_lru_size(struct lruvec *lruvec,
 {
        __update_lru_size(lruvec, lru, zid, nr_pages);
 #ifdef CONFIG_MEMCG
-       mem_cgroup_update_lru_size(lruvec, lru, nr_pages);
+       mem_cgroup_update_lru_size(lruvec, lru, zid, nr_pages);
 #endif
 }
 
index 36d9896fbc1eb0d12e60682f15e96648c13ebf98..f4aac87adcc3555014f6215d6599b604c70388e6 100644 (file)
@@ -972,12 +972,16 @@ static __always_inline struct zoneref *next_zones_zonelist(struct zoneref *z,
  * @zonelist - The zonelist to search for a suitable zone
  * @highest_zoneidx - The zone index of the highest zone to return
  * @nodes - An optional nodemask to filter the zonelist with
- * @zone - The first suitable zone found is returned via this parameter
+ * @return - Zoneref pointer for the first suitable zone found (see below)
  *
  * This function returns the first zone at or below a given zone index that is
  * within the allowed nodemask. The zoneref returned is a cursor that can be
  * used to iterate the zonelist with next_zones_zonelist by advancing it by
  * one before calling.
+ *
+ * When no eligible zone is found, zoneref->zone is NULL (zoneref itself is
+ * never NULL). This may happen either genuinely, or due to concurrent nodemask
+ * update due to cpuset modification.
  */
 static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist,
                                        enum zone_type highest_zoneidx,
index 7c84273d60b963d44c032761cac62194e82d1198..cc7cba219b207de5536f6f9e9353d1a20201e4af 100644 (file)
@@ -346,7 +346,7 @@ struct module {
 
        /* Exported symbols */
        const struct kernel_symbol *syms;
-       const unsigned long *crcs;
+       const s32 *crcs;
        unsigned int num_syms;
 
        /* Kernel parameters. */
@@ -359,18 +359,18 @@ struct module {
        /* GPL-only exported symbols. */
        unsigned int num_gpl_syms;
        const struct kernel_symbol *gpl_syms;
-       const unsigned long *gpl_crcs;
+       const s32 *gpl_crcs;
 
 #ifdef CONFIG_UNUSED_SYMBOLS
        /* unused exported symbols. */
        const struct kernel_symbol *unused_syms;
-       const unsigned long *unused_crcs;
+       const s32 *unused_crcs;
        unsigned int num_unused_syms;
 
        /* GPL-only, unused exported symbols. */
        unsigned int num_unused_gpl_syms;
        const struct kernel_symbol *unused_gpl_syms;
-       const unsigned long *unused_gpl_crcs;
+       const s32 *unused_gpl_crcs;
 #endif
 
 #ifdef CONFIG_MODULE_SIG
@@ -382,7 +382,7 @@ struct module {
 
        /* symbols that will be GPL-only in the near future. */
        const struct kernel_symbol *gpl_future_syms;
-       const unsigned long *gpl_future_crcs;
+       const s32 *gpl_future_crcs;
        unsigned int num_gpl_future_syms;
 
        /* Exception table */
@@ -523,7 +523,7 @@ struct module *find_module(const char *name);
 
 struct symsearch {
        const struct kernel_symbol *start, *stop;
-       const unsigned long *crcs;
+       const s32 *crcs;
        enum {
                NOT_GPL_ONLY,
                GPL_ONLY,
@@ -539,7 +539,7 @@ struct symsearch {
  */
 const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
-                                       const unsigned long **crc,
+                                       const s32 **crc,
                                        bool gplok,
                                        bool warn);
 
index 994f7423a74bd622884c3b646f4123d28697b8ad..27914672602d9d573e6a3da271cec33ccef51b16 100644 (file)
@@ -866,11 +866,15 @@ struct netdev_xdp {
  *     of useless work if you return NETDEV_TX_BUSY.
  *     Required; cannot be NULL.
  *
- * netdev_features_t (*ndo_fix_features)(struct net_device *dev,
- *             netdev_features_t features);
- *     Adjusts the requested feature flags according to device-specific
- *     constraints, and returns the resulting flags. Must not modify
- *     the device state.
+ * netdev_features_t (*ndo_features_check)(struct sk_buff *skb,
+ *                                        struct net_device *dev
+ *                                        netdev_features_t features);
+ *     Called by core transmit path to determine if device is capable of
+ *     performing offload operations on a given packet. This is to give
+ *     the device an opportunity to implement any restrictions that cannot
+ *     be otherwise expressed by feature flags. The check is called with
+ *     the set of features that the stack has calculated and it returns
+ *     those the driver believes to be appropriate.
  *
  * u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb,
  *                         void *accel_priv, select_queue_fallback_t fallback);
@@ -1028,6 +1032,12 @@ struct netdev_xdp {
  *     Called to release previously enslaved netdev.
  *
  *      Feature/offload setting functions.
+ * netdev_features_t (*ndo_fix_features)(struct net_device *dev,
+ *             netdev_features_t features);
+ *     Adjusts the requested feature flags according to device-specific
+ *     constraints, and returns the resulting flags. Must not modify
+ *     the device state.
+ *
  * int (*ndo_set_features)(struct net_device *dev, netdev_features_t features);
  *     Called to update device configuration to new features. Passed
  *     feature set might be less than what was returned by ndo_fix_features()).
@@ -1100,15 +1110,6 @@ struct netdev_xdp {
  *     Callback to use for xmit over the accelerated station. This
  *     is used in place of ndo_start_xmit on accelerated net
  *     devices.
- * netdev_features_t (*ndo_features_check)(struct sk_buff *skb,
- *                                        struct net_device *dev
- *                                        netdev_features_t features);
- *     Called by core transmit path to determine if device is capable of
- *     performing offload operations on a given packet. This is to give
- *     the device an opportunity to implement any restrictions that cannot
- *     be otherwise expressed by feature flags. The check is called with
- *     the set of features that the stack has calculated and it returns
- *     those the driver believes to be appropriate.
  * int (*ndo_set_tx_maxrate)(struct net_device *dev,
  *                          int queue_index, u32 maxrate);
  *     Called when a user wants to set a max-rate limitation of specific
@@ -1510,6 +1511,7 @@ enum netdev_priv_flags {
  *     @max_mtu:       Interface Maximum MTU value
  *     @type:          Interface hardware type
  *     @hard_header_len: Maximum hardware header length.
+ *     @min_header_len:  Minimum hardware header length
  *
  *     @needed_headroom: Extra headroom the hardware may need, but not in all
  *                       cases can this be guaranteed
@@ -1727,6 +1729,7 @@ struct net_device {
        unsigned int            max_mtu;
        unsigned short          type;
        unsigned short          hard_header_len;
+       unsigned short          min_header_len;
 
        unsigned short          needed_headroom;
        unsigned short          needed_tailroom;
@@ -2477,14 +2480,19 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen)
        return NAPI_GRO_CB(skb)->frag0_len < hlen;
 }
 
+static inline void skb_gro_frag0_invalidate(struct sk_buff *skb)
+{
+       NAPI_GRO_CB(skb)->frag0 = NULL;
+       NAPI_GRO_CB(skb)->frag0_len = 0;
+}
+
 static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
                                        unsigned int offset)
 {
        if (!pskb_may_pull(skb, hlen))
                return NULL;
 
-       NAPI_GRO_CB(skb)->frag0 = NULL;
-       NAPI_GRO_CB(skb)->frag0_len = 0;
+       skb_gro_frag0_invalidate(skb);
        return skb->data + offset;
 }
 
@@ -2688,6 +2696,8 @@ static inline bool dev_validate_header(const struct net_device *dev,
 {
        if (likely(len >= dev->hard_header_len))
                return true;
+       if (len < dev->min_header_len)
+               return false;
 
        if (capable(CAP_SYS_RAWIO)) {
                memset(ll_header + len, 0, dev->hard_header_len - len);
index bca536341d1ae51781981906f069a96f612cf52f..1b1ca04820a306ebe5da0aa7d12035c9c3d5e8d0 100644 (file)
@@ -282,7 +282,7 @@ enum nfsstat4 {
 
 static inline bool seqid_mutating_err(u32 err)
 {
-       /* rfc 3530 section 8.1.5: */
+       /* See RFC 7530, section 9.1.7 */
        switch (err) {
        case NFS4ERR_STALE_CLIENTID:
        case NFS4ERR_STALE_STATEID:
@@ -291,6 +291,7 @@ static inline bool seqid_mutating_err(u32 err)
        case NFS4ERR_BADXDR:
        case NFS4ERR_RESOURCE:
        case NFS4ERR_NOFILEHANDLE:
+       case NFS4ERR_MOVED:
                return false;
        };
        return true;
index aacca824a6aef4fcc4d2480aa9eeefd2fe82d6f9..0a3fadc32693a9cf869693f4c406eee5d168e36b 100644 (file)
@@ -110,6 +110,7 @@ extern int watchdog_user_enabled;
 extern int watchdog_thresh;
 extern unsigned long watchdog_enabled;
 extern unsigned long *watchdog_cpumask_bits;
+extern atomic_t watchdog_park_in_progress;
 #ifdef CONFIG_SMP
 extern int sysctl_softlockup_all_cpu_backtrace;
 extern int sysctl_hardlockup_all_cpu_backtrace;
index 1c7eec09e5eba7ae8c0cc8e82172791f992bb361..3a481a49546ef1c85d8f88bf7668f8a2c8e8c0f1 100644 (file)
@@ -204,7 +204,7 @@ static inline void percpu_ref_get(struct percpu_ref *ref)
 static inline bool percpu_ref_tryget(struct percpu_ref *ref)
 {
        unsigned long __percpu *percpu_count;
-       int ret;
+       bool ret;
 
        rcu_read_lock_sched();
 
@@ -238,7 +238,7 @@ static inline bool percpu_ref_tryget(struct percpu_ref *ref)
 static inline bool percpu_ref_tryget_live(struct percpu_ref *ref)
 {
        unsigned long __percpu *percpu_count;
-       int ret = false;
+       bool ret = false;
 
        rcu_read_lock_sched();
 
index 4741ecdb981743151b70afff63b10740dfaa4132..78ed8105e64d1ae0341104c8d129cfeba9402800 100644 (file)
@@ -1259,6 +1259,7 @@ extern void perf_event_disable(struct perf_event *event);
 extern void perf_event_disable_local(struct perf_event *event);
 extern void perf_event_disable_inatomic(struct perf_event *event);
 extern void perf_event_task_tick(void);
+extern int perf_event_account_interrupt(struct perf_event *event);
 #else /* !CONFIG_PERF_EVENTS: */
 static inline void *
 perf_aux_output_begin(struct perf_output_handle *handle,
index f7d95f644eed9b7a15581a490a19a18ea68b050e..7fc1105605bfd2334dab7fd6e96f25a2c33ed566 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/mod_devicetable.h>
-#include <linux/phy_led_triggers.h>
 
 #include <linux/atomic.h>
 
index a2daea0a37d2ae14ed4c9d965bff2400e5528fd2..b37b05bfd1a6dd8af03b6295febf4e14915e6941 100644 (file)
@@ -18,11 +18,11 @@ struct phy_device;
 #ifdef CONFIG_LED_TRIGGER_PHY
 
 #include <linux/leds.h>
+#include <linux/phy.h>
 
 #define PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE      10
-#define PHY_MII_BUS_ID_SIZE    (20 - 3)
 
-#define PHY_LINK_LED_TRIGGER_NAME_SIZE (PHY_MII_BUS_ID_SIZE + \
+#define PHY_LINK_LED_TRIGGER_NAME_SIZE (MII_BUS_ID_SIZE + \
                                       FIELD_SIZEOF(struct mdio_device, addr)+\
                                       PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE)
 
index 5dea8f6440e44f8d7345289847deaa9e9434e136..52bda854593b4a9eae9bad2d9990f9dd166ed609 100644 (file)
@@ -306,7 +306,9 @@ void radix_tree_iter_replace(struct radix_tree_root *,
 void radix_tree_replace_slot(struct radix_tree_root *root,
                             void **slot, void *item);
 void __radix_tree_delete_node(struct radix_tree_root *root,
-                             struct radix_tree_node *node);
+                             struct radix_tree_node *node,
+                             radix_tree_update_node_t update_node,
+                             void *private);
 void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 void radix_tree_clear_tags(struct radix_tree_root *root,
index 321f9ed552a995f396696b71343f66cbd2e01d9e..01f71e1d2e941e359fc5fdd07f0645813ef8f845 100644 (file)
@@ -444,6 +444,10 @@ bool __rcu_is_watching(void);
 #error "Unknown RCU implementation specified to kernel configuration"
 #endif
 
+#define RCU_SCHEDULER_INACTIVE 0
+#define RCU_SCHEDULER_INIT     1
+#define RCU_SCHEDULER_RUNNING  2
+
 /*
  * init_rcu_head_on_stack()/destroy_rcu_head_on_stack() are needed for dynamic
  * initialization and destruction of rcu_head on the stack. rcu_head structures
index e2f3a3281d8fd29de861f4d46ccf7da54ce6eea8..8265d351c9f0e6bc7814fd59ca1efff531e4798f 100644 (file)
@@ -408,7 +408,8 @@ enum rproc_crash_type {
  * @crash_comp: completion used to sync crash handler and the rproc reload
  * @recovery_disabled: flag that state if recovery was disabled
  * @max_notifyid: largest allocated notify id.
- * @table_ptr: our copy of the resource table
+ * @table_ptr: pointer to the resource table in effect
+ * @cached_table: copy of the resource table
  * @has_iommu: flag to indicate if remote processor is behind an MMU
  */
 struct rproc {
@@ -440,6 +441,7 @@ struct rproc {
        bool recovery_disabled;
        int max_notifyid;
        struct resource_table *table_ptr;
+       struct resource_table *cached_table;
        bool has_iommu;
        bool auto_boot;
 };
index 4d1905245c7aa50df56acf0f77c77f3347c28c04..ad3ec9ec61f7b6de743b5d6de4225defcc18be99 100644 (file)
@@ -854,6 +854,16 @@ struct signal_struct {
 
 #define SIGNAL_UNKILLABLE      0x00000040 /* for init: ignore fatal signals */
 
+#define SIGNAL_STOP_MASK (SIGNAL_CLD_MASK | SIGNAL_STOP_STOPPED | \
+                         SIGNAL_STOP_CONTINUED)
+
+static inline void signal_set_stop_flags(struct signal_struct *sig,
+                                        unsigned int flags)
+{
+       WARN_ON(sig->flags & (SIGNAL_GROUP_EXIT|SIGNAL_GROUP_COREDUMP));
+       sig->flags = (sig->flags & ~SIGNAL_STOP_MASK) | flags;
+}
+
 /* If true, all threads except ->group_exit_task have pending SIGKILL */
 static inline int signal_group_exit(const struct signal_struct *sig)
 {
index b53c0cfd417e3bec1c5cfab76787901bafa5884c..a410715bbef8889d148a6b3f8dbd6afc4ae6f4d0 100644 (file)
@@ -2480,7 +2480,7 @@ static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
 
 static inline void skb_free_frag(void *addr)
 {
-       __free_page_frag(addr);
+       page_frag_free(addr);
 }
 
 void *napi_alloc_frag(unsigned int fragsz);
index 084b12bad198232426c6beb27cd348d72797b344..4c536356681543d8749bc5013d619f6c5c7a5bd3 100644 (file)
@@ -226,7 +226,7 @@ static inline const char *__check_heap_object(const void *ptr,
  * (PAGE_SIZE*2).  Larger requests are passed to the page allocator.
  */
 #define KMALLOC_SHIFT_HIGH     (PAGE_SHIFT + 1)
-#define KMALLOC_SHIFT_MAX      (MAX_ORDER + PAGE_SHIFT)
+#define KMALLOC_SHIFT_MAX      (MAX_ORDER + PAGE_SHIFT - 1)
 #ifndef KMALLOC_SHIFT_LOW
 #define KMALLOC_SHIFT_LOW      3
 #endif
@@ -239,7 +239,7 @@ static inline const char *__check_heap_object(const void *ptr,
  * be allocated from the same page.
  */
 #define KMALLOC_SHIFT_HIGH     PAGE_SHIFT
-#define KMALLOC_SHIFT_MAX      30
+#define KMALLOC_SHIFT_MAX      (MAX_ORDER + PAGE_SHIFT - 1)
 #ifndef KMALLOC_SHIFT_LOW
 #define KMALLOC_SHIFT_LOW      3
 #endif
index 85cc819676e81d9f0e85331a17f70b271cd680d1..333ad11b3dd9cf11a8ee2fc2f10bece31c543444 100644 (file)
@@ -216,5 +216,6 @@ void rpc_clnt_xprt_switch_put(struct rpc_clnt *);
 void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *, struct rpc_xprt *);
 bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt,
                        const struct sockaddr *sap);
+void rpc_cleanup_clids(void);
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SUNRPC_CLNT_H */
index e5d19344037491651c6c80f6b310842ee5715126..7440290f64acd3694dfc5c17618c55f6253aae01 100644 (file)
@@ -66,6 +66,7 @@ struct svc_xprt {
 #define XPT_LISTENER   10              /* listening endpoint */
 #define XPT_CACHE_AUTH 11              /* cache auth info */
 #define XPT_LOCAL      12              /* connection from loopback interface */
+#define XPT_KILL_TEMP   13             /* call xpo_kill_temp_xprt before closing */
 
        struct svc_serv         *xpt_server;    /* service for transport */
        atomic_t                xpt_reserved;   /* space on outq that is rsvd */
index 0c729c3c85499a1e51f79ac7252d60d548787fb4..d9718378a8bee0b327d08c2e80a6fd3b5490b967 100644 (file)
@@ -194,8 +194,6 @@ struct platform_freeze_ops {
 };
 
 #ifdef CONFIG_SUSPEND
-extern suspend_state_t mem_sleep_default;
-
 /**
  * suspend_set_ops - set platform dependent suspend operations
  * @ops: The new suspend operations to set.
index 09f4be179ff304ed0c5e921c8b9bd6e33112c886..7f47b7098b1b9b9cfb6aacfca126826160eaaa8c 100644 (file)
@@ -150,8 +150,9 @@ enum {
        SWP_FILE        = (1 << 7),     /* set after swap_activate success */
        SWP_AREA_DISCARD = (1 << 8),    /* single-time swap area discards */
        SWP_PAGE_DISCARD = (1 << 9),    /* freed swap page-cluster discards */
+       SWP_STABLE_WRITES = (1 << 10),  /* no overwrite PG_writeback pages */
                                        /* add others here before... */
-       SWP_SCANNING    = (1 << 10),    /* refcount in scan_swap_map */
+       SWP_SCANNING    = (1 << 11),    /* refcount in scan_swap_map */
 };
 
 #define SWAP_CLUSTER_MAX 32UL
index 183f37c8a5e164ad5864ac433dd69093bac5bad7..4ee479f2f355b1fa2658b1c2aabbdfc376125651 100644 (file)
@@ -9,7 +9,13 @@ struct device;
 struct page;
 struct scatterlist;
 
-extern int swiotlb_force;
+enum swiotlb_force {
+       SWIOTLB_NORMAL,         /* Default - depending on HW DMA mask etc. */
+       SWIOTLB_FORCE,          /* swiotlb=force */
+       SWIOTLB_NO_FORCE,       /* swiotlb=noforce */
+};
+
+extern enum swiotlb_force swiotlb_force;
 
 /*
  * Maximum allowable number of contiguous slabs to map,
@@ -108,11 +114,14 @@ swiotlb_dma_supported(struct device *hwdev, u64 mask);
 
 #ifdef CONFIG_SWIOTLB
 extern void __init swiotlb_free(void);
+unsigned int swiotlb_max_segment(void);
 #else
 static inline void swiotlb_free(void) { }
+static inline unsigned int swiotlb_max_segment(void) { return 0; }
 #endif
 
 extern void swiotlb_print_info(void);
 extern int is_swiotlb_buffer(phys_addr_t paddr);
+extern void swiotlb_set_max_segment(unsigned int);
 
 #endif /* __LINUX_SWIOTLB_H */
index fc5848dad7a43216b3f124c4afdaa6b64b23910c..c93f4b3a59cb7a9f578ec18dd2f6c56014195a90 100644 (file)
@@ -62,8 +62,13 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb)
 
 /* TCP Fast Open Cookie as stored in memory */
 struct tcp_fastopen_cookie {
+       union {
+               u8      val[TCP_FASTOPEN_COOKIE_MAX];
+#if IS_ENABLED(CONFIG_IPV6)
+               struct in6_addr addr;
+#endif
+       };
        s8      len;
-       u8      val[TCP_FASTOPEN_COOKIE_MAX];
        bool    exp;    /* In RFC6994 experimental option format */
 };
 
index bd36ce431e32cbb57a1ec4e97964b78774787a2e..bab0b1ad0613eb7de475b88546cecd7a52645e90 100644 (file)
@@ -8,23 +8,7 @@
 #ifndef _LINUX_TIMERFD_H
 #define _LINUX_TIMERFD_H
 
-/* For O_CLOEXEC and O_NONBLOCK */
-#include <linux/fcntl.h>
-
-/* For _IO helpers */
-#include <linux/ioctl.h>
-
-/*
- * CAREFUL: Check include/asm-generic/fcntl.h when defining
- * new flags, since they might collide with O_* ones. We want
- * to re-use O_* flags that couldn't possibly have a meaning
- * from eventfd, in order to leave a free define-space for
- * shared O_* flags.
- */
-#define TFD_TIMER_ABSTIME (1 << 0)
-#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
-#define TFD_CLOEXEC O_CLOEXEC
-#define TFD_NONBLOCK O_NONBLOCK
+#include <uapi/linux/timerfd.h>
 
 #define TFD_SHARED_FCNTL_FLAGS (TFD_CLOEXEC | TFD_NONBLOCK)
 /* Flags for timerfd_create.  */
@@ -32,6 +16,4 @@
 /* Flags for timerfd_settime.  */
 #define TFD_SETTIME_FLAGS (TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET)
 
-#define TFD_IOC_SET_TICKS      _IOW('T', 0, u64)
-
 #endif /* _LINUX_TIMERFD_H */
index 66204007d7ac32f1f32068c1f46fc1a033e6953f..5209b5ed2a6476dfa5fe6b779f433a795f084ed7 100644 (file)
@@ -56,7 +56,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 
 static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
                                          struct virtio_net_hdr *hdr,
-                                         bool little_endian)
+                                         bool little_endian,
+                                         bool has_data_valid)
 {
        memset(hdr, 0, sizeof(*hdr));   /* no info leak */
 
@@ -91,7 +92,8 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
                                skb_checksum_start_offset(skb));
                hdr->csum_offset = __cpu_to_virtio16(little_endian,
                                skb->csum_offset);
-       } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+       } else if (has_data_valid &&
+                  skb->ip_summed == CHECKSUM_UNNECESSARY) {
                hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
        } /* else everything is zero */
 
index 3ebb168b9afc68ad639b5d32f6182a845c83d759..a34b141f125f0032662f147b598c9fef4fb4bcef 100644 (file)
@@ -309,6 +309,10 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
        }
 
        for (opt_iter = 6; opt_iter < opt_len;) {
+               if (opt_iter + 1 == opt_len) {
+                       err_offset = opt_iter;
+                       goto out;
+               }
                tag_len = opt[opt_iter + 1];
                if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
                        err_offset = opt_iter + 1;
index 487e5739166415625465fa13e0c748dcf1b894ed..dbf0abba33b8da21be05abf6e719f69542da80fc 100644 (file)
@@ -776,6 +776,11 @@ static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
 {
        u32 hash;
 
+       /* @flowlabel may include more than a flow label, eg, the traffic class.
+        * Here we want only the flow label value.
+        */
+       flowlabel &= IPV6_FLOWLABEL_MASK;
+
        if (flowlabel ||
            net->ipv6.sysctl.auto_flowlabels == IP6_AUTO_FLOW_LABEL_OFF ||
            (!autolabel &&
@@ -871,7 +876,7 @@ int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
  *     upper-layer output functions
  */
 int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
-            struct ipv6_txoptions *opt, int tclass);
+            __u32 mark, struct ipv6_txoptions *opt, int tclass);
 
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
 
index d4c1c75b886244f76f9539c0709bb72be7974578..0388b9c5f5e2c7257cc0eb19be469974becab5ed 100644 (file)
@@ -44,6 +44,8 @@ struct lwtunnel_encap_ops {
        int (*get_encap_size)(struct lwtunnel_state *lwtstate);
        int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b);
        int (*xmit)(struct sk_buff *skb);
+
+       struct module *owner;
 };
 
 #ifdef CONFIG_LWTUNNEL
@@ -105,6 +107,8 @@ int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
                           unsigned int num);
 int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
                           unsigned int num);
+int lwtunnel_valid_encap_type(u16 encap_type);
+int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len);
 int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
                         struct nlattr *encap,
                         unsigned int family, const void *cfg,
@@ -168,6 +172,18 @@ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
        return -EOPNOTSUPP;
 }
 
+static inline int lwtunnel_valid_encap_type(u16 encap_type)
+{
+       return -EOPNOTSUPP;
+}
+static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len)
+{
+       /* return 0 since we are not walking attr looking for
+        * RTA_ENCAP_TYPE attribute on nexthops.
+        */
+       return 0;
+}
+
 static inline int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
                                       struct nlattr *encap,
                                       unsigned int family, const void *cfg,
index 924325c46aab2fafc10b3b92bccafd3e00c60c71..7dfdb517f0be826018cf649bb2e410e44d8f9c36 100644 (file)
@@ -207,9 +207,9 @@ struct nft_set_iter {
        unsigned int    skip;
        int             err;
        int             (*fn)(const struct nft_ctx *ctx,
-                             const struct nft_set *set,
+                             struct nft_set *set,
                              const struct nft_set_iter *iter,
-                             const struct nft_set_elem *elem);
+                             struct nft_set_elem *elem);
 };
 
 /**
@@ -301,7 +301,7 @@ struct nft_set_ops {
        void                            (*remove)(const struct nft_set *set,
                                                  const struct nft_set_elem *elem);
        void                            (*walk)(const struct nft_ctx *ctx,
-                                               const struct nft_set *set,
+                                               struct nft_set *set,
                                                struct nft_set_iter *iter);
 
        unsigned int                    (*privsize)(const struct nlattr * const nla[]);
index cbedda077db2ca4bf4aef6e9939b53ee96079920..5ceb2205e4e3ed93461ed4a3956b227f99ac9494 100644 (file)
@@ -9,6 +9,12 @@ struct nft_fib {
 
 extern const struct nla_policy nft_fib_policy[];
 
+static inline bool
+nft_fib_is_loopback(const struct sk_buff *skb, const struct net_device *in)
+{
+       return skb->pkt_type == PACKET_LOOPBACK || in->flags & IFF_LOOPBACK;
+}
+
 int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr);
 int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                 const struct nlattr * const tb[]);
index f0e867f58722f344494c98cbdbe49d7ec875099a..c4f5e6fca17cf4e0029080410202cb66ce0fad37 100644 (file)
@@ -2006,7 +2006,9 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
 void sk_stop_timer(struct sock *sk, struct timer_list *timer);
 
 int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
-                       unsigned int flags);
+                       unsigned int flags,
+                       void (*destructor)(struct sock *sk,
+                                          struct sk_buff *skb));
 int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 
index 958a24d8fae794547c486b5b025f3815c96f82e7..b567e4452a4733de98b720e2c0d9060f21cc92e2 100644 (file)
@@ -352,6 +352,20 @@ static inline int ib_mtu_enum_to_int(enum ib_mtu mtu)
        }
 }
 
+static inline enum ib_mtu ib_mtu_int_to_enum(int mtu)
+{
+       if (mtu >= 4096)
+               return IB_MTU_4096;
+       else if (mtu >= 2048)
+               return IB_MTU_2048;
+       else if (mtu >= 1024)
+               return IB_MTU_1024;
+       else if (mtu >= 512)
+               return IB_MTU_512;
+       else
+               return IB_MTU_256;
+}
+
 enum ib_port_state {
        IB_PORT_NOP             = 0,
        IB_PORT_DOWN            = 1,
index 96dd0b3f70d75ba5362eccecdd8c8371627f22a7..da5033dd8cbcab5bff1557452b7a55e888d46c30 100644 (file)
@@ -809,11 +809,11 @@ static inline void fc_set_wwnn(struct fc_lport *lport, u64 wwnn)
 /**
  * fc_set_wwpn() - Set the World Wide Port Name of a local port
  * @lport: The local port whose WWPN is to be set
- * @wwnn:  The new WWPN
+ * @wwpn:  The new WWPN
  */
-static inline void fc_set_wwpn(struct fc_lport *lport, u64 wwnn)
+static inline void fc_set_wwpn(struct fc_lport *lport, u64 wwpn)
 {
-       lport->wwpn = wwnn;
+       lport->wwpn = wwpn;
 }
 
 /**
index 6902c2a8bd23c2e43f9b8bd7b688c0cc4a6a3ca4..4b6b489a8d7c2defaf51e9ecb121c91901b9cac8 100644 (file)
@@ -55,17 +55,17 @@ struct mcip_cmd {
 
 struct mcip_bcr {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-               unsigned int pad3:8,
-                            idu:1, llm:1, num_cores:6,
-                            iocoh:1,  gfrc:1, dbg:1, pad2:1,
-                            msg:1, sem:1, ipi:1, pad:1,
+               unsigned int pad4:6, pw_dom:1, pad3:1,
+                            idu:1, pad2:1, num_cores:6,
+                            pad:1,  gfrc:1, dbg:1, pw:1,
+                            msg:1, sem:1, ipi:1, slv:1,
                             ver:8;
 #else
                unsigned int ver:8,
-                            pad:1, ipi:1, sem:1, msg:1,
-                            pad2:1, dbg:1, gfrc:1, iocoh:1,
-                            num_cores:6, llm:1, idu:1,
-                            pad3:8;
+                            slv:1, ipi:1, sem:1, msg:1,
+                            pw:1, dbg:1, gfrc:1, pad:1,
+                            num_cores:6, pad2:1, idu:1,
+                            pad3:1, pw_dom:1, pad4:6;
 #endif
 };
 
index 530c57bdefa06567c3bcaba9249845af1d4e535a..915c4357945c27992aa3b7561ab705dedff082ad 100644 (file)
@@ -36,10 +36,10 @@ struct hdmi_codec_daifmt {
                HDMI_AC97,
                HDMI_SPDIF,
        } fmt;
-       int bit_clk_inv:1;
-       int frame_clk_inv:1;
-       int bit_clk_master:1;
-       int frame_clk_master:1;
+       unsigned int bit_clk_inv:1;
+       unsigned int frame_clk_inv:1;
+       unsigned int bit_clk_master:1;
+       unsigned int frame_clk_master:1;
 };
 
 /*
index 2b502f6cc6d036be6e25c6834671be1cde2fd8da..b86168a21d56c7fff1d59dfacbef93049bde888e 100644 (file)
@@ -813,6 +813,7 @@ struct snd_soc_component {
        unsigned int suspended:1; /* is in suspend PM state */
 
        struct list_head list;
+       struct list_head card_aux_list; /* for auxiliary bound components */
        struct list_head card_list;
 
        struct snd_soc_dai_driver *dai_drv;
@@ -1152,6 +1153,7 @@ struct snd_soc_card {
         */
        struct snd_soc_aux_dev *aux_dev;
        int num_aux_devs;
+       struct list_head aux_comp_list;
 
        const struct snd_kcontrol_new *controls;
        int num_controls;
@@ -1547,6 +1549,7 @@ static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
        INIT_LIST_HEAD(&card->widgets);
        INIT_LIST_HEAD(&card->paths);
        INIT_LIST_HEAD(&card->dapm_list);
+       INIT_LIST_HEAD(&card->aux_comp_list);
        INIT_LIST_HEAD(&card->component_dev_list);
 }
 
index 29e6858bb1648b636dcce48072f9fe43e5a8a884..da854fb4530f1f75e9f46a8ad57ec0251217fd7b 100644 (file)
@@ -174,6 +174,10 @@ enum tcm_sense_reason_table {
        TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED  = R(0x16),
        TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED  = R(0x17),
        TCM_COPY_TARGET_DEVICE_NOT_REACHABLE    = R(0x18),
+       TCM_TOO_MANY_TARGET_DESCS               = R(0x19),
+       TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE   = R(0x1a),
+       TCM_TOO_MANY_SEGMENT_DESCS              = R(0x1b),
+       TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE  = R(0x1c),
 #undef R
 };
 
@@ -534,6 +538,7 @@ struct se_node_acl {
        char                    initiatorname[TRANSPORT_IQN_LEN];
        /* Used to signal demo mode created ACL, disabled by default */
        bool                    dynamic_node_acl;
+       bool                    dynamic_stop;
        u32                     queue_depth;
        u32                     acl_index;
        enum target_prot_type   saved_prot_type;
index c14bed4ab0977fc1d7d06b38051644f8e67e2349..88d18a8ceb59f9c6e3c5630a491cf6d3c91cf73c 100644 (file)
@@ -130,8 +130,8 @@ DECLARE_EVENT_CLASS(btrfs__inode,
                                BTRFS_I(inode)->root->root_key.objectid;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), gen = %llu, ino = %lu, blocks = %llu, "
-                 "disk_i_size = %llu, last_trans = %llu, logged_trans = %llu",
+       TP_printk_btrfs("root=%llu(%s) gen=%llu ino=%lu blocks=%llu "
+                 "disk_i_size=%llu last_trans=%llu logged_trans=%llu",
                  show_root_type(__entry->root_objectid),
                  (unsigned long long)__entry->generation,
                  (unsigned long)__entry->ino,
@@ -184,14 +184,16 @@ DEFINE_EVENT(btrfs__inode, btrfs_inode_evict,
 
 TRACE_EVENT_CONDITION(btrfs_get_extent,
 
-       TP_PROTO(struct btrfs_root *root, struct extent_map *map),
+       TP_PROTO(struct btrfs_root *root, struct inode *inode,
+                struct extent_map *map),
 
-       TP_ARGS(root, map),
+       TP_ARGS(root, inode, map),
 
        TP_CONDITION(map),
 
        TP_STRUCT__entry_btrfs(
                __field(        u64,  root_objectid     )
+               __field(        u64,  ino               )
                __field(        u64,  start             )
                __field(        u64,  len               )
                __field(        u64,  orig_start        )
@@ -204,7 +206,8 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
 
        TP_fast_assign_btrfs(root->fs_info,
                __entry->root_objectid  = root->root_key.objectid;
-               __entry->start          = map->start;
+               __entry->ino            = btrfs_ino(inode);
+               __entry->start          = map->start;
                __entry->len            = map->len;
                __entry->orig_start     = map->orig_start;
                __entry->block_start    = map->block_start;
@@ -214,11 +217,12 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
                __entry->compress_type  = map->compress_type;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), start = %llu, len = %llu, "
-                 "orig_start = %llu, block_start = %llu(%s), "
-                 "block_len = %llu, flags = %s, refs = %u, "
-                 "compress_type = %u",
+       TP_printk_btrfs("root=%llu(%s) ino=%llu start=%llu len=%llu "
+                 "orig_start=%llu block_start=%llu(%s) "
+                 "block_len=%llu flags=%s refs=%u "
+                 "compress_type=%u",
                  show_root_type(__entry->root_objectid),
+                 (unsigned long long)__entry->ino,
                  (unsigned long long)__entry->start,
                  (unsigned long long)__entry->len,
                  (unsigned long long)__entry->orig_start,
@@ -259,6 +263,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
                __field(        int,  compress_type     )
                __field(        int,  refs              )
                __field(        u64,  root_objectid     )
+               __field(        u64,  truncated_len     )
        ),
 
        TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
@@ -273,18 +278,21 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
                __entry->refs           = atomic_read(&ordered->refs);
                __entry->root_objectid  =
                                BTRFS_I(inode)->root->root_key.objectid;
+               __entry->truncated_len  = ordered->truncated_len;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), ino = %llu, file_offset = %llu, "
-                 "start = %llu, len = %llu, disk_len = %llu, "
-                 "bytes_left = %llu, flags = %s, compress_type = %d, "
-                 "refs = %d",
+       TP_printk_btrfs("root=%llu(%s) ino=%llu file_offset=%llu "
+                 "start=%llu len=%llu disk_len=%llu "
+                 "truncated_len=%llu "
+                 "bytes_left=%llu flags=%s compress_type=%d "
+                 "refs=%d",
                  show_root_type(__entry->root_objectid),
                  (unsigned long long)__entry->ino,
                  (unsigned long long)__entry->file_offset,
                  (unsigned long long)__entry->start,
                  (unsigned long long)__entry->len,
                  (unsigned long long)__entry->disk_len,
+                 (unsigned long long)__entry->truncated_len,
                  (unsigned long long)__entry->bytes_left,
                  show_ordered_flags(__entry->flags),
                  __entry->compress_type, __entry->refs)
@@ -354,10 +362,10 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
                                 BTRFS_I(inode)->root->root_key.objectid;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), ino = %lu, page_index = %lu, "
-                 "nr_to_write = %ld, pages_skipped = %ld, range_start = %llu, "
-                 "range_end = %llu, for_kupdate = %d, "
-                 "for_reclaim = %d, range_cyclic = %d, writeback_index = %lu",
+       TP_printk_btrfs("root=%llu(%s) ino=%lu page_index=%lu "
+                 "nr_to_write=%ld pages_skipped=%ld range_start=%llu "
+                 "range_end=%llu for_kupdate=%d "
+                 "for_reclaim=%d range_cyclic=%d writeback_index=%lu",
                  show_root_type(__entry->root_objectid),
                  (unsigned long)__entry->ino, __entry->index,
                  __entry->nr_to_write, __entry->pages_skipped,
@@ -400,8 +408,8 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
                         BTRFS_I(page->mapping->host)->root->root_key.objectid;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), ino = %lu, page_index = %lu, start = %llu, "
-                 "end = %llu, uptodate = %d",
+       TP_printk_btrfs("root=%llu(%s) ino=%lu page_index=%lu start=%llu "
+                 "end=%llu uptodate=%d",
                  show_root_type(__entry->root_objectid),
                  (unsigned long)__entry->ino, (unsigned long)__entry->index,
                  (unsigned long long)__entry->start,
@@ -433,7 +441,7 @@ TRACE_EVENT(btrfs_sync_file,
                                 BTRFS_I(inode)->root->root_key.objectid;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), ino = %ld, parent = %ld, datasync = %d",
+       TP_printk_btrfs("root=%llu(%s) ino=%ld parent=%ld datasync=%d",
                  show_root_type(__entry->root_objectid),
                  (unsigned long)__entry->ino, (unsigned long)__entry->parent,
                  __entry->datasync)
@@ -484,9 +492,9 @@ TRACE_EVENT(btrfs_add_block_group,
                __entry->create         = create;
        ),
 
-       TP_printk("%pU: block_group offset = %llu, size = %llu, "
-                 "flags = %llu(%s), bytes_used = %llu, bytes_super = %llu, "
-                 "create = %d", __entry->fsid,
+       TP_printk("%pU: block_group offset=%llu size=%llu "
+                 "flags=%llu(%s) bytes_used=%llu bytes_super=%llu "
+                 "create=%d", __entry->fsid,
                  (unsigned long long)__entry->offset,
                  (unsigned long long)__entry->size,
                  (unsigned long long)__entry->flags,
@@ -535,9 +543,9 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
                __entry->seq            = ref->seq;
        ),
 
-       TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, action = %s, "
-                 "parent = %llu(%s), ref_root = %llu(%s), level = %d, "
-                 "type = %s, seq = %llu",
+       TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s "
+                 "parent=%llu(%s) ref_root=%llu(%s) level=%d "
+                 "type=%s seq=%llu",
                  (unsigned long long)__entry->bytenr,
                  (unsigned long long)__entry->num_bytes,
                  show_ref_action(__entry->action),
@@ -600,9 +608,9 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
                __entry->seq            = ref->seq;
        ),
 
-       TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, action = %s, "
-                 "parent = %llu(%s), ref_root = %llu(%s), owner = %llu, "
-                 "offset = %llu, type = %s, seq = %llu",
+       TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s "
+                 "parent=%llu(%s) ref_root=%llu(%s) owner=%llu "
+                 "offset=%llu type=%s seq=%llu",
                  (unsigned long long)__entry->bytenr,
                  (unsigned long long)__entry->num_bytes,
                  show_ref_action(__entry->action),
@@ -657,7 +665,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head,
                __entry->is_data        = head_ref->is_data;
        ),
 
-       TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, action = %s, is_data = %d",
+       TP_printk_btrfs("bytenr=%llu num_bytes=%llu action=%s is_data=%d",
                  (unsigned long long)__entry->bytenr,
                  (unsigned long long)__entry->num_bytes,
                  show_ref_action(__entry->action),
@@ -721,8 +729,8 @@ DECLARE_EVENT_CLASS(btrfs__chunk,
                __entry->root_objectid  = fs_info->chunk_root->root_key.objectid;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), offset = %llu, size = %llu, "
-                 "num_stripes = %d, sub_stripes = %d, type = %s",
+       TP_printk_btrfs("root=%llu(%s) offset=%llu size=%llu "
+                 "num_stripes=%d sub_stripes=%d type=%s",
                  show_root_type(__entry->root_objectid),
                  (unsigned long long)__entry->offset,
                  (unsigned long long)__entry->size,
@@ -771,8 +779,8 @@ TRACE_EVENT(btrfs_cow_block,
                __entry->cow_level      = btrfs_header_level(cow);
        ),
 
-       TP_printk_btrfs("root = %llu(%s), refs = %d, orig_buf = %llu "
-                 "(orig_level = %d), cow_buf = %llu (cow_level = %d)",
+       TP_printk_btrfs("root=%llu(%s) refs=%d orig_buf=%llu "
+                 "(orig_level=%d) cow_buf=%llu (cow_level=%d)",
                  show_root_type(__entry->root_objectid),
                  __entry->refs,
                  (unsigned long long)__entry->buf_start,
@@ -836,7 +844,7 @@ TRACE_EVENT(btrfs_trigger_flush,
                __assign_str(reason, reason)
        ),
 
-       TP_printk("%pU: %s: flush = %d(%s), flags = %llu(%s), bytes = %llu",
+       TP_printk("%pU: %s: flush=%d(%s) flags=%llu(%s) bytes=%llu",
                  __entry->fsid, __get_str(reason), __entry->flush,
                  show_flush_action(__entry->flush),
                  (unsigned long long)__entry->flags,
@@ -879,8 +887,8 @@ TRACE_EVENT(btrfs_flush_space,
                __entry->ret            =       ret;
        ),
 
-       TP_printk("%pU: state = %d(%s), flags = %llu(%s), num_bytes = %llu, "
-                 "orig_bytes = %llu, ret = %d", __entry->fsid, __entry->state,
+       TP_printk("%pU: state=%d(%s) flags=%llu(%s) num_bytes=%llu "
+                 "orig_bytes=%llu ret=%d", __entry->fsid, __entry->state,
                  show_flush_state(__entry->state),
                  (unsigned long long)__entry->flags,
                  __print_flags((unsigned long)__entry->flags, "|",
@@ -905,7 +913,7 @@ DECLARE_EVENT_CLASS(btrfs__reserved_extent,
                __entry->len            = len;
        ),
 
-       TP_printk_btrfs("root = %llu(%s), start = %llu, len = %llu",
+       TP_printk_btrfs("root=%llu(%s) start=%llu len=%llu",
                  show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
                  (unsigned long long)__entry->start,
                  (unsigned long long)__entry->len)
@@ -944,7 +952,7 @@ TRACE_EVENT(find_free_extent,
                __entry->data           = data;
        ),
 
-       TP_printk_btrfs("root = %Lu(%s), len = %Lu, empty_size = %Lu, flags = %Lu(%s)",
+       TP_printk_btrfs("root=%Lu(%s) len=%Lu empty_size=%Lu flags=%Lu(%s)",
                  show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
                  __entry->num_bytes, __entry->empty_size, __entry->data,
                  __print_flags((unsigned long)__entry->data, "|",
@@ -973,8 +981,8 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
                __entry->len            = len;
        ),
 
-       TP_printk_btrfs("root = %Lu(%s), block_group = %Lu, flags = %Lu(%s), "
-                 "start = %Lu, len = %Lu",
+       TP_printk_btrfs("root=%Lu(%s) block_group=%Lu flags=%Lu(%s) "
+                 "start=%Lu len=%Lu",
                  show_root_type(BTRFS_EXTENT_TREE_OBJECTID),
                  __entry->bg_objectid,
                  __entry->flags, __print_flags((unsigned long)__entry->flags,
@@ -1025,8 +1033,8 @@ TRACE_EVENT(btrfs_find_cluster,
                __entry->min_bytes      = min_bytes;
        ),
 
-       TP_printk_btrfs("block_group = %Lu, flags = %Lu(%s), start = %Lu, len = %Lu,"
-                 " empty_size = %Lu, min_bytes = %Lu", __entry->bg_objectid,
+       TP_printk_btrfs("block_group=%Lu flags=%Lu(%s) start=%Lu len=%Lu "
+                 "empty_size=%Lu min_bytes=%Lu", __entry->bg_objectid,
                  __entry->flags,
                  __print_flags((unsigned long)__entry->flags, "|",
                                BTRFS_GROUP_FLAGS), __entry->start,
@@ -1047,7 +1055,7 @@ TRACE_EVENT(btrfs_failed_cluster_setup,
                __entry->bg_objectid    = block_group->key.objectid;
        ),
 
-       TP_printk_btrfs("block_group = %Lu", __entry->bg_objectid)
+       TP_printk_btrfs("block_group=%Lu", __entry->bg_objectid)
 );
 
 TRACE_EVENT(btrfs_setup_cluster,
@@ -1075,8 +1083,8 @@ TRACE_EVENT(btrfs_setup_cluster,
                __entry->bitmap         = bitmap;
        ),
 
-       TP_printk_btrfs("block_group = %Lu, flags = %Lu(%s), window_start = %Lu, "
-                 "size = %Lu, max_size = %Lu, bitmap = %d",
+       TP_printk_btrfs("block_group=%Lu flags=%Lu(%s) window_start=%Lu "
+                 "size=%Lu max_size=%Lu bitmap=%d",
                  __entry->bg_objectid,
                  __entry->flags,
                  __print_flags((unsigned long)__entry->flags, "|",
@@ -1103,7 +1111,7 @@ TRACE_EVENT(alloc_extent_state,
                __entry->ip     = IP
        ),
 
-       TP_printk("state=%p; mask = %s; caller = %pS", __entry->state,
+       TP_printk("state=%p mask=%s caller=%pS", __entry->state,
                  show_gfp_flags(__entry->mask), (void *)__entry->ip)
 );
 
@@ -1123,7 +1131,7 @@ TRACE_EVENT(free_extent_state,
                __entry->ip = IP
        ),
 
-       TP_printk(" state=%p; caller = %pS", __entry->state,
+       TP_printk("state=%p caller=%pS", __entry->state,
                  (void *)__entry->ip)
 );
 
@@ -1151,28 +1159,32 @@ DECLARE_EVENT_CLASS(btrfs__work,
                __entry->normal_work    = &work->normal_work;
        ),
 
-       TP_printk_btrfs("work=%p (normal_work=%p), wq=%p, func=%pf, ordered_func=%p,"
-                 " ordered_free=%p",
+       TP_printk_btrfs("work=%p (normal_work=%p) wq=%p func=%pf ordered_func=%p "
+                 "ordered_free=%p",
                  __entry->work, __entry->normal_work, __entry->wq,
                   __entry->func, __entry->ordered_func, __entry->ordered_free)
 );
 
-/* For situiations that the work is freed */
+/*
+ * For situiations when the work is freed, we pass fs_info and a tag that that
+ * matches address of the work structure so it can be paired with the
+ * scheduling event.
+ */
 DECLARE_EVENT_CLASS(btrfs__work__done,
 
-       TP_PROTO(struct btrfs_work *work),
+       TP_PROTO(struct btrfs_fs_info *fs_info, void *wtag),
 
-       TP_ARGS(work),
+       TP_ARGS(fs_info, wtag),
 
        TP_STRUCT__entry_btrfs(
-               __field(        void *, work                    )
+               __field(        void *, wtag                    )
        ),
 
-       TP_fast_assign_btrfs(btrfs_work_owner(work),
-               __entry->work           = work;
+       TP_fast_assign_btrfs(fs_info,
+               __entry->wtag           = wtag;
        ),
 
-       TP_printk_btrfs("work->%p", __entry->work)
+       TP_printk_btrfs("work->%p", __entry->wtag)
 );
 
 DEFINE_EVENT(btrfs__work, btrfs_work_queued,
@@ -1191,9 +1203,9 @@ DEFINE_EVENT(btrfs__work, btrfs_work_sched,
 
 DEFINE_EVENT(btrfs__work__done, btrfs_all_work_done,
 
-       TP_PROTO(struct btrfs_work *work),
+       TP_PROTO(struct btrfs_fs_info *fs_info, void *wtag),
 
-       TP_ARGS(work)
+       TP_ARGS(fs_info, wtag)
 );
 
 DEFINE_EVENT(btrfs__work, btrfs_ordered_sched,
@@ -1221,7 +1233,7 @@ DECLARE_EVENT_CLASS(btrfs__workqueue,
                __entry->high           = high;
        ),
 
-       TP_printk_btrfs("name=%s%s, wq=%p", __get_str(name),
+       TP_printk_btrfs("name=%s%s wq=%p", __get_str(name),
                  __print_flags(__entry->high, "",
                                {(WQ_HIGHPRI),  "-high"}),
                  __entry->wq)
@@ -1276,7 +1288,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_data_map,
                __entry->free_reserved  =       free_reserved;
        ),
 
-       TP_printk_btrfs("rootid=%llu, ino=%lu, free_reserved=%llu",
+       TP_printk_btrfs("rootid=%llu ino=%lu free_reserved=%llu",
                  __entry->rootid, __entry->ino, __entry->free_reserved)
 );
 
@@ -1323,7 +1335,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
                __entry->op             = op;
        ),
 
-       TP_printk_btrfs("root=%llu, ino=%lu, start=%llu, len=%llu, reserved=%llu, op=%s",
+       TP_printk_btrfs("root=%llu ino=%lu start=%llu len=%llu reserved=%llu op=%s",
                  __entry->rootid, __entry->ino, __entry->start, __entry->len,
                  __entry->reserved,
                  __print_flags((unsigned long)__entry->op, "",
@@ -1361,7 +1373,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_delayed_ref,
                __entry->reserved       = reserved;
        ),
 
-       TP_printk_btrfs("root=%llu, reserved=%llu, op=free",
+       TP_printk_btrfs("root=%llu reserved=%llu op=free",
                  __entry->ref_root, __entry->reserved)
 );
 
@@ -1388,7 +1400,7 @@ DECLARE_EVENT_CLASS(btrfs_qgroup_extent,
                __entry->num_bytes      = rec->num_bytes;
        ),
 
-       TP_printk_btrfs("bytenr = %llu, num_bytes = %llu",
+       TP_printk_btrfs("bytenr=%llu num_bytes=%llu",
                  (unsigned long long)__entry->bytenr,
                  (unsigned long long)__entry->num_bytes)
 );
@@ -1430,8 +1442,8 @@ TRACE_EVENT(btrfs_qgroup_account_extent,
                __entry->nr_new_roots   = nr_new_roots;
        ),
 
-       TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, nr_old_roots = %llu, "
-                 "nr_new_roots = %llu",
+       TP_printk_btrfs("bytenr=%llu num_bytes=%llu nr_old_roots=%llu "
+                 "nr_new_roots=%llu",
                  __entry->bytenr,
                  __entry->num_bytes,
                  __entry->nr_old_roots,
@@ -1457,7 +1469,7 @@ TRACE_EVENT(qgroup_update_counters,
                __entry->cur_new_count  = cur_new_count;
        ),
 
-       TP_printk_btrfs("qgid = %llu, cur_old_count = %llu, cur_new_count = %llu",
+       TP_printk_btrfs("qgid=%llu cur_old_count=%llu cur_new_count=%llu",
                  __entry->qgid,
                  __entry->cur_old_count,
                  __entry->cur_new_count)
index 9e687ca9a307b1344889186e46dd5e62a85f614f..15bf875d0e4a666d91c959bd10b62318b62d61d5 100644 (file)
@@ -47,8 +47,7 @@
        {(unsigned long)__GFP_WRITE,            "__GFP_WRITE"},         \
        {(unsigned long)__GFP_RECLAIM,          "__GFP_RECLAIM"},       \
        {(unsigned long)__GFP_DIRECT_RECLAIM,   "__GFP_DIRECT_RECLAIM"},\
-       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"},\
-       {(unsigned long)__GFP_OTHER_NODE,       "__GFP_OTHER_NODE"}     \
+       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"}\
 
 #define show_gfp_flags(flags)                                          \
        (flags) ? __print_flags(flags, "|",                             \
index 7ea4c5e7c4487a963acfc75c027514a6cb360169..288c0c54a2b4ace63a94549c136fe255e2982089 100644 (file)
@@ -11,16 +11,16 @@ TRACE_EVENT(swiotlb_bounced,
        TP_PROTO(struct device *dev,
                 dma_addr_t dev_addr,
                 size_t size,
-                int swiotlb_force),
+                enum swiotlb_force swiotlb_force),
 
        TP_ARGS(dev, dev_addr, size, swiotlb_force),
 
        TP_STRUCT__entry(
-               __string(       dev_name,       dev_name(dev)   )
-               __field(        u64,    dma_mask                )
-               __field(        dma_addr_t,     dev_addr        )
-               __field(        size_t, size                    )
-               __field(        int,    swiotlb_force           )
+               __string(       dev_name,       dev_name(dev)           )
+               __field(        u64,    dma_mask                        )
+               __field(        dma_addr_t,     dev_addr                )
+               __field(        size_t, size                            )
+               __field(        enum swiotlb_force,     swiotlb_force   )
        ),
 
        TP_fast_assign(
@@ -37,7 +37,10 @@ TRACE_EVENT(swiotlb_bounced,
                __entry->dma_mask,
                (unsigned long long)__entry->dev_addr,
                __entry->size,
-               __entry->swiotlb_force ? "swiotlb_force" : "" )
+               __print_symbolic(__entry->swiotlb_force,
+                       { SWIOTLB_NORMAL,       "NORMAL" },
+                       { SWIOTLB_FORCE,        "FORCE" },
+                       { SWIOTLB_NO_FORCE,     "NO_FORCE" }))
 );
 
 #endif /*  _TRACE_SWIOTLB_H */
index a8b93e68523941ca5615cbbe0da87f42d779db6d..f330ba4547cfd4c59da3d8f309e4ab76d8bd8b40 100644 (file)
@@ -414,6 +414,7 @@ header-y += telephony.h
 header-y += termios.h
 header-y += thermal.h
 header-y += time.h
+header-y += timerfd.h
 header-y += times.h
 header-y += timex.h
 header-y += tiocl.h
index 0eb0e87dbe9f511672102f2123129328288a9159..d2b0ac799d03c925a6eec2b49bdb14525331687c 100644 (file)
@@ -116,6 +116,12 @@ enum bpf_attach_type {
 
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 
+/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command
+ * to the given target_fd cgroup the descendent cgroup will be able to
+ * override effective bpf program that was inherited from this cgroup
+ */
+#define BPF_F_ALLOW_OVERRIDE   (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -171,6 +177,7 @@ union bpf_attr {
                __u32           target_fd;      /* container object to attach to */
                __u32           attach_bpf_fd;  /* eBPF program to attach */
                __u32           attach_type;
+               __u32           attach_flags;
        };
 } __attribute__((aligned(8)));
 
index 3cbc327801d6dc625f3f7786730fb07d065ac760..c451eec42a83101a6eea0219788165600d128e49 100644 (file)
@@ -1665,14 +1665,15 @@ static inline void cec_msg_report_current_latency(struct cec_msg *msg,
                                                  __u8 audio_out_compensated,
                                                  __u8 audio_out_delay)
 {
-       msg->len = 7;
+       msg->len = 6;
        msg->msg[0] |= 0xf; /* broadcast */
        msg->msg[1] = CEC_MSG_REPORT_CURRENT_LATENCY;
        msg->msg[2] = phys_addr >> 8;
        msg->msg[3] = phys_addr & 0xff;
        msg->msg[4] = video_latency;
        msg->msg[5] = (low_latency_mode << 2) | audio_out_compensated;
-       msg->msg[6] = audio_out_delay;
+       if (audio_out_compensated == 3)
+               msg->msg[msg->len++] = audio_out_delay;
 }
 
 static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
@@ -1686,7 +1687,10 @@ static inline void cec_ops_report_current_latency(const struct cec_msg *msg,
        *video_latency = msg->msg[4];
        *low_latency_mode = (msg->msg[5] >> 2) & 1;
        *audio_out_compensated = msg->msg[5] & 3;
-       *audio_out_delay = msg->msg[6];
+       if (*audio_out_compensated == 3 && msg->len >= 7)
+               *audio_out_delay = msg->msg[6];
+       else
+               *audio_out_delay = 0;
 }
 
 static inline void cec_msg_request_current_latency(struct cec_msg *msg,
index f0db7788f887b9947e0e1aa78d48a9980e80bddf..3dc91a46e8b8da0b243a12a168bbf205e5a87916 100644 (file)
@@ -1384,6 +1384,8 @@ enum ethtool_link_mode_bit_indices {
        ETHTOOL_LINK_MODE_10000baseLR_Full_BIT  = 44,
        ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45,
        ETHTOOL_LINK_MODE_10000baseER_Full_BIT  = 46,
+       ETHTOOL_LINK_MODE_2500baseT_Full_BIT    = 47,
+       ETHTOOL_LINK_MODE_5000baseT_Full_BIT    = 48,
 
 
        /* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
@@ -1393,7 +1395,7 @@ enum ethtool_link_mode_bit_indices {
         */
 
        __ETHTOOL_LINK_MODE_LAST
-         = ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+         = ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
 };
 
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name)     \
index 85ddb74fcd1c8e17d027be5cdb9310048c2d50d8..b23c1914a18217a3e1e185dc0bd47211c98f20a6 100644 (file)
@@ -9,9 +9,8 @@
 
 #include <linux/types.h>
 #include <linux/socket.h>
-#ifndef __KERNEL__
-#include <netinet/in.h>
-#endif
+#include <linux/in.h>
+#include <linux/in6.h>
 
 #define IPPROTO_L2TP           115
 
@@ -31,7 +30,7 @@ struct sockaddr_l2tpip {
        __u32           l2tp_conn_id;   /* Connection ID of tunnel */
 
        /* Pad to size of `struct sockaddr'. */
-       unsigned char   __pad[sizeof(struct sockaddr) -
+       unsigned char   __pad[__SOCK_SIZE__ -
                              sizeof(__kernel_sa_family_t) -
                              sizeof(__be16) - sizeof(struct in_addr) -
                              sizeof(__u32)];
index 8be21e02387db67010fb26b50abb59201b9c0e5c..d0b5fa91ff5493fd4af4dbed049102a8c65debf3 100644 (file)
@@ -9,4 +9,6 @@
 #define NF_LOG_MACDECODE       0x20    /* Decode MAC header */
 #define NF_LOG_MASK            0x2f
 
+#define NF_LOG_PREFIXLEN       128
+
 #endif /* _NETFILTER_NF_LOG_H */
index 881d49e94569648d2f735e81b34fa567627f3019..e3f27e09eb2be460ebfea6a3b8f2d1ffb38d3010 100644 (file)
@@ -235,7 +235,7 @@ enum nft_rule_compat_flags {
 /**
  * enum nft_rule_compat_attributes - nf_tables rule compat attributes
  *
- * @NFTA_RULE_COMPAT_PROTO: numerice value of handled protocol (NLA_U32)
+ * @NFTA_RULE_COMPAT_PROTO: numeric value of handled protocol (NLA_U32)
  * @NFTA_RULE_COMPAT_FLAGS: bitmask of enum nft_rule_compat_flags (NLA_U32)
  */
 enum nft_rule_compat_attributes {
@@ -499,7 +499,7 @@ enum nft_bitwise_attributes {
  * enum nft_byteorder_ops - nf_tables byteorder operators
  *
  * @NFT_BYTEORDER_NTOH: network to host operator
- * @NFT_BYTEORDER_HTON: host to network opertaor
+ * @NFT_BYTEORDER_HTON: host to network operator
  */
 enum nft_byteorder_ops {
        NFT_BYTEORDER_NTOH,
index 6b76e3b0c18eac57491268b5ce395050914cef99..bea982af9cfb80a3081f50af90145a3b9758185c 100644 (file)
@@ -1772,7 +1772,9 @@ enum nl80211_commands {
  *
  * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode
  *     Notification Element based on association request when used with
- *     %NL80211_CMD_NEW_STATION; u8 attribute.
+ *     %NL80211_CMD_NEW_STATION or %NL80211_CMD_SET_STATION (only when
+ *     %NL80211_FEATURE_FULL_AP_CLIENT_STATE is supported, or with TDLS);
+ *     u8 attribute.
  *
  * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
  *     %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
index cb4bcdc5854372e514865c30315e65ae30080527..a4dcd88ec2718621c2cf8e801566e5264c75c071 100644 (file)
@@ -397,7 +397,7 @@ enum {
        TCA_BPF_NAME,
        TCA_BPF_FLAGS,
        TCA_BPF_FLAGS_GEN,
-       TCA_BPF_DIGEST,
+       TCA_BPF_TAG,
        __TCA_BPF_MAX,
 };
 
index c396a8052f73cd91c12b676733f93b68416cd50a..052799e4d751c805de01bc8ed47c3d0a1ecde936 100644 (file)
@@ -23,14 +23,12 @@ struct ipv6_sr_hdr {
        __u8    type;
        __u8    segments_left;
        __u8    first_segment;
-       __u8    flag_1;
-       __u8    flag_2;
-       __u8    reserved;
+       __u8    flags;
+       __u16   reserved;
 
        struct in6_addr segments[0];
 };
 
-#define SR6_FLAG1_CLEANUP      (1 << 7)
 #define SR6_FLAG1_PROTECTED    (1 << 6)
 #define SR6_FLAG1_OAM          (1 << 5)
 #define SR6_FLAG1_ALERT                (1 << 4)
@@ -42,8 +40,7 @@ struct ipv6_sr_hdr {
 #define SR6_TLV_PADDING                4
 #define SR6_TLV_HMAC           5
 
-#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP)
-#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC)
+#define sr_has_hmac(srh) ((srh)->flags & SR6_FLAG1_HMAC)
 
 struct sr6_tlv {
        __u8 type;
index a6b88a6f7f712b271f07e809ee7a79697e6cb8cf..975b50dc8d1d466bb60c6279de7ebde1d05bd54f 100644 (file)
@@ -27,7 +27,7 @@ enum {
        TCA_ACT_BPF_FD,
        TCA_ACT_BPF_NAME,
        TCA_ACT_BPF_PAD,
-       TCA_ACT_BPF_DIGEST,
+       TCA_ACT_BPF_TAG,
        __TCA_ACT_BPF_MAX,
 };
 #define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
diff --git a/include/uapi/linux/timerfd.h b/include/uapi/linux/timerfd.h
new file mode 100644 (file)
index 0000000..6fcfaa8
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  include/linux/timerfd.h
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _UAPI_LINUX_TIMERFD_H
+#define _UAPI_LINUX_TIMERFD_H
+
+#include <linux/types.h>
+
+/* For O_CLOEXEC and O_NONBLOCK */
+#include <linux/fcntl.h>
+
+/* For _IO helpers */
+#include <linux/ioctl.h>
+
+/*
+ * CAREFUL: Check include/asm-generic/fcntl.h when defining
+ * new flags, since they might collide with O_* ones. We want
+ * to re-use O_* flags that couldn't possibly have a meaning
+ * from eventfd, in order to leave a free define-space for
+ * shared O_* flags.
+ *
+ * Also make sure to update the masks in include/linux/timerfd.h
+ * when adding new flags.
+ */
+#define TFD_TIMER_ABSTIME (1 << 0)
+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#define TFD_CLOEXEC O_CLOEXEC
+#define TFD_NONBLOCK O_NONBLOCK
+
+#define TFD_IOC_SET_TICKS      _IOW('T', 0, __u64)
+
+#endif /* _UAPI_LINUX_TIMERFD_H */
index acc63697a0cc415357792e922396a9ef296bb01f..b2a31a55a61237e65e4939a9d2722e136cc73ca0 100644 (file)
@@ -93,6 +93,7 @@ struct usb_ext_prop_desc {
  * |   0 | magic     | LE32         | FUNCTIONFS_DESCRIPTORS_MAGIC_V2      |
  * |   4 | length    | LE32         | length of the whole data chunk       |
  * |   8 | flags     | LE32         | combination of functionfs_flags      |
+ * |     | eventfd   | LE32         | eventfd file descriptor              |
  * |     | fs_count  | LE32         | number of full-speed descriptors     |
  * |     | hs_count  | LE32         | number of high-speed descriptors     |
  * |     | ss_count  | LE32         | number of super-speed descriptors    |
index 46e8a2e369f907716337db007dca0aba1f5f7477..45184a2ef66c219c893769dd73bc5c3485a5c814 100644 (file)
@@ -362,8 +362,8 @@ enum v4l2_quantization {
        /*
         * The default for R'G'B' quantization is always full range, except
         * for the BT2020 colorspace. For Y'CbCr the quantization is always
-        * limited range, except for COLORSPACE_JPEG, SRGB, ADOBERGB,
-        * XV601 or XV709: those are full range.
+        * limited range, except for COLORSPACE_JPEG, XV601 or XV709: those
+        * are full range.
         */
        V4L2_QUANTIZATION_DEFAULT     = 0,
        V4L2_QUANTIZATION_FULL_RANGE  = 1,
@@ -379,8 +379,7 @@ enum v4l2_quantization {
        (((is_rgb_or_hsv) && (colsp) == V4L2_COLORSPACE_BT2020) ? \
         V4L2_QUANTIZATION_LIM_RANGE : \
         (((is_rgb_or_hsv) || (ycbcr_enc) == V4L2_YCBCR_ENC_XV601 || \
-         (ycbcr_enc) == V4L2_YCBCR_ENC_XV709 || (colsp) == V4L2_COLORSPACE_JPEG) || \
-         (colsp) == V4L2_COLORSPACE_ADOBERGB || (colsp) == V4L2_COLORSPACE_SRGB ? \
+         (ycbcr_enc) == V4L2_YCBCR_ENC_XV709 || (colsp) == V4L2_COLORSPACE_JPEG) ? \
         V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE))
 
 enum v4l2_priority {
index 82bdf5626859989085f831ee3a3a70c1b26ff066..bb68cb1b04ed3893faccac5eed815f50521f3813 100644 (file)
@@ -16,3 +16,4 @@ header-y += nes-abi.h
 header-y += ocrdma-abi.h
 header-y += hns-abi.h
 header-y += vmw_pvrdma-abi.h
+header-y += qedr-abi.h
index 48a19bda071b8db5396991dcd97cd9e0f3872ecf..d24eee12128fc5cb7d1f5612e85a7fb9b194520f 100644 (file)
@@ -30,7 +30,7 @@
  * SOFTWARE.
  */
 #ifndef CXGB3_ABI_USER_H
-#define CXBG3_ABI_USER_H
+#define CXGB3_ABI_USER_H
 
 #include <linux/types.h>
 
index dfdfe4e92d3118c0ef42b5c5d64f240eba50dee5..f4f87cff6dc6c5fc9f1a91e32c9e8d3a601f10c8 100644 (file)
@@ -37,7 +37,6 @@
 #define IB_USER_VERBS_H
 
 #include <linux/types.h>
-#include <rdma/ib_verbs.h>
 
 /*
  * Increment this value if any changes that break userspace ABI
@@ -548,11 +547,17 @@ enum {
 };
 
 enum {
-       IB_USER_LEGACY_LAST_QP_ATTR_MASK = IB_QP_DEST_QPN
+       /*
+        * This value is equal to IB_QP_DEST_QPN.
+        */
+       IB_USER_LEGACY_LAST_QP_ATTR_MASK = 1ULL << 20,
 };
 
 enum {
-       IB_USER_LAST_QP_ATTR_MASK = IB_QP_RATE_LIMIT
+       /*
+        * This value is equal to IB_QP_RATE_LIMIT.
+        */
+       IB_USER_LAST_QP_ATTR_MASK = 1ULL << 25,
 };
 
 struct ib_uverbs_ex_create_qp {
index 223b734abccdc3b7f3baae457261dd66862fcd1d..4dd8bd232a1d4efd012fab8757887426ece9c0aa 100644 (file)
@@ -1176,6 +1176,10 @@ config CGROUP_DEBUG
 
          Say N.
 
+config SOCK_CGROUP_DATA
+       bool
+       default n
+
 endif # CGROUPS
 
 config CHECKPOINT_RESTORE
@@ -1983,6 +1987,10 @@ config MODVERSIONS
          make them incompatible with the kernel you are running.  If
          unsure, say N.
 
+config MODULE_REL_CRCS
+       bool
+       depends on MODVERSIONS
+
 config MODULE_SRCVERSION_ALL
        bool "Source checksum for all modules"
        help
index e08b948519223e62aca265284483ee7b1ef1420c..3ec5742b5640f5d265ea8f0d9b8f986cf25b8f1c 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1977,7 +1977,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
                }
 
                rcu_read_lock();
-               sem_lock(sma, sops, nsops);
+               locknum = sem_lock(sma, sops, nsops);
 
                if (!ipc_valid_object(&sma->sem_perm))
                        goto out_unlock_free;
index 8b1dde96a0faa1bda645f0e03388f0a47f565bdc..7b44195da81bb25a080b165402b74cf8c7f59bcc 100644 (file)
@@ -231,9 +231,11 @@ static void untag_chunk(struct node *p)
        if (size)
                new = alloc_chunk(size);
 
+       mutex_lock(&entry->group->mark_mutex);
        spin_lock(&entry->lock);
        if (chunk->dead || !entry->inode) {
                spin_unlock(&entry->lock);
+               mutex_unlock(&entry->group->mark_mutex);
                if (new)
                        free_chunk(new);
                goto out;
@@ -251,6 +253,7 @@ static void untag_chunk(struct node *p)
                list_del_rcu(&chunk->hash);
                spin_unlock(&hash_lock);
                spin_unlock(&entry->lock);
+               mutex_unlock(&entry->group->mark_mutex);
                fsnotify_destroy_mark(entry, audit_tree_group);
                goto out;
        }
@@ -258,8 +261,8 @@ static void untag_chunk(struct node *p)
        if (!new)
                goto Fallback;
 
-       fsnotify_duplicate_mark(&new->mark, entry);
-       if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.inode, NULL, 1)) {
+       if (fsnotify_add_mark_locked(&new->mark, entry->group, entry->inode,
+                                    NULL, 1)) {
                fsnotify_put_mark(&new->mark);
                goto Fallback;
        }
@@ -293,6 +296,7 @@ static void untag_chunk(struct node *p)
                owner->root = new;
        spin_unlock(&hash_lock);
        spin_unlock(&entry->lock);
+       mutex_unlock(&entry->group->mark_mutex);
        fsnotify_destroy_mark(entry, audit_tree_group);
        fsnotify_put_mark(&new->mark);  /* drop initial reference */
        goto out;
@@ -309,6 +313,7 @@ Fallback:
        put_tree(owner);
        spin_unlock(&hash_lock);
        spin_unlock(&entry->lock);
+       mutex_unlock(&entry->group->mark_mutex);
 out:
        fsnotify_put_mark(entry);
        spin_lock(&hash_lock);
@@ -386,18 +391,21 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 
        chunk_entry = &chunk->mark;
 
+       mutex_lock(&old_entry->group->mark_mutex);
        spin_lock(&old_entry->lock);
        if (!old_entry->inode) {
                /* old_entry is being shot, lets just lie */
                spin_unlock(&old_entry->lock);
+               mutex_unlock(&old_entry->group->mark_mutex);
                fsnotify_put_mark(old_entry);
                free_chunk(chunk);
                return -ENOENT;
        }
 
-       fsnotify_duplicate_mark(chunk_entry, old_entry);
-       if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->inode, NULL, 1)) {
+       if (fsnotify_add_mark_locked(chunk_entry, old_entry->group,
+                                    old_entry->inode, NULL, 1)) {
                spin_unlock(&old_entry->lock);
+               mutex_unlock(&old_entry->group->mark_mutex);
                fsnotify_put_mark(chunk_entry);
                fsnotify_put_mark(old_entry);
                return -ENOSPC;
@@ -413,6 +421,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
                chunk->dead = 1;
                spin_unlock(&chunk_entry->lock);
                spin_unlock(&old_entry->lock);
+               mutex_unlock(&old_entry->group->mark_mutex);
 
                fsnotify_destroy_mark(chunk_entry, audit_tree_group);
 
@@ -445,6 +454,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
        spin_unlock(&hash_lock);
        spin_unlock(&chunk_entry->lock);
        spin_unlock(&old_entry->lock);
+       mutex_unlock(&old_entry->group->mark_mutex);
        fsnotify_destroy_mark(old_entry, audit_tree_group);
        fsnotify_put_mark(chunk_entry); /* drop initial reference */
        fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */
index a2ac051c342f87b1372a7aeb33ba816327ee1a43..3d55d95dcf49e600fe8f99c92eb57e7cde043208 100644 (file)
@@ -11,7 +11,6 @@
  */
 #include <linux/bpf.h>
 #include <linux/err.h>
-#include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/filter.h>
@@ -56,7 +55,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
            attr->value_size == 0 || attr->map_flags)
                return ERR_PTR(-EINVAL);
 
-       if (attr->value_size >= 1 << (KMALLOC_SHIFT_MAX - 1))
+       if (attr->value_size > KMALLOC_MAX_SIZE)
                /* if value_size is bigger, the user space won't be able to
                 * access the elements.
                 */
@@ -74,14 +73,10 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
        if (array_size >= U32_MAX - PAGE_SIZE)
                return ERR_PTR(-ENOMEM);
 
-
        /* allocate all map elements and zero-initialize them */
-       array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
-       if (!array) {
-               array = vzalloc(array_size);
-               if (!array)
-                       return ERR_PTR(-ENOMEM);
-       }
+       array = bpf_map_area_alloc(array_size);
+       if (!array)
+               return ERR_PTR(-ENOMEM);
 
        /* copy mandatory map attributes */
        array->map.map_type = attr->map_type;
@@ -97,7 +92,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
 
        if (array_size >= U32_MAX - PAGE_SIZE ||
            elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) {
-               kvfree(array);
+               bpf_map_area_free(array);
                return ERR_PTR(-ENOMEM);
        }
 out:
@@ -262,7 +257,7 @@ static void array_map_free(struct bpf_map *map)
        if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
                bpf_array_free_percpu(array);
 
-       kvfree(array);
+       bpf_map_area_free(array);
 }
 
 static const struct bpf_map_ops array_ops = {
@@ -319,7 +314,8 @@ static void fd_array_map_free(struct bpf_map *map)
        /* make sure it's empty */
        for (i = 0; i < array->map.max_entries; i++)
                BUG_ON(array->ptrs[i] != NULL);
-       kvfree(array);
+
+       bpf_map_area_free(array);
 }
 
 static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
index a515f7b007c61245e7f5397a9d9ab7390a6bd047..da0f53690295610ff5ae447ed98fb6e70c99c4f1 100644 (file)
@@ -52,6 +52,7 @@ void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent)
                e = rcu_dereference_protected(parent->bpf.effective[type],
                                              lockdep_is_held(&cgroup_mutex));
                rcu_assign_pointer(cgrp->bpf.effective[type], e);
+               cgrp->bpf.disallow_override[type] = parent->bpf.disallow_override[type];
        }
 }
 
@@ -82,30 +83,63 @@ void cgroup_bpf_inherit(struct cgroup *cgrp, struct cgroup *parent)
  *
  * Must be called with cgroup_mutex held.
  */
-void __cgroup_bpf_update(struct cgroup *cgrp,
-                        struct cgroup *parent,
-                        struct bpf_prog *prog,
-                        enum bpf_attach_type type)
+int __cgroup_bpf_update(struct cgroup *cgrp, struct cgroup *parent,
+                       struct bpf_prog *prog, enum bpf_attach_type type,
+                       bool new_overridable)
 {
-       struct bpf_prog *old_prog, *effective;
+       struct bpf_prog *old_prog, *effective = NULL;
        struct cgroup_subsys_state *pos;
+       bool overridable = true;
 
-       old_prog = xchg(cgrp->bpf.prog + type, prog);
+       if (parent) {
+               overridable = !parent->bpf.disallow_override[type];
+               effective = rcu_dereference_protected(parent->bpf.effective[type],
+                                                     lockdep_is_held(&cgroup_mutex));
+       }
+
+       if (prog && effective && !overridable)
+               /* if parent has non-overridable prog attached, disallow
+                * attaching new programs to descendent cgroup
+                */
+               return -EPERM;
+
+       if (prog && effective && overridable != new_overridable)
+               /* if parent has overridable prog attached, only
+                * allow overridable programs in descendent cgroup
+                */
+               return -EPERM;
 
-       effective = (!prog && parent) ?
-               rcu_dereference_protected(parent->bpf.effective[type],
-                                         lockdep_is_held(&cgroup_mutex)) :
-               prog;
+       old_prog = cgrp->bpf.prog[type];
+
+       if (prog) {
+               overridable = new_overridable;
+               effective = prog;
+               if (old_prog &&
+                   cgrp->bpf.disallow_override[type] == new_overridable)
+                       /* disallow attaching non-overridable on top
+                        * of existing overridable in this cgroup
+                        * and vice versa
+                        */
+                       return -EPERM;
+       }
+
+       if (!prog && !old_prog)
+               /* report error when trying to detach and nothing is attached */
+               return -ENOENT;
+
+       cgrp->bpf.prog[type] = prog;
 
        css_for_each_descendant_pre(pos, &cgrp->self) {
                struct cgroup *desc = container_of(pos, struct cgroup, self);
 
                /* skip the subtree if the descendant has its own program */
-               if (desc->bpf.prog[type] && desc != cgrp)
+               if (desc->bpf.prog[type] && desc != cgrp) {
                        pos = css_rightmost_descendant(pos);
-               else
+               } else {
                        rcu_assign_pointer(desc->bpf.effective[type],
                                           effective);
+                       desc->bpf.disallow_override[type] = !overridable;
+               }
        }
 
        if (prog)
@@ -115,6 +149,7 @@ void __cgroup_bpf_update(struct cgroup *cgrp,
                bpf_prog_put(old_prog);
                static_branch_dec(&cgroup_bpf_enabled_key);
        }
+       return 0;
 }
 
 /**
index 1eb4f1303756164f2893d964198eecd40b0bcd62..503d4211988afe1d3eddd6d39aba520dc4c245ef 100644 (file)
@@ -146,10 +146,11 @@ void __bpf_prog_free(struct bpf_prog *fp)
        vfree(fp);
 }
 
-int bpf_prog_calc_digest(struct bpf_prog *fp)
+int bpf_prog_calc_tag(struct bpf_prog *fp)
 {
        const u32 bits_offset = SHA_MESSAGE_BYTES - sizeof(__be64);
-       u32 raw_size = bpf_prog_digest_scratch_size(fp);
+       u32 raw_size = bpf_prog_tag_scratch_size(fp);
+       u32 digest[SHA_DIGEST_WORDS];
        u32 ws[SHA_WORKSPACE_WORDS];
        u32 i, bsize, psize, blocks;
        struct bpf_insn *dst;
@@ -162,7 +163,7 @@ int bpf_prog_calc_digest(struct bpf_prog *fp)
        if (!raw)
                return -ENOMEM;
 
-       sha_init(fp->digest);
+       sha_init(digest);
        memset(ws, 0, sizeof(ws));
 
        /* We need to take out the map fd for the digest calculation
@@ -204,13 +205,14 @@ int bpf_prog_calc_digest(struct bpf_prog *fp)
        *bits = cpu_to_be64((psize - 1) << 3);
 
        while (blocks--) {
-               sha_transform(fp->digest, todo, ws);
+               sha_transform(digest, todo, ws);
                todo += SHA_MESSAGE_BYTES;
        }
 
-       result = (__force __be32 *)fp->digest;
+       result = (__force __be32 *)digest;
        for (i = 0; i < SHA_DIGEST_WORDS; i++)
-               result[i] = cpu_to_be32(fp->digest[i]);
+               result[i] = cpu_to_be32(digest[i]);
+       memcpy(fp->tag, result, sizeof(fp->tag));
 
        vfree(raw);
        return 0;
index 34debc1a9641875382b6603820f3e85c4a18dffc..a753bbe7df0a1747658ca75325e28880173613f8 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/bpf.h>
 #include <linux/jhash.h>
 #include <linux/filter.h>
-#include <linux/vmalloc.h>
 #include "percpu_freelist.h"
 #include "bpf_lru_list.h"
 
@@ -103,7 +102,7 @@ static void htab_free_elems(struct bpf_htab *htab)
                free_percpu(pptr);
        }
 free_elems:
-       vfree(htab->elems);
+       bpf_map_area_free(htab->elems);
 }
 
 static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
@@ -125,7 +124,8 @@ static int prealloc_init(struct bpf_htab *htab)
 {
        int err = -ENOMEM, i;
 
-       htab->elems = vzalloc(htab->elem_size * htab->map.max_entries);
+       htab->elems = bpf_map_area_alloc(htab->elem_size *
+                                        htab->map.max_entries);
        if (!htab->elems)
                return -ENOMEM;
 
@@ -274,7 +274,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
                 */
                goto free_htab;
 
-       if (htab->map.value_size >= (1 << (KMALLOC_SHIFT_MAX - 1)) -
+       if (htab->map.value_size >= KMALLOC_MAX_SIZE -
            MAX_BPF_STACK - sizeof(struct htab_elem))
                /* if value_size is bigger, the user space won't be able to
                 * access the elements via bpf syscall. This check also makes
@@ -320,14 +320,10 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
                goto free_htab;
 
        err = -ENOMEM;
-       htab->buckets = kmalloc_array(htab->n_buckets, sizeof(struct bucket),
-                                     GFP_USER | __GFP_NOWARN);
-
-       if (!htab->buckets) {
-               htab->buckets = vmalloc(htab->n_buckets * sizeof(struct bucket));
-               if (!htab->buckets)
-                       goto free_htab;
-       }
+       htab->buckets = bpf_map_area_alloc(htab->n_buckets *
+                                          sizeof(struct bucket));
+       if (!htab->buckets)
+               goto free_htab;
 
        for (i = 0; i < htab->n_buckets; i++) {
                INIT_HLIST_HEAD(&htab->buckets[i].head);
@@ -354,7 +350,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
 free_extra_elems:
        free_percpu(htab->extra_elems);
 free_buckets:
-       kvfree(htab->buckets);
+       bpf_map_area_free(htab->buckets);
 free_htab:
        kfree(htab);
        return ERR_PTR(err);
@@ -1014,7 +1010,7 @@ static void htab_map_free(struct bpf_map *map)
                prealloc_destroy(htab);
 
        free_percpu(htab->extra_elems);
-       kvfree(htab->buckets);
+       bpf_map_area_free(htab->buckets);
        kfree(htab);
 }
 
index 732ae16d12b720e6be3c16b8922b7138e14d08dd..be8519148c255efb92704b5e3b0de102ac4c209c 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/bpf.h>
 #include <linux/jhash.h>
 #include <linux/filter.h>
-#include <linux/vmalloc.h>
 #include <linux/stacktrace.h>
 #include <linux/perf_event.h>
 #include "percpu_freelist.h"
@@ -32,7 +31,7 @@ static int prealloc_elems_and_freelist(struct bpf_stack_map *smap)
        u32 elem_size = sizeof(struct stack_map_bucket) + smap->map.value_size;
        int err;
 
-       smap->elems = vzalloc(elem_size * smap->map.max_entries);
+       smap->elems = bpf_map_area_alloc(elem_size * smap->map.max_entries);
        if (!smap->elems)
                return -ENOMEM;
 
@@ -45,7 +44,7 @@ static int prealloc_elems_and_freelist(struct bpf_stack_map *smap)
        return 0;
 
 free_elems:
-       vfree(smap->elems);
+       bpf_map_area_free(smap->elems);
        return err;
 }
 
@@ -76,12 +75,9 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
        if (cost >= U32_MAX - PAGE_SIZE)
                return ERR_PTR(-E2BIG);
 
-       smap = kzalloc(cost, GFP_USER | __GFP_NOWARN);
-       if (!smap) {
-               smap = vzalloc(cost);
-               if (!smap)
-                       return ERR_PTR(-ENOMEM);
-       }
+       smap = bpf_map_area_alloc(cost);
+       if (!smap)
+               return ERR_PTR(-ENOMEM);
 
        err = -E2BIG;
        cost += n_buckets * (value_size + sizeof(struct stack_map_bucket));
@@ -112,7 +108,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
 put_buffers:
        put_callchain_buffers();
 free_smap:
-       kvfree(smap);
+       bpf_map_area_free(smap);
        return ERR_PTR(err);
 }
 
@@ -262,9 +258,9 @@ static void stack_map_free(struct bpf_map *map)
        /* wait for bpf programs to complete before freeing stack map */
        synchronize_rcu();
 
-       vfree(smap->elems);
+       bpf_map_area_free(smap->elems);
        pcpu_freelist_destroy(&smap->freelist);
-       kvfree(smap);
+       bpf_map_area_free(smap);
        put_callchain_buffers();
 }
 
index e89acea22ecfc9a625de1924b2e4f997d88d158b..bbb016adbaeb61c5d46a525f3e7235d11535335e 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/bpf.h>
 #include <linux/syscalls.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mmzone.h>
 #include <linux/anon_inodes.h>
 #include <linux/file.h>
 #include <linux/license.h>
@@ -49,6 +51,30 @@ void bpf_register_map_type(struct bpf_map_type_list *tl)
        list_add(&tl->list_node, &bpf_map_types);
 }
 
+void *bpf_map_area_alloc(size_t size)
+{
+       /* We definitely need __GFP_NORETRY, so OOM killer doesn't
+        * trigger under memory pressure as we really just want to
+        * fail instead.
+        */
+       const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
+       void *area;
+
+       if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+               area = kmalloc(size, GFP_USER | flags);
+               if (area != NULL)
+                       return area;
+       }
+
+       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
+                        PAGE_KERNEL);
+}
+
+void bpf_map_area_free(void *area)
+{
+       kvfree(area);
+}
+
 int bpf_map_precharge_memlock(u32 pages)
 {
        struct user_struct *user = get_current_user();
@@ -688,17 +714,17 @@ static int bpf_prog_release(struct inode *inode, struct file *filp)
 static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
 {
        const struct bpf_prog *prog = filp->private_data;
-       char prog_digest[sizeof(prog->digest) * 2 + 1] = { };
+       char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
 
-       bin2hex(prog_digest, prog->digest, sizeof(prog->digest));
+       bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
        seq_printf(m,
                   "prog_type:\t%u\n"
                   "prog_jited:\t%u\n"
-                  "prog_digest:\t%s\n"
+                  "prog_tag:\t%s\n"
                   "memlock:\t%llu\n",
                   prog->type,
                   prog->jited,
-                  prog_digest,
+                  prog_tag,
                   prog->pages * 1ULL << PAGE_SHIFT);
 }
 #endif
@@ -894,13 +920,14 @@ static int bpf_obj_get(const union bpf_attr *attr)
 
 #ifdef CONFIG_CGROUP_BPF
 
-#define BPF_PROG_ATTACH_LAST_FIELD attach_type
+#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
 
 static int bpf_prog_attach(const union bpf_attr *attr)
 {
+       enum bpf_prog_type ptype;
        struct bpf_prog *prog;
        struct cgroup *cgrp;
-       enum bpf_prog_type ptype;
+       int ret;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -908,6 +935,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
        if (CHECK_ATTR(BPF_PROG_ATTACH))
                return -EINVAL;
 
+       if (attr->attach_flags & ~BPF_F_ALLOW_OVERRIDE)
+               return -EINVAL;
+
        switch (attr->attach_type) {
        case BPF_CGROUP_INET_INGRESS:
        case BPF_CGROUP_INET_EGRESS:
@@ -930,10 +960,13 @@ static int bpf_prog_attach(const union bpf_attr *attr)
                return PTR_ERR(cgrp);
        }
 
-       cgroup_bpf_update(cgrp, prog, attr->attach_type);
+       ret = cgroup_bpf_update(cgrp, prog, attr->attach_type,
+                               attr->attach_flags & BPF_F_ALLOW_OVERRIDE);
+       if (ret)
+               bpf_prog_put(prog);
        cgroup_put(cgrp);
 
-       return 0;
+       return ret;
 }
 
 #define BPF_PROG_DETACH_LAST_FIELD attach_type
@@ -941,6 +974,7 @@ static int bpf_prog_attach(const union bpf_attr *attr)
 static int bpf_prog_detach(const union bpf_attr *attr)
 {
        struct cgroup *cgrp;
+       int ret;
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -956,7 +990,7 @@ static int bpf_prog_detach(const union bpf_attr *attr)
                if (IS_ERR(cgrp))
                        return PTR_ERR(cgrp);
 
-               cgroup_bpf_update(cgrp, NULL, attr->attach_type);
+               ret = cgroup_bpf_update(cgrp, NULL, attr->attach_type, false);
                cgroup_put(cgrp);
                break;
 
@@ -964,7 +998,7 @@ static int bpf_prog_detach(const union bpf_attr *attr)
                return -EINVAL;
        }
 
-       return 0;
+       return ret;
 }
 #endif /* CONFIG_CGROUP_BPF */
 
index 83ed2f8f6f228b1ae90f66d89e436b71a5c6a27c..cdc43b899f281ebd01dd8cf8110e6fb966c2a1fa 100644 (file)
@@ -2936,7 +2936,7 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
        int insn_cnt = env->prog->len;
        int i, j, err;
 
-       err = bpf_prog_calc_digest(env->prog);
+       err = bpf_prog_calc_tag(env->prog);
        if (err)
                return err;
 
index a98e814f216f9c54f878bcfca32e4747be357c07..f97fe77ceb88aa39ff3bd01f497586f778c052a2 100644 (file)
@@ -318,6 +318,7 @@ bool has_capability(struct task_struct *t, int cap)
 {
        return has_ns_capability(t, &init_user_ns, cap);
 }
+EXPORT_SYMBOL(has_capability);
 
 /**
  * has_ns_capability_noaudit - Does a task have a capability (unaudited)
index 2ee9ec3051b20774b118a57e4609f30e87bf82be..53bbca7c48598e44fa5e45f88626027749ca8932 100644 (file)
@@ -5221,6 +5221,11 @@ err_free_css:
        return ERR_PTR(err);
 }
 
+/*
+ * The returned cgroup is fully initialized including its control mask, but
+ * it isn't associated with its kernfs_node and doesn't have the control
+ * mask applied.
+ */
 static struct cgroup *cgroup_create(struct cgroup *parent)
 {
        struct cgroup_root *root = parent->root;
@@ -5288,11 +5293,6 @@ static struct cgroup *cgroup_create(struct cgroup *parent)
 
        cgroup_propagate_control(cgrp);
 
-       /* @cgrp doesn't have dir yet so the following will only create csses */
-       ret = cgroup_apply_control_enable(cgrp);
-       if (ret)
-               goto out_destroy;
-
        return cgrp;
 
 out_cancel_ref:
@@ -5300,9 +5300,6 @@ out_cancel_ref:
 out_free_cgrp:
        kfree(cgrp);
        return ERR_PTR(ret);
-out_destroy:
-       cgroup_destroy_locked(cgrp);
-       return ERR_PTR(ret);
 }
 
 static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
@@ -6501,15 +6498,16 @@ static __init int cgroup_namespaces_init(void)
 subsys_initcall(cgroup_namespaces_init);
 
 #ifdef CONFIG_CGROUP_BPF
-void cgroup_bpf_update(struct cgroup *cgrp,
-                      struct bpf_prog *prog,
-                      enum bpf_attach_type type)
+int cgroup_bpf_update(struct cgroup *cgrp, struct bpf_prog *prog,
+                     enum bpf_attach_type type, bool overridable)
 {
        struct cgroup *parent = cgroup_parent(cgrp);
+       int ret;
 
        mutex_lock(&cgroup_mutex);
-       __cgroup_bpf_update(cgrp, parent, prog, type);
+       ret = __cgroup_bpf_update(cgrp, parent, prog, type, overridable);
        mutex_unlock(&cgroup_mutex);
+       return ret;
 }
 #endif /* CONFIG_CGROUP_BPF */
 
index f75c4d031eeb2152c75182466dbf5ec97e93c008..0a5f630f5c5430c231b2ba8ccb7d671bca09014e 100644 (file)
@@ -764,7 +764,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
 {
        struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
        int prev_state, ret = 0;
-       bool hasdied = false;
 
        if (num_online_cpus() == 1)
                return -EBUSY;
@@ -809,7 +808,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
                cpuhp_kick_ap_work(cpu);
        }
 
-       hasdied = prev_state != st->state && st->state == CPUHP_OFFLINE;
 out:
        cpu_hotplug_done();
        return ret;
@@ -1302,10 +1300,24 @@ static int cpuhp_cb_check(enum cpuhp_state state)
  */
 static int cpuhp_reserve_state(enum cpuhp_state state)
 {
-       enum cpuhp_state i;
+       enum cpuhp_state i, end;
+       struct cpuhp_step *step;
 
-       for (i = CPUHP_AP_ONLINE_DYN; i <= CPUHP_AP_ONLINE_DYN_END; i++) {
-               if (!cpuhp_ap_states[i].name)
+       switch (state) {
+       case CPUHP_AP_ONLINE_DYN:
+               step = cpuhp_ap_states + CPUHP_AP_ONLINE_DYN;
+               end = CPUHP_AP_ONLINE_DYN_END;
+               break;
+       case CPUHP_BP_PREPARE_DYN:
+               step = cpuhp_bp_states + CPUHP_BP_PREPARE_DYN;
+               end = CPUHP_BP_PREPARE_DYN_END;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (i = state; i <= end; i++, step++) {
+               if (!step->name)
                        return i;
        }
        WARN(1, "No more dynamic states available for CPU hotplug\n");
@@ -1323,7 +1335,7 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
 
        mutex_lock(&cpuhp_state_mutex);
 
-       if (state == CPUHP_AP_ONLINE_DYN) {
+       if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
                ret = cpuhp_reserve_state(state);
                if (ret < 0)
                        goto out;
index ab15509fab8c0659c3f422036f5649718a9e4437..e235bb991bdd8fd0d1c7bef06c2f3b3dcaa4ddaf 100644 (file)
@@ -1469,7 +1469,6 @@ ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
 static void
 list_add_event(struct perf_event *event, struct perf_event_context *ctx)
 {
-
        lockdep_assert_held(&ctx->lock);
 
        WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT);
@@ -1624,6 +1623,8 @@ static void perf_group_attach(struct perf_event *event)
 {
        struct perf_event *group_leader = event->group_leader, *pos;
 
+       lockdep_assert_held(&event->ctx->lock);
+
        /*
         * We can have double attach due to group movement in perf_event_open.
         */
@@ -1697,6 +1698,8 @@ static void perf_group_detach(struct perf_event *event)
        struct perf_event *sibling, *tmp;
        struct list_head *list = NULL;
 
+       lockdep_assert_held(&event->ctx->lock);
+
        /*
         * We can have double detach due to exit/hot-unplug + close.
         */
@@ -1895,9 +1898,29 @@ __perf_remove_from_context(struct perf_event *event,
  */
 static void perf_remove_from_context(struct perf_event *event, unsigned long flags)
 {
-       lockdep_assert_held(&event->ctx->mutex);
+       struct perf_event_context *ctx = event->ctx;
+
+       lockdep_assert_held(&ctx->mutex);
 
        event_function_call(event, __perf_remove_from_context, (void *)flags);
+
+       /*
+        * The above event_function_call() can NO-OP when it hits
+        * TASK_TOMBSTONE. In that case we must already have been detached
+        * from the context (by perf_event_exit_event()) but the grouping
+        * might still be in-tact.
+        */
+       WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT);
+       if ((flags & DETACH_GROUP) &&
+           (event->attach_state & PERF_ATTACH_GROUP)) {
+               /*
+                * Since in that case we cannot possibly be scheduled, simply
+                * detach now.
+                */
+               raw_spin_lock_irq(&ctx->lock);
+               perf_group_detach(event);
+               raw_spin_unlock_irq(&ctx->lock);
+       }
 }
 
 /*
@@ -2249,7 +2272,7 @@ static int  __perf_install_in_context(void *info)
        struct perf_event_context *ctx = event->ctx;
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
        struct perf_event_context *task_ctx = cpuctx->task_ctx;
-       bool activate = true;
+       bool reprogram = true;
        int ret = 0;
 
        raw_spin_lock(&cpuctx->ctx.lock);
@@ -2257,27 +2280,26 @@ static int  __perf_install_in_context(void *info)
                raw_spin_lock(&ctx->lock);
                task_ctx = ctx;
 
-               /* If we're on the wrong CPU, try again */
-               if (task_cpu(ctx->task) != smp_processor_id()) {
-                       ret = -ESRCH;
-                       goto unlock;
-               }
+               reprogram = (ctx->task == current);
 
                /*
-                * If we're on the right CPU, see if the task we target is
-                * current, if not we don't have to activate the ctx, a future
-                * context switch will do that for us.
+                * If the task is running, it must be running on this CPU,
+                * otherwise we cannot reprogram things.
+                *
+                * If its not running, we don't care, ctx->lock will
+                * serialize against it becoming runnable.
                 */
-               if (ctx->task != current)
-                       activate = false;
-               else
-                       WARN_ON_ONCE(cpuctx->task_ctx && cpuctx->task_ctx != ctx);
+               if (task_curr(ctx->task) && !reprogram) {
+                       ret = -ESRCH;
+                       goto unlock;
+               }
 
+               WARN_ON_ONCE(reprogram && cpuctx->task_ctx && cpuctx->task_ctx != ctx);
        } else if (task_ctx) {
                raw_spin_lock(&task_ctx->lock);
        }
 
-       if (activate) {
+       if (reprogram) {
                ctx_sched_out(ctx, cpuctx, EVENT_TIME);
                add_event_to_ctx(event, ctx);
                ctx_resched(cpuctx, task_ctx);
@@ -2328,13 +2350,36 @@ perf_install_in_context(struct perf_event_context *ctx,
        /*
         * Installing events is tricky because we cannot rely on ctx->is_active
         * to be set in case this is the nr_events 0 -> 1 transition.
+        *
+        * Instead we use task_curr(), which tells us if the task is running.
+        * However, since we use task_curr() outside of rq::lock, we can race
+        * against the actual state. This means the result can be wrong.
+        *
+        * If we get a false positive, we retry, this is harmless.
+        *
+        * If we get a false negative, things are complicated. If we are after
+        * perf_event_context_sched_in() ctx::lock will serialize us, and the
+        * value must be correct. If we're before, it doesn't matter since
+        * perf_event_context_sched_in() will program the counter.
+        *
+        * However, this hinges on the remote context switch having observed
+        * our task->perf_event_ctxp[] store, such that it will in fact take
+        * ctx::lock in perf_event_context_sched_in().
+        *
+        * We do this by task_function_call(), if the IPI fails to hit the task
+        * we know any future context switch of task must see the
+        * perf_event_ctpx[] store.
         */
-again:
+
        /*
-        * Cannot use task_function_call() because we need to run on the task's
-        * CPU regardless of whether its current or not.
+        * This smp_mb() orders the task->perf_event_ctxp[] store with the
+        * task_cpu() load, such that if the IPI then does not find the task
+        * running, a future context switch of that task must observe the
+        * store.
         */
-       if (!cpu_function_call(task_cpu(task), __perf_install_in_context, event))
+       smp_mb();
+again:
+       if (!task_function_call(task, __perf_install_in_context, event))
                return;
 
        raw_spin_lock_irq(&ctx->lock);
@@ -2348,12 +2393,16 @@ again:
                raw_spin_unlock_irq(&ctx->lock);
                return;
        }
-       raw_spin_unlock_irq(&ctx->lock);
        /*
-        * Since !ctx->is_active doesn't mean anything, we must IPI
-        * unconditionally.
+        * If the task is not running, ctx->lock will avoid it becoming so,
+        * thus we can safely install the event.
         */
-       goto again;
+       if (task_curr(task)) {
+               raw_spin_unlock_irq(&ctx->lock);
+               goto again;
+       }
+       add_event_to_ctx(event, ctx);
+       raw_spin_unlock_irq(&ctx->lock);
 }
 
 /*
@@ -3438,14 +3487,15 @@ struct perf_read_data {
        int ret;
 };
 
-static int find_cpu_to_read(struct perf_event *event, int local_cpu)
+static int __perf_event_read_cpu(struct perf_event *event, int event_cpu)
 {
-       int event_cpu = event->oncpu;
        u16 local_pkg, event_pkg;
 
        if (event->group_caps & PERF_EV_CAP_READ_ACTIVE_PKG) {
-               event_pkg =  topology_physical_package_id(event_cpu);
-               local_pkg =  topology_physical_package_id(local_cpu);
+               int local_cpu = smp_processor_id();
+
+               event_pkg = topology_physical_package_id(event_cpu);
+               local_pkg = topology_physical_package_id(local_cpu);
 
                if (event_pkg == local_pkg)
                        return local_cpu;
@@ -3575,7 +3625,7 @@ u64 perf_event_read_local(struct perf_event *event)
 
 static int perf_event_read(struct perf_event *event, bool group)
 {
-       int ret = 0, cpu_to_read, local_cpu;
+       int event_cpu, ret = 0;
 
        /*
         * If event is enabled and currently active on a CPU, update the
@@ -3588,21 +3638,25 @@ static int perf_event_read(struct perf_event *event, bool group)
                        .ret = 0,
                };
 
-               local_cpu = get_cpu();
-               cpu_to_read = find_cpu_to_read(event, local_cpu);
-               put_cpu();
+               event_cpu = READ_ONCE(event->oncpu);
+               if ((unsigned)event_cpu >= nr_cpu_ids)
+                       return 0;
+
+               preempt_disable();
+               event_cpu = __perf_event_read_cpu(event, event_cpu);
 
                /*
                 * Purposely ignore the smp_call_function_single() return
                 * value.
                 *
-                * If event->oncpu isn't a valid CPU it means the event got
+                * If event_cpu isn't a valid CPU it means the event got
                 * scheduled out and that will have updated the event count.
                 *
                 * Therefore, either way, we'll have an up-to-date event count
                 * after this.
                 */
-               (void)smp_call_function_single(cpu_to_read, __perf_event_read, &data, 1);
+               (void)smp_call_function_single(event_cpu, __perf_event_read, &data, 1);
+               preempt_enable();
                ret = data.ret;
        } else if (event->state == PERF_EVENT_STATE_INACTIVE) {
                struct perf_event_context *ctx = event->ctx;
@@ -6583,6 +6637,27 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
        char *buf = NULL;
        char *name;
 
+       if (vma->vm_flags & VM_READ)
+               prot |= PROT_READ;
+       if (vma->vm_flags & VM_WRITE)
+               prot |= PROT_WRITE;
+       if (vma->vm_flags & VM_EXEC)
+               prot |= PROT_EXEC;
+
+       if (vma->vm_flags & VM_MAYSHARE)
+               flags = MAP_SHARED;
+       else
+               flags = MAP_PRIVATE;
+
+       if (vma->vm_flags & VM_DENYWRITE)
+               flags |= MAP_DENYWRITE;
+       if (vma->vm_flags & VM_MAYEXEC)
+               flags |= MAP_EXECUTABLE;
+       if (vma->vm_flags & VM_LOCKED)
+               flags |= MAP_LOCKED;
+       if (vma->vm_flags & VM_HUGETLB)
+               flags |= MAP_HUGETLB;
+
        if (file) {
                struct inode *inode;
                dev_t dev;
@@ -6609,27 +6684,6 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
                maj = MAJOR(dev);
                min = MINOR(dev);
 
-               if (vma->vm_flags & VM_READ)
-                       prot |= PROT_READ;
-               if (vma->vm_flags & VM_WRITE)
-                       prot |= PROT_WRITE;
-               if (vma->vm_flags & VM_EXEC)
-                       prot |= PROT_EXEC;
-
-               if (vma->vm_flags & VM_MAYSHARE)
-                       flags = MAP_SHARED;
-               else
-                       flags = MAP_PRIVATE;
-
-               if (vma->vm_flags & VM_DENYWRITE)
-                       flags |= MAP_DENYWRITE;
-               if (vma->vm_flags & VM_MAYEXEC)
-                       flags |= MAP_EXECUTABLE;
-               if (vma->vm_flags & VM_LOCKED)
-                       flags |= MAP_LOCKED;
-               if (vma->vm_flags & VM_HUGETLB)
-                       flags |= MAP_HUGETLB;
-
                goto got_name;
        } else {
                if (vma->vm_ops && vma->vm_ops->name) {
@@ -7034,25 +7088,12 @@ static void perf_log_itrace_start(struct perf_event *event)
        perf_output_end(&handle);
 }
 
-/*
- * Generic event overflow handling, sampling.
- */
-
-static int __perf_event_overflow(struct perf_event *event,
-                                  int throttle, struct perf_sample_data *data,
-                                  struct pt_regs *regs)
+static int
+__perf_event_account_interrupt(struct perf_event *event, int throttle)
 {
-       int events = atomic_read(&event->event_limit);
        struct hw_perf_event *hwc = &event->hw;
-       u64 seq;
        int ret = 0;
-
-       /*
-        * Non-sampling counters might still use the PMI to fold short
-        * hardware counters, ignore those.
-        */
-       if (unlikely(!is_sampling_event(event)))
-               return 0;
+       u64 seq;
 
        seq = __this_cpu_read(perf_throttled_seq);
        if (seq != hwc->interrupts_seq) {
@@ -7080,6 +7121,34 @@ static int __perf_event_overflow(struct perf_event *event,
                        perf_adjust_period(event, delta, hwc->last_period, true);
        }
 
+       return ret;
+}
+
+int perf_event_account_interrupt(struct perf_event *event)
+{
+       return __perf_event_account_interrupt(event, 1);
+}
+
+/*
+ * Generic event overflow handling, sampling.
+ */
+
+static int __perf_event_overflow(struct perf_event *event,
+                                  int throttle, struct perf_sample_data *data,
+                                  struct pt_regs *regs)
+{
+       int events = atomic_read(&event->event_limit);
+       int ret = 0;
+
+       /*
+        * Non-sampling counters might still use the PMI to fold short
+        * hardware counters, ignore those.
+        */
+       if (unlikely(!is_sampling_event(event)))
+               return 0;
+
+       ret = __perf_event_account_interrupt(event, throttle);
+
        /*
         * XXX event_limit might not quite work as expected on inherited
         * events
@@ -9503,6 +9572,37 @@ static int perf_event_set_clock(struct perf_event *event, clockid_t clk_id)
        return 0;
 }
 
+/*
+ * Variation on perf_event_ctx_lock_nested(), except we take two context
+ * mutexes.
+ */
+static struct perf_event_context *
+__perf_event_ctx_lock_double(struct perf_event *group_leader,
+                            struct perf_event_context *ctx)
+{
+       struct perf_event_context *gctx;
+
+again:
+       rcu_read_lock();
+       gctx = READ_ONCE(group_leader->ctx);
+       if (!atomic_inc_not_zero(&gctx->refcount)) {
+               rcu_read_unlock();
+               goto again;
+       }
+       rcu_read_unlock();
+
+       mutex_lock_double(&gctx->mutex, &ctx->mutex);
+
+       if (group_leader->ctx != gctx) {
+               mutex_unlock(&ctx->mutex);
+               mutex_unlock(&gctx->mutex);
+               put_ctx(gctx);
+               goto again;
+       }
+
+       return gctx;
+}
+
 /**
  * sys_perf_event_open - open a performance event, associate it to a task/cpu
  *
@@ -9746,12 +9846,31 @@ SYSCALL_DEFINE5(perf_event_open,
        }
 
        if (move_group) {
-               gctx = group_leader->ctx;
-               mutex_lock_double(&gctx->mutex, &ctx->mutex);
+               gctx = __perf_event_ctx_lock_double(group_leader, ctx);
+
                if (gctx->task == TASK_TOMBSTONE) {
                        err = -ESRCH;
                        goto err_locked;
                }
+
+               /*
+                * Check if we raced against another sys_perf_event_open() call
+                * moving the software group underneath us.
+                */
+               if (!(group_leader->group_caps & PERF_EV_CAP_SOFTWARE)) {
+                       /*
+                        * If someone moved the group out from under us, check
+                        * if this new event wound up on the same ctx, if so
+                        * its the regular !move_group case, otherwise fail.
+                        */
+                       if (gctx != ctx) {
+                               err = -EINVAL;
+                               goto err_locked;
+                       } else {
+                               perf_event_ctx_unlock(group_leader, gctx);
+                               move_group = 0;
+                       }
+               }
        } else {
                mutex_lock(&ctx->mutex);
        }
@@ -9853,7 +9972,7 @@ SYSCALL_DEFINE5(perf_event_open,
        perf_unpin_context(ctx);
 
        if (move_group)
-               mutex_unlock(&gctx->mutex);
+               perf_event_ctx_unlock(group_leader, gctx);
        mutex_unlock(&ctx->mutex);
 
        if (task) {
@@ -9879,7 +9998,7 @@ SYSCALL_DEFINE5(perf_event_open,
 
 err_locked:
        if (move_group)
-               mutex_unlock(&gctx->mutex);
+               perf_event_ctx_unlock(group_leader, gctx);
        mutex_unlock(&ctx->mutex);
 /* err_file: */
        fput(event_file);
index 0842c8ca534b6c7760b254163d88f58cb1229b12..cdf3650361414e39e97018012871579c1eda76f6 100644 (file)
@@ -3323,4 +3323,4 @@ static int __init futex_init(void)
 
        return 0;
 }
-__initcall(futex_init);
+core_initcall(futex_init);
index 8c0a0ae43521c7f8b9e97964912cc3ab5e10fd15..b59e6768c5e94ad831e78b539437cfd99576e780 100644 (file)
@@ -1346,6 +1346,30 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain,
 }
 EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent);
 
+static void __irq_domain_activate_irq(struct irq_data *irq_data)
+{
+       if (irq_data && irq_data->domain) {
+               struct irq_domain *domain = irq_data->domain;
+
+               if (irq_data->parent_data)
+                       __irq_domain_activate_irq(irq_data->parent_data);
+               if (domain->ops->activate)
+                       domain->ops->activate(domain, irq_data);
+       }
+}
+
+static void __irq_domain_deactivate_irq(struct irq_data *irq_data)
+{
+       if (irq_data && irq_data->domain) {
+               struct irq_domain *domain = irq_data->domain;
+
+               if (domain->ops->deactivate)
+                       domain->ops->deactivate(domain, irq_data);
+               if (irq_data->parent_data)
+                       __irq_domain_deactivate_irq(irq_data->parent_data);
+       }
+}
+
 /**
  * irq_domain_activate_irq - Call domain_ops->activate recursively to activate
  *                          interrupt
@@ -1356,13 +1380,9 @@ EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent);
  */
 void irq_domain_activate_irq(struct irq_data *irq_data)
 {
-       if (irq_data && irq_data->domain) {
-               struct irq_domain *domain = irq_data->domain;
-
-               if (irq_data->parent_data)
-                       irq_domain_activate_irq(irq_data->parent_data);
-               if (domain->ops->activate)
-                       domain->ops->activate(domain, irq_data);
+       if (!irqd_is_activated(irq_data)) {
+               __irq_domain_activate_irq(irq_data);
+               irqd_set_activated(irq_data);
        }
 }
 
@@ -1376,13 +1396,9 @@ void irq_domain_activate_irq(struct irq_data *irq_data)
  */
 void irq_domain_deactivate_irq(struct irq_data *irq_data)
 {
-       if (irq_data && irq_data->domain) {
-               struct irq_domain *domain = irq_data->domain;
-
-               if (domain->ops->deactivate)
-                       domain->ops->deactivate(domain, irq_data);
-               if (irq_data->parent_data)
-                       irq_domain_deactivate_irq(irq_data->parent_data);
+       if (irqd_is_activated(irq_data)) {
+               __irq_domain_deactivate_irq(irq_data);
+               irqd_clr_activated(irq_data);
        }
 }
 
index 93ad6c1fb9b6212e706eb3ae08f7b881192008ec..a9b8cf50059151c17f63d35cf4c622ae8b72f131 100644 (file)
@@ -182,6 +182,13 @@ void static_key_slow_dec_deferred(struct static_key_deferred *key)
 }
 EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred);
 
+void static_key_deferred_flush(struct static_key_deferred *key)
+{
+       STATIC_KEY_CHECK_USE();
+       flush_delayed_work(&key->work);
+}
+EXPORT_SYMBOL_GPL(static_key_deferred_flush);
+
 void jump_label_rate_limit(struct static_key_deferred *key,
                unsigned long rl)
 {
index b501e390bb34403c11d6ae09c31ea9fcb769ea8e..9ecedc28b928debb6a5988a5db8b76833133d9e4 100644 (file)
@@ -246,7 +246,9 @@ static void devm_memremap_pages_release(struct device *dev, void *data)
        /* pages are dead and unused, undo the arch mapping */
        align_start = res->start & ~(SECTION_SIZE - 1);
        align_size = ALIGN(resource_size(res), SECTION_SIZE);
+       mem_hotplug_begin();
        arch_remove_memory(align_start, align_size);
+       mem_hotplug_done();
        untrack_pfn(NULL, PHYS_PFN(align_start), align_size);
        pgmap_radix_release(res);
        dev_WARN_ONCE(dev, pgmap->altmap && pgmap->altmap->alloc,
@@ -358,7 +360,9 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
        if (error)
                goto err_pfn_remap;
 
+       mem_hotplug_begin();
        error = arch_add_memory(nid, align_start, align_size, true);
+       mem_hotplug_done();
        if (error)
                goto err_add_memory;
 
index 5088784c0cf9e97c166b7dc06afed9d1c7709d2e..3d8f126208e3ae04eeff3fd1b1e00044c0e3d0d2 100644 (file)
@@ -389,16 +389,16 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
 extern const struct kernel_symbol __stop___ksymtab_gpl[];
 extern const struct kernel_symbol __start___ksymtab_gpl_future[];
 extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
-extern const unsigned long __start___kcrctab[];
-extern const unsigned long __start___kcrctab_gpl[];
-extern const unsigned long __start___kcrctab_gpl_future[];
+extern const s32 __start___kcrctab[];
+extern const s32 __start___kcrctab_gpl[];
+extern const s32 __start___kcrctab_gpl_future[];
 #ifdef CONFIG_UNUSED_SYMBOLS
 extern const struct kernel_symbol __start___ksymtab_unused[];
 extern const struct kernel_symbol __stop___ksymtab_unused[];
 extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
 extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
-extern const unsigned long __start___kcrctab_unused[];
-extern const unsigned long __start___kcrctab_unused_gpl[];
+extern const s32 __start___kcrctab_unused[];
+extern const s32 __start___kcrctab_unused_gpl[];
 #endif
 
 #ifndef CONFIG_MODVERSIONS
@@ -497,7 +497,7 @@ struct find_symbol_arg {
 
        /* Output */
        struct module *owner;
-       const unsigned long *crc;
+       const s32 *crc;
        const struct kernel_symbol *sym;
 };
 
@@ -563,7 +563,7 @@ static bool find_symbol_in_section(const struct symsearch *syms,
  * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
 const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
-                                       const unsigned long **crc,
+                                       const s32 **crc,
                                        bool gplok,
                                        bool warn)
 {
@@ -1145,7 +1145,7 @@ static size_t module_flags_taint(struct module *mod, char *buf)
 
        for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
                if (taint_flags[i].module && test_bit(i, &mod->taints))
-                       buf[l++] = taint_flags[i].true;
+                       buf[l++] = taint_flags[i].c_true;
        }
 
        return l;
@@ -1249,23 +1249,17 @@ static int try_to_force_load(struct module *mod, const char *reason)
 }
 
 #ifdef CONFIG_MODVERSIONS
-/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
-static unsigned long maybe_relocated(unsigned long crc,
-                                    const struct module *crc_owner)
+
+static u32 resolve_rel_crc(const s32 *crc)
 {
-#ifdef ARCH_RELOCATES_KCRCTAB
-       if (crc_owner == NULL)
-               return crc - (unsigned long)reloc_start;
-#endif
-       return crc;
+       return *(u32 *)((void *)crc + *crc);
 }
 
 static int check_version(Elf_Shdr *sechdrs,
                         unsigned int versindex,
                         const char *symname,
                         struct module *mod,
-                        const unsigned long *crc,
-                        const struct module *crc_owner)
+                        const s32 *crc)
 {
        unsigned int i, num_versions;
        struct modversion_info *versions;
@@ -1283,13 +1277,19 @@ static int check_version(Elf_Shdr *sechdrs,
                / sizeof(struct modversion_info);
 
        for (i = 0; i < num_versions; i++) {
+               u32 crcval;
+
                if (strcmp(versions[i].name, symname) != 0)
                        continue;
 
-               if (versions[i].crc == maybe_relocated(*crc, crc_owner))
+               if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
+                       crcval = resolve_rel_crc(crc);
+               else
+                       crcval = *crc;
+               if (versions[i].crc == crcval)
                        return 1;
-               pr_debug("Found checksum %lX vs module %lX\n",
-                      maybe_relocated(*crc, crc_owner), versions[i].crc);
+               pr_debug("Found checksum %X vs module %lX\n",
+                        crcval, versions[i].crc);
                goto bad_version;
        }
 
@@ -1307,7 +1307,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
                                          unsigned int versindex,
                                          struct module *mod)
 {
-       const unsigned long *crc;
+       const s32 *crc;
 
        /*
         * Since this should be found in kernel (which can't be removed), no
@@ -1321,8 +1321,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
        }
        preempt_enable();
        return check_version(sechdrs, versindex,
-                            VMLINUX_SYMBOL_STR(module_layout), mod, crc,
-                            NULL);
+                            VMLINUX_SYMBOL_STR(module_layout), mod, crc);
 }
 
 /* First part is kernel version, which we ignore if module has crcs. */
@@ -1340,8 +1339,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
                                unsigned int versindex,
                                const char *symname,
                                struct module *mod,
-                               const unsigned long *crc,
-                               const struct module *crc_owner)
+                               const s32 *crc)
 {
        return 1;
 }
@@ -1368,7 +1366,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
 {
        struct module *owner;
        const struct kernel_symbol *sym;
-       const unsigned long *crc;
+       const s32 *crc;
        int err;
 
        /*
@@ -1383,8 +1381,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
        if (!sym)
                goto unlock;
 
-       if (!check_version(info->sechdrs, info->index.vers, name, mod, crc,
-                          owner)) {
+       if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) {
                sym = ERR_PTR(-EINVAL);
                goto getname;
        }
index c51edaa04fce389bfcf5a62e59fe7a76bf853c6f..08aa88dde7de806d4cb2b14fd93e87be8dd94501 100644 (file)
@@ -249,7 +249,7 @@ void panic(const char *fmt, ...)
                 * Delay timeout seconds before rebooting the machine.
                 * We can't use the "normal" timers since we just panicked.
                 */
-               pr_emerg("Rebooting in %d seconds..", panic_timeout);
+               pr_emerg("Rebooting in %d seconds..\n", panic_timeout);
 
                for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
                        touch_nmi_watchdog();
@@ -355,7 +355,7 @@ const char *print_tainted(void)
                for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
                        const struct taint_flag *t = &taint_flags[i];
                        *s++ = test_bit(i, &tainted_mask) ?
-                                       t->true : t->false;
+                                       t->c_true : t->c_false;
                }
                *s = 0;
        } else
index df9e8e9e0be7714fa580b547492c940b11221008..eef2ce9686366a72e9dadaa9056bcda8295ae93d 100644 (file)
@@ -151,8 +151,12 @@ out:
 
 static void delayed_free_pidns(struct rcu_head *p)
 {
-       kmem_cache_free(pid_ns_cachep,
-                       container_of(p, struct pid_namespace, rcu));
+       struct pid_namespace *ns = container_of(p, struct pid_namespace, rcu);
+
+       dec_pid_namespaces(ns->ucounts);
+       put_user_ns(ns->user_ns);
+
+       kmem_cache_free(pid_ns_cachep, ns);
 }
 
 static void destroy_pid_namespace(struct pid_namespace *ns)
@@ -162,8 +166,6 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
        ns_free_inum(&ns->ns);
        for (i = 0; i < PIDMAP_ENTRIES; i++)
                kfree(ns->pidmap[i].page);
-       dec_pid_namespaces(ns->ucounts);
-       put_user_ns(ns->user_ns);
        call_rcu(&ns->rcu, delayed_free_pidns);
 }
 
index f67ceb7768b82ac4e183b22042f1f0784011262b..15e6baef5c73f90b6817c0b1c4e871ea40e30318 100644 (file)
@@ -46,7 +46,7 @@ static const char * const mem_sleep_labels[] = {
 const char *mem_sleep_states[PM_SUSPEND_MAX];
 
 suspend_state_t mem_sleep_current = PM_SUSPEND_FREEZE;
-suspend_state_t mem_sleep_default = PM_SUSPEND_MAX;
+static suspend_state_t mem_sleep_default = PM_SUSPEND_MEM;
 
 unsigned int pm_suspend_global_flags;
 EXPORT_SYMBOL_GPL(pm_suspend_global_flags);
@@ -168,7 +168,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
        }
        if (valid_state(PM_SUSPEND_MEM)) {
                mem_sleep_states[PM_SUSPEND_MEM] = mem_sleep_labels[PM_SUSPEND_MEM];
-               if (mem_sleep_default >= PM_SUSPEND_MEM)
+               if (mem_sleep_default == PM_SUSPEND_MEM)
                        mem_sleep_current = PM_SUSPEND_MEM;
        }
 
index 8b2696420abb5de7347429f52d9a3d46d4dbcd24..4ba3d34938c033740b19ad27c74c01a8cdaef2b4 100644 (file)
@@ -1516,7 +1516,7 @@ static void call_console_drivers(int level,
 {
        struct console *con;
 
-       trace_console(text, len);
+       trace_console_rcuidle(text, len);
 
        if (!console_drivers)
                return;
index 80adef7d4c3d01d9ef9ed95c483956d2a858854f..0d6ff3e471be6c1597e0e78fb90d07eb0ce9c546 100644 (file)
@@ -136,6 +136,7 @@ int rcu_jiffies_till_stall_check(void);
 #define TPS(x)  tracepoint_string(x)
 
 void rcu_early_boot_tests(void);
+void rcu_test_sync_prims(void);
 
 /*
  * This function really isn't for public consumption, but RCU is special in
index 1898559e6b60ddc52884f6977fca21e57c6f1f90..b23a4d076f3d2c64862172c83c18f21605e87159 100644 (file)
@@ -185,9 +185,6 @@ static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused
  * benefits of doing might_sleep() to reduce latency.)
  *
  * Cool, huh?  (Due to Josh Triplett.)
- *
- * But we want to make this a static inline later.  The cond_resched()
- * currently makes this problematic.
  */
 void synchronize_sched(void)
 {
@@ -195,7 +192,6 @@ void synchronize_sched(void)
                         lock_is_held(&rcu_lock_map) ||
                         lock_is_held(&rcu_sched_lock_map),
                         "Illegal synchronize_sched() in RCU read-side critical section");
-       cond_resched();
 }
 EXPORT_SYMBOL_GPL(synchronize_sched);
 
index 196f0302e2f4320ebd25dedc31d0ea8a4ab026c1..c64b827ecbca19656395e873ca06da0c92a6298e 100644 (file)
@@ -60,12 +60,17 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 
 /*
  * During boot, we forgive RCU lockdep issues.  After this function is
- * invoked, we start taking RCU lockdep issues seriously.
+ * invoked, we start taking RCU lockdep issues seriously.  Note that unlike
+ * Tree RCU, Tiny RCU transitions directly from RCU_SCHEDULER_INACTIVE
+ * to RCU_SCHEDULER_RUNNING, skipping the RCU_SCHEDULER_INIT stage.
+ * The reason for this is that Tiny RCU does not need kthreads, so does
+ * not have to care about the fact that the scheduler is half-initialized
+ * at a certain phase of the boot process.
  */
 void __init rcu_scheduler_starting(void)
 {
        WARN_ON(nr_context_switches() > 0);
-       rcu_scheduler_active = 1;
+       rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
 }
 
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
index 96c52e43f7cac0e5d6b41004c0c72d269c351f4a..cb4e2056ccf3cf799bb7c045aca346fedb2ed698 100644 (file)
@@ -127,13 +127,16 @@ int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
 int sysctl_panic_on_rcu_stall __read_mostly;
 
 /*
- * The rcu_scheduler_active variable transitions from zero to one just
- * before the first task is spawned.  So when this variable is zero, RCU
- * can assume that there is but one task, allowing RCU to (for example)
+ * The rcu_scheduler_active variable is initialized to the value
+ * RCU_SCHEDULER_INACTIVE and transitions RCU_SCHEDULER_INIT just before the
+ * first task is spawned.  So when this variable is RCU_SCHEDULER_INACTIVE,
+ * RCU can assume that there is but one task, allowing RCU to (for example)
  * optimize synchronize_rcu() to a simple barrier().  When this variable
- * is one, RCU must actually do all the hard work required to detect real
- * grace periods.  This variable is also used to suppress boot-time false
- * positives from lockdep-RCU error checking.
+ * is RCU_SCHEDULER_INIT, RCU must actually do all the hard work required
+ * to detect real grace periods.  This variable is also used to suppress
+ * boot-time false positives from lockdep-RCU error checking.  Finally, it
+ * transitions from RCU_SCHEDULER_INIT to RCU_SCHEDULER_RUNNING after RCU
+ * is fully initialized, including all of its kthreads having been spawned.
  */
 int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
@@ -3980,18 +3983,22 @@ static int __init rcu_spawn_gp_kthread(void)
 early_initcall(rcu_spawn_gp_kthread);
 
 /*
- * This function is invoked towards the end of the scheduler's initialization
- * process.  Before this is called, the idle task might contain
- * RCU read-side critical sections (during which time, this idle
- * task is booting the system).  After this function is called, the
- * idle tasks are prohibited from containing RCU read-side critical
- * sections.  This function also enables RCU lockdep checking.
+ * This function is invoked towards the end of the scheduler's
+ * initialization process.  Before this is called, the idle task might
+ * contain synchronous grace-period primitives (during which time, this idle
+ * task is booting the system, and such primitives are no-ops).  After this
+ * function is called, any synchronous grace-period primitives are run as
+ * expedited, with the requesting task driving the grace period forward.
+ * A later core_initcall() rcu_exp_runtime_mode() will switch to full
+ * runtime RCU functionality.
  */
 void rcu_scheduler_starting(void)
 {
        WARN_ON(num_online_cpus() != 1);
        WARN_ON(nr_context_switches() > 0);
-       rcu_scheduler_active = 1;
+       rcu_test_sync_prims();
+       rcu_scheduler_active = RCU_SCHEDULER_INIT;
+       rcu_test_sync_prims();
 }
 
 /*
index d3053e99fdb67deb01a35a9af998a66658d0ee22..e59e1849b89aca14797999deb3e9e91bdd9b78c2 100644 (file)
@@ -531,6 +531,20 @@ struct rcu_exp_work {
        struct work_struct rew_work;
 };
 
+/*
+ * Common code to drive an expedited grace period forward, used by
+ * workqueues and mid-boot-time tasks.
+ */
+static void rcu_exp_sel_wait_wake(struct rcu_state *rsp,
+                                 smp_call_func_t func, unsigned long s)
+{
+       /* Initialize the rcu_node tree in preparation for the wait. */
+       sync_rcu_exp_select_cpus(rsp, func);
+
+       /* Wait and clean up, including waking everyone. */
+       rcu_exp_wait_wake(rsp, s);
+}
+
 /*
  * Work-queue handler to drive an expedited grace period forward.
  */
@@ -538,12 +552,8 @@ static void wait_rcu_exp_gp(struct work_struct *wp)
 {
        struct rcu_exp_work *rewp;
 
-       /* Initialize the rcu_node tree in preparation for the wait. */
        rewp = container_of(wp, struct rcu_exp_work, rew_work);
-       sync_rcu_exp_select_cpus(rewp->rew_rsp, rewp->rew_func);
-
-       /* Wait and clean up, including waking everyone. */
-       rcu_exp_wait_wake(rewp->rew_rsp, rewp->rew_s);
+       rcu_exp_sel_wait_wake(rewp->rew_rsp, rewp->rew_func, rewp->rew_s);
 }
 
 /*
@@ -569,12 +579,18 @@ static void _synchronize_rcu_expedited(struct rcu_state *rsp,
        if (exp_funnel_lock(rsp, s))
                return;  /* Someone else did our work for us. */
 
-       /* Marshall arguments and schedule the expedited grace period. */
-       rew.rew_func = func;
-       rew.rew_rsp = rsp;
-       rew.rew_s = s;
-       INIT_WORK_ONSTACK(&rew.rew_work, wait_rcu_exp_gp);
-       schedule_work(&rew.rew_work);
+       /* Ensure that load happens before action based on it. */
+       if (unlikely(rcu_scheduler_active == RCU_SCHEDULER_INIT)) {
+               /* Direct call during scheduler init and early_initcalls(). */
+               rcu_exp_sel_wait_wake(rsp, func, s);
+       } else {
+               /* Marshall arguments & schedule the expedited grace period. */
+               rew.rew_func = func;
+               rew.rew_rsp = rsp;
+               rew.rew_s = s;
+               INIT_WORK_ONSTACK(&rew.rew_work, wait_rcu_exp_gp);
+               schedule_work(&rew.rew_work);
+       }
 
        /* Wait for expedited grace period to complete. */
        rdp = per_cpu_ptr(rsp->rda, raw_smp_processor_id());
@@ -676,6 +692,8 @@ void synchronize_rcu_expedited(void)
 {
        struct rcu_state *rsp = rcu_state_p;
 
+       if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
+               return;
        _synchronize_rcu_expedited(rsp, sync_rcu_exp_handler);
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
@@ -693,3 +711,15 @@ void synchronize_rcu_expedited(void)
 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
 #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+
+/*
+ * Switch to run-time mode once Tree RCU has fully initialized.
+ */
+static int __init rcu_exp_runtime_mode(void)
+{
+       rcu_test_sync_prims();
+       rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
+       rcu_test_sync_prims();
+       return 0;
+}
+core_initcall(rcu_exp_runtime_mode);
index 85c5a883c6e31047194a8c74603ce71ab8381f67..56583e764ebf398a7b14f442f63ce6f707f046e4 100644 (file)
@@ -670,7 +670,7 @@ void synchronize_rcu(void)
                         lock_is_held(&rcu_lock_map) ||
                         lock_is_held(&rcu_sched_lock_map),
                         "Illegal synchronize_rcu() in RCU read-side critical section");
-       if (!rcu_scheduler_active)
+       if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
                return;
        if (rcu_gp_is_expedited())
                synchronize_rcu_expedited();
index f19271dce0a9784709d7bc7860a2de972e67a070..4f6db7e6a1179ee00c99f62d854a39b00c959d2b 100644 (file)
@@ -121,11 +121,14 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);
  * Should expedited grace-period primitives always fall back to their
  * non-expedited counterparts?  Intended for use within RCU.  Note
  * that if the user specifies both rcu_expedited and rcu_normal, then
- * rcu_normal wins.
+ * rcu_normal wins.  (Except during the time period during boot from
+ * when the first task is spawned until the rcu_exp_runtime_mode()
+ * core_initcall() is invoked, at which point everything is expedited.)
  */
 bool rcu_gp_is_normal(void)
 {
-       return READ_ONCE(rcu_normal);
+       return READ_ONCE(rcu_normal) &&
+              rcu_scheduler_active != RCU_SCHEDULER_INIT;
 }
 EXPORT_SYMBOL_GPL(rcu_gp_is_normal);
 
@@ -135,13 +138,14 @@ static atomic_t rcu_expedited_nesting =
 /*
  * Should normal grace-period primitives be expedited?  Intended for
  * use within RCU.  Note that this function takes the rcu_expedited
- * sysfs/boot variable into account as well as the rcu_expedite_gp()
- * nesting.  So looping on rcu_unexpedite_gp() until rcu_gp_is_expedited()
- * returns false is a -really- bad idea.
+ * sysfs/boot variable and rcu_scheduler_active into account as well
+ * as the rcu_expedite_gp() nesting.  So looping on rcu_unexpedite_gp()
+ * until rcu_gp_is_expedited() returns false is a -really- bad idea.
  */
 bool rcu_gp_is_expedited(void)
 {
-       return rcu_expedited || atomic_read(&rcu_expedited_nesting);
+       return rcu_expedited || atomic_read(&rcu_expedited_nesting) ||
+              rcu_scheduler_active == RCU_SCHEDULER_INIT;
 }
 EXPORT_SYMBOL_GPL(rcu_gp_is_expedited);
 
@@ -257,7 +261,7 @@ EXPORT_SYMBOL_GPL(rcu_callback_map);
 
 int notrace debug_lockdep_rcu_enabled(void)
 {
-       return rcu_scheduler_active && debug_locks &&
+       return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && debug_locks &&
               current->lockdep_recursion == 0;
 }
 EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled);
@@ -591,7 +595,7 @@ EXPORT_SYMBOL_GPL(call_rcu_tasks);
 void synchronize_rcu_tasks(void)
 {
        /* Complain if the scheduler has not started.  */
-       RCU_LOCKDEP_WARN(!rcu_scheduler_active,
+       RCU_LOCKDEP_WARN(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
                         "synchronize_rcu_tasks called too soon");
 
        /* Wait for the grace period. */
@@ -813,6 +817,23 @@ static void rcu_spawn_tasks_kthread(void)
 
 #endif /* #ifdef CONFIG_TASKS_RCU */
 
+/*
+ * Test each non-SRCU synchronous grace-period wait API.  This is
+ * useful just after a change in mode for these primitives, and
+ * during early boot.
+ */
+void rcu_test_sync_prims(void)
+{
+       if (!IS_ENABLED(CONFIG_PROVE_RCU))
+               return;
+       synchronize_rcu();
+       synchronize_rcu_bh();
+       synchronize_sched();
+       synchronize_rcu_expedited();
+       synchronize_rcu_bh_expedited();
+       synchronize_sched_expedited();
+}
+
 #ifdef CONFIG_PROVE_RCU
 
 /*
@@ -865,6 +886,7 @@ void rcu_early_boot_tests(void)
                early_boot_test_call_rcu_bh();
        if (rcu_self_test_sched)
                early_boot_test_call_rcu_sched();
+       rcu_test_sync_prims();
 }
 
 static int rcu_verify_early_boot_tests(void)
index ff046b73ff2d309ce00fbd3bd8949a8f6f5fd297..3603d93a19689be7188a004f2b999b27e0ebdf2f 100644 (file)
@@ -346,7 +346,7 @@ static bool task_participate_group_stop(struct task_struct *task)
         * fresh group stop.  Read comment in do_signal_stop() for details.
         */
        if (!sig->group_stop_count && !(sig->flags & SIGNAL_STOP_STOPPED)) {
-               sig->flags = SIGNAL_STOP_STOPPED;
+               signal_set_stop_flags(sig, SIGNAL_STOP_STOPPED);
                return true;
        }
        return false;
@@ -843,7 +843,7 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
                         * will take ->siglock, notice SIGNAL_CLD_MASK, and
                         * notify its parent. See get_signal_to_deliver().
                         */
-                       signal->flags = why | SIGNAL_STOP_CONTINUED;
+                       signal_set_stop_flags(signal, why | SIGNAL_STOP_CONTINUED);
                        signal->group_stop_count = 0;
                        signal->group_exit_code = 0;
                }
index b6e4c16377c708027c1c8c52914106fb71e3ca93..9c15a9124e83b50661414fa425393cdb51866313 100644 (file)
@@ -18,10 +18,8 @@ void print_stack_trace(struct stack_trace *trace, int spaces)
        if (WARN_ON(!trace->entries))
                return;
 
-       for (i = 0; i < trace->nr_entries; i++) {
-               printk("%*c", 1 + spaces, ' ');
-               print_ip_sym(trace->entries[i]);
-       }
+       for (i = 0; i < trace->nr_entries; i++)
+               printk("%*c%pS\n", 1 + spaces, ' ', (void *)trace->entries[i]);
 }
 EXPORT_SYMBOL_GPL(print_stack_trace);
 
@@ -29,7 +27,6 @@ int snprint_stack_trace(char *buf, size_t size,
                        struct stack_trace *trace, int spaces)
 {
        int i;
-       unsigned long ip;
        int generated;
        int total = 0;
 
@@ -37,9 +34,8 @@ int snprint_stack_trace(char *buf, size_t size,
                return 0;
 
        for (i = 0; i < trace->nr_entries; i++) {
-               ip = trace->entries[i];
-               generated = snprintf(buf, size, "%*c[<%p>] %pS\n",
-                               1 + spaces, ' ', (void *) ip, (void *) ip);
+               generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ',
+                                    (void *)trace->entries[i]);
 
                total += generated;
 
index 8dbaec0e4f7f079b87f50ea67c82341304387783..1aea594a54dbdac604ca950fdaf93508e5b6e6a7 100644 (file)
@@ -2475,6 +2475,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
                                break;
                        if (neg)
                                continue;
+                       val = convmul * val / convdiv;
                        if ((min && val < *min) || (max && val > *max))
                                continue;
                        *i = val;
index 3109204c87cca83704d10326f8b179671577f3d6..17ac99b60ee58e78975d415f34ddc4ce5a2e5342 100644 (file)
@@ -347,17 +347,16 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
  *
  * Called when the system enters a state where affected tick devices
  * might stop. Note: TICK_BROADCAST_FORCE cannot be undone.
- *
- * Called with interrupts disabled, so clockevents_lock is not
- * required here because the local clock event device cannot go away
- * under us.
  */
 void tick_broadcast_control(enum tick_broadcast_mode mode)
 {
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
        int cpu, bc_stopped;
+       unsigned long flags;
 
+       /* Protects also the local clockevent device. */
+       raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
        td = this_cpu_ptr(&tick_cpu_device);
        dev = td->evtdev;
 
@@ -365,12 +364,11 @@ void tick_broadcast_control(enum tick_broadcast_mode mode)
         * Is the device not affected by the powerstate ?
         */
        if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP))
-               return;
+               goto out;
 
        if (!tick_device_is_functional(dev))
-               return;
+               goto out;
 
-       raw_spin_lock(&tick_broadcast_lock);
        cpu = smp_processor_id();
        bc = tick_broadcast_device.evtdev;
        bc_stopped = cpumask_empty(tick_broadcast_mask);
@@ -420,7 +418,8 @@ void tick_broadcast_control(enum tick_broadcast_mode mode)
                                tick_broadcast_setup_oneshot(bc);
                }
        }
-       raw_spin_unlock(&tick_broadcast_lock);
+out:
+       raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 EXPORT_SYMBOL_GPL(tick_broadcast_control);
 
index ca9fb800336b2904e4c19069ad8c9e29ea926830..38bc4d2208e80bb398f411c2eafb3d2c599f1bc7 100644 (file)
@@ -75,7 +75,7 @@ void tk_debug_account_sleep_time(struct timespec64 *t)
        int bin = min(fls(t->tv_sec), NUM_BINS-1);
 
        sleep_time_bin[bin]++;
-       pr_info("Suspended for %lld.%03lu seconds\n", (s64)t->tv_sec,
-                       t->tv_nsec / NSEC_PER_MSEC);
+       printk_deferred(KERN_INFO "Suspended for %lld.%03lu seconds\n",
+                       (s64)t->tv_sec, t->tv_nsec / NSEC_PER_MSEC);
 }
 
index 775569ec50d03fbf0ca4f755f79d106a63acaf1a..af344a1bf0d0e6270e5e659ffa160753e148cdd9 100644 (file)
@@ -266,7 +266,7 @@ out:
 static struct cpumask save_cpumask;
 static bool disable_migrate;
 
-static void move_to_next_cpu(void)
+static void move_to_next_cpu(bool initmask)
 {
        static struct cpumask *current_mask;
        int next_cpu;
@@ -275,7 +275,7 @@ static void move_to_next_cpu(void)
                return;
 
        /* Just pick the first CPU on first iteration */
-       if (!current_mask) {
+       if (initmask) {
                current_mask = &save_cpumask;
                get_online_cpus();
                cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask);
@@ -330,10 +330,12 @@ static void move_to_next_cpu(void)
 static int kthread_fn(void *data)
 {
        u64 interval;
+       bool initmask = true;
 
        while (!kthread_should_stop()) {
 
-               move_to_next_cpu();
+               move_to_next_cpu(initmask);
+               initmask = false;
 
                local_irq_disable();
                get_sample();
index a133ecd741e437d938ca377cf5e4358bcb586aa4..7ad9e53ad174bc6cdb0f99490f87e419e9381b02 100644 (file)
@@ -1372,7 +1372,7 @@ kprobe_trace_selftest_target(int a1, int a2, int a3, int a4, int a5, int a6)
        return a1 + a2 + a3 + a4 + a5 + a6;
 }
 
-static struct __init trace_event_file *
+static __init struct trace_event_file *
 find_trace_probe_file(struct trace_kprobe *tk, struct trace_array *tr)
 {
        struct trace_event_file *file;
index 9d20d5dd298af25d0cd95635e217180601703959..95c6336fc2b33c6ea47611e9f9974d8521bc08fc 100644 (file)
@@ -128,10 +128,10 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
        struct hlist_head *hashent = ucounts_hashentry(ns, uid);
        struct ucounts *ucounts, *new;
 
-       spin_lock(&ucounts_lock);
+       spin_lock_irq(&ucounts_lock);
        ucounts = find_ucounts(ns, uid, hashent);
        if (!ucounts) {
-               spin_unlock(&ucounts_lock);
+               spin_unlock_irq(&ucounts_lock);
 
                new = kzalloc(sizeof(*new), GFP_KERNEL);
                if (!new)
@@ -141,7 +141,7 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
                new->uid = uid;
                atomic_set(&new->count, 0);
 
-               spin_lock(&ucounts_lock);
+               spin_lock_irq(&ucounts_lock);
                ucounts = find_ucounts(ns, uid, hashent);
                if (ucounts) {
                        kfree(new);
@@ -152,16 +152,18 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
        }
        if (!atomic_add_unless(&ucounts->count, 1, INT_MAX))
                ucounts = NULL;
-       spin_unlock(&ucounts_lock);
+       spin_unlock_irq(&ucounts_lock);
        return ucounts;
 }
 
 static void put_ucounts(struct ucounts *ucounts)
 {
+       unsigned long flags;
+
        if (atomic_dec_and_test(&ucounts->count)) {
-               spin_lock(&ucounts_lock);
+               spin_lock_irqsave(&ucounts_lock, flags);
                hlist_del_init(&ucounts->node);
-               spin_unlock(&ucounts_lock);
+               spin_unlock_irqrestore(&ucounts_lock, flags);
 
                kfree(ucounts);
        }
@@ -225,11 +227,10 @@ static __init int user_namespace_sysctl_init(void)
         * properly.
         */
        user_header = register_sysctl("user", empty);
+       kmemleak_ignore(user_header);
        BUG_ON(!user_header);
        BUG_ON(!setup_userns_sysctls(&init_user_ns));
 #endif
        return 0;
 }
 subsys_initcall(user_namespace_sysctl_init);
-
-
index d4b0fa01cae39cd720661d7a62f50a7926f9db69..63177be0159e9493f6d6ade90efae743aaf117b7 100644 (file)
@@ -49,6 +49,8 @@ unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
 #define for_each_watchdog_cpu(cpu) \
        for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask)
 
+atomic_t watchdog_park_in_progress = ATOMIC_INIT(0);
+
 /*
  * The 'watchdog_running' variable is set to 1 when the watchdog threads
  * are registered/started and is set to 0 when the watchdog threads are
@@ -260,6 +262,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
        int duration;
        int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
 
+       if (atomic_read(&watchdog_park_in_progress) != 0)
+               return HRTIMER_NORESTART;
+
        /* kick the hardlockup detector */
        watchdog_interrupt_count();
 
@@ -467,12 +472,16 @@ static int watchdog_park_threads(void)
 {
        int cpu, ret = 0;
 
+       atomic_set(&watchdog_park_in_progress, 1);
+
        for_each_watchdog_cpu(cpu) {
                ret = kthread_park(per_cpu(softlockup_watchdog, cpu));
                if (ret)
                        break;
        }
 
+       atomic_set(&watchdog_park_in_progress, 0);
+
        return ret;
 }
 
index 84016c8aee6b5d2769495a8c6eee0b4ac559b1a6..12b8dd64078655dd9004d03caa8167da16b57cf5 100644 (file)
@@ -84,6 +84,9 @@ static void watchdog_overflow_callback(struct perf_event *event,
        /* Ensure the watchdog never gets throttled */
        event->hw.interrupts = 0;
 
+       if (atomic_read(&watchdog_park_in_progress) != 0)
+               return;
+
        if (__this_cpu_read(watchdog_nmi_touch) == true) {
                __this_cpu_write(watchdog_nmi_touch, false);
                return;
index b06848a104e6940e128e63a5d3c8c7fb39ffaf8b..eb9e9a7870fa7bdb0f373f858037c1026880c85f 100644 (file)
@@ -164,7 +164,7 @@ config DEBUG_INFO_REDUCED
 
 config DEBUG_INFO_SPLIT
        bool "Produce split debuginfo in .dwo files"
-       depends on DEBUG_INFO
+       depends on DEBUG_INFO && !FRV
        help
          Generate debug info into separate .dwo files. This significantly
          reduces the build directory size for builds with DEBUG_INFO,
index 86c8911b0e3a6fff02b9e52faa11816cfe508362..a3e14ce92a5684a662c2c8f80f97e6fef95943b7 100644 (file)
@@ -144,4 +144,3 @@ int ioremap_page_range(unsigned long addr,
 
        return err;
 }
-EXPORT_SYMBOL_GPL(ioremap_page_range);
index 25f57230380104f419257ea43c1cd3d2e31d7e65..e68604ae3cedf41ce98bc06de2142629fa115cbd 100644 (file)
@@ -730,43 +730,50 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
 }
 EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
 
+static inline void pipe_truncate(struct iov_iter *i)
+{
+       struct pipe_inode_info *pipe = i->pipe;
+       if (pipe->nrbufs) {
+               size_t off = i->iov_offset;
+               int idx = i->idx;
+               int nrbufs = (idx - pipe->curbuf) & (pipe->buffers - 1);
+               if (off) {
+                       pipe->bufs[idx].len = off - pipe->bufs[idx].offset;
+                       idx = next_idx(idx, pipe);
+                       nrbufs++;
+               }
+               while (pipe->nrbufs > nrbufs) {
+                       pipe_buf_release(pipe, &pipe->bufs[idx]);
+                       idx = next_idx(idx, pipe);
+                       pipe->nrbufs--;
+               }
+       }
+}
+
 static void pipe_advance(struct iov_iter *i, size_t size)
 {
        struct pipe_inode_info *pipe = i->pipe;
-       struct pipe_buffer *buf;
-       int idx = i->idx;
-       size_t off = i->iov_offset, orig_sz;
-       
        if (unlikely(i->count < size))
                size = i->count;
-       orig_sz = size;
-
        if (size) {
+               struct pipe_buffer *buf;
+               size_t off = i->iov_offset, left = size;
+               int idx = i->idx;
                if (off) /* make it relative to the beginning of buffer */
-                       size += off - pipe->bufs[idx].offset;
+                       left += off - pipe->bufs[idx].offset;
                while (1) {
                        buf = &pipe->bufs[idx];
-                       if (size <= buf->len)
+                       if (left <= buf->len)
                                break;
-                       size -= buf->len;
+                       left -= buf->len;
                        idx = next_idx(idx, pipe);
                }
-               buf->len = size;
                i->idx = idx;
-               off = i->iov_offset = buf->offset + size;
-       }
-       if (off)
-               idx = next_idx(idx, pipe);
-       if (pipe->nrbufs) {
-               int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
-               /* [curbuf,unused) is in use.  Free [idx,unused) */
-               while (idx != unused) {
-                       pipe_buf_release(pipe, &pipe->bufs[idx]);
-                       idx = next_idx(idx, pipe);
-                       pipe->nrbufs--;
-               }
+               i->iov_offset = buf->offset + left;
        }
-       i->count -= orig_sz;
+       i->count -= size;
+       /* ... and discard everything past that point */
+       pipe_truncate(i);
 }
 
 void iov_iter_advance(struct iov_iter *i, size_t size)
@@ -826,6 +833,7 @@ void iov_iter_pipe(struct iov_iter *i, int direction,
                        size_t count)
 {
        BUG_ON(direction != ITER_PIPE);
+       WARN_ON(pipe->nrbufs == pipe->buffers);
        i->type = direction;
        i->pipe = pipe;
        i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
index 6f382e07de77e2f543389c57e52f48a1f5d026ad..84812a9fb16fbbd1409315ea3752fb9a1e3e39ef 100644 (file)
@@ -640,6 +640,7 @@ static inline void radix_tree_shrink(struct radix_tree_root *root,
                                update_node(node, private);
                }
 
+               WARN_ON_ONCE(!list_empty(&node->private_list));
                radix_tree_node_free(node);
        }
 }
@@ -666,6 +667,7 @@ static void delete_node(struct radix_tree_root *root,
                        root->rnode = NULL;
                }
 
+               WARN_ON_ONCE(!list_empty(&node->private_list));
                radix_tree_node_free(node);
 
                node = parent;
@@ -767,6 +769,7 @@ static void radix_tree_free_nodes(struct radix_tree_node *node)
                        struct radix_tree_node *old = child;
                        offset = child->offset + 1;
                        child = child->parent;
+                       WARN_ON_ONCE(!list_empty(&old->private_list));
                        radix_tree_node_free(old);
                        if (old == entry_to_node(node))
                                return;
@@ -1824,15 +1827,19 @@ EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot);
  *     __radix_tree_delete_node    -    try to free node after clearing a slot
  *     @root:          radix tree root
  *     @node:          node containing @index
+ *     @update_node:   callback for changing leaf nodes
+ *     @private:       private data to pass to @update_node
  *
  *     After clearing the slot at @index in @node from radix tree
  *     rooted at @root, call this function to attempt freeing the
  *     node and shrinking the tree.
  */
 void __radix_tree_delete_node(struct radix_tree_root *root,
-                             struct radix_tree_node *node)
+                             struct radix_tree_node *node,
+                             radix_tree_update_node_t update_node,
+                             void *private)
 {
-       delete_node(root, node, NULL, NULL);
+       delete_node(root, node, update_node, private);
 }
 
 /**
index cb1b54ee8527241de289ab66f34f9a0a1efa761f..a8d74a733a38b54a912f5e292f0a15a2cfff4a95 100644 (file)
@@ -53,7 +53,7 @@
  */
 #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
 
-int swiotlb_force;
+enum swiotlb_force swiotlb_force;
 
 /*
  * Used to do a quick range check in swiotlb_tbl_unmap_single and
@@ -82,6 +82,12 @@ static phys_addr_t io_tlb_overflow_buffer;
 static unsigned int *io_tlb_list;
 static unsigned int io_tlb_index;
 
+/*
+ * Max segment that we can provide which (if pages are contingous) will
+ * not be bounced (unless SWIOTLB_FORCE is set).
+ */
+unsigned int max_segment;
+
 /*
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
@@ -106,8 +112,12 @@ setup_io_tlb_npages(char *str)
        }
        if (*str == ',')
                ++str;
-       if (!strcmp(str, "force"))
-               swiotlb_force = 1;
+       if (!strcmp(str, "force")) {
+               swiotlb_force = SWIOTLB_FORCE;
+       } else if (!strcmp(str, "noforce")) {
+               swiotlb_force = SWIOTLB_NO_FORCE;
+               io_tlb_nslabs = 1;
+       }
 
        return 0;
 }
@@ -120,6 +130,20 @@ unsigned long swiotlb_nr_tbl(void)
 }
 EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
 
+unsigned int swiotlb_max_segment(void)
+{
+       return max_segment;
+}
+EXPORT_SYMBOL_GPL(swiotlb_max_segment);
+
+void swiotlb_set_max_segment(unsigned int val)
+{
+       if (swiotlb_force == SWIOTLB_FORCE)
+               max_segment = 1;
+       else
+               max_segment = rounddown(val, PAGE_SIZE);
+}
+
 /* default to 64MB */
 #define IO_TLB_DEFAULT_SIZE (64UL<<20)
 unsigned long swiotlb_size_or_default(void)
@@ -201,6 +225,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
        if (verbose)
                swiotlb_print_info();
 
+       swiotlb_set_max_segment(io_tlb_nslabs << IO_TLB_SHIFT);
        return 0;
 }
 
@@ -279,6 +304,7 @@ swiotlb_late_init_with_default_size(size_t default_size)
        rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
        if (rc)
                free_pages((unsigned long)vstart, order);
+
        return rc;
 }
 
@@ -333,6 +359,8 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
 
        late_alloc = 1;
 
+       swiotlb_set_max_segment(io_tlb_nslabs << IO_TLB_SHIFT);
+
        return 0;
 
 cleanup4:
@@ -347,6 +375,7 @@ cleanup2:
        io_tlb_end = 0;
        io_tlb_start = 0;
        io_tlb_nslabs = 0;
+       max_segment = 0;
        return -ENOMEM;
 }
 
@@ -375,6 +404,7 @@ void __init swiotlb_free(void)
                                   PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
        }
        io_tlb_nslabs = 0;
+       max_segment = 0;
 }
 
 int is_swiotlb_buffer(phys_addr_t paddr)
@@ -453,11 +483,11 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
                    : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
 
        /*
-        * For mappings greater than a page, we limit the stride (and
-        * hence alignment) to a page size.
+        * For mappings greater than or equal to a page, we limit the stride
+        * (and hence alignment) to a page size.
         */
        nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
-       if (size > PAGE_SIZE)
+       if (size >= PAGE_SIZE)
                stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
        else
                stride = 1;
@@ -543,8 +573,15 @@ static phys_addr_t
 map_single(struct device *hwdev, phys_addr_t phys, size_t size,
           enum dma_data_direction dir, unsigned long attrs)
 {
-       dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
+       dma_addr_t start_dma_addr;
 
+       if (swiotlb_force == SWIOTLB_NO_FORCE) {
+               dev_warn_ratelimited(hwdev, "Cannot do DMA to address %pa\n",
+                                    &phys);
+               return SWIOTLB_MAP_ERROR;
+       }
+
+       start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
        return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size,
                                      dir, attrs);
 }
@@ -721,6 +758,9 @@ static void
 swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
             int do_panic)
 {
+       if (swiotlb_force == SWIOTLB_NO_FORCE)
+               return;
+
        /*
         * Ran out of IOMMU space for this operation. This is very bad.
         * Unfortunately the drivers cannot handle this operation properly.
@@ -763,7 +803,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
         * we can safely return the device addr and not worry about bounce
         * buffering it.
         */
-       if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
+       if (dma_capable(dev, dev_addr, size) && swiotlb_force != SWIOTLB_FORCE)
                return dev_addr;
 
        trace_swiotlb_bounced(dev, dev_addr, size, swiotlb_force);
@@ -904,7 +944,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
                phys_addr_t paddr = sg_phys(sg);
                dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
 
-               if (swiotlb_force ||
+               if (swiotlb_force == SWIOTLB_FORCE ||
                    !dma_capable(hwdev, dev_addr, sg->length)) {
                        phys_addr_t map = map_single(hwdev, sg_phys(sg),
                                                     sg->length, dir, attrs);
index d0e4d1002059360e50254ae2c87dc8f7a87a2dff..3f9afded581be1a013bda4db2c0ec3a721323364 100644 (file)
@@ -138,7 +138,7 @@ static int page_cache_tree_insert(struct address_space *mapping,
                                dax_radix_locked_entry(0, RADIX_DAX_EMPTY));
                        /* Wakeup waiters for exceptional entry lock */
                        dax_wake_mapping_entry_waiter(mapping, page->index, p,
-                                                     false);
+                                                     true);
                }
        }
        __radix_tree_replace(&mapping->page_tree, node, slot, page,
@@ -1791,6 +1791,11 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
 
                cond_resched();
 find_page:
+               if (fatal_signal_pending(current)) {
+                       error = -EINTR;
+                       goto out;
+               }
+
                page = find_get_page(mapping, index);
                if (!page) {
                        page_cache_sync_readahead(mapping,
index 10eedbf14421f29675d18e80569bafc9efd60763..5f3ad65c85de01fa6e4c8a07ef9494410bf2b133 100644 (file)
@@ -783,6 +783,12 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
 
        assert_spin_locked(pmd_lockptr(mm, pmd));
 
+       /*
+        * When we COW a devmap PMD entry, we split it into PTEs, so we should
+        * not be in this function with `flags & FOLL_COW` set.
+        */
+       WARN_ONCE(flags & FOLL_COW, "mm: In follow_devmap_pmd with FOLL_COW set");
+
        if (flags & FOLL_WRITE && !pmd_write(*pmd))
                return NULL;
 
@@ -883,15 +889,17 @@ void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd)
 {
        pmd_t entry;
        unsigned long haddr;
+       bool write = vmf->flags & FAULT_FLAG_WRITE;
 
        vmf->ptl = pmd_lock(vmf->vma->vm_mm, vmf->pmd);
        if (unlikely(!pmd_same(*vmf->pmd, orig_pmd)))
                goto unlock;
 
        entry = pmd_mkyoung(orig_pmd);
+       if (write)
+               entry = pmd_mkdirty(entry);
        haddr = vmf->address & HPAGE_PMD_MASK;
-       if (pmdp_set_access_flags(vmf->vma, haddr, vmf->pmd, entry,
-                               vmf->flags & FAULT_FLAG_WRITE))
+       if (pmdp_set_access_flags(vmf->vma, haddr, vmf->pmd, entry, write))
                update_mmu_cache_pmd(vmf->vma, vmf->address, vmf->pmd);
 
 unlock:
@@ -919,8 +927,7 @@ static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd,
        }
 
        for (i = 0; i < HPAGE_PMD_NR; i++) {
-               pages[i] = alloc_page_vma_node(GFP_HIGHUSER_MOVABLE |
-                                              __GFP_OTHER_NODE, vma,
+               pages[i] = alloc_page_vma_node(GFP_HIGHUSER_MOVABLE, vma,
                                               vmf->address, page_to_nid(page));
                if (unlikely(!pages[i] ||
                             mem_cgroup_try_charge(pages[i], vma->vm_mm,
@@ -1127,6 +1134,16 @@ out_unlock:
        return ret;
 }
 
+/*
+ * FOLL_FORCE can write to even unwritable pmd's, but only
+ * after we've gone through a COW cycle and they are dirty.
+ */
+static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags)
+{
+       return pmd_write(pmd) ||
+              ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd));
+}
+
 struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
                                   unsigned long addr,
                                   pmd_t *pmd,
@@ -1137,7 +1154,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 
        assert_spin_locked(pmd_lockptr(mm, pmd));
 
-       if (flags & FOLL_WRITE && !pmd_write(*pmd))
+       if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, flags))
                goto out;
 
        /* Avoid dumping huge zero page */
index 3edb759c5c7d15dfeacb4eb18e4a901602a0ee23..c7025c132670a4d8e3279d1ebb7730718fb6aa8a 100644 (file)
@@ -1773,23 +1773,32 @@ free:
 }
 
 /*
- * When releasing a hugetlb pool reservation, any surplus pages that were
- * allocated to satisfy the reservation must be explicitly freed if they were
- * never used.
- * Called with hugetlb_lock held.
+ * This routine has two main purposes:
+ * 1) Decrement the reservation count (resv_huge_pages) by the value passed
+ *    in unused_resv_pages.  This corresponds to the prior adjustments made
+ *    to the associated reservation map.
+ * 2) Free any unused surplus pages that may have been allocated to satisfy
+ *    the reservation.  As many as unused_resv_pages may be freed.
+ *
+ * Called with hugetlb_lock held.  However, the lock could be dropped (and
+ * reacquired) during calls to cond_resched_lock.  Whenever dropping the lock,
+ * we must make sure nobody else can claim pages we are in the process of
+ * freeing.  Do this by ensuring resv_huge_page always is greater than the
+ * number of huge pages we plan to free when dropping the lock.
  */
 static void return_unused_surplus_pages(struct hstate *h,
                                        unsigned long unused_resv_pages)
 {
        unsigned long nr_pages;
 
-       /* Uncommit the reservation */
-       h->resv_huge_pages -= unused_resv_pages;
-
        /* Cannot return gigantic pages currently */
        if (hstate_is_gigantic(h))
-               return;
+               goto out;
 
+       /*
+        * Part (or even all) of the reservation could have been backed
+        * by pre-allocated pages. Only free surplus pages.
+        */
        nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
 
        /*
@@ -1799,12 +1808,22 @@ static void return_unused_surplus_pages(struct hstate *h,
         * when the nodes with surplus pages have no free pages.
         * free_pool_huge_page() will balance the the freed pages across the
         * on-line nodes with memory and will handle the hstate accounting.
+        *
+        * Note that we decrement resv_huge_pages as we free the pages.  If
+        * we drop the lock, resv_huge_pages will still be sufficiently large
+        * to cover subsequent pages we may free.
         */
        while (nr_pages--) {
+               h->resv_huge_pages--;
+               unused_resv_pages--;
                if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
-                       break;
+                       goto out;
                cond_resched_lock(&hugetlb_lock);
        }
+
+out:
+       /* Fully uncommit the reservation */
+       h->resv_huge_pages -= unused_resv_pages;
 }
 
 
index b82b3e2151574ae1abbb2cd57624114727975410..f479365530b6484bbd5cae42064521fed362961e 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/ftrace.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/printk.h>
@@ -300,6 +301,8 @@ void kasan_report(unsigned long addr, size_t size,
        if (likely(!kasan_report_enabled()))
                return;
 
+       disable_trace_on_warning();
+
        info.access_addr = (void *)addr;
        info.access_size = size;
        info.is_write = is_write;
index e32389a970305eaf60b36da896e2226a8ce18a0d..77ae3239c3de17bfbf7ba29b56a5cb270611cfd8 100644 (file)
@@ -943,7 +943,7 @@ static void collapse_huge_page(struct mm_struct *mm,
        VM_BUG_ON(address & ~HPAGE_PMD_MASK);
 
        /* Only allocate from the target node */
-       gfp = alloc_hugepage_khugepaged_gfpmask() | __GFP_OTHER_NODE | __GFP_THISNODE;
+       gfp = alloc_hugepage_khugepaged_gfpmask() | __GFP_THISNODE;
 
        /*
         * Before allocating the hugepage, release the mmap_sem read lock.
@@ -1242,7 +1242,6 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
        struct vm_area_struct *vma;
        unsigned long addr;
        pmd_t *pmd, _pmd;
-       bool deposited = false;
 
        i_mmap_lock_write(mapping);
        vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
@@ -1267,26 +1266,10 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
                        spinlock_t *ptl = pmd_lock(vma->vm_mm, pmd);
                        /* assume page table is clear */
                        _pmd = pmdp_collapse_flush(vma, addr, pmd);
-                       /*
-                        * now deposit the pgtable for arch that need it
-                        * otherwise free it.
-                        */
-                       if (arch_needs_pgtable_deposit()) {
-                               /*
-                                * The deposit should be visibile only after
-                                * collapse is seen by others.
-                                */
-                               smp_wmb();
-                               pgtable_trans_huge_deposit(vma->vm_mm, pmd,
-                                                          pmd_pgtable(_pmd));
-                               deposited = true;
-                       }
                        spin_unlock(ptl);
                        up_write(&vma->vm_mm->mmap_sem);
-                       if (!deposited) {
-                               atomic_long_dec(&vma->vm_mm->nr_ptes);
-                               pte_free(vma->vm_mm, pmd_pgtable(_pmd));
-                       }
+                       atomic_long_dec(&vma->vm_mm->nr_ptes);
+                       pte_free(vma->vm_mm, pmd_pgtable(_pmd));
                }
        }
        i_mmap_unlock_write(mapping);
@@ -1326,8 +1309,7 @@ static void collapse_shmem(struct mm_struct *mm,
        VM_BUG_ON(start & (HPAGE_PMD_NR - 1));
 
        /* Only allocate from the target node */
-       gfp = alloc_hugepage_khugepaged_gfpmask() |
-               __GFP_OTHER_NODE | __GFP_THISNODE;
+       gfp = alloc_hugepage_khugepaged_gfpmask() | __GFP_THISNODE;
 
        new_page = khugepaged_alloc_page(hpage, gfp, node);
        if (!new_page) {
index 4048897e7b01a6e5e82333c0852629eded927ff3..b822e158b319e8f2f02ecbfe76c31b6466be51f1 100644 (file)
@@ -625,8 +625,8 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
 unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
                                           int nid, unsigned int lru_mask)
 {
+       struct lruvec *lruvec = mem_cgroup_lruvec(NODE_DATA(nid), memcg);
        unsigned long nr = 0;
-       struct mem_cgroup_per_node *mz;
        enum lru_list lru;
 
        VM_BUG_ON((unsigned)nid >= nr_node_ids);
@@ -634,8 +634,7 @@ unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
        for_each_lru(lru) {
                if (!(BIT(lru) & lru_mask))
                        continue;
-               mz = mem_cgroup_nodeinfo(memcg, nid);
-               nr += mz->lru_size[lru];
+               nr += mem_cgroup_get_lru_size(lruvec, lru);
        }
        return nr;
 }
@@ -1002,6 +1001,7 @@ out:
  * mem_cgroup_update_lru_size - account for adding or removing an lru page
  * @lruvec: mem_cgroup per zone lru vector
  * @lru: index of lru list the page is sitting on
+ * @zid: zone id of the accounted pages
  * @nr_pages: positive when adding or negative when removing
  *
  * This function must be called under lru_lock, just before a page is added
@@ -1009,27 +1009,25 @@ out:
  * so as to allow it to check that lru_size 0 is consistent with list_empty).
  */
 void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
-                               int nr_pages)
+                               int zid, int nr_pages)
 {
        struct mem_cgroup_per_node *mz;
        unsigned long *lru_size;
        long size;
-       bool empty;
 
        if (mem_cgroup_disabled())
                return;
 
        mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
-       lru_size = mz->lru_size + lru;
-       empty = list_empty(lruvec->lists + lru);
+       lru_size = &mz->lru_zone_size[zid][lru];
 
        if (nr_pages < 0)
                *lru_size += nr_pages;
 
        size = *lru_size;
-       if (WARN_ONCE(size < 0 || empty != !size,
-               "%s(%p, %d, %d): lru_size %ld but %sempty\n",
-               __func__, lruvec, lru, nr_pages, size, empty ? "" : "not ")) {
+       if (WARN_ONCE(size < 0,
+               "%s(%p, %d, %d): lru_size %ld\n",
+               __func__, lruvec, lru, nr_pages, size)) {
                VM_BUG_ON(1);
                *lru_size = 0;
        }
@@ -4355,9 +4353,9 @@ static int mem_cgroup_do_precharge(unsigned long count)
                return ret;
        }
 
-       /* Try charges one by one with reclaim */
+       /* Try charges one by one with reclaim, but do not retry */
        while (count--) {
-               ret = try_charge(mc.to, GFP_KERNEL & ~__GFP_NORETRY, 1);
+               ret = try_charge(mc.to, GFP_KERNEL __GFP_NORETRY, 1);
                if (ret)
                        return ret;
                mc.precharge++;
index 7d23b505024846301d0e1bb77783489455c8c742..6bf2b471e30ca566a55160e4131bf7e7b9c3c4ea 100644 (file)
@@ -3008,13 +3008,6 @@ static int do_set_pmd(struct vm_fault *vmf, struct page *page)
        ret = 0;
        count_vm_event(THP_FILE_MAPPED);
 out:
-       /*
-        * If we are going to fallback to pte mapping, do a
-        * withdraw with pmd lock held.
-        */
-       if (arch_needs_pgtable_deposit() && ret == VM_FAULT_FALLBACK)
-               vmf->prealloc_pte = pgtable_trans_huge_withdraw(vma->vm_mm,
-                                                               vmf->pmd);
        spin_unlock(vmf->ptl);
        return ret;
 }
@@ -3055,20 +3048,18 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
 
                ret = do_set_pmd(vmf, page);
                if (ret != VM_FAULT_FALLBACK)
-                       goto fault_handled;
+                       return ret;
        }
 
        if (!vmf->pte) {
                ret = pte_alloc_one_map(vmf);
                if (ret)
-                       goto fault_handled;
+                       return ret;
        }
 
        /* Re-check under ptl */
-       if (unlikely(!pte_none(*vmf->pte))) {
-               ret = VM_FAULT_NOPAGE;
-               goto fault_handled;
-       }
+       if (unlikely(!pte_none(*vmf->pte)))
+               return VM_FAULT_NOPAGE;
 
        flush_icache_page(vma, page);
        entry = mk_pte(page, vma->vm_page_prot);
@@ -3088,15 +3079,8 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
 
        /* no need to invalidate: a not-present page won't be cached */
        update_mmu_cache(vma, vmf->address, vmf->pte);
-       ret = 0;
 
-fault_handled:
-       /* preallocated pagetable is unused: free it */
-       if (vmf->prealloc_pte) {
-               pte_free(vmf->vma->vm_mm, vmf->prealloc_pte);
-               vmf->prealloc_pte = 0;
-       }
-       return ret;
+       return 0;
 }
 
 
@@ -3360,15 +3344,24 @@ static int do_shared_fault(struct vm_fault *vmf)
 static int do_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
+       int ret;
 
        /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */
        if (!vma->vm_ops->fault)
-               return VM_FAULT_SIGBUS;
-       if (!(vmf->flags & FAULT_FLAG_WRITE))
-               return do_read_fault(vmf);
-       if (!(vma->vm_flags & VM_SHARED))
-               return do_cow_fault(vmf);
-       return do_shared_fault(vmf);
+               ret = VM_FAULT_SIGBUS;
+       else if (!(vmf->flags & FAULT_FLAG_WRITE))
+               ret = do_read_fault(vmf);
+       else if (!(vma->vm_flags & VM_SHARED))
+               ret = do_cow_fault(vmf);
+       else
+               ret = do_shared_fault(vmf);
+
+       /* preallocated pagetable is unused: free it */
+       if (vmf->prealloc_pte) {
+               pte_free(vma->vm_mm, vmf->prealloc_pte);
+               vmf->prealloc_pte = 0;
+       }
+       return ret;
 }
 
 static int numa_migrate_prep(struct page *page, struct vm_area_struct *vma,
@@ -3779,8 +3772,8 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
 }
 #endif /* __PAGETABLE_PMD_FOLDED */
 
-static int __follow_pte(struct mm_struct *mm, unsigned long address,
-               pte_t **ptepp, spinlock_t **ptlp)
+static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
+               pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
 {
        pgd_t *pgd;
        pud_t *pud;
@@ -3797,11 +3790,20 @@ static int __follow_pte(struct mm_struct *mm, unsigned long address,
 
        pmd = pmd_offset(pud, address);
        VM_BUG_ON(pmd_trans_huge(*pmd));
-       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
-               goto out;
 
-       /* We cannot handle huge page PFN maps. Luckily they don't exist. */
-       if (pmd_huge(*pmd))
+       if (pmd_huge(*pmd)) {
+               if (!pmdpp)
+                       goto out;
+
+               *ptlp = pmd_lock(mm, pmd);
+               if (pmd_huge(*pmd)) {
+                       *pmdpp = pmd;
+                       return 0;
+               }
+               spin_unlock(*ptlp);
+       }
+
+       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
                goto out;
 
        ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
@@ -3817,16 +3819,30 @@ out:
        return -EINVAL;
 }
 
-int follow_pte(struct mm_struct *mm, unsigned long address, pte_t **ptepp,
-              spinlock_t **ptlp)
+static inline int follow_pte(struct mm_struct *mm, unsigned long address,
+                            pte_t **ptepp, spinlock_t **ptlp)
+{
+       int res;
+
+       /* (void) is needed to make gcc happy */
+       (void) __cond_lock(*ptlp,
+                          !(res = __follow_pte_pmd(mm, address, ptepp, NULL,
+                                          ptlp)));
+       return res;
+}
+
+int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
+                            pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
 {
        int res;
 
        /* (void) is needed to make gcc happy */
        (void) __cond_lock(*ptlp,
-                          !(res = __follow_pte(mm, address, ptepp, ptlp)));
+                          !(res = __follow_pte_pmd(mm, address, ptepp, pmdpp,
+                                          ptlp)));
        return res;
 }
+EXPORT_SYMBOL(follow_pte_pmd);
 
 /**
  * follow_pfn - look up PFN at a user virtual address
index e43142c15631fefdf5a605ced247a6429825252f..b8c11e063ff0746316fb792f4fe1dde0094cb828 100644 (file)
@@ -1033,36 +1033,39 @@ static void node_states_set_node(int node, struct memory_notify *arg)
        node_set_state(node, N_MEMORY);
 }
 
-int zone_can_shift(unsigned long pfn, unsigned long nr_pages,
-                  enum zone_type target)
+bool zone_can_shift(unsigned long pfn, unsigned long nr_pages,
+                  enum zone_type target, int *zone_shift)
 {
        struct zone *zone = page_zone(pfn_to_page(pfn));
        enum zone_type idx = zone_idx(zone);
        int i;
 
+       *zone_shift = 0;
+
        if (idx < target) {
                /* pages must be at end of current zone */
                if (pfn + nr_pages != zone_end_pfn(zone))
-                       return 0;
+                       return false;
 
                /* no zones in use between current zone and target */
                for (i = idx + 1; i < target; i++)
                        if (zone_is_initialized(zone - idx + i))
-                               return 0;
+                               return false;
        }
 
        if (target < idx) {
                /* pages must be at beginning of current zone */
                if (pfn != zone->zone_start_pfn)
-                       return 0;
+                       return false;
 
                /* no zones in use between current zone and target */
                for (i = target + 1; i < idx; i++)
                        if (zone_is_initialized(zone - idx + i))
-                               return 0;
+                               return false;
        }
 
-       return target - idx;
+       *zone_shift = target - idx;
+       return true;
 }
 
 /* Must be protected by mem_hotplug_begin() */
@@ -1089,10 +1092,13 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
            !can_online_high_movable(zone))
                return -EINVAL;
 
-       if (online_type == MMOP_ONLINE_KERNEL)
-               zone_shift = zone_can_shift(pfn, nr_pages, ZONE_NORMAL);
-       else if (online_type == MMOP_ONLINE_MOVABLE)
-               zone_shift = zone_can_shift(pfn, nr_pages, ZONE_MOVABLE);
+       if (online_type == MMOP_ONLINE_KERNEL) {
+               if (!zone_can_shift(pfn, nr_pages, ZONE_NORMAL, &zone_shift))
+                       return -EINVAL;
+       } else if (online_type == MMOP_ONLINE_MOVABLE) {
+               if (!zone_can_shift(pfn, nr_pages, ZONE_MOVABLE, &zone_shift))
+                       return -EINVAL;
+       }
 
        zone = move_pfn_range(zone_shift, pfn, pfn + nr_pages);
        if (!zone)
@@ -1477,17 +1483,20 @@ bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 }
 
 /*
- * Confirm all pages in a range [start, end) is belongs to the same zone.
+ * Confirm all pages in a range [start, end) belong to the same zone.
+ * When true, return its valid [start, end).
  */
-int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
+int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
+                        unsigned long *valid_start, unsigned long *valid_end)
 {
        unsigned long pfn, sec_end_pfn;
+       unsigned long start, end;
        struct zone *zone = NULL;
        struct page *page;
        int i;
-       for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
+       for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn + 1);
             pfn < end_pfn;
-            pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
+            pfn = sec_end_pfn, sec_end_pfn += PAGES_PER_SECTION) {
                /* Make sure the memory section is present first */
                if (!present_section_nr(pfn_to_section_nr(pfn)))
                        continue;
@@ -1503,10 +1512,20 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
                        page = pfn_to_page(pfn + i);
                        if (zone && page_zone(page) != zone)
                                return 0;
+                       if (!zone)
+                               start = pfn + i;
                        zone = page_zone(page);
+                       end = pfn + MAX_ORDER_NR_PAGES;
                }
        }
-       return 1;
+
+       if (zone) {
+               *valid_start = start;
+               *valid_end = end;
+               return 1;
+       } else {
+               return 0;
+       }
 }
 
 /*
@@ -1833,6 +1852,7 @@ static int __ref __offline_pages(unsigned long start_pfn,
        long offlined_pages;
        int ret, drain, retry_max, node;
        unsigned long flags;
+       unsigned long valid_start, valid_end;
        struct zone *zone;
        struct memory_notify arg;
 
@@ -1843,10 +1863,10 @@ static int __ref __offline_pages(unsigned long start_pfn,
                return -EINVAL;
        /* This makes hotplug much easier...and readable.
           we assume this for now. .*/
-       if (!test_pages_in_a_zone(start_pfn, end_pfn))
+       if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
                return -EINVAL;
 
-       zone = page_zone(pfn_to_page(start_pfn));
+       zone = page_zone(pfn_to_page(valid_start));
        node = zone_to_nid(zone);
        nr_pages = end_pfn - start_pfn;
 
index 2e346645eb80d6bb8f97761c30aed6a512017e59..1e7873e40c9a16e922d4800e6dc41486eee23540 100644 (file)
@@ -2017,8 +2017,8 @@ retry_cpuset:
 
        nmask = policy_nodemask(gfp, pol);
        zl = policy_zonelist(gfp, pol, node);
-       mpol_cond_put(pol);
        page = __alloc_pages_nodemask(gfp, order, zl, nmask);
+       mpol_cond_put(pol);
 out:
        if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
                goto retry_cpuset;
index 2c6d5f64feca409e9fdca4b551a240882e421476..f3e0c69a97b76997d9fa65cda0b7e1b1fb8fa29a 100644 (file)
@@ -1864,14 +1864,14 @@ int move_freepages(struct zone *zone,
 #endif
 
        for (page = start_page; page <= end_page;) {
-               /* Make sure we are not inadvertently changing nodes */
-               VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
-
                if (!pfn_valid_within(page_to_pfn(page))) {
                        page++;
                        continue;
                }
 
+               /* Make sure we are not inadvertently changing nodes */
+               VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
+
                if (!PageBuddy(page)) {
                        page++;
                        continue;
@@ -2583,30 +2583,22 @@ int __isolate_free_page(struct page *page, unsigned int order)
  * Update NUMA hit/miss statistics
  *
  * Must be called with interrupts disabled.
- *
- * When __GFP_OTHER_NODE is set assume the node of the preferred
- * zone is the local node. This is useful for daemons who allocate
- * memory on behalf of other processes.
  */
-static inline void zone_statistics(struct zone *preferred_zone, struct zone *z,
-                                                               gfp_t flags)
+static inline void zone_statistics(struct zone *preferred_zone, struct zone *z)
 {
 #ifdef CONFIG_NUMA
-       int local_nid = numa_node_id();
        enum zone_stat_item local_stat = NUMA_LOCAL;
 
-       if (unlikely(flags & __GFP_OTHER_NODE)) {
+       if (z->node != numa_node_id())
                local_stat = NUMA_OTHER;
-               local_nid = preferred_zone->node;
-       }
 
-       if (z->node == local_nid) {
+       if (z->node == preferred_zone->node)
                __inc_zone_state(z, NUMA_HIT);
-               __inc_zone_state(z, local_stat);
-       } else {
+       else {
                __inc_zone_state(z, NUMA_MISS);
                __inc_zone_state(preferred_zone, NUMA_FOREIGN);
        }
+       __inc_zone_state(z, local_stat);
 #endif
 }
 
@@ -2674,7 +2666,7 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
        }
 
        __count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
-       zone_statistics(preferred_zone, zone, gfp_flags);
+       zone_statistics(preferred_zone, zone);
        local_irq_restore(flags);
 
        VM_BUG_ON_PAGE(bad_range(zone, page), page);
@@ -3531,12 +3523,13 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        struct page *page = NULL;
        unsigned int alloc_flags;
        unsigned long did_some_progress;
-       enum compact_priority compact_priority = DEF_COMPACT_PRIORITY;
+       enum compact_priority compact_priority;
        enum compact_result compact_result;
-       int compaction_retries = 0;
-       int no_progress_loops = 0;
+       int compaction_retries;
+       int no_progress_loops;
        unsigned long alloc_start = jiffies;
        unsigned int stall_timeout = 10 * HZ;
+       unsigned int cpuset_mems_cookie;
 
        /*
         * In the slowpath, we sanity check order to avoid ever trying to
@@ -3557,6 +3550,23 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
                                (__GFP_ATOMIC|__GFP_DIRECT_RECLAIM)))
                gfp_mask &= ~__GFP_ATOMIC;
 
+retry_cpuset:
+       compaction_retries = 0;
+       no_progress_loops = 0;
+       compact_priority = DEF_COMPACT_PRIORITY;
+       cpuset_mems_cookie = read_mems_allowed_begin();
+       /*
+        * We need to recalculate the starting point for the zonelist iterator
+        * because we might have used different nodemask in the fast path, or
+        * there was a cpuset modification and we are retrying - otherwise we
+        * could end up iterating over non-eligible zones endlessly.
+        */
+       ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
+                                       ac->high_zoneidx, ac->nodemask);
+       if (!ac->preferred_zoneref->zone)
+               goto nopage;
+
+
        /*
         * The fast path uses conservative alloc_flags to succeed only until
         * kswapd needs to be woken up, and to avoid the cost of setting up
@@ -3716,6 +3726,13 @@ retry:
                                &compaction_retries))
                goto retry;
 
+       /*
+        * It's possible we raced with cpuset update so the OOM would be
+        * premature (see below the nopage: label for full explanation).
+        */
+       if (read_mems_allowed_retry(cpuset_mems_cookie))
+               goto retry_cpuset;
+
        /* Reclaim has failed us, start killing things */
        page = __alloc_pages_may_oom(gfp_mask, order, ac, &did_some_progress);
        if (page)
@@ -3728,6 +3745,16 @@ retry:
        }
 
 nopage:
+       /*
+        * When updating a task's mems_allowed or mempolicy nodemask, it is
+        * possible to race with parallel threads in such a way that our
+        * allocation can fail while the mask is being updated. If we are about
+        * to fail, check if the cpuset changed during allocation and if so,
+        * retry.
+        */
+       if (read_mems_allowed_retry(cpuset_mems_cookie))
+               goto retry_cpuset;
+
        warn_alloc(gfp_mask,
                        "page allocation failure: order:%u", order);
 got_pg:
@@ -3742,7 +3769,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
                        struct zonelist *zonelist, nodemask_t *nodemask)
 {
        struct page *page;
-       unsigned int cpuset_mems_cookie;
        unsigned int alloc_flags = ALLOC_WMARK_LOW;
        gfp_t alloc_mask = gfp_mask; /* The gfp_t that was actually used for allocation */
        struct alloc_context ac = {
@@ -3779,9 +3805,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
        if (IS_ENABLED(CONFIG_CMA) && ac.migratetype == MIGRATE_MOVABLE)
                alloc_flags |= ALLOC_CMA;
 
-retry_cpuset:
-       cpuset_mems_cookie = read_mems_allowed_begin();
-
        /* Dirty zone balancing only done in the fast path */
        ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE);
 
@@ -3792,8 +3815,13 @@ retry_cpuset:
         */
        ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
                                        ac.high_zoneidx, ac.nodemask);
-       if (!ac.preferred_zoneref) {
+       if (!ac.preferred_zoneref->zone) {
                page = NULL;
+               /*
+                * This might be due to race with cpuset_current_mems_allowed
+                * update, so make sure we retry with original nodemask in the
+                * slow path.
+                */
                goto no_zone;
        }
 
@@ -3802,6 +3830,7 @@ retry_cpuset:
        if (likely(page))
                goto out;
 
+no_zone:
        /*
         * Runtime PM, block IO and its error handling path can deadlock
         * because I/O on the device might not complete.
@@ -3813,21 +3842,10 @@ retry_cpuset:
         * Restore the original nodemask if it was potentially replaced with
         * &cpuset_current_mems_allowed to optimize the fast-path attempt.
         */
-       if (cpusets_enabled())
+       if (unlikely(ac.nodemask != nodemask))
                ac.nodemask = nodemask;
-       page = __alloc_pages_slowpath(alloc_mask, order, &ac);
 
-no_zone:
-       /*
-        * When updating a task's mems_allowed, it is possible to race with
-        * parallel threads in such a way that an allocation can fail while
-        * the mask is being updated. If a page allocation is about to fail,
-        * check if the cpuset changed during allocation and if so, retry.
-        */
-       if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) {
-               alloc_mask = gfp_mask;
-               goto retry_cpuset;
-       }
+       page = __alloc_pages_slowpath(alloc_mask, order, &ac);
 
 out:
        if (memcg_kmem_enabled() && (gfp_mask & __GFP_ACCOUNT) && page &&
@@ -3904,8 +3922,8 @@ EXPORT_SYMBOL(free_pages);
  * drivers to provide a backing region of memory for use as either an
  * sk_buff->head, or to be used in the "frags" portion of skb_shared_info.
  */
-static struct page *__page_frag_refill(struct page_frag_cache *nc,
-                                      gfp_t gfp_mask)
+static struct page *__page_frag_cache_refill(struct page_frag_cache *nc,
+                                            gfp_t gfp_mask)
 {
        struct page *page = NULL;
        gfp_t gfp = gfp_mask;
@@ -3925,22 +3943,23 @@ static struct page *__page_frag_refill(struct page_frag_cache *nc,
        return page;
 }
 
-void __page_frag_drain(struct page *page, unsigned int order,
-                      unsigned int count)
+void __page_frag_cache_drain(struct page *page, unsigned int count)
 {
        VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
 
        if (page_ref_sub_and_test(page, count)) {
+               unsigned int order = compound_order(page);
+
                if (order == 0)
                        free_hot_cold_page(page, false);
                else
                        __free_pages_ok(page, order);
        }
 }
-EXPORT_SYMBOL(__page_frag_drain);
+EXPORT_SYMBOL(__page_frag_cache_drain);
 
-void *__alloc_page_frag(struct page_frag_cache *nc,
-                       unsigned int fragsz, gfp_t gfp_mask)
+void *page_frag_alloc(struct page_frag_cache *nc,
+                     unsigned int fragsz, gfp_t gfp_mask)
 {
        unsigned int size = PAGE_SIZE;
        struct page *page;
@@ -3948,7 +3967,7 @@ void *__alloc_page_frag(struct page_frag_cache *nc,
 
        if (unlikely(!nc->va)) {
 refill:
-               page = __page_frag_refill(nc, gfp_mask);
+               page = __page_frag_cache_refill(nc, gfp_mask);
                if (!page)
                        return NULL;
 
@@ -3991,19 +4010,19 @@ refill:
 
        return nc->va + offset;
 }
-EXPORT_SYMBOL(__alloc_page_frag);
+EXPORT_SYMBOL(page_frag_alloc);
 
 /*
  * Frees a page fragment allocated out of either a compound or order 0 page.
  */
-void __free_page_frag(void *addr)
+void page_frag_free(void *addr)
 {
        struct page *page = virt_to_head_page(addr);
 
        if (unlikely(put_page_testzero(page)))
                __free_pages_ok(page, compound_order(page));
 }
-EXPORT_SYMBOL(__free_page_frag);
+EXPORT_SYMBOL(page_frag_free);
 
 static void *make_alloc_exact(unsigned long addr, unsigned int order,
                size_t size)
@@ -7255,6 +7274,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
                .zone = page_zone(pfn_to_page(start)),
                .mode = MIGRATE_SYNC,
                .ignore_skip_hint = true,
+               .gfp_mask = GFP_KERNEL,
        };
        INIT_LIST_HEAD(&cc.migratepages);
 
index bb53285a1d99666676e85697330f1a052f7c3cc0..3a7587a0314dc73fb4929a824a74f9b8948ea502 100644 (file)
@@ -415,6 +415,7 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
                struct shrink_control *sc, unsigned long nr_to_split)
 {
        LIST_HEAD(list), *pos, *next;
+       LIST_HEAD(to_remove);
        struct inode *inode;
        struct shmem_inode_info *info;
        struct page *page;
@@ -441,9 +442,8 @@ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
                /* Check if there's anything to gain */
                if (round_up(inode->i_size, PAGE_SIZE) ==
                                round_up(inode->i_size, HPAGE_PMD_SIZE)) {
-                       list_del_init(&info->shrinklist);
+                       list_move(&info->shrinklist, &to_remove);
                        removed++;
-                       iput(inode);
                        goto next;
                }
 
@@ -454,6 +454,13 @@ next:
        }
        spin_unlock(&sbinfo->shrinklist_lock);
 
+       list_for_each_safe(pos, next, &to_remove) {
+               info = list_entry(pos, struct shmem_inode_info, shrinklist);
+               inode = &info->vfs_inode;
+               list_del_init(&info->shrinklist);
+               iput(inode);
+       }
+
        list_for_each_safe(pos, next, &list) {
                int ret;
 
index 29bc6c0dedd07020e9f433332f907620239343a5..4f2ec6bb46ebe949d2e19ff154faddc7e2526f02 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2457,7 +2457,6 @@ union freelist_init_state {
                unsigned int pos;
                unsigned int *list;
                unsigned int count;
-               unsigned int rand;
        };
        struct rnd_state rnd_state;
 };
@@ -2483,8 +2482,7 @@ static bool freelist_state_initialize(union freelist_init_state *state,
        } else {
                state->list = cachep->random_seq;
                state->count = count;
-               state->pos = 0;
-               state->rand = rand;
+               state->pos = rand % count;
                ret = true;
        }
        return ret;
@@ -2493,7 +2491,9 @@ static bool freelist_state_initialize(union freelist_init_state *state,
 /* Get the next entry on the list and randomize it using a random shift */
 static freelist_idx_t next_random_slot(union freelist_init_state *state)
 {
-       return (state->list[state->pos++] + state->rand) % state->count;
+       if (state->pos >= state->count)
+               state->pos = 0;
+       return state->list[state->pos++];
 }
 
 /* Swap two freelist entries */
index 067598a008493fabb68d48120a904943fff4e08c..7ec0a965c6a3a366550b2500f9880f65e5025138 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -496,10 +496,11 @@ static inline int check_valid_pointer(struct kmem_cache *s,
        return 1;
 }
 
-static void print_section(char *text, u8 *addr, unsigned int length)
+static void print_section(char *level, char *text, u8 *addr,
+                         unsigned int length)
 {
        metadata_access_enable();
-       print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
+       print_hex_dump(level, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
                        length, 1);
        metadata_access_disable();
 }
@@ -636,14 +637,15 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
               p, p - addr, get_freepointer(s, p));
 
        if (s->flags & SLAB_RED_ZONE)
-               print_section("Redzone ", p - s->red_left_pad, s->red_left_pad);
+               print_section(KERN_ERR, "Redzone ", p - s->red_left_pad,
+                             s->red_left_pad);
        else if (p > addr + 16)
-               print_section("Bytes b4 ", p - 16, 16);
+               print_section(KERN_ERR, "Bytes b4 ", p - 16, 16);
 
-       print_section("Object ", p, min_t(unsigned long, s->object_size,
-                               PAGE_SIZE));
+       print_section(KERN_ERR, "Object ", p,
+                     min_t(unsigned long, s->object_size, PAGE_SIZE));
        if (s->flags & SLAB_RED_ZONE)
-               print_section("Redzone ", p + s->object_size,
+               print_section(KERN_ERR, "Redzone ", p + s->object_size,
                        s->inuse - s->object_size);
 
        if (s->offset)
@@ -658,7 +660,8 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
 
        if (off != size_from_object(s))
                /* Beginning of the filler is the free pointer */
-               print_section("Padding ", p + off, size_from_object(s) - off);
+               print_section(KERN_ERR, "Padding ", p + off,
+                             size_from_object(s) - off);
 
        dump_stack();
 }
@@ -820,7 +823,7 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
                end--;
 
        slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1);
-       print_section("Padding ", end - remainder, remainder);
+       print_section(KERN_ERR, "Padding ", end - remainder, remainder);
 
        restore_bytes(s, "slab padding", POISON_INUSE, end - remainder, end);
        return 0;
@@ -973,7 +976,7 @@ static void trace(struct kmem_cache *s, struct page *page, void *object,
                        page->freelist);
 
                if (!alloc)
-                       print_section("Object ", (void *)object,
+                       print_section(KERN_INFO, "Object ", (void *)object,
                                        s->object_size);
 
                dump_stack();
@@ -1419,6 +1422,10 @@ static int init_cache_random_seq(struct kmem_cache *s)
        int err;
        unsigned long i, count = oo_objects(s->oo);
 
+       /* Bailout if already initialised */
+       if (s->random_seq)
+               return 0;
+
        err = cache_random_seq_create(s, count, GFP_KERNEL);
        if (err) {
                pr_err("SLUB: Unable to initialize free list for %s\n",
index 1c6e0321205dd2d34abc7f39a0753c128eb7ae53..4761701d1721e63fb8334e3a63fcc11b9e5e6443 100644 (file)
@@ -943,11 +943,25 @@ bool reuse_swap_page(struct page *page, int *total_mapcount)
        count = page_trans_huge_mapcount(page, total_mapcount);
        if (count <= 1 && PageSwapCache(page)) {
                count += page_swapcount(page);
-               if (count == 1 && !PageWriteback(page)) {
+               if (count != 1)
+                       goto out;
+               if (!PageWriteback(page)) {
                        delete_from_swap_cache(page);
                        SetPageDirty(page);
+               } else {
+                       swp_entry_t entry;
+                       struct swap_info_struct *p;
+
+                       entry.val = page_private(page);
+                       p = swap_info_get(entry);
+                       if (p->flags & SWP_STABLE_WRITES) {
+                               spin_unlock(&p->lock);
+                               return false;
+                       }
+                       spin_unlock(&p->lock);
                }
        }
+out:
        return count <= 1;
 }
 
@@ -2448,6 +2462,10 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                error = -ENOMEM;
                goto bad_swap;
        }
+
+       if (bdi_cap_stable_pages_required(inode_to_bdi(inode)))
+               p->flags |= SWP_STABLE_WRITES;
+
        if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) {
                int cpu;
 
index 6aa5b01d3e757b9b462993f3421050fd8831ceea..532a2a750952daffed4e4242d36a449eb9ba8837 100644 (file)
@@ -242,6 +242,16 @@ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru)
        return node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru);
 }
 
+unsigned long lruvec_zone_lru_size(struct lruvec *lruvec, enum lru_list lru,
+                                  int zone_idx)
+{
+       if (!mem_cgroup_disabled())
+               return mem_cgroup_get_zone_lru_size(lruvec, lru, zone_idx);
+
+       return zone_page_state(&lruvec_pgdat(lruvec)->node_zones[zone_idx],
+                              NR_ZONE_LRU_BASE + lru);
+}
+
 /*
  * Add a shrinker callback to be called from the vm.
  */
@@ -1382,8 +1392,7 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode)
  * be complete before mem_cgroup_update_lru_size due to a santity check.
  */
 static __always_inline void update_lru_sizes(struct lruvec *lruvec,
-                       enum lru_list lru, unsigned long *nr_zone_taken,
-                       unsigned long nr_taken)
+                       enum lru_list lru, unsigned long *nr_zone_taken)
 {
        int zid;
 
@@ -1392,11 +1401,11 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec,
                        continue;
 
                __update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]);
-       }
-
 #ifdef CONFIG_MEMCG
-       mem_cgroup_update_lru_size(lruvec, lru, -nr_taken);
+               mem_cgroup_update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]);
 #endif
+       }
+
 }
 
 /*
@@ -1501,7 +1510,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
        *nr_scanned = scan;
        trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan, scan,
                                    nr_taken, mode, is_file_lru(lru));
-       update_lru_sizes(lruvec, lru, nr_zone_taken, nr_taken);
+       update_lru_sizes(lruvec, lru, nr_zone_taken);
        return nr_taken;
 }
 
@@ -2047,10 +2056,8 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
                if (!managed_zone(zone))
                        continue;
 
-               inactive_zone = zone_page_state(zone,
-                               NR_ZONE_LRU_BASE + (file * LRU_FILE));
-               active_zone = zone_page_state(zone,
-                               NR_ZONE_LRU_BASE + (file * LRU_FILE) + LRU_ACTIVE);
+               inactive_zone = lruvec_zone_lru_size(lruvec, file * LRU_FILE, zid);
+               active_zone = lruvec_zone_lru_size(lruvec, (file * LRU_FILE) + LRU_ACTIVE, zid);
 
                inactive -= min(inactive, inactive_zone);
                active -= min(active, active_zone);
index 241fa5d6b3b2fe155ed0f458b9d188a926a51e80..abb58ffa3c64cb330d7e3d7aca7897aab0fea6a4 100644 (file)
@@ -473,7 +473,8 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
        if (WARN_ON_ONCE(node->exceptional))
                goto out_invalid;
        inc_node_state(page_pgdat(virt_to_page(node)), WORKINGSET_NODERECLAIM);
-       __radix_tree_delete_node(&mapping->page_tree, node);
+       __radix_tree_delete_node(&mapping->page_tree, node,
+                                workingset_update_node, mapping);
 
 out_invalid:
        spin_unlock(&mapping->tree_lock);
index 067a0d62f31841d16913d36e38531a277ab59b01..cabf09e0128beebdee2b8a959361fe6464fb3469 100644 (file)
@@ -78,7 +78,13 @@ static u64 zswap_duplicate_entry;
 
 /* Enable/disable zswap (disabled by default) */
 static bool zswap_enabled;
-module_param_named(enabled, zswap_enabled, bool, 0644);
+static int zswap_enabled_param_set(const char *,
+                                  const struct kernel_param *);
+static struct kernel_param_ops zswap_enabled_param_ops = {
+       .set =          zswap_enabled_param_set,
+       .get =          param_get_bool,
+};
+module_param_cb(enabled, &zswap_enabled_param_ops, &zswap_enabled, 0644);
 
 /* Crypto compressor to use */
 #define ZSWAP_COMPRESSOR_DEFAULT "lzo"
@@ -176,6 +182,9 @@ static atomic_t zswap_pools_count = ATOMIC_INIT(0);
 /* used by param callback function */
 static bool zswap_init_started;
 
+/* fatal error during init */
+static bool zswap_init_failed;
+
 /*********************************
 * helpers and fwd declarations
 **********************************/
@@ -624,6 +633,11 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
        char *s = strstrip((char *)val);
        int ret;
 
+       if (zswap_init_failed) {
+               pr_err("can't set param, initialization failed\n");
+               return -ENODEV;
+       }
+
        /* no change required */
        if (!strcmp(s, *(char **)kp->arg))
                return 0;
@@ -703,6 +717,17 @@ static int zswap_zpool_param_set(const char *val,
        return __zswap_param_set(val, kp, NULL, zswap_compressor);
 }
 
+static int zswap_enabled_param_set(const char *val,
+                                  const struct kernel_param *kp)
+{
+       if (zswap_init_failed) {
+               pr_err("can't enable, initialization failed\n");
+               return -ENODEV;
+       }
+
+       return param_set_bool(val, kp);
+}
+
 /*********************************
 * writeback code
 **********************************/
@@ -1201,6 +1226,9 @@ hp_fail:
 dstmem_fail:
        zswap_entry_cache_destroy();
 cache_fail:
+       /* if built-in, we aren't unloaded on failure; don't allow use */
+       zswap_init_failed = true;
+       zswap_enabled = false;
        return -ENOMEM;
 }
 /* must be late so crypto has time to come up */
index a1005007224ca04ee673fb948776107d6ba075c4..a29bb4b41c50e3c55463eaee2a5dda1292b757f6 100644 (file)
@@ -258,10 +258,6 @@ config XPS
 config HWBM
        bool
 
-config SOCK_CGROUP_DATA
-       bool
-       default n
-
 config CGROUP_NET_PRIO
        bool "Network priority cgroup"
        depends on CGROUPS
index 4855d18a8511072b499043d1160ad1ff4b2f9f3e..038b109b2be70e8da91589a1bf3c82e73a3903ca 100644 (file)
@@ -264,7 +264,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
 {
        ax25_clear_queues(ax25);
 
-       if (!sock_flag(ax25->sk, SOCK_DESTROY))
+       if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
                ax25_stop_heartbeat(ax25);
        ax25_stop_t1timer(ax25);
        ax25_stop_t2timer(ax25);
index 9c561e683f4b8b68642b626b51a0dcda30260e97..0854ebd8613e9bf9044b04099b11341325d6e194 100644 (file)
@@ -474,7 +474,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
        primary_if = batadv_primary_if_get_selected(bat_priv);
        if (!primary_if) {
                ret = -EINVAL;
-               goto put_primary_if;
+               goto free_skb;
        }
 
        /* Create one header to be copied to all fragments */
@@ -502,7 +502,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
                if (!skb_fragment) {
                        ret = -ENOMEM;
-                       goto free_skb;
+                       goto put_primary_if;
                }
 
                batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
@@ -511,7 +511,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                ret = batadv_send_unicast_skb(skb_fragment, neigh_node);
                if (ret != NET_XMIT_SUCCESS) {
                        ret = NET_XMIT_DROP;
-                       goto free_skb;
+                       goto put_primary_if;
                }
 
                frag_header.no++;
@@ -519,7 +519,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
                /* The initial check in this function should cover this case */
                if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
                        ret = -EINVAL;
-                       goto free_skb;
+                       goto put_primary_if;
                }
        }
 
@@ -527,7 +527,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
        if (batadv_skb_head_push(skb, header_size) < 0 ||
            pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0) {
                ret = -ENOMEM;
-               goto free_skb;
+               goto put_primary_if;
        }
 
        memcpy(skb->data, &frag_header, header_size);
index 8ca6a929bf1255cb432fd4bd59d34345d62e09c4..95087e6e8258366af95579bb308d1a6e18266f0e 100644 (file)
@@ -399,7 +399,7 @@ bridged_dnat:
                                br_nf_hook_thresh(NF_BR_PRE_ROUTING,
                                                  net, sk, skb, skb->dev,
                                                  NULL,
-                                                 br_nf_pre_routing_finish);
+                                                 br_nf_pre_routing_finish_bridge);
                                return 0;
                        }
                        ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr);
index 71c7453268c1cf5a34949b0451f457ac18a4657b..7109b389ea585ab4b3a52bac803ae1fd860c2f65 100644 (file)
@@ -781,20 +781,6 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
        return 0;
 }
 
-static int br_dev_newlink(struct net *src_net, struct net_device *dev,
-                         struct nlattr *tb[], struct nlattr *data[])
-{
-       struct net_bridge *br = netdev_priv(dev);
-
-       if (tb[IFLA_ADDRESS]) {
-               spin_lock_bh(&br->lock);
-               br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
-               spin_unlock_bh(&br->lock);
-       }
-
-       return register_netdevice(dev);
-}
-
 static int br_port_slave_changelink(struct net_device *brdev,
                                    struct net_device *dev,
                                    struct nlattr *tb[],
@@ -1115,6 +1101,25 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
        return 0;
 }
 
+static int br_dev_newlink(struct net *src_net, struct net_device *dev,
+                         struct nlattr *tb[], struct nlattr *data[])
+{
+       struct net_bridge *br = netdev_priv(dev);
+       int err;
+
+       if (tb[IFLA_ADDRESS]) {
+               spin_lock_bh(&br->lock);
+               br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
+               spin_unlock_bh(&br->lock);
+       }
+
+       err = br_changelink(dev, tb, data);
+       if (err)
+               return err;
+
+       return register_netdevice(dev);
+}
+
 static size_t br_get_size(const struct net_device *brdev)
 {
        return nla_total_size(sizeof(u32)) +    /* IFLA_BR_FORWARD_DELAY  */
index 1108079d934f8383a599d7997b08100fca0465e9..5488e4a6ccd062e6f6e7e2b841dde5ef055d4337 100644 (file)
@@ -445,6 +445,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
  * @func: callback function on filter match
  * @data: returned parameter for callback function
  * @ident: string for calling module identification
+ * @sk: socket pointer (might be NULL)
  *
  * Description:
  *  Invokes the callback function with the received sk_buff and the given
@@ -468,7 +469,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
  */
 int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
                    void (*func)(struct sk_buff *, void *), void *data,
-                   char *ident)
+                   char *ident, struct sock *sk)
 {
        struct receiver *r;
        struct hlist_head *rl;
@@ -496,6 +497,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
                r->func    = func;
                r->data    = data;
                r->ident   = ident;
+               r->sk      = sk;
 
                hlist_add_head_rcu(&r->list, rl);
                d->entries++;
@@ -520,8 +522,11 @@ EXPORT_SYMBOL(can_rx_register);
 static void can_rx_delete_receiver(struct rcu_head *rp)
 {
        struct receiver *r = container_of(rp, struct receiver, rcu);
+       struct sock *sk = r->sk;
 
        kmem_cache_free(rcv_cache, r);
+       if (sk)
+               sock_put(sk);
 }
 
 /**
@@ -596,8 +601,11 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
        spin_unlock(&can_rcvlists_lock);
 
        /* schedule the receiver item for deletion */
-       if (r)
+       if (r) {
+               if (r->sk)
+                       sock_hold(r->sk);
                call_rcu(&r->rcu, can_rx_delete_receiver);
+       }
 }
 EXPORT_SYMBOL(can_rx_unregister);
 
index fca0fe9fc45a497cdf3da82d5414e846e7cc61b7..b86f5129e8385fe84ef671bb914e8e05c2977ca0 100644 (file)
 
 struct receiver {
        struct hlist_node list;
-       struct rcu_head rcu;
        canid_t can_id;
        canid_t mask;
        unsigned long matches;
        void (*func)(struct sk_buff *, void *);
        void *data;
        char *ident;
+       struct sock *sk;
+       struct rcu_head rcu;
 };
 
 #define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
index 21ac75390e3d64f795faad074b515d34ce0bbfa3..95d13b233c65161cf3595a8b0036207f5c2892e3 100644 (file)
@@ -734,14 +734,23 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
 
 static void bcm_remove_op(struct bcm_op *op)
 {
-       hrtimer_cancel(&op->timer);
-       hrtimer_cancel(&op->thrtimer);
-
-       if (op->tsklet.func)
-               tasklet_kill(&op->tsklet);
+       if (op->tsklet.func) {
+               while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
+                      test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
+                      hrtimer_active(&op->timer)) {
+                       hrtimer_cancel(&op->timer);
+                       tasklet_kill(&op->tsklet);
+               }
+       }
 
-       if (op->thrtsklet.func)
-               tasklet_kill(&op->thrtsklet);
+       if (op->thrtsklet.func) {
+               while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
+                      test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
+                      hrtimer_active(&op->thrtimer)) {
+                       hrtimer_cancel(&op->thrtimer);
+                       tasklet_kill(&op->thrtsklet);
+               }
+       }
 
        if ((op->frames) && (op->frames != &op->sframe))
                kfree(op->frames);
@@ -1216,7 +1225,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                                err = can_rx_register(dev, op->can_id,
                                                      REGMASK(op->can_id),
                                                      bcm_rx_handler, op,
-                                                     "bcm");
+                                                     "bcm", sk);
 
                                op->rx_reg_dev = dev;
                                dev_put(dev);
@@ -1225,7 +1234,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                } else
                        err = can_rx_register(NULL, op->can_id,
                                              REGMASK(op->can_id),
-                                             bcm_rx_handler, op, "bcm");
+                                             bcm_rx_handler, op, "bcm", sk);
                if (err) {
                        /* this bcm rx op is broken -> remove it */
                        list_del(&op->list);
index a54ab0c821048ab2034bf32cef3c1f35e0dc82a5..7056a1a2bb70098e691ce557f05e5bc1f27cb42f 100644 (file)
@@ -442,7 +442,7 @@ static inline int cgw_register_filter(struct cgw_job *gwj)
 {
        return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
                               gwj->ccgw.filter.can_mask, can_can_gw_rcv,
-                              gwj, "gw");
+                              gwj, "gw", NULL);
 }
 
 static inline void cgw_unregister_filter(struct cgw_job *gwj)
index b075f028d7e23958e9433a4b19f4475ad930b547..6dc546a06673ff41fc121c546ebd0567bb0da05f 100644 (file)
@@ -190,7 +190,7 @@ static int raw_enable_filters(struct net_device *dev, struct sock *sk,
        for (i = 0; i < count; i++) {
                err = can_rx_register(dev, filter[i].can_id,
                                      filter[i].can_mask,
-                                     raw_rcv, sk, "raw");
+                                     raw_rcv, sk, "raw", sk);
                if (err) {
                        /* clean up successfully registered filters */
                        while (--i >= 0)
@@ -211,7 +211,7 @@ static int raw_enable_errfilter(struct net_device *dev, struct sock *sk,
 
        if (err_mask)
                err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
-                                     raw_rcv, sk, "raw");
+                                     raw_rcv, sk, "raw", sk);
 
        return err;
 }
index 3949ce70be07bc90b1ee7e67ca95f09c1d5258f3..292e33bd916e650c0317ab630a0c60a400d21c7d 100644 (file)
@@ -214,7 +214,7 @@ static int ceph_aes_crypt(const struct ceph_crypto_key *key, bool encrypt,
        SKCIPHER_REQUEST_ON_STACK(req, key->tfm);
        struct sg_table sgt;
        struct scatterlist prealloc_sg;
-       char iv[AES_BLOCK_SIZE];
+       char iv[AES_BLOCK_SIZE] __aligned(8);
        int pad_byte = AES_BLOCK_SIZE - (in_len & (AES_BLOCK_SIZE - 1));
        int crypt_len = encrypt ? in_len + pad_byte : in_len;
        int ret;
index 662bea5871656f190a61e35b3c5cd21c2f132441..ea633342ab0d046cbc49e55b679440ef9e015c2d 100644 (file)
@@ -332,7 +332,9 @@ void __skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb, int len)
 EXPORT_SYMBOL(__skb_free_datagram_locked);
 
 int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
-                       unsigned int flags)
+                       unsigned int flags,
+                       void (*destructor)(struct sock *sk,
+                                          struct sk_buff *skb))
 {
        int err = 0;
 
@@ -342,6 +344,8 @@ int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
                if (skb == skb_peek(&sk->sk_receive_queue)) {
                        __skb_unlink(skb, &sk->sk_receive_queue);
                        atomic_dec(&skb->users);
+                       if (destructor)
+                               destructor(sk, skb);
                        err = 0;
                }
                spin_unlock_bh(&sk->sk_receive_queue.lock);
@@ -375,7 +379,7 @@ EXPORT_SYMBOL(__sk_queue_drop_skb);
 
 int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
 {
-       int err = __sk_queue_drop_skb(sk, skb, flags);
+       int err = __sk_queue_drop_skb(sk, skb, flags, NULL);
 
        kfree_skb(skb);
        sk_mem_reclaim_partial(sk);
index 8db5a0b4b52061afe9cd44dead33cc69523d15df..29101c98399f40b6b8e42c31a255d8f1fb6bd7a1 100644 (file)
@@ -1695,24 +1695,19 @@ EXPORT_SYMBOL_GPL(net_dec_egress_queue);
 
 static struct static_key netstamp_needed __read_mostly;
 #ifdef HAVE_JUMP_LABEL
-/* We are not allowed to call static_key_slow_dec() from irq context
- * If net_disable_timestamp() is called from irq context, defer the
- * static_key_slow_dec() calls.
- */
 static atomic_t netstamp_needed_deferred;
-#endif
-
-void net_enable_timestamp(void)
+static void netstamp_clear(struct work_struct *work)
 {
-#ifdef HAVE_JUMP_LABEL
        int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
 
-       if (deferred) {
-               while (--deferred)
-                       static_key_slow_dec(&netstamp_needed);
-               return;
-       }
+       while (deferred--)
+               static_key_slow_dec(&netstamp_needed);
+}
+static DECLARE_WORK(netstamp_work, netstamp_clear);
 #endif
+
+void net_enable_timestamp(void)
+{
        static_key_slow_inc(&netstamp_needed);
 }
 EXPORT_SYMBOL(net_enable_timestamp);
@@ -1720,12 +1715,12 @@ EXPORT_SYMBOL(net_enable_timestamp);
 void net_disable_timestamp(void)
 {
 #ifdef HAVE_JUMP_LABEL
-       if (in_interrupt()) {
-               atomic_inc(&netstamp_needed_deferred);
-               return;
-       }
-#endif
+       /* net_disable_timestamp() can be called from non process context */
+       atomic_inc(&netstamp_needed_deferred);
+       schedule_work(&netstamp_work);
+#else
        static_key_slow_dec(&netstamp_needed);
+#endif
 }
 EXPORT_SYMBOL(net_disable_timestamp);
 
@@ -2795,9 +2790,9 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
        if (skb->ip_summed != CHECKSUM_NONE &&
            !can_checksum_protocol(features, type)) {
                features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
-       } else if (illegal_highdma(skb->dev, skb)) {
-               features &= ~NETIF_F_SG;
        }
+       if (illegal_highdma(skb->dev, skb))
+               features &= ~NETIF_F_SG;
 
        return features;
 }
@@ -4441,7 +4436,9 @@ static void skb_gro_reset_offset(struct sk_buff *skb)
            pinfo->nr_frags &&
            !PageHighMem(skb_frag_page(frag0))) {
                NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
-               NAPI_GRO_CB(skb)->frag0_len = skb_frag_size(frag0);
+               NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int,
+                                                   skb_frag_size(frag0),
+                                                   skb->end - skb->tail);
        }
 }
 
index e23766c7e3ba19414494d242af86c1029e8eee61..d92de0a1f0a49d51ec8329c65d46a4f2ae304ebd 100644 (file)
@@ -1405,9 +1405,12 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
        if (regs.len > reglen)
                regs.len = reglen;
 
-       regbuf = vzalloc(reglen);
-       if (reglen && !regbuf)
-               return -ENOMEM;
+       regbuf = NULL;
+       if (reglen) {
+               regbuf = vzalloc(reglen);
+               if (!regbuf)
+                       return -ENOMEM;
+       }
 
        ops->get_regs(dev, &regs, regbuf);
 
@@ -1712,7 +1715,7 @@ static noinline_for_stack int ethtool_get_channels(struct net_device *dev,
 static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
                                                   void __user *useraddr)
 {
-       struct ethtool_channels channels, max;
+       struct ethtool_channels channels, max = { .cmd = ETHTOOL_GCHANNELS };
        u32 max_rx_in_use = 0;
 
        if (!dev->ethtool_ops->set_channels || !dev->ethtool_ops->get_channels)
index fe4e1531976c3a36127b6ad4af33f24534af4c52..1b7673aac59d51a5f8b5ef3f2076f1440c017fae 100644 (file)
@@ -67,8 +67,8 @@ EXPORT_SYMBOL(skb_flow_dissector_init);
  * The function will try to retrieve a be32 entity at
  * offset poff
  */
-__be16 skb_flow_get_be16(const struct sk_buff *skb, int poff, void *data,
-                        int hlen)
+static __be16 skb_flow_get_be16(const struct sk_buff *skb, int poff,
+                               void *data, int hlen)
 {
        __be16 *u, _u;
 
index 71bb3e2eca080735a771a4c4eaf1a3b74b48da9e..b3eef90b2df9d05b62750d3d6fafd7b096f92bd9 100644 (file)
@@ -386,6 +386,7 @@ static const struct lwtunnel_encap_ops bpf_encap_ops = {
        .fill_encap     = bpf_fill_encap_info,
        .get_encap_size = bpf_encap_nlsize,
        .cmp_encap      = bpf_encap_cmp,
+       .owner          = THIS_MODULE,
 };
 
 static int __init bpf_lwt_init(void)
index a5d4e866ce88b4d055798d9ea55fc905b351fb3d..c23465005f2f4ced93d7bcb2754fb267c2cf00d0 100644 (file)
@@ -26,6 +26,7 @@
 #include <net/lwtunnel.h>
 #include <net/rtnetlink.h>
 #include <net/ip6_fib.h>
+#include <net/nexthop.h>
 
 #ifdef CONFIG_MODULES
 
@@ -114,25 +115,77 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
        ret = -EOPNOTSUPP;
        rcu_read_lock();
        ops = rcu_dereference(lwtun_encaps[encap_type]);
+       if (likely(ops && ops->build_state && try_module_get(ops->owner))) {
+               ret = ops->build_state(dev, encap, family, cfg, lws);
+               if (ret)
+                       module_put(ops->owner);
+       }
+       rcu_read_unlock();
+
+       return ret;
+}
+EXPORT_SYMBOL(lwtunnel_build_state);
+
+int lwtunnel_valid_encap_type(u16 encap_type)
+{
+       const struct lwtunnel_encap_ops *ops;
+       int ret = -EINVAL;
+
+       if (encap_type == LWTUNNEL_ENCAP_NONE ||
+           encap_type > LWTUNNEL_ENCAP_MAX)
+               return ret;
+
+       rcu_read_lock();
+       ops = rcu_dereference(lwtun_encaps[encap_type]);
+       rcu_read_unlock();
 #ifdef CONFIG_MODULES
        if (!ops) {
                const char *encap_type_str = lwtunnel_encap_str(encap_type);
 
                if (encap_type_str) {
-                       rcu_read_unlock();
+                       __rtnl_unlock();
                        request_module("rtnl-lwt-%s", encap_type_str);
+                       rtnl_lock();
+
                        rcu_read_lock();
                        ops = rcu_dereference(lwtun_encaps[encap_type]);
+                       rcu_read_unlock();
                }
        }
 #endif
-       if (likely(ops && ops->build_state))
-               ret = ops->build_state(dev, encap, family, cfg, lws);
-       rcu_read_unlock();
+       return ops ? 0 : -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(lwtunnel_valid_encap_type);
 
-       return ret;
+int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining)
+{
+       struct rtnexthop *rtnh = (struct rtnexthop *)attr;
+       struct nlattr *nla_entype;
+       struct nlattr *attrs;
+       struct nlattr *nla;
+       u16 encap_type;
+       int attrlen;
+
+       while (rtnh_ok(rtnh, remaining)) {
+               attrlen = rtnh_attrlen(rtnh);
+               if (attrlen > 0) {
+                       attrs = rtnh_attrs(rtnh);
+                       nla = nla_find(attrs, attrlen, RTA_ENCAP);
+                       nla_entype = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
+
+                       if (nla_entype) {
+                               encap_type = nla_get_u16(nla_entype);
+
+                               if (lwtunnel_valid_encap_type(encap_type) != 0)
+                                       return -EOPNOTSUPP;
+                       }
+               }
+               rtnh = rtnh_next(rtnh, &remaining);
+       }
+
+       return 0;
 }
-EXPORT_SYMBOL(lwtunnel_build_state);
+EXPORT_SYMBOL(lwtunnel_valid_encap_type_attr);
 
 void lwtstate_free(struct lwtunnel_state *lws)
 {
@@ -144,6 +197,7 @@ void lwtstate_free(struct lwtunnel_state *lws)
        } else {
                kfree(lws);
        }
+       module_put(ops->owner);
 }
 EXPORT_SYMBOL(lwtstate_free);
 
index 7bb12e07ffef4273e156893cc150ea5c9d79e8bd..e7c12caa20c88acc9a5dd86f07d11644fb58341d 100644 (file)
@@ -2923,7 +2923,8 @@ static void neigh_proc_update(struct ctl_table *ctl, int write)
                return;
 
        set_bit(index, p->data_state);
-       call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
+       if (index == NEIGH_VAR_DELAY_PROBE_TIME)
+               call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
        if (!dev) /* NULL dev means this is default value */
                neigh_copy_dflt_parms(net, p, index);
 }
index 5a03730fbc1a84376985d4d68d8b80d8f38b0985..734c71468b013838516cfe8c744dcd0e797a6e2b 100644 (file)
@@ -369,7 +369,7 @@ static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
 
        local_irq_save(flags);
        nc = this_cpu_ptr(&netdev_alloc_cache);
-       data = __alloc_page_frag(nc, fragsz, gfp_mask);
+       data = page_frag_alloc(nc, fragsz, gfp_mask);
        local_irq_restore(flags);
        return data;
 }
@@ -391,7 +391,7 @@ static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
 {
        struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
 
-       return __alloc_page_frag(&nc->page, fragsz, gfp_mask);
+       return page_frag_alloc(&nc->page, fragsz, gfp_mask);
 }
 
 void *napi_alloc_frag(unsigned int fragsz)
@@ -441,7 +441,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
        local_irq_save(flags);
 
        nc = this_cpu_ptr(&netdev_alloc_cache);
-       data = __alloc_page_frag(nc, len, gfp_mask);
+       data = page_frag_alloc(nc, len, gfp_mask);
        pfmemalloc = nc->pfmemalloc;
 
        local_irq_restore(flags);
@@ -505,7 +505,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
        if (sk_memalloc_socks())
                gfp_mask |= __GFP_MEMALLOC;
 
-       data = __alloc_page_frag(&nc->page, len, gfp_mask);
+       data = page_frag_alloc(&nc->page, len, gfp_mask);
        if (unlikely(!data))
                return NULL;
 
index f560e0826009851e79a1f8a8b90f4ded3cfc382d..4eca27dc5c9478e36120a5128a7c11d6208b45a9 100644 (file)
@@ -222,7 +222,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
   "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
   "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
   "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_KCM"      ,
-  "sk_lock-AF_MAX"
+  "sk_lock-AF_QIPCRTR", "sk_lock-AF_MAX"
 };
 static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
@@ -239,7 +239,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
   "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
   "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
   "slock-AF_NFC"   , "slock-AF_VSOCK"    ,"slock-AF_KCM"       ,
-  "slock-AF_MAX"
+  "slock-AF_QIPCRTR", "slock-AF_MAX"
 };
 static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
@@ -256,7 +256,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
   "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
   "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
   "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_KCM"      ,
-  "clock-AF_MAX"
+  "clock-AF_QIPCRTR", "clock-AF_MAX"
 };
 
 /*
index ba347184bda9b3fee1f86db847352ab133ddaa3f..8fedc2d497709b3dea9202894f45bf5cab043361 100644 (file)
@@ -606,7 +606,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                        if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
                                                                    skb) < 0)
                                return 1;
-                       goto discard;
+                       consume_skb(skb);
+                       return 0;
                }
                if (dh->dccph_type == DCCP_PKT_RESET)
                        goto discard;
index adfc790f71935913801f90d3ab46b7c133af4ec3..c4e879c021868719d928f49e2ef2f5c5d1876534 100644 (file)
@@ -227,7 +227,7 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
                opt = ireq->ipv6_opt;
                if (!opt)
                        opt = rcu_dereference(np->opt);
-               err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
+               err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -281,7 +281,7 @@ static void dccp_v6_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
        dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
        if (!IS_ERR(dst)) {
                skb_dst_set(skb, dst);
-               ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
+               ip6_xmit(ctl_sk, skb, &fl6, 0, NULL, 0);
                DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
                DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
                return;
index 5fff951a0a4928ccf28fb681be86c7df6a05e94f..0f99297b2fb3517942bf74fee08ed3e61d65a4f0 100644 (file)
@@ -273,6 +273,7 @@ static int dsa_user_port_apply(struct device_node *port, u32 index,
        if (err) {
                dev_warn(ds->dev, "Failed to create slave %d: %d\n",
                         index, err);
+               ds->ports[index].netdev = NULL;
                return err;
        }
 
@@ -394,9 +395,11 @@ static int dsa_dst_apply(struct dsa_switch_tree *dst)
                        return err;
        }
 
-       err = dsa_cpu_port_ethtool_setup(dst->ds[0]);
-       if (err)
-               return err;
+       if (dst->ds[0]) {
+               err = dsa_cpu_port_ethtool_setup(dst->ds[0]);
+               if (err)
+                       return err;
+       }
 
        /* If we use a tagging format that doesn't have an ethertype
         * field, make sure that all packets from this point on get
@@ -433,7 +436,8 @@ static void dsa_dst_unapply(struct dsa_switch_tree *dst)
                dsa_ds_unapply(dst, ds);
        }
 
-       dsa_cpu_port_ethtool_restore(dst->ds[0]);
+       if (dst->ds[0])
+               dsa_cpu_port_ethtool_restore(dst->ds[0]);
 
        pr_info("DSA: tree %d unapplied\n", dst->tree);
        dst->applied = false;
index 68c9eea0051872eb151ee7d05f92dcc4638e3db6..7d45961108511488003380da656bf8a4f2fd7d84 100644 (file)
@@ -1105,10 +1105,8 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
        /* Use already configured phy mode */
        if (p->phy_interface == PHY_INTERFACE_MODE_NA)
                p->phy_interface = p->phy->interface;
-       phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
-                          p->phy_interface);
-
-       return 0;
+       return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
+                                 p->phy_interface);
 }
 
 static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
@@ -1203,6 +1201,8 @@ int dsa_slave_suspend(struct net_device *slave_dev)
 {
        struct dsa_slave_priv *p = netdev_priv(slave_dev);
 
+       netif_device_detach(slave_dev);
+
        if (p->phy) {
                phy_stop(p->phy);
                p->old_pause = -1;
index 8c5a479681ca9ed8c2686208fc570e819a4db31a..516c87e75de7009e9e4f0cbdc80f8160c318fdf4 100644 (file)
@@ -356,6 +356,7 @@ void ether_setup(struct net_device *dev)
        dev->header_ops         = &eth_header_ops;
        dev->type               = ARPHRD_ETHER;
        dev->hard_header_len    = ETH_HLEN;
+       dev->min_header_len     = ETH_HLEN;
        dev->mtu                = ETH_DATA_LEN;
        dev->min_mtu            = ETH_MIN_MTU;
        dev->max_mtu            = ETH_DATA_LEN;
index 89a8cac4726a5e354371bb0c76a7e60cd2d7026e..51b27ae09fbd725bcd8030982e5850215ac4ce5c 100644 (file)
@@ -1263,7 +1263,7 @@ void __init arp_init(void)
 /*
  *     ax25 -> ASCII conversion
  */
-static char *ax2asc2(ax25_address *a, char *buf)
+static void ax2asc2(ax25_address *a, char *buf)
 {
        char c, *s;
        int n;
@@ -1285,10 +1285,10 @@ static char *ax2asc2(ax25_address *a, char *buf)
        *s++ = n + '0';
        *s++ = '\0';
 
-       if (*buf == '\0' || *buf == '-')
-               return "*";
-
-       return buf;
+       if (*buf == '\0' || *buf == '-') {
+               buf[0] = '*';
+               buf[1] = '\0';
+       }
 }
 #endif /* CONFIG_AX25 */
 
@@ -1322,7 +1322,7 @@ static void arp_format_neigh_entry(struct seq_file *seq,
        }
 #endif
        sprintf(tbuf, "%pI4", n->primary_key);
-       seq_printf(seq, "%-16s 0x%-10x0x%-10x%s     *        %s\n",
+       seq_printf(seq, "%-16s 0x%-10x0x%-10x%-17s     *        %s\n",
                   tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name);
        read_unlock(&n->lock);
 }
index 72d6f056d863603c959e1d04b9f863909a37c758..ae206163c273381ba6e8bd8a24fa050619a4a6ae 100644 (file)
@@ -1587,6 +1587,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option)
                                goto validate_return_locked;
                        }
 
+               if (opt_iter + 1 == opt_len) {
+                       err_offset = opt_iter;
+                       goto validate_return_locked;
+               }
                tag_len = tag[1];
                if (tag_len > (opt_len - opt_iter)) {
                        err_offset = opt_iter + 1;
index eae0332b0e8c1f861ce629ed9ce3ddc45802a6b8..7db2ad2e82d3193ff1748bf393f536ba3a5a3eb9 100644 (file)
@@ -46,6 +46,7 @@
 #include <net/rtnetlink.h>
 #include <net/xfrm.h>
 #include <net/l3mdev.h>
+#include <net/lwtunnel.h>
 #include <trace/events/fib.h>
 
 #ifndef CONFIG_IP_MULTIPLE_TABLES
@@ -677,6 +678,10 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
                        cfg->fc_mx_len = nla_len(attr);
                        break;
                case RTA_MULTIPATH:
+                       err = lwtunnel_valid_encap_type_attr(nla_data(attr),
+                                                            nla_len(attr));
+                       if (err < 0)
+                               goto errout;
                        cfg->fc_mp = nla_data(attr);
                        cfg->fc_mp_len = nla_len(attr);
                        break;
@@ -691,6 +696,9 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
                        break;
                case RTA_ENCAP_TYPE:
                        cfg->fc_encap_type = nla_get_u16(attr);
+                       err = lwtunnel_valid_encap_type(cfg->fc_encap_type);
+                       if (err < 0)
+                               goto errout;
                        break;
                }
        }
index 7a5b4c7d9a87b18051a94aa2e16e6b85c8d85aa6..9a375b908d01fae08b46b46df2e2579a4c268027 100644 (file)
@@ -1279,8 +1279,9 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
                    nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))
                        goto nla_put_failure;
 #endif
-               if (fi->fib_nh->nh_lwtstate)
-                       lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate);
+               if (fi->fib_nh->nh_lwtstate &&
+                   lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate) < 0)
+                       goto nla_put_failure;
        }
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
        if (fi->fib_nhs > 1) {
@@ -1316,8 +1317,10 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
                            nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
                                goto nla_put_failure;
 #endif
-                       if (nh->nh_lwtstate)
-                               lwtunnel_fill_encap(skb, nh->nh_lwtstate);
+                       if (nh->nh_lwtstate &&
+                           lwtunnel_fill_encap(skb, nh->nh_lwtstate) < 0)
+                               goto nla_put_failure;
+
                        /* length of rtnetlink header + attributes */
                        rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
                } endfor_nexthops(fi);
@@ -1618,8 +1621,13 @@ void fib_select_multipath(struct fib_result *res, int hash)
 void fib_select_path(struct net *net, struct fib_result *res,
                     struct flowi4 *fl4, int mp_hash)
 {
+       bool oif_check;
+
+       oif_check = (fl4->flowi4_oif == 0 ||
+                    fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF);
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-       if (res->fi->fib_nhs > 1 && fl4->flowi4_oif == 0) {
+       if (res->fi->fib_nhs > 1 && oif_check) {
                if (mp_hash < 0)
                        mp_hash = get_hash_from_flowi4(fl4) >> 1;
 
@@ -1629,7 +1637,7 @@ void fib_select_path(struct net *net, struct fib_result *res,
 #endif
        if (!res->prefixlen &&
            res->table->tb_num_default > 1 &&
-           res->type == RTN_UNICAST && !fl4->flowi4_oif)
+           res->type == RTN_UNICAST && oif_check)
                fib_select_default(fl4, res);
 
        if (!fl4->saddr)
index 5b15459955f84cfc26dd2b12f129b1ee4014e62b..44fd86de2823dd17de16276a8ec01b190e69b8b4 100644 (file)
@@ -1172,6 +1172,7 @@ static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im)
                                psf->sf_crcount = im->crcount;
                }
                in_dev_put(pmc->interface);
+               kfree(pmc);
        }
        spin_unlock_bh(&im->lock);
 }
index fac275c4810865a5b9b9ca1ac9fc826b8482aa9f..b67719f459537d49d958de9874414ea868c4a8e1 100644 (file)
@@ -1629,6 +1629,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
        sk->sk_protocol = ip_hdr(skb)->protocol;
        sk->sk_bound_dev_if = arg->bound_dev_if;
        sk->sk_sndbuf = sysctl_wmem_default;
+       sk->sk_mark = fl4.flowi4_mark;
        err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
                             len, 0, &ipc, &rt, MSG_DONTWAIT);
        if (unlikely(err)) {
index 53ae0c6315ad03e46f93ae68cb930fff5848edcd..900011709e3b8e4807daaa6bf537c3871a7d9306 100644 (file)
@@ -1238,7 +1238,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
                pktinfo->ipi_ifindex = 0;
                pktinfo->ipi_spec_dst.s_addr = 0;
        }
-       skb_dst_drop(skb);
+       /* We need to keep the dst for __ip_options_echo()
+        * We could restrict the test to opt.ts_needtime || opt.srr,
+        * but the following is good enough as IP options are not often used.
+        */
+       if (unlikely(IPCB(skb)->opt.optlen))
+               skb_dst_force(skb);
+       else
+               skb_dst_drop(skb);
 }
 
 int ip_setsockopt(struct sock *sk, int level,
index fed3d29f9eb3b716664b8d9eba052695cbb867bd..0fd1976ab63bbd9be357e41b9acd71dcfa507665 100644 (file)
@@ -313,6 +313,7 @@ static const struct lwtunnel_encap_ops ip_tun_lwt_ops = {
        .fill_encap = ip_tun_fill_encap_info,
        .get_encap_size = ip_tun_encap_nlsize,
        .cmp_encap = ip_tun_cmp_encap,
+       .owner = THIS_MODULE,
 };
 
 static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
@@ -403,6 +404,7 @@ static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = {
        .fill_encap = ip6_tun_fill_encap_info,
        .get_encap_size = ip6_tun_encap_nlsize,
        .cmp_encap = ip_tun_cmp_encap,
+       .owner = THIS_MODULE,
 };
 
 void __init ip_tunnel_core_init(void)
index 21db00d0362bb60d48aed2c900b857f86cef5793..0a783cd73faf25d9ec4d7605759038e4e0aef345 100644 (file)
@@ -144,6 +144,11 @@ clusterip_config_find_get(struct net *net, __be32 clusterip, int entry)
        rcu_read_lock_bh();
        c = __clusterip_config_find(net, clusterip);
        if (c) {
+#ifdef CONFIG_PROC_FS
+               if (!c->pde)
+                       c = NULL;
+               else
+#endif
                if (unlikely(!atomic_inc_not_zero(&c->refcount)))
                        c = NULL;
                else if (entry)
@@ -166,14 +171,15 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
 
 static struct clusterip_config *
 clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
-                       struct net_device *dev)
+                     struct net_device *dev)
 {
+       struct net *net = dev_net(dev);
        struct clusterip_config *c;
-       struct clusterip_net *cn = net_generic(dev_net(dev), clusterip_net_id);
+       struct clusterip_net *cn = net_generic(net, clusterip_net_id);
 
        c = kzalloc(sizeof(*c), GFP_ATOMIC);
        if (!c)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        c->dev = dev;
        c->clusterip = ip;
@@ -185,6 +191,17 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
        atomic_set(&c->refcount, 1);
        atomic_set(&c->entries, 1);
 
+       spin_lock_bh(&cn->lock);
+       if (__clusterip_config_find(net, ip)) {
+               spin_unlock_bh(&cn->lock);
+               kfree(c);
+
+               return ERR_PTR(-EBUSY);
+       }
+
+       list_add_rcu(&c->list, &cn->configs);
+       spin_unlock_bh(&cn->lock);
+
 #ifdef CONFIG_PROC_FS
        {
                char buffer[16];
@@ -195,16 +212,16 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
                                          cn->procdir,
                                          &clusterip_proc_fops, c);
                if (!c->pde) {
+                       spin_lock_bh(&cn->lock);
+                       list_del_rcu(&c->list);
+                       spin_unlock_bh(&cn->lock);
                        kfree(c);
-                       return NULL;
+
+                       return ERR_PTR(-ENOMEM);
                }
        }
 #endif
 
-       spin_lock_bh(&cn->lock);
-       list_add_rcu(&c->list, &cn->configs);
-       spin_unlock_bh(&cn->lock);
-
        return c;
 }
 
@@ -410,9 +427,9 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
 
                        config = clusterip_config_init(cipinfo,
                                                        e->ip.dst.s_addr, dev);
-                       if (!config) {
+                       if (IS_ERR(config)) {
                                dev_put(dev);
-                               return -ENOMEM;
+                               return PTR_ERR(config);
                        }
                        dev_mc_add(config->dev, config->clustermac);
                }
index f273098e48fd5bbe0ffb95c0daeb315c3a6f06f1..37fb9552e85898d0ee9b311f22af31563c621de7 100644 (file)
@@ -63,10 +63,10 @@ static bool rpfilter_lookup_reverse(struct net *net, struct flowi4 *fl4,
        return dev_match || flags & XT_RPFILTER_LOOSE;
 }
 
-static bool rpfilter_is_local(const struct sk_buff *skb)
+static bool
+rpfilter_is_loopback(const struct sk_buff *skb, const struct net_device *in)
 {
-       const struct rtable *rt = skb_rtable(skb);
-       return rt && (rt->rt_flags & RTCF_LOCAL);
+       return skb->pkt_type == PACKET_LOOPBACK || in->flags & IFF_LOOPBACK;
 }
 
 static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
@@ -79,7 +79,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        info = par->matchinfo;
        invert = info->flags & XT_RPFILTER_INVERT;
 
-       if (rpfilter_is_local(skb))
+       if (rpfilter_is_loopback(skb, xt_in(par)))
                return true ^ invert;
 
        iph = ip_hdr(skb);
index fd8220213afc36375f83d0af902443cf2f5a4a8f..146d86105183e1a456a0f17ed6bb5371aa1e8f76 100644 (file)
@@ -126,6 +126,8 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
        /* ip_route_me_harder expects skb->dst to be set */
        skb_dst_set_noref(nskb, skb_dst(oldskb));
 
+       nskb->mark = IP4_REPLY_MARK(net, oldskb->mark);
+
        skb_reserve(nskb, LL_MAX_HEADER);
        niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
                                   ip4_dst_hoplimit(skb_dst(nskb)));
index 965b1a161369323e37dd5f103c34cbc3e4e901b5..2981291910dd2cac2d508fcde89083afc22affd4 100644 (file)
@@ -26,13 +26,6 @@ static __be32 get_saddr(__be32 addr)
        return addr;
 }
 
-static bool fib4_is_local(const struct sk_buff *skb)
-{
-       const struct rtable *rt = skb_rtable(skb);
-
-       return rt && (rt->rt_flags & RTCF_LOCAL);
-}
-
 #define DSCP_BITS     0xfc
 
 void nft_fib4_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
@@ -95,8 +88,10 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
        else
                oif = NULL;
 
-       if (nft_hook(pkt) == NF_INET_PRE_ROUTING && fib4_is_local(pkt->skb)) {
-               nft_fib_store_result(dest, priv->result, pkt, LOOPBACK_IFINDEX);
+       if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
+           nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
+               nft_fib_store_result(dest, priv->result, pkt,
+                                    nft_in(pkt)->ifindex);
                return;
        }
 
@@ -131,7 +126,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
        switch (res.type) {
        case RTN_UNICAST:
                break;
-       case RTN_LOCAL: /* should not appear here, see fib4_is_local() above */
+       case RTN_LOCAL: /* Should not see RTN_LOCAL here */
                return;
        default:
                break;
index 86cca610f4c2c368476dee3602d1f74ac2cd5794..68d77b1f1495bb8dace1f6aa9c0e9a6ee5b2e5dd 100644 (file)
@@ -642,6 +642,8 @@ static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh,
 {
        struct sk_buff *skb = skb_peek(&sk->sk_write_queue);
 
+       if (!skb)
+               return 0;
        pfh->wcheck = csum_partial((char *)&pfh->icmph,
                sizeof(struct icmphdr), pfh->wcheck);
        pfh->icmph.checksum = csum_fold(pfh->wcheck);
index 0fcac8e7a2b2fb9fdb9f74bdcadf32bd177ceb39..709ffe67d1de1609be7d3e4a98d9314b01e5f265 100644 (file)
@@ -2472,7 +2472,7 @@ static int rt_fill_info(struct net *net,  __be32 dst, __be32 src, u32 table_id,
        r->rtm_dst_len  = 32;
        r->rtm_src_len  = 0;
        r->rtm_tos      = fl4->flowi4_tos;
-       r->rtm_table    = table_id;
+       r->rtm_table    = table_id < 256 ? table_id : RT_TABLE_COMPAT;
        if (nla_put_u32(skb, RTA_TABLE, table_id))
                goto nla_put_failure;
        r->rtm_type     = rt->rt_type;
index 22cbd61079b5a9d2661583b7d96eea46eddb685d..b2fa498b15d173739d0ebc5b6dd0577bf8dc4c08 100644 (file)
@@ -951,7 +951,7 @@ static struct ctl_table ipv4_net_table[] = {
                .data           = &init_net.ipv4.sysctl_tcp_notsent_lowat,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_douintvec,
        },
        {
                .procname       = "tcp_tw_reuse",
index 4a044964da6670829e5c47fef52d2cd76360b59f..0efb4c7f6704f662b6c762e48698a41564add2a4 100644 (file)
@@ -770,6 +770,12 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
                                ret = -EAGAIN;
                                break;
                        }
+                       /* if __tcp_splice_read() got nothing while we have
+                        * an skb in receive queue, we do not want to loop.
+                        * This might happen with URG data.
+                        */
+                       if (!skb_queue_empty(&sk->sk_receive_queue))
+                               break;
                        sk_wait_data(sk, &timeo, NULL);
                        if (signal_pending(current)) {
                                ret = sock_intr_errno(timeo);
index 4e777a3243f94457d9928e3967bb83947da563f6..dd2560c83a8592359af70919bddb4a628630b0b3 100644 (file)
@@ -113,7 +113,7 @@ static bool tcp_fastopen_cookie_gen(struct request_sock *req,
                struct tcp_fastopen_cookie tmp;
 
                if (__tcp_fastopen_cookie_gen(&ip6h->saddr, &tmp)) {
-                       struct in6_addr *buf = (struct in6_addr *) tmp.val;
+                       struct in6_addr *buf = &tmp.addr;
                        int i;
 
                        for (i = 0; i < 4; i++)
@@ -205,6 +205,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
         * scaled. So correct it appropriately.
         */
        tp->snd_wnd = ntohs(tcp_hdr(skb)->window);
+       tp->max_window = tp->snd_wnd;
 
        /* Activate the retrans timer so that SYNACK can be retransmitted.
         * The request socket is not added to the ehash
index 6c790754ae3ebfad5d31499eabbed7b5c3b360c4..41dcbd568cbe2403f2a9e659669afe462a42e228 100644 (file)
@@ -5078,7 +5078,7 @@ static void tcp_check_space(struct sock *sk)
        if (sock_flag(sk, SOCK_QUEUE_SHRUNK)) {
                sock_reset_flag(sk, SOCK_QUEUE_SHRUNK);
                /* pairs with tcp_poll() */
-               smp_mb__after_atomic();
+               smp_mb();
                if (sk->sk_socket &&
                    test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
                        tcp_new_space(sk);
index d46f4d5b1c62edf95791e9d47d966c3bc61e1888..ba8f02d0f283c6eaaf14ed89103adea135093353 100644 (file)
@@ -606,7 +606,6 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst,
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(tcp_peer_is_proven);
 
 void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst)
 {
index 1d5331a1b1dc2677316148ba9852c191e7ed0fd4..8ce50dc3ab8cac821b8a2c3e0d31f0aa42f5c9d5 100644 (file)
@@ -2518,9 +2518,11 @@ u32 __tcp_select_window(struct sock *sk)
        int full_space = min_t(int, tp->window_clamp, allowed_space);
        int window;
 
-       if (mss > full_space)
+       if (unlikely(mss > full_space)) {
                mss = full_space;
-
+               if (mss <= 0)
+                       return 0;
+       }
        if (free_space < (full_space >> 1)) {
                icsk->icsk_ack.quick = 0;
 
index f6c50af24a64737672f7ede2ff41158bfed5f1b4..3d063eb3784828b142874c92fd2db026bea0f3b3 100644 (file)
@@ -117,7 +117,7 @@ static void jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
             (fwmark > 0 && skb->mark == fwmark)) &&
            (full || tp->snd_cwnd != tcp_probe.lastcwnd)) {
 
-               spin_lock(&tcp_probe.lock);
+               spin_lock_bh(&tcp_probe.lock);
                /* If log fills, just silently drop */
                if (tcp_probe_avail() > 1) {
                        struct tcp_log *p = tcp_probe.log + tcp_probe.head;
@@ -157,7 +157,7 @@ static void jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                        tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1);
                }
                tcp_probe.lastcwnd = tp->snd_cwnd;
-               spin_unlock(&tcp_probe.lock);
+               spin_unlock_bh(&tcp_probe.lock);
 
                wake_up(&tcp_probe.wait);
        }
index 1307a7c2e5445d37d1d1c4f5fbfd5bf7c29040d7..8aab7d78d25bc6eaa42dcc960cdbd5086f614cad 100644 (file)
@@ -1501,7 +1501,7 @@ try_again:
        return err;
 
 csum_copy_err:
-       if (!__sk_queue_drop_skb(sk, skb, flags)) {
+       if (!__sk_queue_drop_skb(sk, skb, flags, udp_skb_destructor)) {
                UDP_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
                UDP_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
        }
index c1e124bc8e1e3fcab42290acd8888e42d93ccf50..a7bcc0ab5e99543a08410abe6ff3dbfc9b3753b7 100644 (file)
@@ -3386,9 +3386,15 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                        }
 
                        if (idev) {
-                               if (idev->if_flags & IF_READY)
-                                       /* device is already configured. */
+                               if (idev->if_flags & IF_READY) {
+                                       /* device is already configured -
+                                        * but resend MLD reports, we might
+                                        * have roamed and need to update
+                                        * multicast snooping switches
+                                        */
+                                       ipv6_mc_up(idev);
                                        break;
+                               }
                                idev->if_flags |= IF_READY;
                        }
 
@@ -4009,6 +4015,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id)
 
        if (bump_id)
                rt_genid_bump_ipv6(dev_net(dev));
+
+       /* Make sure that a new temporary address will be created
+        * before this temporary address becomes deprecated.
+        */
+       if (ifp->flags & IFA_F_TEMPORARY)
+               addrconf_verify_rtnl();
 }
 
 static void addrconf_dad_run(struct inet6_dev *idev)
@@ -5540,8 +5552,7 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
        struct net_device *dev;
        struct inet6_dev *idev;
 
-       rcu_read_lock();
-       for_each_netdev_rcu(net, dev) {
+       for_each_netdev(net, dev) {
                idev = __in6_dev_get(dev);
                if (idev) {
                        int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
@@ -5550,7 +5561,6 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
                                dev_disable_change(idev);
                }
        }
-       rcu_read_unlock();
 }
 
 static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
index a3eaafd8710091c0484a5c608862d13808d612b3..eec27f87efaca15133cf1d5225e37e6a2f6a6f8a 100644 (file)
@@ -167,18 +167,22 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
        if (np->sndflow)
                fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
 
-       addr_type = ipv6_addr_type(&usin->sin6_addr);
-
-       if (addr_type == IPV6_ADDR_ANY) {
+       if (ipv6_addr_any(&usin->sin6_addr)) {
                /*
                 *      connect to self
                 */
-               usin->sin6_addr.s6_addr[15] = 0x01;
+               if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+                       ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+                                              &usin->sin6_addr);
+               else
+                       usin->sin6_addr = in6addr_loopback;
        }
 
+       addr_type = ipv6_addr_type(&usin->sin6_addr);
+
        daddr = &usin->sin6_addr;
 
-       if (addr_type == IPV6_ADDR_MAPPED) {
+       if (addr_type & IPV6_ADDR_MAPPED) {
                struct sockaddr_in sin;
 
                if (__ipv6_only_sock(sk)) {
index e4198502fd98ce55c1ab6d4d9767b8506b2cf707..275cac628a95066f0a27e93f5015ddeb0172c28c 100644 (file)
@@ -327,7 +327,6 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
        struct ipv6_sr_hdr *hdr;
        struct inet6_dev *idev;
        struct in6_addr *addr;
-       bool cleanup = false;
        int accept_seg6;
 
        hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
@@ -351,11 +350,7 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
 #endif
 
 looped_back:
-       if (hdr->segments_left > 0) {
-               if (hdr->nexthdr != NEXTHDR_IPV6 && hdr->segments_left == 1 &&
-                   sr_has_cleanup(hdr))
-                       cleanup = true;
-       } else {
+       if (hdr->segments_left == 0) {
                if (hdr->nexthdr == NEXTHDR_IPV6) {
                        int offset = (hdr->hdrlen + 1) << 3;
 
@@ -418,21 +413,6 @@ looped_back:
 
        ipv6_hdr(skb)->daddr = *addr;
 
-       if (cleanup) {
-               int srhlen = (hdr->hdrlen + 1) << 3;
-               int nh = hdr->nexthdr;
-
-               skb_pull_rcsum(skb, sizeof(struct ipv6hdr) + srhlen);
-               memmove(skb_network_header(skb) + srhlen,
-                       skb_network_header(skb),
-                       (unsigned char *)hdr - skb_network_header(skb));
-               skb->network_header += srhlen;
-               ipv6_hdr(skb)->nexthdr = nh;
-               ipv6_hdr(skb)->payload_len = htons(skb->len -
-                                                  sizeof(struct ipv6hdr));
-               skb_push_rcsum(skb, sizeof(struct ipv6hdr));
-       }
-
        skb_dst_drop(skb);
 
        ip6_route_input(skb);
@@ -453,13 +433,8 @@ looped_back:
                }
                ipv6_hdr(skb)->hop_limit--;
 
-               /* be sure that srh is still present before reinjecting */
-               if (!cleanup) {
-                       skb_pull(skb, sizeof(struct ipv6hdr));
-                       goto looped_back;
-               }
-               skb_set_transport_header(skb, sizeof(struct ipv6hdr));
-               IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
+               skb_pull(skb, sizeof(struct ipv6hdr));
+               goto looped_back;
        }
 
        dst_input(skb);
index a7bc54ab46e2d10ab18abdc3fcef511f06574343..13b5e85fe0d56471ab792b1e75801def3800ee9c 100644 (file)
@@ -238,6 +238,7 @@ static const struct lwtunnel_encap_ops ila_encap_ops = {
        .fill_encap = ila_fill_encap_info,
        .get_encap_size = ila_encap_nlsize,
        .cmp_encap = ila_encap_cmp,
+       .owner = THIS_MODULE,
 };
 
 int ila_lwt_init(void)
index 7396e75e161b83ee2b8a426bce0eb770884960dd..75c308239243305a508e62d01814d88da7248018 100644 (file)
@@ -176,7 +176,7 @@ int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused
        /* Restore final destination back after routing done */
        fl6.daddr = sk->sk_v6_daddr;
 
-       res = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
+       res = ip6_xmit(sk, skb, &fl6, sk->sk_mark, rcu_dereference(np->opt),
                       np->tclass);
        rcu_read_unlock();
        return res;
index 75b6108234dd05a54af0ae51c7c11eaf1ca26d75..630b73be599977599c0021849fc6eb689cfefad7 100644 (file)
@@ -367,35 +367,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev)
 
 
 static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-               u8 type, u8 code, int offset, __be32 info)
+                      u8 type, u8 code, int offset, __be32 info)
 {
-       const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data;
-       __be16 *p = (__be16 *)(skb->data + offset);
-       int grehlen = offset + 4;
+       const struct gre_base_hdr *greh;
+       const struct ipv6hdr *ipv6h;
+       int grehlen = sizeof(*greh);
        struct ip6_tnl *t;
+       int key_off = 0;
        __be16 flags;
+       __be32 key;
 
-       flags = p[0];
-       if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
-               if (flags&(GRE_VERSION|GRE_ROUTING))
-                       return;
-               if (flags&GRE_KEY) {
-                       grehlen += 4;
-                       if (flags&GRE_CSUM)
-                               grehlen += 4;
-               }
+       if (!pskb_may_pull(skb, offset + grehlen))
+               return;
+       greh = (const struct gre_base_hdr *)(skb->data + offset);
+       flags = greh->flags;
+       if (flags & (GRE_VERSION | GRE_ROUTING))
+               return;
+       if (flags & GRE_CSUM)
+               grehlen += 4;
+       if (flags & GRE_KEY) {
+               key_off = grehlen + offset;
+               grehlen += 4;
        }
 
-       /* If only 8 bytes returned, keyed message will be dropped here */
-       if (!pskb_may_pull(skb, grehlen))
+       if (!pskb_may_pull(skb, offset + grehlen))
                return;
        ipv6h = (const struct ipv6hdr *)skb->data;
-       p = (__be16 *)(skb->data + offset);
+       greh = (const struct gre_base_hdr *)(skb->data + offset);
+       key = key_off ? *(__be32 *)(skb->data + key_off) : 0;
 
        t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,
-                               flags & GRE_KEY ?
-                               *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
-                               p[1]);
+                                key, greh->protocol);
        if (!t)
                return;
 
@@ -582,6 +584,9 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
                return -1;
 
        offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+       /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+       ipv6h = ipv6_hdr(skb);
+
        if (offset > 0) {
                struct ipv6_tlv_tnl_enc_lim *tel;
                tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
index 89c59e656f44939863ceada610d3442d2de666ba..fc7b4017ba241f9dd39d49bd6258ecd4a16e3a3a 100644 (file)
@@ -191,6 +191,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
        ops = rcu_dereference(inet6_offloads[proto]);
        if (!ops || !ops->callbacks.gro_receive) {
                __pskb_pull(skb, skb_gro_offset(skb));
+               skb_gro_frag0_invalidate(skb);
                proto = ipv6_gso_pull_exthdrs(skb, proto);
                skb_gro_pull(skb, -skb_transport_offset(skb));
                skb_reset_transport_header(skb);
index 38122d04fadc646c27a5ccdf0eef5eb6d7923a27..7cebee58e55b7f6f23279ac2515a69df936b5712 100644 (file)
@@ -172,7 +172,7 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
  * which are using proper atomic operations or spinlocks.
  */
 int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
-            struct ipv6_txoptions *opt, int tclass)
+            __u32 mark, struct ipv6_txoptions *opt, int tclass)
 {
        struct net *net = sock_net(sk);
        const struct ipv6_pinfo *np = inet6_sk(sk);
@@ -240,7 +240,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
 
        skb->protocol = htons(ETH_P_IPV6);
        skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->mark = mark;
 
        mtu = dst_mtu(dst);
        if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
@@ -1021,6 +1021,11 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
                }
        }
 #endif
+       if (ipv6_addr_v4mapped(&fl6->saddr) &&
+           !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) {
+               err = -EAFNOSUPPORT;
+               goto out_err_release;
+       }
 
        return 0;
 
@@ -1344,7 +1349,7 @@ emsgsize:
         */
        if (transhdrlen && sk->sk_protocol == IPPROTO_UDP &&
            headersize == sizeof(struct ipv6hdr) &&
-           length < mtu - headersize &&
+           length <= mtu - headersize &&
            !(flags & MSG_MORE) &&
            rt->dst.dev->features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM))
                csummode = CHECKSUM_PARTIAL;
index 36d2921809428eb520256dffb39393ed023b7ec7..75fac933c209a0f430279dea10b5dd2426a7ed31 100644 (file)
@@ -400,18 +400,19 @@ ip6_tnl_dev_uninit(struct net_device *dev)
 
 __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
 {
-       const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw;
-       __u8 nexthdr = ipv6h->nexthdr;
-       __u16 off = sizeof(*ipv6h);
+       const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw;
+       unsigned int nhoff = raw - skb->data;
+       unsigned int off = nhoff + sizeof(*ipv6h);
+       u8 next, nexthdr = ipv6h->nexthdr;
 
        while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) {
-               __u16 optlen = 0;
                struct ipv6_opt_hdr *hdr;
-               if (raw + off + sizeof(*hdr) > skb->data &&
-                   !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr)))
+               u16 optlen;
+
+               if (!pskb_may_pull(skb, off + sizeof(*hdr)))
                        break;
 
-               hdr = (struct ipv6_opt_hdr *) (raw + off);
+               hdr = (struct ipv6_opt_hdr *)(skb->data + off);
                if (nexthdr == NEXTHDR_FRAGMENT) {
                        struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr;
                        if (frag_hdr->frag_off)
@@ -422,20 +423,29 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
                } else {
                        optlen = ipv6_optlen(hdr);
                }
+               /* cache hdr->nexthdr, since pskb_may_pull() might
+                * invalidate hdr
+                */
+               next = hdr->nexthdr;
                if (nexthdr == NEXTHDR_DEST) {
-                       __u16 i = off + 2;
+                       u16 i = 2;
+
+                       /* Remember : hdr is no longer valid at this point. */
+                       if (!pskb_may_pull(skb, off + optlen))
+                               break;
+
                        while (1) {
                                struct ipv6_tlv_tnl_enc_lim *tel;
 
                                /* No more room for encapsulation limit */
-                               if (i + sizeof (*tel) > off + optlen)
+                               if (i + sizeof(*tel) > optlen)
                                        break;
 
-                               tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i];
+                               tel = (struct ipv6_tlv_tnl_enc_lim *)(skb->data + off + i);
                                /* return index of option if found and valid */
                                if (tel->type == IPV6_TLV_TNL_ENCAP_LIMIT &&
                                    tel->length == 1)
-                                       return i;
+                                       return i + off - nhoff;
                                /* else jump to next option */
                                if (tel->type)
                                        i += tel->length + 2;
@@ -443,7 +453,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw)
                                        i++;
                        }
                }
-               nexthdr = hdr->nexthdr;
+               nexthdr = next;
                off += optlen;
        }
        return 0;
@@ -1108,7 +1118,7 @@ route_lookup:
                                     t->parms.name);
                goto tx_err_dst_release;
        }
-       mtu = dst_mtu(dst) - psh_hlen;
+       mtu = dst_mtu(dst) - psh_hlen - t->tun_hlen;
        if (encap_limit >= 0) {
                max_headroom += 8;
                mtu -= 8;
@@ -1117,7 +1127,7 @@ route_lookup:
                mtu = IPV6_MIN_MTU;
        if (skb_dst(skb) && !t->parms.collect_md)
                skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
-       if (skb->len > mtu && !skb_is_gso(skb)) {
+       if (skb->len - t->tun_hlen > mtu && !skb_is_gso(skb)) {
                *pmtu = mtu;
                err = -EMSGSIZE;
                goto tx_err_dst_release;
@@ -1303,6 +1313,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
                fl6.flowlabel = key->label;
        } else {
                offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+               /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+               ipv6h = ipv6_hdr(skb);
                if (offset > 0) {
                        struct ipv6_tlv_tnl_enc_lim *tel;
 
index f4b4a4a5f4ba740f4a290e2394034fe335941abe..d82042c8d8fd4b38eac12a58eb634438aab726a7 100644 (file)
@@ -189,12 +189,12 @@ static int vti6_tnl_create2(struct net_device *dev)
        struct vti6_net *ip6n = net_generic(net, vti6_net_id);
        int err;
 
+       dev->rtnl_link_ops = &vti6_link_ops;
        err = register_netdevice(dev);
        if (err < 0)
                goto out;
 
        strcpy(t->parms.name, dev->name);
-       dev->rtnl_link_ops = &vti6_link_ops;
 
        dev_hold(dev);
        vti6_tnl_link(ip6n, t);
index 14a3903f1c82d83d44c39befdfe827833d09b13c..1bdc703cb9668bd77690c3d8f1ec0062d7b88c43 100644 (file)
@@ -81,7 +81,7 @@ static void mld_gq_timer_expire(unsigned long data);
 static void mld_ifc_timer_expire(unsigned long data);
 static void mld_ifc_event(struct inet6_dev *idev);
 static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
-static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr);
+static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc);
 static void mld_clear_delrec(struct inet6_dev *idev);
 static bool mld_in_v1_mode(const struct inet6_dev *idev);
 static int sf_setstate(struct ifmcaddr6 *pmc);
@@ -692,9 +692,9 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
                        dev_mc_del(dev, buf);
        }
 
-       if (mc->mca_flags & MAF_NOREPORT)
-               goto done;
        spin_unlock_bh(&mc->mca_lock);
+       if (mc->mca_flags & MAF_NOREPORT)
+               return;
 
        if (!mc->idev->dead)
                igmp6_leave_group(mc);
@@ -702,8 +702,6 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc)
        spin_lock_bh(&mc->mca_lock);
        if (del_timer(&mc->mca_timer))
                atomic_dec(&mc->mca_refcnt);
-done:
-       ip6_mc_clear_src(mc);
        spin_unlock_bh(&mc->mca_lock);
 }
 
@@ -748,10 +746,11 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
        spin_unlock_bh(&idev->mc_lock);
 }
 
-static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca)
+static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
 {
        struct ifmcaddr6 *pmc, *pmc_prev;
-       struct ip6_sf_list *psf, *psf_next;
+       struct ip6_sf_list *psf;
+       struct in6_addr *pmca = &im->mca_addr;
 
        spin_lock_bh(&idev->mc_lock);
        pmc_prev = NULL;
@@ -768,14 +767,21 @@ static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca)
        }
        spin_unlock_bh(&idev->mc_lock);
 
+       spin_lock_bh(&im->mca_lock);
        if (pmc) {
-               for (psf = pmc->mca_tomb; psf; psf = psf_next) {
-                       psf_next = psf->sf_next;
-                       kfree(psf);
+               im->idev = pmc->idev;
+               im->mca_crcount = idev->mc_qrv;
+               im->mca_sfmode = pmc->mca_sfmode;
+               if (pmc->mca_sfmode == MCAST_INCLUDE) {
+                       im->mca_tomb = pmc->mca_tomb;
+                       im->mca_sources = pmc->mca_sources;
+                       for (psf = im->mca_sources; psf; psf = psf->sf_next)
+                               psf->sf_crcount = im->mca_crcount;
                }
                in6_dev_put(pmc->idev);
                kfree(pmc);
        }
+       spin_unlock_bh(&im->mca_lock);
 }
 
 static void mld_clear_delrec(struct inet6_dev *idev)
@@ -904,7 +910,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
        mca_get(mc);
        write_unlock_bh(&idev->lock);
 
-       mld_del_delrec(idev, &mc->mca_addr);
+       mld_del_delrec(idev, mc);
        igmp6_group_added(mc);
        ma_put(mc);
        return 0;
@@ -927,6 +933,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
                                write_unlock_bh(&idev->lock);
 
                                igmp6_group_dropped(ma);
+                               ip6_mc_clear_src(ma);
 
                                ma_put(ma);
                                return 0;
@@ -2501,15 +2508,17 @@ void ipv6_mc_down(struct inet6_dev *idev)
        /* Withdraw multicast list */
 
        read_lock_bh(&idev->lock);
-       mld_ifc_stop_timer(idev);
-       mld_gq_stop_timer(idev);
-       mld_dad_stop_timer(idev);
 
        for (i = idev->mc_list; i; i = i->next)
                igmp6_group_dropped(i);
-       read_unlock_bh(&idev->lock);
 
-       mld_clear_delrec(idev);
+       /* Should stop timer after group drop. or we will
+        * start timer again in mld_ifc_event()
+        */
+       mld_ifc_stop_timer(idev);
+       mld_gq_stop_timer(idev);
+       mld_dad_stop_timer(idev);
+       read_unlock_bh(&idev->lock);
 }
 
 static void ipv6_mc_reset(struct inet6_dev *idev)
@@ -2531,8 +2540,10 @@ void ipv6_mc_up(struct inet6_dev *idev)
 
        read_lock_bh(&idev->lock);
        ipv6_mc_reset(idev);
-       for (i = idev->mc_list; i; i = i->next)
+       for (i = idev->mc_list; i; i = i->next) {
+               mld_del_delrec(idev, i);
                igmp6_group_added(i);
+       }
        read_unlock_bh(&idev->lock);
 }
 
@@ -2565,6 +2576,7 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
 
        /* Deactivate timers */
        ipv6_mc_down(idev);
+       mld_clear_delrec(idev);
 
        /* Delete all-nodes address. */
        /* We cannot call ipv6_dev_mc_dec() directly, our caller in
@@ -2579,11 +2591,9 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
        write_lock_bh(&idev->lock);
        while ((i = idev->mc_list) != NULL) {
                idev->mc_list = i->next;
-               write_unlock_bh(&idev->lock);
 
-               igmp6_group_dropped(i);
+               write_unlock_bh(&idev->lock);
                ma_put(i);
-
                write_lock_bh(&idev->lock);
        }
        write_unlock_bh(&idev->lock);
index d5263dc364a97a2a5530e69defd46df225b004b1..b12e61b7b16ce9f3f98a0906558c98803a48a9a3 100644 (file)
@@ -72,10 +72,10 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
        return ret;
 }
 
-static bool rpfilter_is_local(const struct sk_buff *skb)
+static bool
+rpfilter_is_loopback(const struct sk_buff *skb, const struct net_device *in)
 {
-       const struct rt6_info *rt = (const void *) skb_dst(skb);
-       return rt && (rt->rt6i_flags & RTF_LOCAL);
+       return skb->pkt_type == PACKET_LOOPBACK || in->flags & IFF_LOOPBACK;
 }
 
 static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
@@ -85,7 +85,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
        struct ipv6hdr *iph;
        bool invert = info->flags & XT_RPFILTER_INVERT;
 
-       if (rpfilter_is_local(skb))
+       if (rpfilter_is_loopback(skb, xt_in(par)))
                return true ^ invert;
 
        iph = ipv6_hdr(skb);
index 10090400c72f19b7dd21d6543a2c1d740a9bd595..eedee5d108d98422eab5753d7c619b269e07685e 100644 (file)
@@ -157,6 +157,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
        fl6.fl6_sport = otcph->dest;
        fl6.fl6_dport = otcph->source;
        fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
+       fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
        security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
        dst = ip6_route_output(net, NULL, &fl6);
        if (dst->error) {
@@ -180,6 +181,8 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
 
        skb_dst_set(nskb, dst);
 
+       nskb->mark = fl6.flowi6_mark;
+
        skb_reserve(nskb, hh_len + dst->header_len);
        ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP,
                                    ip6_dst_hoplimit(dst));
index c947aad8bcc620e87cacd942d146cdfb7ad2a73e..765facf03d45c47b9913b1adcdaf59b6fe09383c 100644 (file)
 #include <net/ip6_fib.h>
 #include <net/ip6_route.h>
 
-static bool fib6_is_local(const struct sk_buff *skb)
-{
-       const struct rt6_info *rt = (const void *)skb_dst(skb);
-
-       return rt && (rt->rt6i_flags & RTF_LOCAL);
-}
-
 static int get_ifindex(const struct net_device *dev)
 {
        return dev ? dev->ifindex : 0;
@@ -164,8 +157,10 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
 
        lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif);
 
-       if (nft_hook(pkt) == NF_INET_PRE_ROUTING && fib6_is_local(pkt->skb)) {
-               nft_fib_store_result(dest, priv->result, pkt, LOOPBACK_IFINDEX);
+       if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
+           nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
+               nft_fib_store_result(dest, priv->result, pkt,
+                                    nft_in(pkt)->ifindex);
                return;
        }
 
index 8417c41d8ec8398a72c56f9b37b16d94702cbbf3..7ea85370c11c81e8743e6a3086a32a0011f35d17 100644 (file)
@@ -1464,7 +1464,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
        struct fib6_node *fn;
 
        /* Get the "current" route for this destination and
-        * check if the redirect has come from approriate router.
+        * check if the redirect has come from appropriate router.
         *
         * RFC 4861 specifies that redirects should only be
         * accepted if they come from the nexthop to the target.
@@ -2768,7 +2768,7 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
           old MTU is the lowest MTU in the path, update the route PMTU
           to reflect the increase. In this case if the other nodes' MTU
           also have the lowest MTU, TOO BIG MESSAGE will be lead to
-          PMTU discouvery.
+          PMTU discovery.
         */
        if (rt->dst.dev == arg->dev &&
            dst_metric_raw(&rt->dst, RTAX_MTU) &&
@@ -2896,6 +2896,11 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (tb[RTA_MULTIPATH]) {
                cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
                cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+
+               err = lwtunnel_valid_encap_type_attr(cfg->fc_mp,
+                                                    cfg->fc_mp_len);
+               if (err < 0)
+                       goto errout;
        }
 
        if (tb[RTA_PREF]) {
@@ -2909,9 +2914,14 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (tb[RTA_ENCAP])
                cfg->fc_encap = tb[RTA_ENCAP];
 
-       if (tb[RTA_ENCAP_TYPE])
+       if (tb[RTA_ENCAP_TYPE]) {
                cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]);
 
+               err = lwtunnel_valid_encap_type(cfg->fc_encap_type);
+               if (err < 0)
+                       goto errout;
+       }
+
        if (tb[RTA_EXPIRES]) {
                unsigned long timeout = addrconf_timeout_fixup(nla_get_u32(tb[RTA_EXPIRES]), HZ);
 
@@ -3317,7 +3327,8 @@ static int rt6_fill_node(struct net *net,
        if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
                goto nla_put_failure;
 
-       lwtunnel_fill_encap(skb, rt->dst.lwtstate);
+       if (lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0)
+               goto nla_put_failure;
 
        nlmsg_end(skb, nlh);
        return 0;
index b172d85c650a376f541ea05d72046c76b8404303..a855eb325b030a666fe92c56a2d432c77d9dfe7a 100644 (file)
@@ -176,6 +176,8 @@ static int seg6_genl_set_tunsrc(struct sk_buff *skb, struct genl_info *info)
 
        val = nla_data(info->attrs[SEG6_ATTR_DST]);
        t_new = kmemdup(val, sizeof(*val), GFP_KERNEL);
+       if (!t_new)
+               return -ENOMEM;
 
        mutex_lock(&sdata->lock);
 
index ef1c8a46e7aceee45b2044d4b4338dc3aed88807..6ef3dfb6e811642f1fc9b680e0b255a9399bb024 100644 (file)
@@ -174,7 +174,7 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
         * hash function (RadioGatun) with up to 1216 bits
         */
 
-       /* saddr(16) + first_seg(1) + cleanup(1) + keyid(4) + seglist(16n) */
+       /* saddr(16) + first_seg(1) + flags(1) + keyid(4) + seglist(16n) */
        plen = 16 + 1 + 1 + 4 + (hdr->first_segment + 1) * 16;
 
        /* this limit allows for 14 segments */
@@ -186,7 +186,7 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
         *
         * 1. Source IPv6 address (128 bits)
         * 2. first_segment value (8 bits)
-        * 3. cleanup flag (8 bits: highest bit is cleanup value, others are 0)
+        * 3. Flags (8 bits)
         * 4. HMAC Key ID (32 bits)
         * 5. All segments in the segments list (n * 128 bits)
         */
@@ -202,8 +202,8 @@ int seg6_hmac_compute(struct seg6_hmac_info *hinfo, struct ipv6_sr_hdr *hdr,
        /* first_segment value */
        *off++ = hdr->first_segment;
 
-       /* cleanup flag */
-       *off++ = !!(sr_has_cleanup(hdr)) << 7;
+       /* flags */
+       *off++ = hdr->flags;
 
        /* HMAC Key ID */
        memcpy(off, &hmackeyid, 4);
@@ -400,7 +400,7 @@ static int seg6_hmac_init_algo(void)
                        *p_tfm = tfm;
                }
 
-               p_tfm = this_cpu_ptr(algo->tfms);
+               p_tfm = raw_cpu_ptr(algo->tfms);
                tfm = *p_tfm;
 
                shsize = sizeof(*shash) + crypto_shash_descsize(tfm);
index bbfca22c34aeec5c63e9494e672f959c5a06b380..c46f8cbf5ab5aa4031d4080d70079e99859d4eb4 100644 (file)
@@ -265,7 +265,9 @@ int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
        slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
 
 #ifdef CONFIG_DST_CACHE
+       preempt_disable();
        dst = dst_cache_get(&slwt->cache);
+       preempt_enable();
 #endif
 
        if (unlikely(!dst)) {
@@ -286,7 +288,9 @@ int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
                }
 
 #ifdef CONFIG_DST_CACHE
+               preempt_disable();
                dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
+               preempt_enable();
 #endif
        }
 
@@ -418,6 +422,7 @@ static const struct lwtunnel_encap_ops seg6_iptun_ops = {
        .fill_encap = seg6_fill_encap_info,
        .get_encap_size = seg6_encap_nlsize,
        .cmp_encap = seg6_encap_cmp,
+       .owner = THIS_MODULE,
 };
 
 int __init seg6_iptunnel_init(void)
index fad992ad4bc83e8fa0dbdae194a4f8b54e28efa2..99853c6e33a8c3def99ecb56e288cce4a38a997b 100644 (file)
@@ -1380,6 +1380,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
        err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
        if (err) {
                free_percpu(dev->tstats);
+               dev->tstats = NULL;
                return err;
        }
 
index 73bc8fc68acdc1ed947bfdb7624b3308a9b70806..4c60c6f71cd30bf18f270c3d994f193ad13045ae 100644 (file)
@@ -148,8 +148,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
         *      connect() to INADDR_ANY means loopback (BSD'ism).
         */
 
-       if (ipv6_addr_any(&usin->sin6_addr))
-               usin->sin6_addr.s6_addr[15] = 0x1;
+       if (ipv6_addr_any(&usin->sin6_addr)) {
+               if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+                       ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+                                              &usin->sin6_addr);
+               else
+                       usin->sin6_addr = in6addr_loopback;
+       }
 
        addr_type = ipv6_addr_type(&usin->sin6_addr);
 
@@ -188,7 +193,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
         *      TCP over IPv4
         */
 
-       if (addr_type == IPV6_ADDR_MAPPED) {
+       if (addr_type & IPV6_ADDR_MAPPED) {
                u32 exthdrlen = icsk->icsk_ext_hdr_len;
                struct sockaddr_in sin;
 
@@ -469,7 +474,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                opt = ireq->ipv6_opt;
                if (!opt)
                        opt = rcu_dereference(np->opt);
-               err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
+               err = ip6_xmit(sk, skb, fl6, sk->sk_mark, opt, np->tclass);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -840,7 +845,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
        dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
        if (!IS_ERR(dst)) {
                skb_dst_set(buff, dst);
-               ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
+               ip6_xmit(ctl_sk, buff, &fl6, fl6.flowi6_mark, NULL, tclass);
                TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
                if (rst)
                        TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
@@ -991,6 +996,16 @@ drop:
        return 0; /* don't send reset */
 }
 
+static void tcp_v6_restore_cb(struct sk_buff *skb)
+{
+       /* We need to move header back to the beginning if xfrm6_policy_check()
+        * and tcp_v6_fill_cb() are going to be called again.
+        * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
+        */
+       memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
+               sizeof(struct inet6_skb_parm));
+}
+
 static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
                                         struct request_sock *req,
                                         struct dst_entry *dst,
@@ -1182,8 +1197,10 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                                                      sk_gfp_mask(sk, GFP_ATOMIC));
                        consume_skb(ireq->pktopts);
                        ireq->pktopts = NULL;
-                       if (newnp->pktoptions)
+                       if (newnp->pktoptions) {
+                               tcp_v6_restore_cb(newnp->pktoptions);
                                skb_set_owner_r(newnp->pktoptions, newsk);
+                       }
                }
        }
 
@@ -1198,16 +1215,6 @@ out:
        return NULL;
 }
 
-static void tcp_v6_restore_cb(struct sk_buff *skb)
-{
-       /* We need to move header back to the beginning if xfrm6_policy_check()
-        * and tcp_v6_fill_cb() are going to be called again.
-        * ip6_datagram_recv_specific_ctl() also expects IP6CB to be there.
-        */
-       memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6,
-               sizeof(struct inet6_skb_parm));
-}
-
 /* The socket must have it's spinlock held when we get
  * here, unless it is a TCP_LISTEN socket.
  *
index 4d5c4eee4b3f506cf030bb9bce20c5b94086e011..221825a9407afebba47106f60729f91e2992158c 100644 (file)
@@ -441,7 +441,7 @@ try_again:
        return err;
 
 csum_copy_err:
-       if (!__sk_queue_drop_skb(sk, skb, flags)) {
+       if (!__sk_queue_drop_skb(sk, skb, flags, udp_skb_destructor)) {
                if (is_udp4) {
                        UDP_INC_STATS(sock_net(sk),
                                      UDP_MIB_CSUMERRORS, is_udplite);
@@ -1033,6 +1033,10 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                        if (addr_len < SIN6_LEN_RFC2133)
                                return -EINVAL;
                        daddr = &sin6->sin6_addr;
+                       if (ipv6_addr_any(daddr) &&
+                           ipv6_addr_v4mapped(&np->saddr))
+                               ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+                                                      daddr);
                        break;
                case AF_INET:
                        goto do_udp_sendmsg;
index acbe61c7e6831205ca1d725f65263c849ef092e4..160dc89335e207e593401f43c0637a766bdb9b68 100644 (file)
@@ -383,9 +383,6 @@ EXPORT_SYMBOL(hashbin_new);
  *    for deallocating this structure if it's complex. If not the user can
  *    just supply kfree, which should take care of the job.
  */
-#ifdef CONFIG_LOCKDEP
-static int hashbin_lock_depth = 0;
-#endif
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
        irda_queue_t* queue;
@@ -396,22 +393,27 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
        IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 
        /* Synchronize */
-       if ( hashbin->hb_type & HB_LOCK ) {
-               spin_lock_irqsave_nested(&hashbin->hb_spinlock, flags,
-                                        hashbin_lock_depth++);
-       }
+       if (hashbin->hb_type & HB_LOCK)
+               spin_lock_irqsave(&hashbin->hb_spinlock, flags);
 
        /*
         *  Free the entries in the hashbin, TODO: use hashbin_clear when
         *  it has been shown to work
         */
        for (i = 0; i < HASHBIN_SIZE; i ++ ) {
-               queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
-               while (queue ) {
-                       if (free_func)
-                               (*free_func)(queue);
-                       queue = dequeue_first(
-                               (irda_queue_t**) &hashbin->hb_queue[i]);
+               while (1) {
+                       queue = dequeue_first((irda_queue_t**) &hashbin->hb_queue[i]);
+
+                       if (!queue)
+                               break;
+
+                       if (free_func) {
+                               if (hashbin->hb_type & HB_LOCK)
+                                       spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
+                               free_func(queue);
+                               if (hashbin->hb_type & HB_LOCK)
+                                       spin_lock_irqsave(&hashbin->hb_spinlock, flags);
+                       }
                }
        }
 
@@ -420,12 +422,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
        hashbin->magic = ~HB_MAGIC;
 
        /* Release lock */
-       if ( hashbin->hb_type & HB_LOCK) {
+       if (hashbin->hb_type & HB_LOCK)
                spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
-#ifdef CONFIG_LOCKDEP
-               hashbin_lock_depth--;
-#endif
-       }
 
        /*
         *  Free the hashbin structure
index cfb9e5f4e28f52c699072eaf41f12f3a6e667160..13190b38f22ee5116fb7701feed22ec436031a4e 100644 (file)
@@ -1044,7 +1044,8 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg,
 {
        struct sock *sk = sock->sk;
        struct iucv_sock *iucv = iucv_sk(sk);
-       size_t headroom, linear;
+       size_t headroom = 0;
+       size_t linear;
        struct sk_buff *skb;
        struct iucv_message txmsg = {0};
        struct cmsghdr *cmsg;
@@ -1122,18 +1123,20 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg,
         * this is fine for SOCK_SEQPACKET (unless we want to support
         * segmented records using the MSG_EOR flag), but
         * for SOCK_STREAM we might want to improve it in future */
-       headroom = (iucv->transport == AF_IUCV_TRANS_HIPER)
-                  ? sizeof(struct af_iucv_trans_hdr) + ETH_HLEN : 0;
-       if (headroom + len < PAGE_SIZE) {
+       if (iucv->transport == AF_IUCV_TRANS_HIPER) {
+               headroom = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
                linear = len;
        } else {
-               /* In nonlinear "classic" iucv skb,
-                * reserve space for iucv_array
-                */
-               if (iucv->transport != AF_IUCV_TRANS_HIPER)
-                       headroom += sizeof(struct iucv_array) *
-                                   (MAX_SKB_FRAGS + 1);
-               linear = PAGE_SIZE - headroom;
+               if (len < PAGE_SIZE) {
+                       linear = len;
+               } else {
+                       /* In nonlinear "classic" iucv skb,
+                        * reserve space for iucv_array
+                        */
+                       headroom = sizeof(struct iucv_array) *
+                                  (MAX_SKB_FRAGS + 1);
+                       linear = PAGE_SIZE - headroom;
+               }
        }
        skb = sock_alloc_send_pskb(sk, headroom + linear, len - linear,
                                   noblock, &err, 0);
index 7e08a4d3d77d0650e9f0c50cd0ab9a8568147f37..a646f348124095c1bdff2d14a77ea5c0ac892bc1 100644 (file)
@@ -929,23 +929,25 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                        goto out_error;
        }
 
-       /* New message, alloc head skb */
-       head = alloc_skb(0, sk->sk_allocation);
-       while (!head) {
-               kcm_push(kcm);
-               err = sk_stream_wait_memory(sk, &timeo);
-               if (err)
-                       goto out_error;
-
+       if (msg_data_left(msg)) {
+               /* New message, alloc head skb */
                head = alloc_skb(0, sk->sk_allocation);
-       }
+               while (!head) {
+                       kcm_push(kcm);
+                       err = sk_stream_wait_memory(sk, &timeo);
+                       if (err)
+                               goto out_error;
 
-       skb = head;
+                       head = alloc_skb(0, sk->sk_allocation);
+               }
 
-       /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling
-        * csum_and_copy_from_iter from skb_do_copy_data_nocache.
-        */
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
+               skb = head;
+
+               /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling
+                * csum_and_copy_from_iter from skb_do_copy_data_nocache.
+                */
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+       }
 
 start:
        while (msg_data_left(msg)) {
@@ -1018,10 +1020,12 @@ wait_for_memory:
        if (eor) {
                bool not_busy = skb_queue_empty(&sk->sk_write_queue);
 
-               /* Message complete, queue it on send buffer */
-               __skb_queue_tail(&sk->sk_write_queue, head);
-               kcm->seq_skb = NULL;
-               KCM_STATS_INCR(kcm->stats.tx_msgs);
+               if (head) {
+                       /* Message complete, queue it on send buffer */
+                       __skb_queue_tail(&sk->sk_write_queue, head);
+                       kcm->seq_skb = NULL;
+                       KCM_STATS_INCR(kcm->stats.tx_msgs);
+               }
 
                if (msg->msg_flags & MSG_BATCH) {
                        kcm->tx_wait_more = true;
@@ -1040,8 +1044,10 @@ wait_for_memory:
        } else {
                /* Message not complete, save state */
 partial_message:
-               kcm->seq_skb = head;
-               kcm_tx_msg(head)->last_skb = skb;
+               if (head) {
+                       kcm->seq_skb = head;
+                       kcm_tx_msg(head)->last_skb = skb;
+               }
        }
 
        KCM_STATS_ADD(kcm->stats.tx_bytes, copied);
index 8f560f7140a05694c13904d9b171ba67d9d11292..aebf281d09eeb31c531eb624bd2ddd78cab8da9b 100644 (file)
@@ -263,6 +263,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb,
 int l2tp_nl_register_ops(enum l2tp_pwtype pw_type,
                         const struct l2tp_nl_cmd_ops *ops);
 void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 
 /* Session reference counts. Incremented when code obtains a reference
  * to a session.
index 3d73278b86ca34bfbd774dc8f52e490169445e1b..28c21546d5b60dcd07bbf6347389e97c918bf40f 100644 (file)
@@ -11,6 +11,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <asm/ioctls.h>
 #include <linux/icmp.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
@@ -553,6 +554,30 @@ out:
        return err ? err : copied;
 }
 
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+       struct sk_buff *skb;
+       int amount;
+
+       switch (cmd) {
+       case SIOCOUTQ:
+               amount = sk_wmem_alloc_get(sk);
+               break;
+       case SIOCINQ:
+               spin_lock_bh(&sk->sk_receive_queue.lock);
+               skb = skb_peek(&sk->sk_receive_queue);
+               amount = skb ? skb->len : 0;
+               spin_unlock_bh(&sk->sk_receive_queue.lock);
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return put_user(amount, (int __user *)arg);
+}
+EXPORT_SYMBOL(l2tp_ioctl);
+
 static struct proto l2tp_ip_prot = {
        .name              = "L2TP/IP",
        .owner             = THIS_MODULE,
@@ -561,7 +586,7 @@ static struct proto l2tp_ip_prot = {
        .bind              = l2tp_ip_bind,
        .connect           = l2tp_ip_connect,
        .disconnect        = l2tp_ip_disconnect,
-       .ioctl             = udp_ioctl,
+       .ioctl             = l2tp_ioctl,
        .destroy           = l2tp_ip_destroy_sock,
        .setsockopt        = ip_setsockopt,
        .getsockopt        = ip_getsockopt,
index 331ccf5a7bad80e011997e071489d7775b0c68c6..f47c45250f86c9189e0a6bbfd92b21cbe2069406 100644 (file)
@@ -722,7 +722,7 @@ static struct proto l2tp_ip6_prot = {
        .bind              = l2tp_ip6_bind,
        .connect           = l2tp_ip6_connect,
        .disconnect        = l2tp_ip6_disconnect,
-       .ioctl             = udp_ioctl,
+       .ioctl             = l2tp_ioctl,
        .destroy           = l2tp_ip6_destroy_sock,
        .setsockopt        = ipv6_setsockopt,
        .getsockopt        = ipv6_getsockopt,
index 3e821daf9dd4a2fbf00550591e92b153efd4a73a..8bc5a1bd2d453542df31506f543feb64b64cdd96 100644 (file)
@@ -821,7 +821,10 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
                 * another trick required to cope with how the PROCOM state
                 * machine works. -acme
                 */
+               skb_orphan(skb);
+               sock_hold(sk);
                skb->sk = sk;
+               skb->destructor = sock_efree;
        }
        if (!sock_owned_by_user(sk))
                llc_conn_rcv(sk, skb);
index d0e1e804ebd73dcebcf2f930b921233a49b0f454..5404d0d195cc581613e356b75bd70321e617673e 100644 (file)
@@ -290,7 +290,10 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
 
        ev->type   = LLC_SAP_EV_TYPE_PDU;
        ev->reason = 0;
+       skb_orphan(skb);
+       sock_hold(sk);
        skb->sk = sk;
+       skb->destructor = sock_efree;
        llc_sap_state_process(sap, skb);
 }
 
index e75cbf6ecc26e4ec7bde777c385e001c0e49e371..a0d901d8992ea892bbb44890e08d6f782c68b4e3 100644 (file)
@@ -231,9 +231,6 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
                    !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
                        continue;
 
-               if (!sta->uploaded || !test_sta_flag(sta, WLAN_STA_ASSOC))
-                       continue;
-
                max_bw = max(max_bw, ieee80211_get_sta_bw(&sta->sta));
        }
        rcu_read_unlock();
index ecfdd97758a386ed9d642a3fc141f2ec6da13db2..5c3af5eb405232167bbd62a13b4d1f37370d6bc0 100644 (file)
@@ -124,7 +124,7 @@ static int aes_siv_encrypt(const u8 *key, size_t key_len,
 
        /* CTR */
 
-       tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, 0);
+       tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm2)) {
                kfree(tmp);
                return PTR_ERR(tfm2);
@@ -183,7 +183,7 @@ static int aes_siv_decrypt(const u8 *key, size_t key_len,
 
        /* CTR */
 
-       tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, 0);
+       tfm2 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm2))
                return PTR_ERR(tfm2);
        /* K2 for CTR */
@@ -272,7 +272,7 @@ int fils_encrypt_assoc_req(struct sk_buff *skb,
        crypt_len = skb->data + skb->len - encr;
        skb_put(skb, AES_BLOCK_SIZE);
        return aes_siv_encrypt(assoc_data->fils_kek, assoc_data->fils_kek_len,
-                              encr, crypt_len, 1, addr, len, encr);
+                              encr, crypt_len, 5, addr, len, encr);
 }
 
 int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
index 41497b670e2bde0e55a2a35f5fbbdb60148ddd54..d37ae7dc114b2c2eb5b8dc4773c6a688b047e0a2 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright (c) 2016        Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1295,6 +1296,26 @@ static void ieee80211_iface_work(struct work_struct *work)
                } else if (ieee80211_is_action(mgmt->frame_control) &&
                           mgmt->u.action.category == WLAN_CATEGORY_VHT) {
                        switch (mgmt->u.action.u.vht_group_notif.action_code) {
+                       case WLAN_VHT_ACTION_OPMODE_NOTIF: {
+                               struct ieee80211_rx_status *status;
+                               enum nl80211_band band;
+                               u8 opmode;
+
+                               status = IEEE80211_SKB_RXCB(skb);
+                               band = status->band;
+                               opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
+
+                               mutex_lock(&local->sta_mtx);
+                               sta = sta_info_get_bss(sdata, mgmt->sa);
+
+                               if (sta)
+                                       ieee80211_vht_handle_opmode(sdata, sta,
+                                                                   opmode,
+                                                                   band);
+
+                               mutex_unlock(&local->sta_mtx);
+                               break;
+                       }
                        case WLAN_VHT_ACTION_GROUPID_MGMT:
                                ieee80211_process_mu_groups(sdata, mgmt);
                                break;
index 1822c77f2b1c3125ec1bc63fa6b7de085a26bbed..56fb47953b72420b3ceb4e3f5d27dc9c4d23928b 100644 (file)
@@ -913,12 +913,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                supp_ht = supp_ht || sband->ht_cap.ht_supported;
                supp_vht = supp_vht || sband->vht_cap.vht_supported;
 
-               if (sband->ht_cap.ht_supported)
-                       local->rx_chains =
-                               max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
-                                   local->rx_chains);
+               if (!sband->ht_cap.ht_supported)
+                       continue;
 
                /* TODO: consider VHT for RX chains, hopefully it's the same */
+               local->rx_chains =
+                       max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
+                           local->rx_chains);
+
+               /* no need to mask, SM_PS_DISABLED has all bits set */
+               sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
+                                    IEEE80211_HT_CAP_SM_PS_SHIFT;
        }
 
        /* if low-level driver supports AP, we also support VLAN */
index 42120d965263d2ec1719211da37b7900814e4122..50e1b7f78bd49605d2dbca4c215befecc1d8d001 100644 (file)
@@ -339,7 +339,7 @@ int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata,
        /* fast-forward to vendor IEs */
        offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0);
 
-       if (offset) {
+       if (offset < ifmsh->ie_len) {
                len = ifmsh->ie_len - offset;
                data = ifmsh->ie + offset;
                if (skb_tailroom(skb) < len)
index 3e289a64ed4317a8a495cb7cac8197fb9ce10c3e..3090dd4342f6eee6f2d3bdba67493849622ac1a7 100644 (file)
@@ -2472,7 +2472,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        if (!ifmsh->mshcfg.dot11MeshForwarding)
                goto out;
 
-       fwd_skb = skb_copy_expand(skb, local->tx_headroom, 0, GFP_ATOMIC);
+       fwd_skb = skb_copy_expand(skb, local->tx_headroom +
+                                      sdata->encrypt_headroom, 0, GFP_ATOMIC);
        if (!fwd_skb) {
                net_info_ratelimited("%s: failed to clone mesh frame\n",
                                    sdata->name);
@@ -2880,17 +2881,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 
                switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
                case WLAN_VHT_ACTION_OPMODE_NOTIF: {
-                       u8 opmode;
-
                        /* verify opmode is present */
                        if (len < IEEE80211_MIN_ACTION_SIZE + 2)
                                goto invalid;
-
-                       opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
-
-                       ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
-                                                   opmode, status->band);
-                       goto handled;
+                       goto queue;
                }
                case WLAN_VHT_ACTION_GROUPID_MGMT: {
                        if (len < IEEE80211_MIN_ACTION_SIZE + 25)
@@ -3942,21 +3936,31 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
        u64_stats_update_end(&stats->syncp);
 
        if (fast_rx->internal_forward) {
-               struct sta_info *dsta = sta_info_get(rx->sdata, skb->data);
+               struct sk_buff *xmit_skb = NULL;
+               bool multicast = is_multicast_ether_addr(skb->data);
+
+               if (multicast) {
+                       xmit_skb = skb_copy(skb, GFP_ATOMIC);
+               } else if (sta_info_get(rx->sdata, skb->data)) {
+                       xmit_skb = skb;
+                       skb = NULL;
+               }
 
-               if (dsta) {
+               if (xmit_skb) {
                        /*
                         * Send to wireless media and increase priority by 256
                         * to keep the received priority instead of
                         * reclassifying the frame (see cfg80211_classify8021d).
                         */
-                       skb->priority += 256;
-                       skb->protocol = htons(ETH_P_802_3);
-                       skb_reset_network_header(skb);
-                       skb_reset_mac_header(skb);
-                       dev_queue_xmit(skb);
-                       return true;
+                       xmit_skb->priority += 256;
+                       xmit_skb->protocol = htons(ETH_P_802_3);
+                       skb_reset_network_header(xmit_skb);
+                       skb_reset_mac_header(xmit_skb);
+                       dev_queue_xmit(xmit_skb);
                }
+
+               if (!skb)
+                       return true;
        }
 
        /* deliver to local stack */
index b6cfcf038c11fa529e00da2eed70f6ff48426a37..50c309094c37ba5e73160613f6e316c0a6a161f2 100644 (file)
@@ -1501,8 +1501,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
 
                /* This will evaluate to 1, 3, 5 or 7. */
                for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++)
-                       if (ignored_acs & BIT(ac))
-                               continue;
+                       if (!(ignored_acs & ieee80211_ac_to_qos_mask[ac]))
+                               break;
                tid = 7 - 2 * ac;
 
                ieee80211_send_null_response(sta, tid, reason, true, false);
index 0d8b716e509edca48fbc65ceaf06e6b7d6a2c189..797e847cbc49a1a5f1a515f01aa68c0212aed997 100644 (file)
@@ -1243,7 +1243,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
 
 static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
                                          struct ieee80211_vif *vif,
-                                         struct ieee80211_sta *pubsta,
+                                         struct sta_info *sta,
                                          struct sk_buff *skb)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -1257,10 +1257,13 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
        if (!ieee80211_is_data(hdr->frame_control))
                return NULL;
 
-       if (pubsta) {
+       if (sta) {
                u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
 
-               txq = pubsta->txq[tid];
+               if (!sta->uploaded)
+                       return NULL;
+
+               txq = sta->sta.txq[tid];
        } else if (vif) {
                txq = vif->txq;
        }
@@ -1503,23 +1506,17 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
        struct fq *fq = &local->fq;
        struct ieee80211_vif *vif;
        struct txq_info *txqi;
-       struct ieee80211_sta *pubsta;
 
        if (!local->ops->wake_tx_queue ||
            sdata->vif.type == NL80211_IFTYPE_MONITOR)
                return false;
 
-       if (sta && sta->uploaded)
-               pubsta = &sta->sta;
-       else
-               pubsta = NULL;
-
        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                sdata = container_of(sdata->bss,
                                     struct ieee80211_sub_if_data, u.ap);
 
        vif = &sdata->vif;
-       txqi = ieee80211_get_txq(local, vif, pubsta, skb);
+       txqi = ieee80211_get_txq(local, vif, sta, skb);
 
        if (!txqi)
                return false;
index 6832bf6ab69fe012ea4eeb3c02b79523083cdc58..43e45bb660bcde02af964a31a71efd64f07ba448 100644 (file)
@@ -527,8 +527,10 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 
        u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
 
-       if (changed > 0)
+       if (changed > 0) {
+               ieee80211_recalc_min_chandef(sdata);
                rate_control_rate_update(local, sband, sta, changed);
+       }
 }
 
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
index 15fe97644ffe048c9b1d5818c0b1aec56eb988f4..5b77377e5a15474e39037be5e6e873ebceb33555 100644 (file)
@@ -98,18 +98,19 @@ bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
 }
 EXPORT_SYMBOL_GPL(mpls_pkt_too_big);
 
-static u32 mpls_multipath_hash(struct mpls_route *rt,
-                              struct sk_buff *skb, bool bos)
+static u32 mpls_multipath_hash(struct mpls_route *rt, struct sk_buff *skb)
 {
        struct mpls_entry_decoded dec;
+       unsigned int mpls_hdr_len = 0;
        struct mpls_shim_hdr *hdr;
        bool eli_seen = false;
        int label_index;
        u32 hash = 0;
 
-       for (label_index = 0; label_index < MAX_MP_SELECT_LABELS && !bos;
+       for (label_index = 0; label_index < MAX_MP_SELECT_LABELS;
             label_index++) {
-               if (!pskb_may_pull(skb, sizeof(*hdr) * label_index))
+               mpls_hdr_len += sizeof(*hdr);
+               if (!pskb_may_pull(skb, mpls_hdr_len))
                        break;
 
                /* Read and decode the current label */
@@ -134,37 +135,38 @@ static u32 mpls_multipath_hash(struct mpls_route *rt,
                        eli_seen = true;
                }
 
-               bos = dec.bos;
-               if (bos && pskb_may_pull(skb, sizeof(*hdr) * label_index +
-                                        sizeof(struct iphdr))) {
+               if (!dec.bos)
+                       continue;
+
+               /* found bottom label; does skb have room for a header? */
+               if (pskb_may_pull(skb, mpls_hdr_len + sizeof(struct iphdr))) {
                        const struct iphdr *v4hdr;
 
-                       v4hdr = (const struct iphdr *)(mpls_hdr(skb) +
-                                                      label_index);
+                       v4hdr = (const struct iphdr *)(hdr + 1);
                        if (v4hdr->version == 4) {
                                hash = jhash_3words(ntohl(v4hdr->saddr),
                                                    ntohl(v4hdr->daddr),
                                                    v4hdr->protocol, hash);
                        } else if (v4hdr->version == 6 &&
-                               pskb_may_pull(skb, sizeof(*hdr) * label_index +
-                                             sizeof(struct ipv6hdr))) {
+                                  pskb_may_pull(skb, mpls_hdr_len +
+                                                sizeof(struct ipv6hdr))) {
                                const struct ipv6hdr *v6hdr;
 
-                               v6hdr = (const struct ipv6hdr *)(mpls_hdr(skb) +
-                                                               label_index);
-
+                               v6hdr = (const struct ipv6hdr *)(hdr + 1);
                                hash = __ipv6_addr_jhash(&v6hdr->saddr, hash);
                                hash = __ipv6_addr_jhash(&v6hdr->daddr, hash);
                                hash = jhash_1word(v6hdr->nexthdr, hash);
                        }
                }
+
+               break;
        }
 
        return hash;
 }
 
 static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
-                                            struct sk_buff *skb, bool bos)
+                                            struct sk_buff *skb)
 {
        int alive = ACCESS_ONCE(rt->rt_nhn_alive);
        u32 hash = 0;
@@ -180,7 +182,7 @@ static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
        if (alive <= 0)
                return NULL;
 
-       hash = mpls_multipath_hash(rt, skb, bos);
+       hash = mpls_multipath_hash(rt, skb);
        nh_index = hash % alive;
        if (alive == rt->rt_nhn)
                goto out;
@@ -278,17 +280,11 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
        hdr = mpls_hdr(skb);
        dec = mpls_entry_decode(hdr);
 
-       /* Pop the label */
-       skb_pull(skb, sizeof(*hdr));
-       skb_reset_network_header(skb);
-
-       skb_orphan(skb);
-
        rt = mpls_route_input_rcu(net, dec.label);
        if (!rt)
                goto drop;
 
-       nh = mpls_select_multipath(rt, skb, dec.bos);
+       nh = mpls_select_multipath(rt, skb);
        if (!nh)
                goto drop;
 
@@ -297,6 +293,12 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
        if (!mpls_output_possible(out_dev))
                goto drop;
 
+       /* Pop the label */
+       skb_pull(skb, sizeof(*hdr));
+       skb_reset_network_header(skb);
+
+       skb_orphan(skb);
+
        if (skb_warn_if_lro(skb))
                goto drop;
 
index 2f7ccd93441671d6aac3fd690cfc61283848579a..1d281c1ff7c10b3ae6e0245e2b95cc404dd791c4 100644 (file)
@@ -215,6 +215,7 @@ static const struct lwtunnel_encap_ops mpls_iptun_ops = {
        .fill_encap = mpls_fill_encap_info,
        .get_encap_size = mpls_encap_nlsize,
        .cmp_encap = mpls_encap_cmp,
+       .owner = THIS_MODULE,
 };
 
 static int __init mpls_iptunnel_init(void)
index 63729b489c2c17608575e4f58adb0c264e182d0b..bbc45f8a7b2de6801eab367fa7f3611e23b92b9e 100644 (file)
@@ -494,7 +494,7 @@ config NFT_CT
        depends on NF_CONNTRACK
        tristate "Netfilter nf_tables conntrack module"
        help
-         This option adds the "meta" expression that you can use to match
+         This option adds the "ct" expression that you can use to match
          connection tracking information such as the flow state.
 
 config NFT_SET_RBTREE
index 3a073cd9fcf49ed9cfd228a420cc2de928ca4459..4e8083c5e01d1ec631258af169c18aceed101e3a 100644 (file)
@@ -85,11 +85,11 @@ static __read_mostly DEFINE_SPINLOCK(nf_conntrack_locks_all_lock);
 static __read_mostly bool nf_conntrack_locks_all;
 
 /* every gc cycle scans at most 1/GC_MAX_BUCKETS_DIV part of table */
-#define GC_MAX_BUCKETS_DIV     64u
-/* upper bound of scan intervals */
-#define GC_INTERVAL_MAX                (2 * HZ)
-/* maximum conntracks to evict per gc run */
-#define GC_MAX_EVICTS          256u
+#define GC_MAX_BUCKETS_DIV     128u
+/* upper bound of full table scan */
+#define GC_MAX_SCAN_JIFFIES    (16u * HZ)
+/* desired ratio of entries found to be expired */
+#define GC_EVICT_RATIO 50u
 
 static struct conntrack_gc_work conntrack_gc_work;
 
@@ -938,6 +938,7 @@ static noinline int early_drop(struct net *net, unsigned int _hash)
 
 static void gc_worker(struct work_struct *work)
 {
+       unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u);
        unsigned int i, goal, buckets = 0, expired_count = 0;
        struct conntrack_gc_work *gc_work;
        unsigned int ratio, scanned = 0;
@@ -979,8 +980,7 @@ static void gc_worker(struct work_struct *work)
                 */
                rcu_read_unlock();
                cond_resched_rcu_qs();
-       } while (++buckets < goal &&
-                expired_count < GC_MAX_EVICTS);
+       } while (++buckets < goal);
 
        if (gc_work->exiting)
                return;
@@ -997,27 +997,25 @@ static void gc_worker(struct work_struct *work)
         * 1. Minimize time until we notice a stale entry
         * 2. Maximize scan intervals to not waste cycles
         *
-        * Normally, expired_count will be 0, this increases the next_run time
-        * to priorize 2) above.
+        * Normally, expire ratio will be close to 0.
         *
-        * As soon as a timed-out entry is found, move towards 1) and increase
-        * the scan frequency.
-        * In case we have lots of evictions next scan is done immediately.
+        * As soon as a sizeable fraction of the entries have expired
+        * increase scan frequency.
         */
        ratio = scanned ? expired_count * 100 / scanned : 0;
-       if (ratio >= 90 || expired_count == GC_MAX_EVICTS) {
-               gc_work->next_gc_run = 0;
-               next_run = 0;
-       } else if (expired_count) {
-               gc_work->next_gc_run /= 2U;
-               next_run = msecs_to_jiffies(1);
+       if (ratio > GC_EVICT_RATIO) {
+               gc_work->next_gc_run = min_interval;
        } else {
-               if (gc_work->next_gc_run < GC_INTERVAL_MAX)
-                       gc_work->next_gc_run += msecs_to_jiffies(1);
+               unsigned int max = GC_MAX_SCAN_JIFFIES / GC_MAX_BUCKETS_DIV;
 
-               next_run = gc_work->next_gc_run;
+               BUILD_BUG_ON((GC_MAX_SCAN_JIFFIES / GC_MAX_BUCKETS_DIV) == 0);
+
+               gc_work->next_gc_run += min_interval;
+               if (gc_work->next_gc_run > max)
+                       gc_work->next_gc_run = max;
        }
 
+       next_run = gc_work->next_gc_run;
        gc_work->last_bucket = i;
        queue_delayed_work(system_long_wq, &gc_work->dwork, next_run);
 }
@@ -1025,7 +1023,7 @@ static void gc_worker(struct work_struct *work)
 static void conntrack_gc_work_init(struct conntrack_gc_work *gc_work)
 {
        INIT_DELAYED_WORK(&gc_work->dwork, gc_worker);
-       gc_work->next_gc_run = GC_INTERVAL_MAX;
+       gc_work->next_gc_run = HZ;
        gc_work->exiting = false;
 }
 
@@ -1917,7 +1915,7 @@ int nf_conntrack_init_start(void)
        nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED);
 
        conntrack_gc_work_init(&conntrack_gc_work);
-       queue_delayed_work(system_long_wq, &conntrack_gc_work.dwork, GC_INTERVAL_MAX);
+       queue_delayed_work(system_long_wq, &conntrack_gc_work.dwork, HZ);
 
        return 0;
 
index 3dca90dc24ad392a6be6076e4ddbc345a1959ac0..ffb9e8ada899b770293744ed0da5bebba4b2166e 100644 (file)
@@ -13,7 +13,6 @@
 /* Internal logging interface, which relies on the real
    LOG target modules */
 
-#define NF_LOG_PREFIXLEN               128
 #define NFLOGGER_NAME_LEN              64
 
 static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;
index a019a87e58ee8151620eb3d8500979d02dba54c1..1b913760f205be79e1809c983cb3140c284a00cc 100644 (file)
@@ -928,7 +928,8 @@ static struct nft_chain *nf_tables_chain_lookup(const struct nft_table *table,
 }
 
 static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
-       [NFTA_CHAIN_TABLE]      = { .type = NLA_STRING },
+       [NFTA_CHAIN_TABLE]      = { .type = NLA_STRING,
+                                   .len = NFT_TABLE_MAXNAMELEN - 1 },
        [NFTA_CHAIN_HANDLE]     = { .type = NLA_U64 },
        [NFTA_CHAIN_NAME]       = { .type = NLA_STRING,
                                    .len = NFT_CHAIN_MAXNAMELEN - 1 },
@@ -1854,7 +1855,8 @@ static struct nft_rule *nf_tables_rule_lookup(const struct nft_chain *chain,
 }
 
 static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
-       [NFTA_RULE_TABLE]       = { .type = NLA_STRING },
+       [NFTA_RULE_TABLE]       = { .type = NLA_STRING,
+                                   .len = NFT_TABLE_MAXNAMELEN - 1 },
        [NFTA_RULE_CHAIN]       = { .type = NLA_STRING,
                                    .len = NFT_CHAIN_MAXNAMELEN - 1 },
        [NFTA_RULE_HANDLE]      = { .type = NLA_U64 },
@@ -2115,7 +2117,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
         * is called on error from nf_tables_newrule().
         */
        expr = nft_expr_first(rule);
-       while (expr->ops && expr != nft_expr_last(rule)) {
+       while (expr != nft_expr_last(rule) && expr->ops) {
                nf_tables_expr_destroy(ctx, expr);
                expr = nft_expr_next(expr);
        }
@@ -2443,7 +2445,8 @@ nft_select_set_ops(const struct nlattr * const nla[],
 }
 
 static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
-       [NFTA_SET_TABLE]                = { .type = NLA_STRING },
+       [NFTA_SET_TABLE]                = { .type = NLA_STRING,
+                                           .len = NFT_TABLE_MAXNAMELEN - 1 },
        [NFTA_SET_NAME]                 = { .type = NLA_STRING,
                                            .len = NFT_SET_MAXNAMELEN - 1 },
        [NFTA_SET_FLAGS]                = { .type = NLA_U32 },
@@ -3084,9 +3087,9 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
 }
 
 static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
-                                       const struct nft_set *set,
+                                       struct nft_set *set,
                                        const struct nft_set_iter *iter,
-                                       const struct nft_set_elem *elem)
+                                       struct nft_set_elem *elem)
 {
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
        enum nft_registers dreg;
@@ -3192,8 +3195,10 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
 };
 
 static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
-       [NFTA_SET_ELEM_LIST_TABLE]      = { .type = NLA_STRING },
-       [NFTA_SET_ELEM_LIST_SET]        = { .type = NLA_STRING },
+       [NFTA_SET_ELEM_LIST_TABLE]      = { .type = NLA_STRING,
+                                           .len = NFT_TABLE_MAXNAMELEN - 1 },
+       [NFTA_SET_ELEM_LIST_SET]        = { .type = NLA_STRING,
+                                           .len = NFT_SET_MAXNAMELEN - 1 },
        [NFTA_SET_ELEM_LIST_ELEMENTS]   = { .type = NLA_NESTED },
        [NFTA_SET_ELEM_LIST_SET_ID]     = { .type = NLA_U32 },
 };
@@ -3303,9 +3308,9 @@ struct nft_set_dump_args {
 };
 
 static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
-                                 const struct nft_set *set,
+                                 struct nft_set *set,
                                  const struct nft_set_iter *iter,
-                                 const struct nft_set_elem *elem)
+                                 struct nft_set_elem *elem)
 {
        struct nft_set_dump_args *args;
 
@@ -3317,7 +3322,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
        u8 genmask = nft_genmask_cur(net);
-       const struct nft_set *set;
+       struct nft_set *set;
        struct nft_set_dump_args args;
        struct nft_ctx ctx;
        struct nlattr *nla[NFTA_SET_ELEM_LIST_MAX + 1];
@@ -3740,10 +3745,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                goto err5;
        }
 
+       if (set->size &&
+           !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact)) {
+               err = -ENFILE;
+               goto err6;
+       }
+
        nft_trans_elem(trans) = elem;
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
        return 0;
 
+err6:
+       set->ops->remove(set, &elem);
 err5:
        kfree(trans);
 err4:
@@ -3790,15 +3803,9 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
                return -EBUSY;
 
        nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
-               if (set->size &&
-                   !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact))
-                       return -ENFILE;
-
                err = nft_add_set_elem(&ctx, set, attr, nlh->nlmsg_flags);
-               if (err < 0) {
-                       atomic_dec(&set->nelems);
+               if (err < 0)
                        break;
-               }
        }
        return err;
 }
@@ -3883,9 +3890,9 @@ err1:
 }
 
 static int nft_flush_set(const struct nft_ctx *ctx,
-                        const struct nft_set *set,
+                        struct nft_set *set,
                         const struct nft_set_iter *iter,
-                        const struct nft_set_elem *elem)
+                        struct nft_set_elem *elem)
 {
        struct nft_trans *trans;
        int err;
@@ -3899,9 +3906,10 @@ static int nft_flush_set(const struct nft_ctx *ctx,
                err = -ENOENT;
                goto err1;
        }
+       set->ndeact++;
 
-       nft_trans_elem_set(trans) = (struct nft_set *)set;
-       nft_trans_elem(trans) = *((struct nft_set_elem *)elem);
+       nft_trans_elem_set(trans) = set;
+       nft_trans_elem(trans) = *elem;
        list_add_tail(&trans->list, &ctx->net->nft.commit_list);
 
        return 0;
@@ -4032,8 +4040,10 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table,
 EXPORT_SYMBOL_GPL(nf_tables_obj_lookup);
 
 static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
-       [NFTA_OBJ_TABLE]        = { .type = NLA_STRING },
-       [NFTA_OBJ_NAME]         = { .type = NLA_STRING },
+       [NFTA_OBJ_TABLE]        = { .type = NLA_STRING,
+                                   .len = NFT_TABLE_MAXNAMELEN - 1 },
+       [NFTA_OBJ_NAME]         = { .type = NLA_STRING,
+                                   .len = NFT_OBJ_MAXNAMELEN - 1 },
        [NFTA_OBJ_TYPE]         = { .type = NLA_U32 },
        [NFTA_OBJ_DATA]         = { .type = NLA_NESTED },
 };
@@ -4262,10 +4272,11 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
                                if (idx > s_idx)
                                        memset(&cb->args[1], 0,
                                               sizeof(cb->args) - sizeof(cb->args[0]));
-                               if (filter->table[0] &&
+                               if (filter && filter->table[0] &&
                                    strcmp(filter->table, table->name))
                                        goto cont;
-                               if (filter->type != NFT_OBJECT_UNSPEC &&
+                               if (filter &&
+                                   filter->type != NFT_OBJECT_UNSPEC &&
                                    obj->type->type != filter->type)
                                        goto cont;
 
@@ -5009,9 +5020,9 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
                                 const struct nft_chain *chain);
 
 static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
-                                       const struct nft_set *set,
+                                       struct nft_set *set,
                                        const struct nft_set_iter *iter,
-                                       const struct nft_set_elem *elem)
+                                       struct nft_set_elem *elem)
 {
        const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
        const struct nft_data *data;
@@ -5035,7 +5046,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
 {
        const struct nft_rule *rule;
        const struct nft_expr *expr, *last;
-       const struct nft_set *set;
+       struct nft_set *set;
        struct nft_set_binding *binding;
        struct nft_set_iter iter;
 
index 7de2f46734a428d0938fef91aa914865c62d680e..049ad2d9ee66959367a051903563dca6ba654edb 100644 (file)
@@ -98,7 +98,8 @@ out:
 }
 
 static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = {
-       [NFTA_DYNSET_SET_NAME]  = { .type = NLA_STRING },
+       [NFTA_DYNSET_SET_NAME]  = { .type = NLA_STRING,
+                                   .len = NFT_SET_MAXNAMELEN - 1 },
        [NFTA_DYNSET_SET_ID]    = { .type = NLA_U32 },
        [NFTA_DYNSET_OP]        = { .type = NLA_U32 },
        [NFTA_DYNSET_SREG_KEY]  = { .type = NLA_U32 },
index 6271e40a3dd6d00b0a19f31a5ef5509185120505..6f6e64423643a8c2991f2dedab65aff9e8c92720 100644 (file)
@@ -39,7 +39,8 @@ static void nft_log_eval(const struct nft_expr *expr,
 
 static const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = {
        [NFTA_LOG_GROUP]        = { .type = NLA_U16 },
-       [NFTA_LOG_PREFIX]       = { .type = NLA_STRING },
+       [NFTA_LOG_PREFIX]       = { .type = NLA_STRING,
+                                   .len = NF_LOG_PREFIXLEN - 1 },
        [NFTA_LOG_SNAPLEN]      = { .type = NLA_U32 },
        [NFTA_LOG_QTHRESHOLD]   = { .type = NLA_U16 },
        [NFTA_LOG_LEVEL]        = { .type = NLA_U32 },
index d4f97fa7e21d0036690e229768ab097fc5220cfc..e21aea7e5ec8f141ea3155d1da3c491484c00a73 100644 (file)
@@ -49,7 +49,8 @@ static void nft_lookup_eval(const struct nft_expr *expr,
 }
 
 static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {
-       [NFTA_LOOKUP_SET]       = { .type = NLA_STRING },
+       [NFTA_LOOKUP_SET]       = { .type = NLA_STRING,
+                                   .len = NFT_SET_MAXNAMELEN - 1 },
        [NFTA_LOOKUP_SET_ID]    = { .type = NLA_U32 },
        [NFTA_LOOKUP_SREG]      = { .type = NLA_U32 },
        [NFTA_LOOKUP_DREG]      = { .type = NLA_U32 },
index 415a65ba2b85eb93a6866fe42909aa6fcfd74cb3..1ae8c49ca4a1fac06f69c41f68a36b7e85593adb 100644 (file)
@@ -193,10 +193,12 @@ nft_objref_select_ops(const struct nft_ctx *ctx,
 }
 
 static const struct nla_policy nft_objref_policy[NFTA_OBJREF_MAX + 1] = {
-       [NFTA_OBJREF_IMM_NAME]  = { .type = NLA_STRING },
+       [NFTA_OBJREF_IMM_NAME]  = { .type = NLA_STRING,
+                                   .len = NFT_OBJ_MAXNAMELEN - 1 },
        [NFTA_OBJREF_IMM_TYPE]  = { .type = NLA_U32 },
        [NFTA_OBJREF_SET_SREG]  = { .type = NLA_U32 },
-       [NFTA_OBJREF_SET_NAME]  = { .type = NLA_STRING },
+       [NFTA_OBJREF_SET_NAME]  = { .type = NLA_STRING,
+                                   .len = NFT_SET_MAXNAMELEN - 1 },
        [NFTA_OBJREF_SET_ID]    = { .type = NLA_U32 },
 };
 
index 36d2b10965464cd8abc3ad57326aefb00b003971..7d699bbd45b0eaae1574a094f54a85d8219d390a 100644 (file)
@@ -250,6 +250,22 @@ static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt,
        return 0;
 }
 
+static int nft_payload_csum_inet(struct sk_buff *skb, const u32 *src,
+                                __wsum fsum, __wsum tsum, int csum_offset)
+{
+       __sum16 sum;
+
+       if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
+               return -1;
+
+       nft_csum_replace(&sum, fsum, tsum);
+       if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||
+           skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
+               return -1;
+
+       return 0;
+}
+
 static void nft_payload_set_eval(const struct nft_expr *expr,
                                 struct nft_regs *regs,
                                 const struct nft_pktinfo *pkt)
@@ -259,7 +275,6 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
        const u32 *src = &regs->data[priv->sreg];
        int offset, csum_offset;
        __wsum fsum, tsum;
-       __sum16 sum;
 
        switch (priv->base) {
        case NFT_PAYLOAD_LL_HEADER:
@@ -282,18 +297,14 @@ static void nft_payload_set_eval(const struct nft_expr *expr,
        csum_offset = offset + priv->csum_offset;
        offset += priv->offset;
 
-       if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
+       if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) &&
            (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER ||
             skb->ip_summed != CHECKSUM_PARTIAL)) {
-               if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
-                       goto err;
-
                fsum = skb_checksum(skb, offset, priv->len, 0);
                tsum = csum_partial(src, priv->len, 0);
-               nft_csum_replace(&sum, fsum, tsum);
 
-               if (!skb_make_writable(skb, csum_offset + sizeof(sum)) ||
-                   skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
+               if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
+                   nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset))
                        goto err;
 
                if (priv->csum_flags &&
index 3e19fa1230dc6b9274090257be97b91827699485..dbb6aaff67ec5c151f8c8c6333721421f8e85076 100644 (file)
@@ -38,7 +38,7 @@ static void nft_queue_eval(const struct nft_expr *expr,
 
        if (priv->queues_total > 1) {
                if (priv->flags & NFT_QUEUE_FLAG_CPU_FANOUT) {
-                       int cpu = smp_processor_id();
+                       int cpu = raw_smp_processor_id();
 
                        queue = priv->queuenum + cpu % priv->queues_total;
                } else {
index bd6efc53f26d01d8c8ac246c36fa4b1cf970ce31..2d6fe3559912674385e7679557fc31ddeb901b38 100644 (file)
@@ -110,30 +110,32 @@ static int nft_quota_obj_init(const struct nlattr * const tb[],
 static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
                             bool reset)
 {
+       u64 consumed, consumed_cap;
        u32 flags = priv->flags;
-       u64 consumed;
-
-       if (reset) {
-               consumed = atomic64_xchg(&priv->consumed, 0);
-               if (test_and_clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
-                       flags |= NFT_QUOTA_F_DEPLETED;
-       } else {
-               consumed = atomic64_read(&priv->consumed);
-       }
 
        /* Since we inconditionally increment consumed quota for each packet
         * that we see, don't go over the quota boundary in what we send to
         * userspace.
         */
-       if (consumed > priv->quota)
-               consumed = priv->quota;
+       consumed = atomic64_read(&priv->consumed);
+       if (consumed >= priv->quota) {
+               consumed_cap = priv->quota;
+               flags |= NFT_QUOTA_F_DEPLETED;
+       } else {
+               consumed_cap = consumed;
+       }
 
        if (nla_put_be64(skb, NFTA_QUOTA_BYTES, cpu_to_be64(priv->quota),
                         NFTA_QUOTA_PAD) ||
-           nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed),
+           nla_put_be64(skb, NFTA_QUOTA_CONSUMED, cpu_to_be64(consumed_cap),
                         NFTA_QUOTA_PAD) ||
            nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
                goto nla_put_failure;
+
+       if (reset) {
+               atomic64_sub(consumed, &priv->consumed);
+               clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
+       }
        return 0;
 
 nla_put_failure:
index 1e20e2bbb6d924b5cdb331acf8610c8719763c7c..e36069fb76aebd4140098f38a3758135e78b8d43 100644 (file)
@@ -212,7 +212,7 @@ static void nft_hash_remove(const struct nft_set *set,
        rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params);
 }
 
-static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
+static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
                          struct nft_set_iter *iter)
 {
        struct nft_hash *priv = nft_set_priv(set);
index 08376e50f6cdc26d7864e846b5a07f2ca662207c..f06f55ee516de44d3b0367cc52afb32173a2d0e8 100644 (file)
@@ -221,7 +221,7 @@ static void *nft_rbtree_deactivate(const struct net *net,
 }
 
 static void nft_rbtree_walk(const struct nft_ctx *ctx,
-                           const struct nft_set *set,
+                           struct nft_set *set,
                            struct nft_set_iter *iter)
 {
        const struct nft_rbtree *priv = nft_set_priv(set);
index 28c56b95fb7ff6ebaf5a99d8cfcbf583a01e73f5..ea7c67050792c9093c28b397e5ae164a570a0e33 100644 (file)
@@ -1502,10 +1502,7 @@ static int __init netlbl_init(void)
        printk(KERN_INFO "NetLabel: Initializing\n");
        printk(KERN_INFO "NetLabel:  domain hash size = %u\n",
               (1 << NETLBL_DOMHSH_BITSIZE));
-       printk(KERN_INFO "NetLabel:  protocols ="
-              " UNLABELED"
-              " CIPSOv4"
-              "\n");
+       printk(KERN_INFO "NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO\n");
 
        ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE);
        if (ret_val != 0)
index 6b78bab27755b2758f3c8ecd5b9c6d61615af4b6..54253ea5976e694ba93a9145e575197fce9df69a 100644 (file)
@@ -514,7 +514,7 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
        int hooknum, nh_off, err = NF_ACCEPT;
 
        nh_off = skb_network_offset(skb);
-       skb_pull(skb, nh_off);
+       skb_pull_rcsum(skb, nh_off);
 
        /* See HOOK2MANIP(). */
        if (maniptype == NF_NAT_MANIP_SRC)
@@ -579,6 +579,7 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
        err = nf_nat_packet(ct, ctinfo, hooknum, skb);
 push:
        skb_push(skb, nh_off);
+       skb_postpush_rcsum(skb, skb->data, nh_off);
 
        return err;
 }
@@ -886,7 +887,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
 
        /* The conntrack module expects to be working at L3. */
        nh_ofs = skb_network_offset(skb);
-       skb_pull(skb, nh_ofs);
+       skb_pull_rcsum(skb, nh_ofs);
 
        if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
                err = handle_fragments(net, key, info->zone.id, skb);
@@ -900,6 +901,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                err = ovs_ct_lookup(net, key, info, skb);
 
        skb_push(skb, nh_ofs);
+       skb_postpush_rcsum(skb, skb->data, nh_ofs);
        if (err)
                kfree_skb(skb);
        return err;
index b9e1a13b4ba36a0bc7edf6a8c2c116c7d48c970c..70f5b6a4683c29351284e3385f56caf1bce37ac7 100644 (file)
@@ -1497,6 +1497,8 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po)
        f->arr[f->num_members] = sk;
        smp_wmb();
        f->num_members++;
+       if (f->num_members == 1)
+               dev_add_pack(&f->prot_hook);
        spin_unlock(&f->lock);
 }
 
@@ -1513,6 +1515,8 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
        BUG_ON(i >= f->num_members);
        f->arr[i] = f->arr[f->num_members - 1];
        f->num_members--;
+       if (f->num_members == 0)
+               __dev_remove_pack(&f->prot_hook);
        spin_unlock(&f->lock);
 }
 
@@ -1619,6 +1623,7 @@ static void fanout_release_data(struct packet_fanout *f)
 
 static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 {
+       struct packet_rollover *rollover = NULL;
        struct packet_sock *po = pkt_sk(sk);
        struct packet_fanout *f, *match;
        u8 type = type_flags & 0xff;
@@ -1641,23 +1646,28 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
                return -EINVAL;
        }
 
+       mutex_lock(&fanout_mutex);
+
+       err = -EINVAL;
        if (!po->running)
-               return -EINVAL;
+               goto out;
 
+       err = -EALREADY;
        if (po->fanout)
-               return -EALREADY;
+               goto out;
 
        if (type == PACKET_FANOUT_ROLLOVER ||
            (type_flags & PACKET_FANOUT_FLAG_ROLLOVER)) {
-               po->rollover = kzalloc(sizeof(*po->rollover), GFP_KERNEL);
-               if (!po->rollover)
-                       return -ENOMEM;
-               atomic_long_set(&po->rollover->num, 0);
-               atomic_long_set(&po->rollover->num_huge, 0);
-               atomic_long_set(&po->rollover->num_failed, 0);
+               err = -ENOMEM;
+               rollover = kzalloc(sizeof(*rollover), GFP_KERNEL);
+               if (!rollover)
+                       goto out;
+               atomic_long_set(&rollover->num, 0);
+               atomic_long_set(&rollover->num_huge, 0);
+               atomic_long_set(&rollover->num_failed, 0);
+               po->rollover = rollover;
        }
 
-       mutex_lock(&fanout_mutex);
        match = NULL;
        list_for_each_entry(f, &fanout_list, list) {
                if (f->id == id &&
@@ -1687,7 +1697,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
                match->prot_hook.func = packet_rcv_fanout;
                match->prot_hook.af_packet_priv = match;
                match->prot_hook.id_match = match_fanout_group;
-               dev_add_pack(&match->prot_hook);
                list_add(&match->list, &fanout_list);
        }
        err = -EINVAL;
@@ -1704,36 +1713,40 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
                }
        }
 out:
-       mutex_unlock(&fanout_mutex);
-       if (err) {
-               kfree(po->rollover);
+       if (err && rollover) {
+               kfree(rollover);
                po->rollover = NULL;
        }
+       mutex_unlock(&fanout_mutex);
        return err;
 }
 
-static void fanout_release(struct sock *sk)
+/* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes
+ * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout.
+ * It is the responsibility of the caller to call fanout_release_data() and
+ * free the returned packet_fanout (after synchronize_net())
+ */
+static struct packet_fanout *fanout_release(struct sock *sk)
 {
        struct packet_sock *po = pkt_sk(sk);
        struct packet_fanout *f;
 
+       mutex_lock(&fanout_mutex);
        f = po->fanout;
-       if (!f)
-               return;
+       if (f) {
+               po->fanout = NULL;
 
-       mutex_lock(&fanout_mutex);
-       po->fanout = NULL;
+               if (atomic_dec_and_test(&f->sk_ref))
+                       list_del(&f->list);
+               else
+                       f = NULL;
 
-       if (atomic_dec_and_test(&f->sk_ref)) {
-               list_del(&f->list);
-               dev_remove_pack(&f->prot_hook);
-               fanout_release_data(f);
-               kfree(f);
+               if (po->rollover)
+                       kfree_rcu(po->rollover, rcu);
        }
        mutex_unlock(&fanout_mutex);
 
-       if (po->rollover)
-               kfree_rcu(po->rollover, rcu);
+       return f;
 }
 
 static bool packet_extra_vlan_len_allowed(const struct net_device *dev,
@@ -1976,7 +1989,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
                return -EINVAL;
        *len -= sizeof(vnet_hdr);
 
-       if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le()))
+       if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true))
                return -EINVAL;
 
        return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr));
@@ -2237,7 +2250,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        if (po->has_vnet_hdr) {
                if (virtio_net_hdr_from_skb(skb, h.raw + macoff -
                                            sizeof(struct virtio_net_hdr),
-                                           vio_le())) {
+                                           vio_le(), true)) {
                        spin_lock(&sk->sk_receive_queue.lock);
                        goto drop_n_account;
                }
@@ -2755,7 +2768,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        struct virtio_net_hdr vnet_hdr = { 0 };
        int offset = 0;
        struct packet_sock *po = pkt_sk(sk);
-       int hlen, tlen;
+       int hlen, tlen, linear;
        int extra_len = 0;
 
        /*
@@ -2816,8 +2829,9 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        err = -ENOBUFS;
        hlen = LL_RESERVED_SPACE(dev);
        tlen = dev->needed_tailroom;
-       skb = packet_alloc_skb(sk, hlen + tlen, hlen, len,
-                              __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len),
+       linear = __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len);
+       linear = max(linear, min_t(int, len, dev->hard_header_len));
+       skb = packet_alloc_skb(sk, hlen + tlen, hlen, len, linear,
                               msg->msg_flags & MSG_DONTWAIT, &err);
        if (skb == NULL)
                goto out_unlock;
@@ -2906,6 +2920,7 @@ static int packet_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
        struct packet_sock *po;
+       struct packet_fanout *f;
        struct net *net;
        union tpacket_req_u req_u;
 
@@ -2945,9 +2960,14 @@ static int packet_release(struct socket *sock)
                packet_set_ring(sk, &req_u, 1, 1);
        }
 
-       fanout_release(sk);
+       f = fanout_release(sk);
 
        synchronize_net();
+
+       if (f) {
+               fanout_release_data(f);
+               kfree(f);
+       }
        /*
         *      Now the socket is dead. No more input will appear.
         */
@@ -3899,7 +3919,6 @@ static int packet_notifier(struct notifier_block *this,
                                }
                                if (msg == NETDEV_UNREGISTER) {
                                        packet_cached_dev_reset(po);
-                                       fanout_release(sk);
                                        po->ifindex = -1;
                                        if (po->prot_hook.dev)
                                                dev_put(po->prot_hook.dev);
index c985ecbe9bd62a81899d43eb802003d6bb4ebe08..ae5ac175b2bef96ffa614bc799db5cd90a7bdc08 100644 (file)
@@ -252,7 +252,7 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
        const int pkt_len = 20;
        struct qrtr_hdr *hdr;
        struct sk_buff *skb;
-       u32 *buf;
+       __le32 *buf;
 
        skb = alloc_skb(QRTR_HDR_SIZE + pkt_len, GFP_KERNEL);
        if (!skb)
@@ -269,7 +269,7 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
        hdr->dst_node_id = cpu_to_le32(dst_node);
        hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL);
 
-       buf = (u32 *)skb_put(skb, pkt_len);
+       buf = (__le32 *)skb_put(skb, pkt_len);
        memset(buf, 0, pkt_len);
        buf[0] = cpu_to_le32(QRTR_TYPE_RESUME_TX);
        buf[1] = cpu_to_le32(src_node);
index 2095c83ce7730d49550103a8efad943d28815617..e10456ef6f7a43c1b1a3c153012805015c51e9f5 100644 (file)
@@ -900,8 +900,6 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
                        goto err;
                }
                act->order = i;
-               if (event == RTM_GETACTION)
-                       act->tcfa_refcnt++;
                list_add_tail(&act->list, &actions);
        }
 
@@ -914,7 +912,8 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
                return ret;
        }
 err:
-       tcf_action_destroy(&actions, 0);
+       if (event != RTM_GETACTION)
+               tcf_action_destroy(&actions, 0);
        return ret;
 }
 
index 1c60317f01214ad77c17415bb2d7bc194b124615..520baa41cba3a8d24a659b67c5a5ed8a44129f37 100644 (file)
@@ -123,12 +123,11 @@ static int tcf_bpf_dump_ebpf_info(const struct tcf_bpf *prog,
            nla_put_string(skb, TCA_ACT_BPF_NAME, prog->bpf_name))
                return -EMSGSIZE;
 
-       nla = nla_reserve(skb, TCA_ACT_BPF_DIGEST,
-                         sizeof(prog->filter->digest));
+       nla = nla_reserve(skb, TCA_ACT_BPF_TAG, sizeof(prog->filter->tag));
        if (nla == NULL)
                return -EMSGSIZE;
 
-       memcpy(nla_data(nla), prog->filter->digest, nla_len(nla));
+       memcpy(nla_data(nla), prog->filter->tag, nla_len(nla));
 
        return 0;
 }
index adc776048d1a899f7955d0a92dd48b374178f3bb..d9c97018317dd7e26b6c99dfa83b8d6daeca6d19 100644 (file)
@@ -555,11 +555,11 @@ static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog,
            nla_put_string(skb, TCA_BPF_NAME, prog->bpf_name))
                return -EMSGSIZE;
 
-       nla = nla_reserve(skb, TCA_BPF_DIGEST, sizeof(prog->filter->digest));
+       nla = nla_reserve(skb, TCA_BPF_TAG, sizeof(prog->filter->tag));
        if (nla == NULL)
                return -EMSGSIZE;
 
-       memcpy(nla_data(nla), prog->filter->digest, nla_len(nla));
+       memcpy(nla_data(nla), prog->filter->tag, nla_len(nla));
 
        return 0;
 }
index 970db7a41684aa2a494b97663f91ca932308de05..5752789acc135250c312199c2d6e5e15d05fdea0 100644 (file)
@@ -568,9 +568,9 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
                               &mask->icmp.type,
                               TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,
                               sizeof(key->icmp.type));
-               fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV4_CODE,
+               fl_set_key_val(tb, &key->icmp.code, TCA_FLOWER_KEY_ICMPV6_CODE,
                               &mask->icmp.code,
-                              TCA_FLOWER_KEY_ICMPV4_CODE_MASK,
+                              TCA_FLOWER_KEY_ICMPV6_CODE_MASK,
                               sizeof(key->icmp.code));
        }
 
index f935429bd5ef1fcbe6a4272876b76e2ebb574c4b..b12bc2abea931a7defd1e23eb86a20fe09e76388 100644 (file)
 #include <net/sch_generic.h>
 #include <net/pkt_cls.h>
 
-struct cls_mall_filter {
+struct cls_mall_head {
        struct tcf_exts exts;
        struct tcf_result res;
        u32 handle;
-       struct rcu_head rcu;
        u32 flags;
-};
-
-struct cls_mall_head {
-       struct cls_mall_filter *filter;
        struct rcu_head rcu;
 };
 
@@ -33,38 +28,29 @@ static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                         struct tcf_result *res)
 {
        struct cls_mall_head *head = rcu_dereference_bh(tp->root);
-       struct cls_mall_filter *f = head->filter;
 
-       if (tc_skip_sw(f->flags))
+       if (tc_skip_sw(head->flags))
                return -1;
 
-       return tcf_exts_exec(skb, &f->exts, res);
+       return tcf_exts_exec(skb, &head->exts, res);
 }
 
 static int mall_init(struct tcf_proto *tp)
 {
-       struct cls_mall_head *head;
-
-       head = kzalloc(sizeof(*head), GFP_KERNEL);
-       if (!head)
-               return -ENOBUFS;
-
-       rcu_assign_pointer(tp->root, head);
-
        return 0;
 }
 
-static void mall_destroy_filter(struct rcu_head *head)
+static void mall_destroy_rcu(struct rcu_head *rcu)
 {
-       struct cls_mall_filter *f = container_of(head, struct cls_mall_filter, rcu);
+       struct cls_mall_head *head = container_of(rcu, struct cls_mall_head,
+                                                 rcu);
 
-       tcf_exts_destroy(&f->exts);
-
-       kfree(f);
+       tcf_exts_destroy(&head->exts);
+       kfree(head);
 }
 
 static int mall_replace_hw_filter(struct tcf_proto *tp,
-                                 struct cls_mall_filter *f,
+                                 struct cls_mall_head *head,
                                  unsigned long cookie)
 {
        struct net_device *dev = tp->q->dev_queue->dev;
@@ -74,7 +60,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
        offload.type = TC_SETUP_MATCHALL;
        offload.cls_mall = &mall_offload;
        offload.cls_mall->command = TC_CLSMATCHALL_REPLACE;
-       offload.cls_mall->exts = &f->exts;
+       offload.cls_mall->exts = &head->exts;
        offload.cls_mall->cookie = cookie;
 
        return dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol,
@@ -82,7 +68,7 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
 }
 
 static void mall_destroy_hw_filter(struct tcf_proto *tp,
-                                  struct cls_mall_filter *f,
+                                  struct cls_mall_head *head,
                                   unsigned long cookie)
 {
        struct net_device *dev = tp->q->dev_queue->dev;
@@ -103,29 +89,20 @@ static bool mall_destroy(struct tcf_proto *tp, bool force)
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
        struct net_device *dev = tp->q->dev_queue->dev;
-       struct cls_mall_filter *f = head->filter;
 
-       if (!force && f)
-               return false;
+       if (!head)
+               return true;
 
-       if (f) {
-               if (tc_should_offload(dev, tp, f->flags))
-                       mall_destroy_hw_filter(tp, f, (unsigned long) f);
+       if (tc_should_offload(dev, tp, head->flags))
+               mall_destroy_hw_filter(tp, head, (unsigned long) head);
 
-               call_rcu(&f->rcu, mall_destroy_filter);
-       }
-       kfree_rcu(head, rcu);
+       call_rcu(&head->rcu, mall_destroy_rcu);
        return true;
 }
 
 static unsigned long mall_get(struct tcf_proto *tp, u32 handle)
 {
-       struct cls_mall_head *head = rtnl_dereference(tp->root);
-       struct cls_mall_filter *f = head->filter;
-
-       if (f && f->handle == handle)
-               return (unsigned long) f;
-       return 0;
+       return 0UL;
 }
 
 static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
@@ -134,7 +111,7 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
 };
 
 static int mall_set_parms(struct net *net, struct tcf_proto *tp,
-                         struct cls_mall_filter *f,
+                         struct cls_mall_head *head,
                          unsigned long base, struct nlattr **tb,
                          struct nlattr *est, bool ovr)
 {
@@ -147,11 +124,11 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
                return err;
 
        if (tb[TCA_MATCHALL_CLASSID]) {
-               f->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
-               tcf_bind_filter(tp, &f->res, base);
+               head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
+               tcf_bind_filter(tp, &head->res, base);
        }
 
-       tcf_exts_change(tp, &f->exts, &e);
+       tcf_exts_change(tp, &head->exts, &e);
 
        return 0;
 }
@@ -162,21 +139,17 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
                       unsigned long *arg, bool ovr)
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
-       struct cls_mall_filter *fold = (struct cls_mall_filter *) *arg;
        struct net_device *dev = tp->q->dev_queue->dev;
-       struct cls_mall_filter *f;
        struct nlattr *tb[TCA_MATCHALL_MAX + 1];
+       struct cls_mall_head *new;
        u32 flags = 0;
        int err;
 
        if (!tca[TCA_OPTIONS])
                return -EINVAL;
 
-       if (head->filter)
-               return -EBUSY;
-
-       if (fold)
-               return -EINVAL;
+       if (head)
+               return -EEXIST;
 
        err = nla_parse_nested(tb, TCA_MATCHALL_MAX,
                               tca[TCA_OPTIONS], mall_policy);
@@ -189,23 +162,23 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
                        return -EINVAL;
        }
 
-       f = kzalloc(sizeof(*f), GFP_KERNEL);
-       if (!f)
+       new = kzalloc(sizeof(*new), GFP_KERNEL);
+       if (!new)
                return -ENOBUFS;
 
-       tcf_exts_init(&f->exts, TCA_MATCHALL_ACT, 0);
+       tcf_exts_init(&new->exts, TCA_MATCHALL_ACT, 0);
 
        if (!handle)
                handle = 1;
-       f->handle = handle;
-       f->flags = flags;
+       new->handle = handle;
+       new->flags = flags;
 
-       err = mall_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
+       err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], ovr);
        if (err)
                goto errout;
 
        if (tc_should_offload(dev, tp, flags)) {
-               err = mall_replace_hw_filter(tp, f, (unsigned long) f);
+               err = mall_replace_hw_filter(tp, new, (unsigned long) new);
                if (err) {
                        if (tc_skip_sw(flags))
                                goto errout;
@@ -214,39 +187,29 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
                }
        }
 
-       *arg = (unsigned long) f;
-       rcu_assign_pointer(head->filter, f);
-
+       *arg = (unsigned long) head;
+       rcu_assign_pointer(tp->root, new);
+       if (head)
+               call_rcu(&head->rcu, mall_destroy_rcu);
        return 0;
 
 errout:
-       kfree(f);
+       kfree(new);
        return err;
 }
 
 static int mall_delete(struct tcf_proto *tp, unsigned long arg)
 {
-       struct cls_mall_head *head = rtnl_dereference(tp->root);
-       struct cls_mall_filter *f = (struct cls_mall_filter *) arg;
-       struct net_device *dev = tp->q->dev_queue->dev;
-
-       if (tc_should_offload(dev, tp, f->flags))
-               mall_destroy_hw_filter(tp, f, (unsigned long) f);
-
-       RCU_INIT_POINTER(head->filter, NULL);
-       tcf_unbind_filter(tp, &f->res);
-       call_rcu(&f->rcu, mall_destroy_filter);
-       return 0;
+       return -EOPNOTSUPP;
 }
 
 static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
-       struct cls_mall_filter *f = head->filter;
 
        if (arg->count < arg->skip)
                goto skip;
-       if (arg->fn(tp, (unsigned long) f, arg) < 0)
+       if (arg->fn(tp, (unsigned long) head, arg) < 0)
                arg->stop = 1;
 skip:
        arg->count++;
@@ -255,28 +218,28 @@ skip:
 static int mall_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
                     struct sk_buff *skb, struct tcmsg *t)
 {
-       struct cls_mall_filter *f = (struct cls_mall_filter *) fh;
+       struct cls_mall_head *head = (struct cls_mall_head *) fh;
        struct nlattr *nest;
 
-       if (!f)
+       if (!head)
                return skb->len;
 
-       t->tcm_handle = f->handle;
+       t->tcm_handle = head->handle;
 
        nest = nla_nest_start(skb, TCA_OPTIONS);
        if (!nest)
                goto nla_put_failure;
 
-       if (f->res.classid &&
-           nla_put_u32(skb, TCA_MATCHALL_CLASSID, f->res.classid))
+       if (head->res.classid &&
+           nla_put_u32(skb, TCA_MATCHALL_CLASSID, head->res.classid))
                goto nla_put_failure;
 
-       if (tcf_exts_dump(skb, &f->exts))
+       if (tcf_exts_dump(skb, &head->exts))
                goto nla_put_failure;
 
        nla_nest_end(skb, nest);
 
-       if (tcf_exts_dump_stats(skb, &f->exts) < 0)
+       if (tcf_exts_dump_stats(skb, &head->exts) < 0)
                goto nla_put_failure;
 
        return skb->len;
index 5ed8e79bf102e1c2a9ef1955aee6dba01869545e..64dfd35ccdcccbf35b2f6273565f2dbf89f941c5 100644 (file)
@@ -222,7 +222,8 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
        SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
 
        rcu_read_lock();
-       res = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), np->tclass);
+       res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt),
+                      np->tclass);
        rcu_read_unlock();
        return res;
 }
index 7e869d0cca69826ee3e892e389bacdc9a58a1637..4f5a2b580aa52deb75e00c92d8b60992cf5bdaa6 100644 (file)
@@ -68,7 +68,7 @@ static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
                goto out;
        }
 
-       segs = skb_segment(skb, features | NETIF_F_HW_CSUM);
+       segs = skb_segment(skb, features | NETIF_F_HW_CSUM | NETIF_F_SG);
        if (IS_ERR(segs))
                goto out;
 
index e54082699520ae40d8ab4c282c230f3b3787db92..34efaa4ef2f6acfbed9b490f948f214e91a5606c 100644 (file)
@@ -1048,7 +1048,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
                             (new_transport->state == SCTP_PF)))
                                new_transport = asoc->peer.active_path;
                        if (new_transport->state == SCTP_UNCONFIRMED) {
-                               WARN_ONCE(1, "Atempt to send packet on unconfirmed path.");
+                               WARN_ONCE(1, "Attempt to send packet on unconfirmed path.");
                                sctp_chunk_fail(chunk, 0);
                                sctp_chunk_free(chunk);
                                continue;
index 318c6786d6539a301ac7b76d82a49a1af3818d10..1b5d669e30292a57ed57dd920d81be2a57f97b22 100644 (file)
@@ -235,8 +235,12 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
                                              sctp_assoc_t id)
 {
        struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
-       struct sctp_transport *transport;
+       struct sctp_af *af = sctp_get_af_specific(addr->ss_family);
        union sctp_addr *laddr = (union sctp_addr *)addr;
+       struct sctp_transport *transport;
+
+       if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len))
+               return NULL;
 
        addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
                                               laddr,
@@ -7422,7 +7426,8 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
                 */
                release_sock(sk);
                current_timeo = schedule_timeout(current_timeo);
-               BUG_ON(sk != asoc->base.sk);
+               if (sk != asoc->base.sk)
+                       goto do_error;
                lock_sock(sk);
 
                *timeo_p = current_timeo;
index a8c2307590b87ce5774f275fcbc1397f095d4c27..0758e13754e2faccb257d2f6ba9cca7b2da1baab 100644 (file)
@@ -533,7 +533,7 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
        return used;
 }
 
-int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
        int err = simple_setattr(dentry, iattr);
 
index dc6fb79a361f1ca3ab9869fc02ba05c1a533ad9b..25d9a9cf7b66b7f4e501d38d91f6a1908830972e 100644 (file)
@@ -260,7 +260,7 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
        if (!oa->data)
                return -ENOMEM;
 
-       creds = kmalloc(sizeof(struct svc_cred), GFP_KERNEL);
+       creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL);
        if (!creds) {
                kfree(oa->data);
                return -ENOMEM;
index 886e9d381771ab8c05ed514a399a089c106b2282..1530825985221a1aeb5f77ee81f4251acdef9d96 100644 (file)
@@ -1489,7 +1489,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
        case RPC_GSS_PROC_DESTROY:
                if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
                        goto auth_err;
-               rsci->h.expiry_time = get_seconds();
+               rsci->h.expiry_time = seconds_since_boot();
                set_bit(CACHE_NEGATIVE, &rsci->h.flags);
                if (resv->iov_len + 4 > PAGE_SIZE)
                        goto drop;
index 1efbe48e794f804b24f30e566994b873a85727bb..1dc9f3bac0997384a9b3daab33d8ceeda3d726d9 100644 (file)
@@ -336,6 +336,11 @@ out:
 
 static DEFINE_IDA(rpc_clids);
 
+void rpc_cleanup_clids(void)
+{
+       ida_destroy(&rpc_clids);
+}
+
 static int rpc_alloc_clid(struct rpc_clnt *clnt)
 {
        int clid;
index d1c330a7953a0bc9bb4e08162baf77740504b80c..c73de181467a307346872629ac5c62ce1cde3d72 100644 (file)
@@ -119,6 +119,7 @@ out:
 static void __exit
 cleanup_sunrpc(void)
 {
+       rpc_cleanup_clids();
        rpcauth_remove_module();
        cleanup_socket_xprt();
        svc_cleanup_xprt_sock();
index 3bc1d61694cbbbf7a094a1849b747b65760550b2..9c9db55a0c1e1735e522e406797c4efb25930b07 100644 (file)
@@ -799,6 +799,8 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
 
        if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
                dprintk("svc_recv: found XPT_CLOSE\n");
+               if (test_and_clear_bit(XPT_KILL_TEMP, &xprt->xpt_flags))
+                       xprt->xpt_ops->xpo_kill_temp_xprt(xprt);
                svc_delete_xprt(xprt);
                /* Leave XPT_BUSY set on the dead xprt: */
                goto out;
@@ -1020,9 +1022,11 @@ void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
                le = to_be_closed.next;
                list_del_init(le);
                xprt = list_entry(le, struct svc_xprt, xpt_list);
-               dprintk("svc_age_temp_xprts_now: closing %p\n", xprt);
-               xprt->xpt_ops->xpo_kill_temp_xprt(xprt);
-               svc_close_xprt(xprt);
+               set_bit(XPT_CLOSE, &xprt->xpt_flags);
+               set_bit(XPT_KILL_TEMP, &xprt->xpt_flags);
+               dprintk("svc_age_temp_xprts_now: queuing xprt %p for closing\n",
+                               xprt);
+               svc_xprt_enqueue(xprt);
        }
 }
 EXPORT_SYMBOL_GPL(svc_age_temp_xprts_now);
index 57d35fbb1c28570b5c23f5e06974e8b902853846..172b537f8cfc942ef62574b74cff7ac5f421fba9 100644 (file)
@@ -347,8 +347,6 @@ int rdma_read_chunk_frmr(struct svcxprt_rdma *xprt,
        atomic_inc(&rdma_stat_read);
        return ret;
  err:
-       ib_dma_unmap_sg(xprt->sc_cm_id->device,
-                       frmr->sg, frmr->sg_nents, frmr->direction);
        svc_rdma_put_context(ctxt, 0);
        svc_rdma_put_frmr(xprt, frmr);
        return ret;
index 6b109a808d4c5f43677ff25bd5450d5e8c1dd920..02462d67d1914b6e4b20c4daf7a493b29049a2e4 100644 (file)
@@ -169,7 +169,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb,
 
        /* Send response, if necessary */
        if (respond && (mtyp == DSC_REQ_MSG)) {
-               rskb = tipc_buf_acquire(MAX_H_SIZE);
+               rskb = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC);
                if (!rskb)
                        return;
                tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer);
@@ -278,7 +278,7 @@ int tipc_disc_create(struct net *net, struct tipc_bearer *b,
        req = kmalloc(sizeof(*req), GFP_ATOMIC);
        if (!req)
                return -ENOMEM;
-       req->buf = tipc_buf_acquire(MAX_H_SIZE);
+       req->buf = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC);
        if (!req->buf) {
                kfree(req);
                return -ENOMEM;
index bda89bf9f4ff185f64c68c06d8b88a4385380c58..4e8647aef01c1d070751adc6a24c63769b66e599 100644 (file)
@@ -1395,7 +1395,7 @@ tnl:
                        msg_set_seqno(hdr, seqno++);
                pktlen = msg_size(hdr);
                msg_set_size(&tnlhdr, pktlen + INT_H_SIZE);
-               tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE);
+               tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE, GFP_ATOMIC);
                if (!tnlskb) {
                        pr_warn("%sunable to send packet\n", link_co_err);
                        return;
index a22be502f1bd06dc8ec23ab44e56d32f4c3dd469..ab02d07424764ad4b269b6ad560167f528454b80 100644 (file)
@@ -58,12 +58,12 @@ static unsigned int align(unsigned int i)
  * NOTE: Headroom is reserved to allow prepending of a data link header.
  *       There may also be unrequested tailroom present at the buffer's end.
  */
-struct sk_buff *tipc_buf_acquire(u32 size)
+struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
 {
        struct sk_buff *skb;
        unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
 
-       skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
+       skb = alloc_skb_fclone(buf_size, gfp);
        if (skb) {
                skb_reserve(skb, BUF_HEADROOM);
                skb_put(skb, size);
@@ -95,7 +95,7 @@ struct sk_buff *tipc_msg_create(uint user, uint type,
        struct tipc_msg *msg;
        struct sk_buff *buf;
 
-       buf = tipc_buf_acquire(hdr_sz + data_sz);
+       buf = tipc_buf_acquire(hdr_sz + data_sz, GFP_ATOMIC);
        if (unlikely(!buf))
                return NULL;
 
@@ -261,7 +261,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
 
        /* No fragmentation needed? */
        if (likely(msz <= pktmax)) {
-               skb = tipc_buf_acquire(msz);
+               skb = tipc_buf_acquire(msz, GFP_KERNEL);
                if (unlikely(!skb))
                        return -ENOMEM;
                skb_orphan(skb);
@@ -282,7 +282,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
        msg_set_importance(&pkthdr, msg_importance(mhdr));
 
        /* Prepare first fragment */
-       skb = tipc_buf_acquire(pktmax);
+       skb = tipc_buf_acquire(pktmax, GFP_KERNEL);
        if (!skb)
                return -ENOMEM;
        skb_orphan(skb);
@@ -313,7 +313,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
                        pktsz = drem + INT_H_SIZE;
                else
                        pktsz = pktmax;
-               skb = tipc_buf_acquire(pktsz);
+               skb = tipc_buf_acquire(pktsz, GFP_KERNEL);
                if (!skb) {
                        rc = -ENOMEM;
                        goto error;
@@ -448,7 +448,7 @@ bool tipc_msg_make_bundle(struct sk_buff **skb,  struct tipc_msg *msg,
        if (msz > (max / 2))
                return false;
 
-       _skb = tipc_buf_acquire(max);
+       _skb = tipc_buf_acquire(max, GFP_ATOMIC);
        if (!_skb)
                return false;
 
@@ -496,7 +496,7 @@ bool tipc_msg_reverse(u32 own_node,  struct sk_buff **skb, int err)
 
        /* Never return SHORT header; expand by replacing buffer if necessary */
        if (msg_short(hdr)) {
-               *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen);
+               *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen, GFP_ATOMIC);
                if (!*skb)
                        goto exit;
                memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
index 8d408612ffa490521e310b3c643f2407a6c822f3..2c3dc38abf9c25814c0d9e3c31711706f2bca664 100644 (file)
@@ -820,7 +820,7 @@ static inline bool msg_is_reset(struct tipc_msg *hdr)
        return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG);
 }
 
-struct sk_buff *tipc_buf_acquire(u32 size);
+struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp);
 bool tipc_msg_validate(struct sk_buff *skb);
 bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
 void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type,
index c1cfd92de17aee30a310305707a70ecb87fd2548..23f8899e0f8c3d7bda50bc57801bcc63ceab448c 100644 (file)
@@ -69,7 +69,7 @@ static struct sk_buff *named_prepare_buf(struct net *net, u32 type, u32 size,
                                         u32 dest)
 {
        struct tipc_net *tn = net_generic(net, tipc_net_id);
-       struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size);
+       struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size, GFP_ATOMIC);
        struct tipc_msg *msg;
 
        if (buf != NULL) {
index 9d2f4c2b08abc56ecb627ff067ad359c54e735fd..27753325e06e4355d71270d8c5c8818bef3e94c5 100644 (file)
@@ -263,6 +263,11 @@ static void tipc_node_write_lock(struct tipc_node *n)
        write_lock_bh(&n->lock);
 }
 
+static void tipc_node_write_unlock_fast(struct tipc_node *n)
+{
+       write_unlock_bh(&n->lock);
+}
+
 static void tipc_node_write_unlock(struct tipc_node *n)
 {
        struct net *net = n->net;
@@ -417,7 +422,7 @@ void tipc_node_subscribe(struct net *net, struct list_head *subscr, u32 addr)
        }
        tipc_node_write_lock(n);
        list_add_tail(subscr, &n->publ_list);
-       tipc_node_write_unlock(n);
+       tipc_node_write_unlock_fast(n);
        tipc_node_put(n);
 }
 
@@ -435,7 +440,7 @@ void tipc_node_unsubscribe(struct net *net, struct list_head *subscr, u32 addr)
        }
        tipc_node_write_lock(n);
        list_del_init(subscr);
-       tipc_node_write_unlock(n);
+       tipc_node_write_unlock_fast(n);
        tipc_node_put(n);
 }
 
index 215849ce453dfbd70bccceacc4d42b1a2a6d37d8..3cd6402e812cb05c5fc0872941a8a6c683e367f3 100644 (file)
@@ -86,12 +86,12 @@ struct outqueue_entry {
 static void tipc_recv_work(struct work_struct *work);
 static void tipc_send_work(struct work_struct *work);
 static void tipc_clean_outqueues(struct tipc_conn *con);
-static void tipc_sock_release(struct tipc_conn *con);
 
 static void tipc_conn_kref_release(struct kref *kref)
 {
        struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
-       struct sockaddr_tipc *saddr = con->server->saddr;
+       struct tipc_server *s = con->server;
+       struct sockaddr_tipc *saddr = s->saddr;
        struct socket *sock = con->sock;
        struct sock *sk;
 
@@ -103,9 +103,13 @@ static void tipc_conn_kref_release(struct kref *kref)
                }
                saddr->scope = -TIPC_NODE_SCOPE;
                kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr));
-               tipc_sock_release(con);
                sock_release(sock);
                con->sock = NULL;
+
+               spin_lock_bh(&s->idr_lock);
+               idr_remove(&s->conn_idr, con->conid);
+               s->idr_in_use--;
+               spin_unlock_bh(&s->idr_lock);
        }
 
        tipc_clean_outqueues(con);
@@ -128,8 +132,10 @@ static struct tipc_conn *tipc_conn_lookup(struct tipc_server *s, int conid)
 
        spin_lock_bh(&s->idr_lock);
        con = idr_find(&s->conn_idr, conid);
-       if (con)
+       if (con && test_bit(CF_CONNECTED, &con->flags))
                conn_get(con);
+       else
+               con = NULL;
        spin_unlock_bh(&s->idr_lock);
        return con;
 }
@@ -186,26 +192,15 @@ static void tipc_unregister_callbacks(struct tipc_conn *con)
        write_unlock_bh(&sk->sk_callback_lock);
 }
 
-static void tipc_sock_release(struct tipc_conn *con)
-{
-       struct tipc_server *s = con->server;
-
-       if (con->conid)
-               s->tipc_conn_release(con->conid, con->usr_data);
-
-       tipc_unregister_callbacks(con);
-}
-
 static void tipc_close_conn(struct tipc_conn *con)
 {
        struct tipc_server *s = con->server;
 
        if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
+               tipc_unregister_callbacks(con);
 
-               spin_lock_bh(&s->idr_lock);
-               idr_remove(&s->conn_idr, con->conid);
-               s->idr_in_use--;
-               spin_unlock_bh(&s->idr_lock);
+               if (con->conid)
+                       s->tipc_conn_release(con->conid, con->usr_data);
 
                /* We shouldn't flush pending works as we may be in the
                 * thread. In fact the races with pending rx/tx work structs
@@ -458,6 +453,11 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,
        if (!con)
                return -EINVAL;
 
+       if (!test_bit(CF_CONNECTED, &con->flags)) {
+               conn_put(con);
+               return 0;
+       }
+
        e = tipc_alloc_entry(data, len);
        if (!e) {
                conn_put(con);
@@ -471,12 +471,8 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,
        list_add_tail(&e->list, &con->outqueue);
        spin_unlock_bh(&con->outqueue_lock);
 
-       if (test_bit(CF_CONNECTED, &con->flags)) {
-               if (!queue_work(s->send_wq, &con->swork))
-                       conn_put(con);
-       } else {
+       if (!queue_work(s->send_wq, &con->swork))
                conn_put(con);
-       }
        return 0;
 }
 
@@ -500,7 +496,7 @@ static void tipc_send_to_sock(struct tipc_conn *con)
        int ret;
 
        spin_lock_bh(&con->outqueue_lock);
-       while (1) {
+       while (test_bit(CF_CONNECTED, &con->flags)) {
                e = list_entry(con->outqueue.next, struct outqueue_entry,
                               list);
                if ((struct list_head *) e == &con->outqueue)
@@ -623,14 +619,12 @@ int tipc_server_start(struct tipc_server *s)
 void tipc_server_stop(struct tipc_server *s)
 {
        struct tipc_conn *con;
-       int total = 0;
        int id;
 
        spin_lock_bh(&s->idr_lock);
-       for (id = 0; total < s->idr_in_use; id++) {
+       for (id = 0; s->idr_in_use; id++) {
                con = idr_find(&s->conn_idr, id);
                if (con) {
-                       total++;
                        spin_unlock_bh(&s->idr_lock);
                        tipc_close_conn(con);
                        spin_lock_bh(&s->idr_lock);
index 0dd02244e21d72b8e53e371d51eeae53e4b15a41..9d94e65d0894183b4af94ed24e84b94c0478b551 100644 (file)
@@ -54,6 +54,8 @@ struct tipc_subscriber {
 
 static void tipc_subscrp_delete(struct tipc_subscription *sub);
 static void tipc_subscrb_put(struct tipc_subscriber *subscriber);
+static void tipc_subscrp_put(struct tipc_subscription *subscription);
+static void tipc_subscrp_get(struct tipc_subscription *subscription);
 
 /**
  * htohl - convert value to endianness used by destination
@@ -123,6 +125,7 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
 {
        struct tipc_name_seq seq;
 
+       tipc_subscrp_get(sub);
        tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq);
        if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper))
                return;
@@ -132,30 +135,23 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
 
        tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref,
                                node);
+       tipc_subscrp_put(sub);
 }
 
 static void tipc_subscrp_timeout(unsigned long data)
 {
        struct tipc_subscription *sub = (struct tipc_subscription *)data;
-       struct tipc_subscriber *subscriber = sub->subscriber;
 
        /* Notify subscriber of timeout */
        tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
                                TIPC_SUBSCR_TIMEOUT, 0, 0);
 
-       spin_lock_bh(&subscriber->lock);
-       tipc_subscrp_delete(sub);
-       spin_unlock_bh(&subscriber->lock);
-
-       tipc_subscrb_put(subscriber);
+       tipc_subscrp_put(sub);
 }
 
 static void tipc_subscrb_kref_release(struct kref *kref)
 {
-       struct tipc_subscriber *subcriber = container_of(kref,
-                                           struct tipc_subscriber, kref);
-
-       kfree(subcriber);
+       kfree(container_of(kref,struct tipc_subscriber, kref));
 }
 
 static void tipc_subscrb_put(struct tipc_subscriber *subscriber)
@@ -168,6 +164,59 @@ static void tipc_subscrb_get(struct tipc_subscriber *subscriber)
        kref_get(&subscriber->kref);
 }
 
+static void tipc_subscrp_kref_release(struct kref *kref)
+{
+       struct tipc_subscription *sub = container_of(kref,
+                                                    struct tipc_subscription,
+                                                    kref);
+       struct tipc_net *tn = net_generic(sub->net, tipc_net_id);
+       struct tipc_subscriber *subscriber = sub->subscriber;
+
+       spin_lock_bh(&subscriber->lock);
+       tipc_nametbl_unsubscribe(sub);
+       list_del(&sub->subscrp_list);
+       atomic_dec(&tn->subscription_count);
+       spin_unlock_bh(&subscriber->lock);
+       kfree(sub);
+       tipc_subscrb_put(subscriber);
+}
+
+static void tipc_subscrp_put(struct tipc_subscription *subscription)
+{
+       kref_put(&subscription->kref, tipc_subscrp_kref_release);
+}
+
+static void tipc_subscrp_get(struct tipc_subscription *subscription)
+{
+       kref_get(&subscription->kref);
+}
+
+/* tipc_subscrb_subscrp_delete - delete a specific subscription or all
+ * subscriptions for a given subscriber.
+ */
+static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber,
+                                       struct tipc_subscr *s)
+{
+       struct list_head *subscription_list = &subscriber->subscrp_list;
+       struct tipc_subscription *sub, *temp;
+
+       spin_lock_bh(&subscriber->lock);
+       list_for_each_entry_safe(sub, temp, subscription_list,  subscrp_list) {
+               if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr)))
+                       continue;
+
+               tipc_subscrp_get(sub);
+               spin_unlock_bh(&subscriber->lock);
+               tipc_subscrp_delete(sub);
+               tipc_subscrp_put(sub);
+               spin_lock_bh(&subscriber->lock);
+
+               if (s)
+                       break;
+       }
+       spin_unlock_bh(&subscriber->lock);
+}
+
 static struct tipc_subscriber *tipc_subscrb_create(int conid)
 {
        struct tipc_subscriber *subscriber;
@@ -177,8 +226,8 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid)
                pr_warn("Subscriber rejected, no memory\n");
                return NULL;
        }
-       kref_init(&subscriber->kref);
        INIT_LIST_HEAD(&subscriber->subscrp_list);
+       kref_init(&subscriber->kref);
        subscriber->conid = conid;
        spin_lock_init(&subscriber->lock);
 
@@ -187,55 +236,22 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid)
 
 static void tipc_subscrb_delete(struct tipc_subscriber *subscriber)
 {
-       struct tipc_subscription *sub, *temp;
-       u32 timeout;
-
-       spin_lock_bh(&subscriber->lock);
-       /* Destroy any existing subscriptions for subscriber */
-       list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list,
-                                subscrp_list) {
-               timeout = htohl(sub->evt.s.timeout, sub->swap);
-               if ((timeout == TIPC_WAIT_FOREVER) || del_timer(&sub->timer)) {
-                       tipc_subscrp_delete(sub);
-                       tipc_subscrb_put(subscriber);
-               }
-       }
-       spin_unlock_bh(&subscriber->lock);
-
+       tipc_subscrb_subscrp_delete(subscriber, NULL);
        tipc_subscrb_put(subscriber);
 }
 
 static void tipc_subscrp_delete(struct tipc_subscription *sub)
 {
-       struct tipc_net *tn = net_generic(sub->net, tipc_net_id);
+       u32 timeout = htohl(sub->evt.s.timeout, sub->swap);
 
-       tipc_nametbl_unsubscribe(sub);
-       list_del(&sub->subscrp_list);
-       kfree(sub);
-       atomic_dec(&tn->subscription_count);
+       if (timeout == TIPC_WAIT_FOREVER || del_timer(&sub->timer))
+               tipc_subscrp_put(sub);
 }
 
 static void tipc_subscrp_cancel(struct tipc_subscr *s,
                                struct tipc_subscriber *subscriber)
 {
-       struct tipc_subscription *sub, *temp;
-       u32 timeout;
-
-       spin_lock_bh(&subscriber->lock);
-       /* Find first matching subscription, exit if not found */
-       list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list,
-                                subscrp_list) {
-               if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
-                       timeout = htohl(sub->evt.s.timeout, sub->swap);
-                       if ((timeout == TIPC_WAIT_FOREVER) ||
-                           del_timer(&sub->timer)) {
-                               tipc_subscrp_delete(sub);
-                               tipc_subscrb_put(subscriber);
-                       }
-                       break;
-               }
-       }
-       spin_unlock_bh(&subscriber->lock);
+       tipc_subscrb_subscrp_delete(subscriber, s);
 }
 
 static struct tipc_subscription *tipc_subscrp_create(struct net *net,
@@ -272,6 +288,7 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net,
        sub->swap = swap;
        memcpy(&sub->evt.s, s, sizeof(*s));
        atomic_inc(&tn->subscription_count);
+       kref_init(&sub->kref);
        return sub;
 }
 
@@ -288,17 +305,16 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s,
 
        spin_lock_bh(&subscriber->lock);
        list_add(&sub->subscrp_list, &subscriber->subscrp_list);
-       tipc_subscrb_get(subscriber);
        sub->subscriber = subscriber;
        tipc_nametbl_subscribe(sub);
+       tipc_subscrb_get(subscriber);
        spin_unlock_bh(&subscriber->lock);
 
+       setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub);
        timeout = htohl(sub->evt.s.timeout, swap);
-       if (timeout == TIPC_WAIT_FOREVER)
-               return;
 
-       setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub);
-       mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout));
+       if (timeout != TIPC_WAIT_FOREVER)
+               mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout));
 }
 
 /* Handle one termination request for the subscriber */
index be60103082c923c0fd768f52c081af38eb42491b..ffdc214c117a924f34b416fde415fcd18201ebc0 100644 (file)
@@ -57,6 +57,7 @@ struct tipc_subscriber;
  * @evt: template for events generated by subscription
  */
 struct tipc_subscription {
+       struct kref kref;
        struct tipc_subscriber *subscriber;
        struct net *net;
        struct timer_list timer;
index 127656ebe7be47af8ebb8ea288340177fd068049..cef79873b09d2051663fedf37dc52874b7f7c415 100644 (file)
@@ -995,6 +995,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        unsigned int hash;
        struct unix_address *addr;
        struct hlist_head *list;
+       struct path path = { NULL, NULL };
 
        err = -EINVAL;
        if (sunaddr->sun_family != AF_UNIX)
@@ -1010,9 +1011,20 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        addr_len = err;
 
+       if (sun_path[0]) {
+               umode_t mode = S_IFSOCK |
+                      (SOCK_INODE(sock)->i_mode & ~current_umask());
+               err = unix_mknod(sun_path, mode, &path);
+               if (err) {
+                       if (err == -EEXIST)
+                               err = -EADDRINUSE;
+                       goto out;
+               }
+       }
+
        err = mutex_lock_interruptible(&u->bindlock);
        if (err)
-               goto out;
+               goto out_put;
 
        err = -EINVAL;
        if (u->addr)
@@ -1029,16 +1041,6 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        atomic_set(&addr->refcnt, 1);
 
        if (sun_path[0]) {
-               struct path path;
-               umode_t mode = S_IFSOCK |
-                      (SOCK_INODE(sock)->i_mode & ~current_umask());
-               err = unix_mknod(sun_path, mode, &path);
-               if (err) {
-                       if (err == -EEXIST)
-                               err = -EADDRINUSE;
-                       unix_release_addr(addr);
-                       goto out_up;
-               }
                addr->hash = UNIX_HASH_SIZE;
                hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
                spin_lock(&unix_table_lock);
@@ -1065,6 +1067,9 @@ out_unlock:
        spin_unlock(&unix_table_lock);
 out_up:
        mutex_unlock(&u->bindlock);
+out_put:
+       if (err)
+               path_put(&path);
 out:
        return err;
 }
index 3df85a751a85285f609c5583e7ad864c7c822560..aee396b9f190bb4454844c7282fd4d3f5d85b5e7 100644 (file)
@@ -4615,6 +4615,15 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
                break;
        }
 
+       /*
+        * Older kernel versions ignored this attribute entirely, so don't
+        * reject attempts to update it but mark it as unused instead so the
+        * driver won't look at the data.
+        */
+       if (statype != CFG80211_STA_AP_CLIENT_UNASSOC &&
+           statype != CFG80211_STA_TDLS_PEER_SETUP)
+               params->opmode_notif_used = false;
+
        return 0;
 }
 EXPORT_SYMBOL(cfg80211_check_station_change);
@@ -4854,6 +4863,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
                params.local_pm = pm;
        }
 
+       if (info->attrs[NL80211_ATTR_OPMODE_NOTIF]) {
+               params.opmode_notif_used = true;
+               params.opmode_notif =
+                       nla_get_u8(info->attrs[NL80211_ATTR_OPMODE_NOTIF]);
+       }
+
        /* Include parameters for TDLS peer (will check later) */
        err = nl80211_set_station_tdls(info, &params);
        if (err)
@@ -5901,6 +5916,7 @@ do {                                                                          \
                        break;
                }
                cfg->ht_opmode = ht_opmode;
+               mask |= (1 << (NL80211_MESHCONF_HT_OPMODE - 1));
        }
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPactivePathToRootTimeout,
                                  1, 65535, mask,
@@ -14502,13 +14518,17 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
 
        list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
                bool schedule_destroy_work = false;
-               bool schedule_scan_stop = false;
                struct cfg80211_sched_scan_request *sched_scan_req =
                        rcu_dereference(rdev->sched_scan_req);
 
                if (sched_scan_req && notify->portid &&
-                   sched_scan_req->owner_nlportid == notify->portid)
-                       schedule_scan_stop = true;
+                   sched_scan_req->owner_nlportid == notify->portid) {
+                       sched_scan_req->owner_nlportid = 0;
+
+                       if (rdev->ops->sched_scan_stop &&
+                           rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
+                               schedule_work(&rdev->sched_scan_stop_wk);
+               }
 
                list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
                        cfg80211_mlme_unregister_socket(wdev, notify->portid);
@@ -14539,12 +14559,6 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
                                spin_unlock(&rdev->destroy_list_lock);
                                schedule_work(&rdev->destroy_work);
                        }
-               } else if (schedule_scan_stop) {
-                       sched_scan_req->owner_nlportid = 0;
-
-                       if (rdev->ops->sched_scan_stop &&
-                           rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
-                               schedule_work(&rdev->sched_scan_stop_wk);
                }
        }
 
index a6d2a43bbf2e290368410a6338abefecfa114f54..b124f62ed6cb30b0e89a2d698dc6a346b65e6b62 100644 (file)
@@ -105,4 +105,11 @@ config SAMPLE_BLACKFIN_GPTIMERS
        help
          Build samples of blackfin gptimers sample module.
 
+config SAMPLE_VFIO_MDEV_MTTY
+       tristate "Build VFIO mtty example mediated device sample code -- loadable modules only"
+       depends on VFIO_MDEV_DEVICE && m
+       help
+         Build a virtual tty sample driver for use as a VFIO
+         mediated device
+
 endif # SAMPLES
index e17d66d77f099c48f88bdc8518ca34c45b39cf29..86a137e451d978bec15778e13766648b6cfb3f18 100644 (file)
@@ -2,4 +2,5 @@
 
 obj-$(CONFIG_SAMPLES)  += kobject/ kprobes/ trace_events/ livepatch/ \
                           hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
-                          configfs/ connector/ v4l/ trace_printk/ blackfin/
+                          configfs/ connector/ v4l/ trace_printk/ blackfin/ \
+                          vfio-mdev/
index 09f7fe7e5fd74c289586711263d99bd9e25b1c2c..d8014065d479f9b85d96ae3d09664b1b14894467 100644 (file)
@@ -4,7 +4,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <net/ethernet.h>
+#include <linux/if_ether.h>
 #include <net/if.h>
 #include <linux/if_packet.h>
 #include <arpa/inet.h>
index 92a44729dbe43ec05f5556939d37ab0a9fc2fa2f..7ef2a12b25b244b2700ab7feee961fb91b435970 100644 (file)
@@ -4,6 +4,7 @@
  * modify it under the terms of version 2 of the GNU General Public
  * License as published by the Free Software Foundation.
  */
+#define KBUILD_MODNAME "foo"
 #include <uapi/linux/bpf.h>
 #include <uapi/linux/if_ether.h>
 #include <uapi/linux/if_packet.h>
index 504058631ffccef319f9bc7f6a3349d6f854bdbd..4bfcaf93fcf308e8b94c44cfc46c186e74d56cb7 100644 (file)
@@ -104,7 +104,7 @@ static int attach_filter(int cg_fd, int type, int verdict)
                return EXIT_FAILURE;
        }
 
-       ret = bpf_prog_attach(prog_fd, cg_fd, type);
+       ret = bpf_prog_attach(prog_fd, cg_fd, type, 0);
        if (ret < 0) {
                printf("Failed to attach prog to cgroup: '%s'\n",
                       strerror(errno));
index 6e69be37f87f700dfd6a2c13a8d6310164b0cdd9..3049b1f26267c40836c79423362aeeb125b5761b 100644 (file)
@@ -79,11 +79,12 @@ int main(int argc, char **argv)
        if (join_cgroup(FOO))
                goto err;
 
-       if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS)) {
+       if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS, 1)) {
                log_err("Attaching prog to /foo");
                goto err;
        }
 
+       printf("Attached DROP prog. This ping in cgroup /foo should fail...\n");
        assert(system(PING_CMD) != 0);
 
        /* Create cgroup /foo/bar, get fd, and join it */
@@ -94,24 +95,27 @@ int main(int argc, char **argv)
        if (join_cgroup(BAR))
                goto err;
 
+       printf("Attached DROP prog. This ping in cgroup /foo/bar should fail...\n");
        assert(system(PING_CMD) != 0);
 
-       if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
+       if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) {
                log_err("Attaching prog to /foo/bar");
                goto err;
        }
 
+       printf("Attached PASS prog. This ping in cgroup /foo/bar should pass...\n");
        assert(system(PING_CMD) == 0);
 
-
        if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) {
                log_err("Detaching program from /foo/bar");
                goto err;
        }
 
+       printf("Detached PASS from /foo/bar while DROP is attached to /foo.\n"
+              "This ping in cgroup /foo/bar should fail...\n");
        assert(system(PING_CMD) != 0);
 
-       if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
+       if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) {
                log_err("Attaching prog to /foo/bar");
                goto err;
        }
@@ -121,8 +125,60 @@ int main(int argc, char **argv)
                goto err;
        }
 
+       printf("Attached PASS from /foo/bar and detached DROP from /foo.\n"
+              "This ping in cgroup /foo/bar should pass...\n");
        assert(system(PING_CMD) == 0);
 
+       if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) {
+               log_err("Attaching prog to /foo/bar");
+               goto err;
+       }
+
+       if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 0)) {
+               errno = 0;
+               log_err("Unexpected success attaching prog to /foo/bar");
+               goto err;
+       }
+
+       if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) {
+               log_err("Detaching program from /foo/bar");
+               goto err;
+       }
+
+       if (!bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) {
+               errno = 0;
+               log_err("Unexpected success in double detach from /foo");
+               goto err;
+       }
+
+       if (bpf_prog_attach(allow_prog, foo, BPF_CGROUP_INET_EGRESS, 0)) {
+               log_err("Attaching non-overridable prog to /foo");
+               goto err;
+       }
+
+       if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 0)) {
+               errno = 0;
+               log_err("Unexpected success attaching non-overridable prog to /foo/bar");
+               goto err;
+       }
+
+       if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) {
+               errno = 0;
+               log_err("Unexpected success attaching overridable prog to /foo/bar");
+               goto err;
+       }
+
+       if (!bpf_prog_attach(allow_prog, foo, BPF_CGROUP_INET_EGRESS, 1)) {
+               errno = 0;
+               log_err("Unexpected success attaching overridable prog to /foo");
+               goto err;
+       }
+
+       if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS, 0)) {
+               log_err("Attaching different non-overridable prog to /foo");
+               goto err;
+       }
+
        goto out;
 
 err:
@@ -132,5 +188,9 @@ out:
        close(foo);
        close(bar);
        cleanup_cgroup_environment();
+       if (!rc)
+               printf("PASS\n");
+       else
+               printf("FAIL\n");
        return rc;
 }
index 0791b949cbe418e49fa29ab1efb52007e29d67d8..c3cfb23e23b52832d795b2cc095f94b3f49d9f0b 100644 (file)
@@ -75,7 +75,7 @@ int main(int argc, char **argv)
                return EXIT_FAILURE;
        }
 
-       ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE);
+       ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE, 0);
        if (ret < 0) {
                printf("Failed to attach prog to cgroup: '%s'\n",
                       strerror(errno));
index 455ef0d06e932516e0591438c7b6e4d8ef831ac2..db036077b64480b6af3c9f42d6ac61b758384152 100644 (file)
@@ -55,7 +55,7 @@ int main(int argc, char **argv)
        }
 
        ret = bpf_prog_attach(prog_fd[filter_id], cg_fd,
-                             BPF_CGROUP_INET_SOCK_CREATE);
+                             BPF_CGROUP_INET_SOCK_CREATE, 0);
        if (ret < 0) {
                printf("Failed to attach prog to cgroup: '%s'\n",
                       strerror(errno));
index f4fa6af22def9fa9c01df1525c7a61b3aecb8cdd..ccca1e3480171501f01779ca88fc26305bff2491 100644 (file)
@@ -9,7 +9,6 @@
 #include <string.h>
 #include <fcntl.h>
 #include <poll.h>
-#include <sys/ioctl.h>
 #include <linux/perf_event.h>
 #include <linux/bpf.h>
 #include <errno.h>
index 85c38ecd3a2dcf5f65f99011a73be87d78c287ff..0f4f6e8c8611e3dea0e758215a65cc185ecdae02 100644 (file)
@@ -8,6 +8,7 @@
  * encapsulating the incoming packet in an IPv4/v6 header
  * and then XDP_TX it out.
  */
+#define KBUILD_MODNAME "foo"
 #include <uapi/linux/bpf.h>
 #include <linux/in.h>
 #include <linux/if_ether.h>
index a932edbe38eb9eba5a1b3429bb67cc9c99d0d3a6..cbbd868a50a8b145bf018329542f4fde829e06da 100644 (file)
@@ -1,13 +1 @@
-#
-# Makefile for mtty.c file
-#
-KERNEL_DIR:=/lib/modules/$(shell uname -r)/build
-
-obj-m:=mtty.o
-
-modules clean modules_install:
-       $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) $@
-
-default: modules
-
-module: modules
+obj-$(CONFIG_SAMPLE_VFIO_MDEV_MTTY) += mtty.o
index 6b633a4ea33399aa32e6f3655b05c980aeb33403..ca495686b9c31786d0df8c16407bd06d28ee1b40 100644 (file)
@@ -164,7 +164,7 @@ static struct mdev_state *find_mdev_state_by_uuid(uuid_le uuid)
        struct mdev_state *mds;
 
        list_for_each_entry(mds, &mdev_devices_list, next) {
-               if (uuid_le_cmp(mds->mdev->uuid, uuid) == 0)
+               if (uuid_le_cmp(mdev_uuid(mds->mdev), uuid) == 0)
                        return mds;
        }
 
@@ -341,7 +341,8 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
                                pr_err("Serial port %d: Fifo level trigger\n",
                                        index);
 #endif
-                               mtty_trigger_interrupt(mdev_state->mdev->uuid);
+                               mtty_trigger_interrupt(
+                                               mdev_uuid(mdev_state->mdev));
                        }
                } else {
 #if defined(DEBUG_INTR)
@@ -355,7 +356,8 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
                         */
                        if (mdev_state->s[index].uart_reg[UART_IER] &
                                                                UART_IER_RLSI)
-                               mtty_trigger_interrupt(mdev_state->mdev->uuid);
+                               mtty_trigger_interrupt(
+                                               mdev_uuid(mdev_state->mdev));
                }
                mutex_unlock(&mdev_state->rxtx_lock);
                break;
@@ -374,7 +376,8 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
                                pr_err("Serial port %d: IER_THRI write\n",
                                        index);
 #endif
-                               mtty_trigger_interrupt(mdev_state->mdev->uuid);
+                               mtty_trigger_interrupt(
+                                               mdev_uuid(mdev_state->mdev));
                        }
 
                        mutex_unlock(&mdev_state->rxtx_lock);
@@ -445,7 +448,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
 #if defined(DEBUG_INTR)
                        pr_err("Serial port %d: MCR_OUT2 write\n", index);
 #endif
-                       mtty_trigger_interrupt(mdev_state->mdev->uuid);
+                       mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev));
                }
 
                if ((mdev_state->s[index].uart_reg[UART_IER] & UART_IER_MSI) &&
@@ -453,7 +456,7 @@ static void handle_bar_write(unsigned int index, struct mdev_state *mdev_state,
 #if defined(DEBUG_INTR)
                        pr_err("Serial port %d: MCR RTS/DTR write\n", index);
 #endif
-                       mtty_trigger_interrupt(mdev_state->mdev->uuid);
+                       mtty_trigger_interrupt(mdev_uuid(mdev_state->mdev));
                }
                break;
 
@@ -504,7 +507,8 @@ static void handle_bar_read(unsigned int index, struct mdev_state *mdev_state,
 #endif
                        if (mdev_state->s[index].uart_reg[UART_IER] &
                                                         UART_IER_THRI)
-                               mtty_trigger_interrupt(mdev_state->mdev->uuid);
+                               mtty_trigger_interrupt(
+                                       mdev_uuid(mdev_state->mdev));
                }
                mutex_unlock(&mdev_state->rxtx_lock);
 
@@ -734,7 +738,7 @@ int mtty_create(struct kobject *kobj, struct mdev_device *mdev)
 
        for (i = 0; i < 2; i++) {
                snprintf(name, MTTY_STRING_LEN, "%s-%d",
-                       dev_driver_string(mdev->parent->dev), i + 1);
+                       dev_driver_string(mdev_parent_dev(mdev)), i + 1);
                if (!strcmp(kobj->name, name)) {
                        nr_ports = i + 1;
                        break;
@@ -1069,7 +1073,7 @@ int mtty_get_region_info(struct mdev_device *mdev,
 {
        unsigned int size = 0;
        struct mdev_state *mdev_state;
-       int bar_index;
+       u32 bar_index;
 
        if (!mdev)
                return -EINVAL;
@@ -1078,8 +1082,11 @@ int mtty_get_region_info(struct mdev_device *mdev,
        if (!mdev_state)
                return -EINVAL;
 
-       mutex_lock(&mdev_state->ops_lock);
        bar_index = region_info->index;
+       if (bar_index >= VFIO_PCI_NUM_REGIONS)
+               return -EINVAL;
+
+       mutex_lock(&mdev_state->ops_lock);
 
        switch (bar_index) {
        case VFIO_PCI_CONFIG_REGION_INDEX:
@@ -1176,7 +1183,10 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
 
                memcpy(&mdev_state->dev_info, &info, sizeof(info));
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               if (copy_to_user((void __user *)arg, &info, minsz))
+                       return -EFAULT;
+
+               return 0;
        }
        case VFIO_DEVICE_GET_REGION_INFO:
        {
@@ -1197,7 +1207,10 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
                if (ret)
                        return ret;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               if (copy_to_user((void __user *)arg, &info, minsz))
+                       return -EFAULT;
+
+               return 0;
        }
 
        case VFIO_DEVICE_GET_IRQ_INFO:
@@ -1217,10 +1230,10 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
                if (ret)
                        return ret;
 
-               if (info.count == -1)
-                       return -EINVAL;
+               if (copy_to_user((void __user *)arg, &info, minsz))
+                       return -EFAULT;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return 0;
        }
        case VFIO_DEVICE_SET_IRQS:
        {
@@ -1298,10 +1311,8 @@ static ssize_t
 sample_mdev_dev_show(struct device *dev, struct device_attribute *attr,
                     char *buf)
 {
-       struct mdev_device *mdev = to_mdev_device(dev);
-
-       if (mdev)
-               return sprintf(buf, "This is MDEV %s\n", dev_name(&mdev->dev));
+       if (mdev_from_dev(dev))
+               return sprintf(buf, "This is MDEV %s\n", dev_name(dev));
 
        return sprintf(buf, "\n");
 }
@@ -1402,7 +1413,7 @@ struct attribute_group *mdev_type_groups[] = {
        NULL,
 };
 
-struct parent_ops mdev_fops = {
+struct mdev_parent_ops mdev_fops = {
        .owner                  = THIS_MODULE,
        .dev_attr_groups        = mtty_dev_groups,
        .mdev_attr_groups       = mdev_dev_groups,
@@ -1447,6 +1458,7 @@ static int __init mtty_dev_init(void)
 
        if (IS_ERR(mtty_dev.vd_class)) {
                pr_err("Error: failed to register mtty_dev class\n");
+               ret = PTR_ERR(mtty_dev.vd_class);
                goto failed1;
        }
 
@@ -1458,7 +1470,8 @@ static int __init mtty_dev_init(void)
        if (ret)
                goto failed2;
 
-       if (mdev_register_device(&mtty_dev.dev, &mdev_fops) != 0)
+       ret = mdev_register_device(&mtty_dev.dev, &mdev_fops);
+       if (ret)
                goto failed3;
 
        mutex_init(&mdev_list_lock);
index eadcd4d359d91fc7823a75263c44c520e05f900b..d883116ebaa452d9c2f6c657de53121ebd9d50bd 100644 (file)
@@ -164,6 +164,7 @@ cmd_gensymtypes_c =                                                         \
     $(CPP) -D__GENKSYMS__ $(c_flags) $< |                                   \
     $(GENKSYMS) $(if $(1), -T $(2))                                         \
      $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
+     $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS))                             \
      $(if $(KBUILD_PRESERVE),-p)                                            \
      -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 
@@ -337,6 +338,7 @@ cmd_gensymtypes_S =                                                         \
     $(CPP) -D__GENKSYMS__ $(c_flags) -xc - |                                \
     $(GENKSYMS) $(if $(1), -T $(2))                                         \
      $(patsubst y,-s _,$(CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX))             \
+     $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS))                             \
      $(if $(KBUILD_PRESERVE),-p)                                            \
      -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null))
 
index 06121ce524a76006072459d352d727b4aebdf203..c9235d8340f1e7ba33eacfaee94642c18f5fd211 100644 (file)
@@ -44,7 +44,7 @@ char *cur_filename, *source_file;
 int in_source_file;
 
 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
-          flag_preserve, flag_warnings;
+          flag_preserve, flag_warnings, flag_rel_crcs;
 static const char *mod_prefix = "";
 
 static int errors;
@@ -693,7 +693,10 @@ void export_symbol(const char *name)
                        fputs(">\n", debugfile);
 
                /* Used as a linker script. */
-               printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
+               printf(!flag_rel_crcs ? "%s__crc_%s = 0x%08lx;\n" :
+                      "SECTIONS { .rodata : ALIGN(4) { "
+                      "%s__crc_%s = .; LONG(0x%08lx); } }\n",
+                      mod_prefix, name, crc);
        }
 }
 
@@ -730,7 +733,7 @@ void error_with_pos(const char *fmt, ...)
 
 static void genksyms_usage(void)
 {
-       fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
+       fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
 #ifdef __GNU_LIBRARY__
              "  -s, --symbol-prefix   Select symbol prefix\n"
              "  -d, --debug           Increment the debug level (repeatable)\n"
@@ -742,6 +745,7 @@ static void genksyms_usage(void)
              "  -q, --quiet           Disable warnings (default)\n"
              "  -h, --help            Print this message\n"
              "  -V, --version         Print the release version\n"
+             "  -R, --relative-crc    Emit section relative symbol CRCs\n"
 #else                          /* __GNU_LIBRARY__ */
              "  -s                    Select symbol prefix\n"
              "  -d                    Increment the debug level (repeatable)\n"
@@ -753,6 +757,7 @@ static void genksyms_usage(void)
              "  -q                    Disable warnings (default)\n"
              "  -h                    Print this message\n"
              "  -V                    Print the release version\n"
+             "  -R                    Emit section relative symbol CRCs\n"
 #endif                         /* __GNU_LIBRARY__ */
              , stderr);
 }
@@ -774,13 +779,14 @@ int main(int argc, char **argv)
                {"preserve", 0, 0, 'p'},
                {"version", 0, 0, 'V'},
                {"help", 0, 0, 'h'},
+               {"relative-crc", 0, 0, 'R'},
                {0, 0, 0, 0}
        };
 
-       while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
+       while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
                                &long_opts[0], NULL)) != EOF)
 #else                          /* __GNU_LIBRARY__ */
-       while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
+       while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
 #endif                         /* __GNU_LIBRARY__ */
                switch (o) {
                case 's':
@@ -823,6 +829,9 @@ int main(int argc, char **argv)
                case 'h':
                        genksyms_usage();
                        return 0;
+               case 'R':
+                       flag_rel_crcs = 1;
+                       break;
                default:
                        genksyms_usage();
                        return 1;
index 299b92ca1ae092d82e9a0e3bffaec45988ebcc37..5d554419170b7d54ec82ddb1d31093d3eab0aa7d 100644 (file)
@@ -219,6 +219,10 @@ static int symbol_valid(struct sym_entry *s)
                "_SDA2_BASE_",          /* ppc */
                NULL };
 
+       static char *special_prefixes[] = {
+               "__crc_",               /* modversions */
+               NULL };
+
        static char *special_suffixes[] = {
                "_veneer",              /* arm */
                "_from_arm",            /* arm */
@@ -259,6 +263,14 @@ static int symbol_valid(struct sym_entry *s)
                if (strcmp(sym_name, special_symbols[i]) == 0)
                        return 0;
 
+       for (i = 0; special_prefixes[i]; i++) {
+               int l = strlen(special_prefixes[i]);
+
+               if (l <= strlen(sym_name) &&
+                   strncmp(sym_name, special_prefixes[i], l) == 0)
+                       return 0;
+       }
+
        for (i = 0; special_suffixes[i]; i++) {
                int l = strlen(sym_name) - strlen(special_suffixes[i]);
 
index 29c89a6bad3d3ac34e539189e83769f1c63ddab3..4dedd0d3d3a7fda58af2bc6150b9f6b6195d2cac 100644 (file)
@@ -621,6 +621,16 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
        if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
                is_crc = true;
                crc = (unsigned int) sym->st_value;
+               if (sym->st_shndx != SHN_UNDEF && sym->st_shndx != SHN_ABS) {
+                       unsigned int *crcp;
+
+                       /* symbol points to the CRC in the ELF object */
+                       crcp = (void *)info->hdr + sym->st_value +
+                              info->sechdrs[sym->st_shndx].sh_offset -
+                              (info->hdr->e_type != ET_REL ?
+                               info->sechdrs[sym->st_shndx].sh_addr : 0);
+                       crc = *crcp;
+               }
                sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
                                export);
        }
index c7c6619431d5fb4922dd729e9e49dd910d7967d2..d98550abe16d40250be4327197c48866953b5645 100644 (file)
@@ -5887,7 +5887,7 @@ static int selinux_setprocattr(struct task_struct *p,
                return error;
 
        /* Obtain a SID for the context, if one was specified. */
-       if (size && str[1] && str[1] != '\n') {
+       if (size && str[0] && str[0] != '\n') {
                if (str[size-1] == '\n') {
                        str[size-1] = 0;
                        size--;
index c850345c43b53dd5616b155f34f741d0ca30701c..dfa5156f35856324d86f05315edfb2ef9cf4e74e 100644 (file)
@@ -419,7 +419,6 @@ int snd_seq_pool_done(struct snd_seq_pool *pool)
 {
        unsigned long flags;
        struct snd_seq_event_cell *ptr;
-       int max_count = 5 * HZ;
 
        if (snd_BUG_ON(!pool))
                return -EINVAL;
@@ -432,14 +431,8 @@ int snd_seq_pool_done(struct snd_seq_pool *pool)
        if (waitqueue_active(&pool->output_sleep))
                wake_up(&pool->output_sleep);
 
-       while (atomic_read(&pool->counter) > 0) {
-               if (max_count == 0) {
-                       pr_warn("ALSA: snd_seq_pool_done timeout: %d cells remain\n", atomic_read(&pool->counter));
-                       break;
-               }
+       while (atomic_read(&pool->counter) > 0)
                schedule_timeout_uninterruptible(1);
-               max_count--;
-       }
        
        /* release all resources */
        spin_lock_irqsave(&pool->lock, flags);
index 0bec02e89d5118b3dffe1e22e88e423baa037491..450c5187eecb6bb083736d2d2a1aad43b98c7c3f 100644 (file)
@@ -181,6 +181,8 @@ void __exit snd_seq_queues_delete(void)
        }
 }
 
+static void queue_use(struct snd_seq_queue *queue, int client, int use);
+
 /* allocate a new queue -
  * return queue index value or negative value for error
  */
@@ -192,11 +194,11 @@ int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
        if (q == NULL)
                return -ENOMEM;
        q->info_flags = info_flags;
+       queue_use(q, client, 1);
        if (queue_list_add(q) < 0) {
                queue_delete(q);
                return -ENOMEM;
        }
-       snd_seq_queue_use(q->queue, client, 1); /* use this queue */
        return q->queue;
 }
 
@@ -502,19 +504,9 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client,
        return result;
 }
 
-
-/* use or unuse this queue -
- * if it is the first client, starts the timer.
- * if it is not longer used by any clients, stop the timer.
- */
-int snd_seq_queue_use(int queueid, int client, int use)
+/* use or unuse this queue */
+static void queue_use(struct snd_seq_queue *queue, int client, int use)
 {
-       struct snd_seq_queue *queue;
-
-       queue = queueptr(queueid);
-       if (queue == NULL)
-               return -EINVAL;
-       mutex_lock(&queue->timer_mutex);
        if (use) {
                if (!test_and_set_bit(client, queue->clients_bitmap))
                        queue->clients++;
@@ -529,6 +521,21 @@ int snd_seq_queue_use(int queueid, int client, int use)
        } else {
                snd_seq_timer_close(queue);
        }
+}
+
+/* use or unuse this queue -
+ * if it is the first client, starts the timer.
+ * if it is not longer used by any clients, stop the timer.
+ */
+int snd_seq_queue_use(int queueid, int client, int use)
+{
+       struct snd_seq_queue *queue;
+
+       queue = queueptr(queueid);
+       if (queue == NULL)
+               return -EINVAL;
+       mutex_lock(&queue->timer_mutex);
+       queue_use(queue, client, use);
        mutex_unlock(&queue->timer_mutex);
        queuefree(queue);
        return 0;
index ee47924aef0df676223975a08df37ad055cc1f51..827161bc269cfa1414972692bcdb45d0a42ad9ed 100644 (file)
@@ -117,7 +117,7 @@ destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream)
                conn = &efw->in_conn;
 
        amdtp_stream_destroy(stream);
-       cmp_connection_destroy(&efw->out_conn);
+       cmp_connection_destroy(conn);
 }
 
 static int
index 4ad3bd7fd4453e3a64fc4cd95001165510292559..f1657a4e0621ef4999349477ce6e71fdbcd7f411 100644 (file)
@@ -343,7 +343,7 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
        if (err < 0)
                amdtp_stream_destroy(&tscm->rx_stream);
 
-       return 0;
+       return err;
 }
 
 /* At bus reset, streaming is stopped and some registers are clear. */
index cf9bc042fe966361588b8dc92b66e308fd50e657..3fc201c3b95a33380217950d91285c83d3d7fb8a 100644 (file)
@@ -3639,6 +3639,7 @@ HDA_CODEC_ENTRY(0x10de0070, "GPU 70 HDMI/DP",     patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0071, "GPU 71 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0072, "GPU 72 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de007d, "GPU 7d HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de0080, "GPU 80 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0082, "GPU 82 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0083, "GPU 83 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",      patch_nvhdmi_2ch),
index 9448daff9d8b55d5de49ef9a4ff66fd9e2a80f6b..7d660ee1d5e84e6f7eaa42404232d9aad461b25c 100644 (file)
@@ -2230,6 +2230,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
        SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
        SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
+       SND_PCI_QUIRK(0x1043, 0x8691, "ASUS ROG Ranger VIII", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
        SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
        SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
@@ -6983,6 +6984,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
        SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
        SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
+       SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
        SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
        SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
        SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
index efe3a44658d5a5e6d3a82d5f23ed8f8afd190d5a..4576f987a4a5fec34a1bb780e0ba1ccb71dfeada 100644 (file)
@@ -561,9 +561,9 @@ static void nau8825_xtalk_prepare(struct nau8825 *nau8825)
        nau8825_xtalk_backup(nau8825);
        /* Config IIS as master to output signal by codec */
        regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
-               NAU8825_I2S_MS_MASK | NAU8825_I2S_DRV_MASK |
+               NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK |
                NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_MASTER |
-               (0x2 << NAU8825_I2S_DRV_SFT) | 0x1);
+               (0x2 << NAU8825_I2S_LRC_DIV_SFT) | 0x1);
        /* Ramp up headphone volume to 0dB to get better performance and
         * avoid pop noise in headphone.
         */
@@ -657,7 +657,7 @@ static void nau8825_xtalk_clean(struct nau8825 *nau8825)
                NAU8825_IRQ_RMS_EN, NAU8825_IRQ_RMS_EN);
        /* Recover default value for IIS */
        regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
-               NAU8825_I2S_MS_MASK | NAU8825_I2S_DRV_MASK |
+               NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK |
                NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE);
        /* Restore value of specific register for cross talk */
        nau8825_xtalk_restore(nau8825);
@@ -2006,7 +2006,8 @@ static void nau8825_fll_apply(struct nau8825 *nau8825,
                        NAU8825_FLL_INTEGER_MASK, fll_param->fll_int);
        /* FLL pre-scaler */
        regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL4,
-                       NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div);
+                       NAU8825_FLL_REF_DIV_MASK,
+                       fll_param->clk_ref_div << NAU8825_FLL_REF_DIV_SFT);
        /* select divided VCO input */
        regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5,
                NAU8825_FLL_CLK_SW_MASK, NAU8825_FLL_CLK_SW_REF);
index 5d1704e732415dd04134f44ddab9971156c97de1..514fd13c2f4624bb96b237422dfd63fae52adf17 100644 (file)
 #define NAU8825_FLL_CLK_SRC_FS                 (0x3 << NAU8825_FLL_CLK_SRC_SFT)
 
 /* FLL4 (0x07) */
-#define NAU8825_FLL_REF_DIV_MASK               (0x3 << 10)
+#define NAU8825_FLL_REF_DIV_SFT        10
+#define NAU8825_FLL_REF_DIV_MASK       (0x3 << NAU8825_FLL_REF_DIV_SFT)
 
 /* FLL5 (0x08) */
 #define NAU8825_FLL_PDB_DAC_EN         (0x1 << 15)
 
 /* I2S_PCM_CTRL2 (0x1d) */
 #define NAU8825_I2S_TRISTATE   (1 << 15) /* 0 - normal mode, 1 - Hi-Z output */
-#define NAU8825_I2S_DRV_SFT    12
-#define NAU8825_I2S_DRV_MASK   (0x3 << NAU8825_I2S_DRV_SFT)
+#define NAU8825_I2S_LRC_DIV_SFT        12
+#define NAU8825_I2S_LRC_DIV_MASK       (0x3 << NAU8825_I2S_LRC_DIV_SFT)
 #define NAU8825_I2S_MS_SFT     3
 #define NAU8825_I2S_MS_MASK    (1 << NAU8825_I2S_MS_SFT)
 #define NAU8825_I2S_MS_MASTER  (1 << NAU8825_I2S_MS_SFT)
index 10c2a564a715dc82e198a4bb50c5691662685c7a..1ac96ef9ee2077dc70ba940f939e8162ce1dec26 100644 (file)
@@ -3833,6 +3833,9 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
                }
        }
 
+       regmap_update_bits(rt5645->regmap, RT5645_ADDA_CLK1,
+               RT5645_I2S_PD1_MASK, RT5645_I2S_PD1_2);
+
        if (rt5645->pdata.jd_invert) {
                regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
                        RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
index 8877b74b0510fedefe81adc6637c9d72cf9c722f..bb94d50052d7a7233282b50afca134e4f2f7cf3f 100644 (file)
@@ -126,6 +126,16 @@ static const struct reg_default aic3x_reg[] = {
        { 108, 0x00 }, { 109, 0x00 },
 };
 
+static bool aic3x_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case AIC3X_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static const struct regmap_config aic3x_regmap = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -133,6 +143,9 @@ static const struct regmap_config aic3x_regmap = {
        .max_register = DAC_ICC_ADJ,
        .reg_defaults = aic3x_reg,
        .num_reg_defaults = ARRAY_SIZE(aic3x_reg),
+
+       .volatile_reg = aic3x_volatile_reg,
+
        .cache_type = REGCACHE_RBTREE,
 };
 
index 593b7d1aed4695bbf6e538fa924bc6263901041f..d72ccef9e238d39807657597d1c8496022718bb5 100644 (file)
@@ -1551,7 +1551,7 @@ static int wm_adsp_load(struct wm_adsp *dsp)
        const struct wmfw_region *region;
        const struct wm_adsp_region *mem;
        const char *region_name;
-       char *file, *text;
+       char *file, *text = NULL;
        struct wm_adsp_buf *buf;
        unsigned int reg;
        int regions = 0;
@@ -1700,10 +1700,21 @@ static int wm_adsp_load(struct wm_adsp *dsp)
                         regions, le32_to_cpu(region->len), offset,
                         region_name);
 
+               if ((pos + le32_to_cpu(region->len) + sizeof(*region)) >
+                   firmware->size) {
+                       adsp_err(dsp,
+                                "%s.%d: %s region len %d bytes exceeds file length %zu\n",
+                                file, regions, region_name,
+                                le32_to_cpu(region->len), firmware->size);
+                       ret = -EINVAL;
+                       goto out_fw;
+               }
+
                if (text) {
                        memcpy(text, region->data, le32_to_cpu(region->len));
                        adsp_info(dsp, "%s: %s\n", file, text);
                        kfree(text);
+                       text = NULL;
                }
 
                if (reg) {
@@ -1748,6 +1759,7 @@ out_fw:
        regmap_async_complete(regmap);
        wm_adsp_buf_free(&buf_list);
        release_firmware(firmware);
+       kfree(text);
 out:
        kfree(file);
 
@@ -2233,6 +2245,17 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                }
 
                if (reg) {
+                       if ((pos + le32_to_cpu(blk->len) + sizeof(*blk)) >
+                           firmware->size) {
+                               adsp_err(dsp,
+                                        "%s.%d: %s region len %d bytes exceeds file length %zu\n",
+                                        file, blocks, region_name,
+                                        le32_to_cpu(blk->len),
+                                        firmware->size);
+                               ret = -EINVAL;
+                               goto out_fw;
+                       }
+
                        buf = wm_adsp_buf_alloc(blk->data,
                                                le32_to_cpu(blk->len),
                                                &buf_list);
index 2998954a1c7459e02c3397956e690a276120f06d..bdf8398cbc81b68b445f202636e8949db5e5cae5 100644 (file)
@@ -681,22 +681,19 @@ static int dw_i2s_probe(struct platform_device *pdev)
        }
 
        if (!pdata) {
-               ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-               if (ret == -EPROBE_DEFER) {
-                       dev_err(&pdev->dev,
-                               "failed to register PCM, deferring probe\n");
-                       return ret;
-               } else if (ret) {
-                       dev_err(&pdev->dev,
-                               "Could not register DMA PCM: %d\n"
-                               "falling back to PIO mode\n", ret);
+               if (irq >= 0) {
                        ret = dw_pcm_register(pdev);
-                       if (ret) {
-                               dev_err(&pdev->dev,
-                                       "Could not register PIO PCM: %d\n",
+                       dev->use_pio = true;
+               } else {
+                       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
+                                       0);
+                       dev->use_pio = false;
+               }
+
+               if (ret) {
+                       dev_err(&pdev->dev, "could not register pcm: %d\n",
                                        ret);
-                               goto err_clk_disable;
-                       }
+                       goto err_clk_disable;
                }
        }
 
index 50349437d9615107a3a08fa481b6b2d61612e51c..fde08660b63be270f95436424e32e443bdb8a0de 100644 (file)
@@ -224,6 +224,12 @@ struct fsl_ssi_soc_data {
  * @dbg_stats: Debugging statistics
  *
  * @soc: SoC specific data
+ *
+ * @fifo_watermark: the FIFO watermark setting.  Notifies DMA when
+ *             there are @fifo_watermark or fewer words in TX fifo or
+ *             @fifo_watermark or more empty words in RX fifo.
+ * @dma_maxburst: max number of words to transfer in one go.  So far,
+ *             this is always the same as fifo_watermark.
  */
 struct fsl_ssi_private {
        struct regmap *regs;
@@ -263,6 +269,9 @@ struct fsl_ssi_private {
 
        const struct fsl_ssi_soc_data *soc;
        struct device *dev;
+
+       u32 fifo_watermark;
+       u32 dma_maxburst;
 };
 
 /*
@@ -1051,21 +1060,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
        regmap_write(regs, CCSR_SSI_SRCR, srcr);
        regmap_write(regs, CCSR_SSI_SCR, scr);
 
-       /*
-        * Set the watermark for transmit FIFI 0 and receive FIFO 0. We don't
-        * use FIFO 1. We program the transmit water to signal a DMA transfer
-        * if there are only two (or fewer) elements left in the FIFO. Two
-        * elements equals one frame (left channel, right channel). This value,
-        * however, depends on the depth of the transmit buffer.
-        *
-        * We set the watermark on the same level as the DMA burstsize.  For
-        * fiq it is probably better to use the biggest possible watermark
-        * size.
-        */
-       if (ssi_private->use_dma)
-               wm = ssi_private->fifo_depth - 2;
-       else
-               wm = ssi_private->fifo_depth;
+       wm = ssi_private->fifo_watermark;
 
        regmap_write(regs, CCSR_SSI_SFCSR,
                        CCSR_SSI_SFCSR_TFWM0(wm) | CCSR_SSI_SFCSR_RFWM0(wm) |
@@ -1373,12 +1368,8 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev,
                dev_dbg(&pdev->dev, "could not get baud clock: %ld\n",
                         PTR_ERR(ssi_private->baudclk));
 
-       /*
-        * We have burstsize be "fifo_depth - 2" to match the SSI
-        * watermark setting in fsl_ssi_startup().
-        */
-       ssi_private->dma_params_tx.maxburst = ssi_private->fifo_depth - 2;
-       ssi_private->dma_params_rx.maxburst = ssi_private->fifo_depth - 2;
+       ssi_private->dma_params_tx.maxburst = ssi_private->dma_maxburst;
+       ssi_private->dma_params_rx.maxburst = ssi_private->dma_maxburst;
        ssi_private->dma_params_tx.addr = ssi_private->ssi_phys + CCSR_SSI_STX0;
        ssi_private->dma_params_rx.addr = ssi_private->ssi_phys + CCSR_SSI_SRX0;
 
@@ -1543,6 +1534,47 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                 /* Older 8610 DTs didn't have the fifo-depth property */
                ssi_private->fifo_depth = 8;
 
+       /*
+        * Set the watermark for transmit FIFO 0 and receive FIFO 0. We don't
+        * use FIFO 1 but set the watermark appropriately nontheless.
+        * We program the transmit water to signal a DMA transfer
+        * if there are N elements left in the FIFO. For chips with 15-deep
+        * FIFOs, set watermark to 8.  This allows the SSI to operate at a
+        * high data rate without channel slipping. Behavior is unchanged
+        * for the older chips with a fifo depth of only 8.  A value of 4
+        * might be appropriate for the older chips, but is left at
+        * fifo_depth-2 until sombody has a chance to test.
+        *
+        * We set the watermark on the same level as the DMA burstsize.  For
+        * fiq it is probably better to use the biggest possible watermark
+        * size.
+        */
+       switch (ssi_private->fifo_depth) {
+       case 15:
+               /*
+                * 2 samples is not enough when running at high data
+                * rates (like 48kHz @ 16 bits/channel, 16 channels)
+                * 8 seems to split things evenly and leave enough time
+                * for the DMA to fill the FIFO before it's over/under
+                * run.
+                */
+               ssi_private->fifo_watermark = 8;
+               ssi_private->dma_maxburst = 8;
+               break;
+       case 8:
+       default:
+               /*
+                * maintain old behavior for older chips.
+                * Keeping it the same because I don't have an older
+                * board to test with.
+                * I suspect this could be changed to be something to
+                * leave some more space in the fifo.
+                */
+               ssi_private->fifo_watermark = ssi_private->fifo_depth - 2;
+               ssi_private->dma_maxburst = ssi_private->fifo_depth - 2;
+               break;
+       }
+
        dev_set_drvdata(&pdev->dev, ssi_private);
 
        if (ssi_private->soc->imx) {
index 507a86a5eafe5646bb9731f865b85571eb6ffdfc..8d2fb2d6f532c833726e5dfbac2fe191eb95a15e 100644 (file)
@@ -142,7 +142,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
                 * for Jack detection and button press
                 */
                ret = snd_soc_dai_set_sysclk(codec_dai, RT5640_SCLK_S_RCCLK,
-                                            0,
+                                            48000 * 512,
                                             SND_SOC_CLOCK_IN);
                if (!ret) {
                        if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && priv->mclk)
@@ -825,10 +825,20 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
        if ((byt_rt5640_quirk & BYT_RT5640_MCLK_EN) && (is_valleyview())) {
                priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
                if (IS_ERR(priv->mclk)) {
+                       ret_val = PTR_ERR(priv->mclk);
+
                        dev_err(&pdev->dev,
-                               "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-                               PTR_ERR(priv->mclk));
-                       return PTR_ERR(priv->mclk);
+                               "Failed to get MCLK from pmc_plt_clk_3: %d\n",
+                               ret_val);
+
+                       /*
+                        * Fall back to bit clock usage for -ENOENT (clock not
+                        * available likely due to missing dependencies), bail
+                        * for all other errors, including -EPROBE_DEFER
+                        */
+                       if (ret_val != -ENOENT)
+                               return ret_val;
+                       byt_rt5640_quirk &= ~BYT_RT5640_MCLK_EN;
                }
        }
 
index 84b5101e6ca691df0e0896b59a95e07a55e3b5e7..6c6b63a6b338f50f0eb218f231506f0017e56241 100644 (file)
@@ -180,6 +180,9 @@ static int skl_pcm_open(struct snd_pcm_substream *substream,
        snd_pcm_set_sync(substream);
 
        mconfig = skl_tplg_fe_get_cpr_module(dai, substream->stream);
+       if (!mconfig)
+               return -EINVAL;
+
        skl_tplg_d0i3_get(skl, mconfig->d0i3_caps);
 
        return 0;
index 8fc3178bc79cf975809d7c808c0b03cb1d91f846..b30bd384c8d38338d50994e9a92673aba123824d 100644 (file)
@@ -515,6 +515,9 @@ EXPORT_SYMBOL_GPL(skl_sst_init_fw);
 
 void skl_sst_dsp_cleanup(struct device *dev, struct skl_sst *ctx)
 {
+
+       if (ctx->dsp->fw)
+               release_firmware(ctx->dsp->fw);
        skl_clear_module_table(ctx->dsp);
        skl_freeup_uuid_list(ctx);
        skl_ipc_free(&ctx->ipc);
index 4bd68de761309b57285bf203aa2ee46cabc440cc..99b5b0835c1e840c66e45676ff81cd57a4c1875c 100644 (file)
@@ -1030,10 +1030,8 @@ static int __rsnd_kctrl_new(struct rsnd_mod *mod,
                return -ENOMEM;
 
        ret = snd_ctl_add(card, kctrl);
-       if (ret < 0) {
-               snd_ctl_free_one(kctrl);
+       if (ret < 0)
                return ret;
-       }
 
        cfg->update = update;
        cfg->card = card;
index f1901bb1466ec67b12189713c66ad040f1ae75c7..baa1afa41e3dd57fdc36655b7d3bbd147ade820f 100644 (file)
@@ -1748,6 +1748,7 @@ static int soc_bind_aux_dev(struct snd_soc_card *card, int num)
 
        component->init = aux_dev->init;
        component->auxiliary = 1;
+       list_add(&component->card_aux_list, &card->aux_comp_list);
 
        return 0;
 
@@ -1758,16 +1759,14 @@ err_defer:
 
 static int soc_probe_aux_devices(struct snd_soc_card *card)
 {
-       struct snd_soc_component *comp;
+       struct snd_soc_component *comp, *tmp;
        int order;
        int ret;
 
        for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
                order++) {
-               list_for_each_entry(comp, &card->component_dev_list, card_list) {
-                       if (!comp->auxiliary)
-                               continue;
-
+               list_for_each_entry_safe(comp, tmp, &card->aux_comp_list,
+                                        card_aux_list) {
                        if (comp->driver->probe_order == order) {
                                ret = soc_probe_component(card, comp);
                                if (ret < 0) {
@@ -1776,6 +1775,7 @@ static int soc_probe_aux_devices(struct snd_soc_card *card)
                                                comp->name, ret);
                                        return ret;
                                }
+                               list_del(&comp->card_aux_list);
                        }
                }
        }
index e7a1eaa2772f4418534d094e576b424a76aaa844..6aba14009c92abc853d72575ed447e934ed5e458 100644 (file)
@@ -2184,9 +2184,11 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd)
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
                break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
+               break;
        }
 
 out:
index 65670b2b408cca0d4bffb2931cb7443cd4ba75b1..fbfb1fab88d5be60de7c40ed8fa1dd78d6fae727 100644 (file)
@@ -514,13 +514,12 @@ static void remove_widget(struct snd_soc_component *comp,
                            == SND_SOC_TPLG_TYPE_MIXER)
                                kfree(kcontrol->tlv.p);
 
-                       snd_ctl_remove(card, kcontrol);
-
                        /* Private value is used as struct soc_mixer_control
                         * for volume mixers or soc_bytes_ext for bytes
                         * controls.
                         */
                        kfree((void *)kcontrol->private_value);
+                       snd_ctl_remove(card, kcontrol);
                }
                kfree(w->kcontrol_news);
        }
index 15d1d5c63c3c40faa5f62316370ea9d8e711fa75..c90607ebe155b4dce4cfa8aa75fc14ecab953d52 100644 (file)
@@ -384,6 +384,9 @@ static void snd_complete_urb(struct urb *urb)
        if (unlikely(atomic_read(&ep->chip->shutdown)))
                goto exit_clear;
 
+       if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+               goto exit_clear;
+
        if (usb_pipeout(ep->pipe)) {
                retire_outbound_urb(ep, ctx);
                /* can be stopped during retire callback */
@@ -534,6 +537,11 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
                        alive, ep->ep_num);
        clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
+       ep->data_subs = NULL;
+       ep->sync_slave = NULL;
+       ep->retire_data_urb = NULL;
+       ep->prepare_data_urb = NULL;
+
        return 0;
 }
 
@@ -912,9 +920,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 /**
  * snd_usb_endpoint_start: start an snd_usb_endpoint
  *
- * @ep:                the endpoint to start
- * @can_sleep: flag indicating whether the operation is executed in
- *             non-atomic context
+ * @ep: the endpoint to start
  *
  * A call to this function will increment the use count of the endpoint.
  * In case it is not already running, the URBs for this endpoint will be
@@ -924,7 +930,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
  *
  * Returns an error if the URB submission failed, 0 in all other cases.
  */
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 {
        int err;
        unsigned int i;
@@ -938,8 +944,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep)
 
        /* just to be sure */
        deactivate_urbs(ep, false);
-       if (can_sleep)
-               wait_clear_urbs(ep);
 
        ep->active_mask = 0;
        ep->unlink_mask = 0;
@@ -1020,10 +1024,6 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 
        if (--ep->use_count == 0) {
                deactivate_urbs(ep, false);
-               ep->data_subs = NULL;
-               ep->sync_slave = NULL;
-               ep->retire_data_urb = NULL;
-               ep->prepare_data_urb = NULL;
                set_bit(EP_FLAG_STOPPING, &ep->flags);
        }
 }
index 6428392d8f6244688e65d8be3d04bc9c30c68ce5..584f295d7c7738a6b91753c8c48eed0bf101a200 100644 (file)
@@ -18,7 +18,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
                                struct audioformat *fmt,
                                struct snd_usb_endpoint *sync_ep);
 
-int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, bool can_sleep);
+int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
index 90009c0b3a92e42f2598e05b451a0cbc0d79c8bf..ab3c280a23d1fa430c39f55816296cf453ad2613 100644 (file)
@@ -754,8 +754,9 @@ int line6_probe(struct usb_interface *interface,
                goto error;
        }
 
+       line6_get_interval(line6);
+
        if (properties->capabilities & LINE6_CAP_CONTROL) {
-               line6_get_interval(line6);
                ret = line6_init_cap_control(line6);
                if (ret < 0)
                        goto error;
index 34c6d4f2c0b62967656b1687594161142bedf127..9aa5b18554812a949503375e23764b3d926a0f2d 100644 (file)
@@ -218,7 +218,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
        }
 }
 
-static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
+static int start_endpoints(struct snd_usb_substream *subs)
 {
        int err;
 
@@ -231,7 +231,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
                dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep);
 
                ep->data_subs = subs;
-               err = snd_usb_endpoint_start(ep, can_sleep);
+               err = snd_usb_endpoint_start(ep);
                if (err < 0) {
                        clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
                        return err;
@@ -260,7 +260,7 @@ static int start_endpoints(struct snd_usb_substream *subs, bool can_sleep)
                dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
 
                ep->sync_slave = subs->data_endpoint;
-               err = snd_usb_endpoint_start(ep, can_sleep);
+               err = snd_usb_endpoint_start(ep);
                if (err < 0) {
                        clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
                        return err;
@@ -850,7 +850,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               ret = start_endpoints(subs, true);
+               ret = start_endpoints(subs);
 
  unlock:
        snd_usb_unlock_shutdown(subs->stream->chip);
@@ -1666,7 +1666,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               err = start_endpoints(subs, false);
+               err = start_endpoints(subs);
                if (err < 0)
                        return err;
 
index b3fd2382fdd9ed62f102e210489eadd17f4e3b8f..eb4b9f7a571e0f154fd7e00b81ef2c5ff7a17130 100644 (file)
@@ -1135,6 +1135,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
        case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
        case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
        case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+       case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
        case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
        case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
        case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
index 0eb0e87dbe9f511672102f2123129328288a9159..d2b0ac799d03c925a6eec2b49bdb14525331687c 100644 (file)
@@ -116,6 +116,12 @@ enum bpf_attach_type {
 
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 
+/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command
+ * to the given target_fd cgroup the descendent cgroup will be able to
+ * override effective bpf program that was inherited from this cgroup
+ */
+#define BPF_F_ALLOW_OVERRIDE   (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -171,6 +177,7 @@ union bpf_attr {
                __u32           target_fd;      /* container object to attach to */
                __u32           attach_bpf_fd;  /* eBPF program to attach */
                __u32           attach_type;
+               __u32           attach_flags;
        };
 } __attribute__((aligned(8)));
 
index 3ddb58a36d3c2534ce6207581a4fee1730c6e6a0..ae752fa4eaa741989040d982772740691486a1e3 100644 (file)
@@ -168,7 +168,8 @@ int bpf_obj_get(const char *pathname)
        return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr));
 }
 
-int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
+int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type,
+                   unsigned int flags)
 {
        union bpf_attr attr;
 
@@ -176,6 +177,7 @@ int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type)
        attr.target_fd     = target_fd;
        attr.attach_bpf_fd = prog_fd;
        attr.attach_type   = type;
+       attr.attach_flags  = flags;
 
        return sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
 }
index a2f9853dd88259d810e6506ec5ac48d863bc074b..4ac6c4b841001b86a58ae5e9ad72cda60d8a5814 100644 (file)
@@ -41,7 +41,8 @@ int bpf_map_delete_elem(int fd, void *key);
 int bpf_map_get_next_key(int fd, void *key, void *next_key);
 int bpf_obj_pin(int fd, const char *pathname);
 int bpf_obj_get(const char *pathname);
-int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type);
+int bpf_prog_attach(int prog_fd, int attachable_fd, enum bpf_attach_type type,
+                   unsigned int flags);
 int bpf_prog_detach(int attachable_fd, enum bpf_attach_type type);
 
 
index 3284bb14ae789bcb0513cba80e8ef0dd43e0812d..8aad81151d5068bacbc1e6d3c114248e9847bf84 100644 (file)
@@ -213,6 +213,9 @@ static int get_value(struct parse_opt_ctx_t *p,
                else
                        err = get_arg(p, opt, flags, (const char **)opt->value);
 
+               if (opt->set)
+                       *(bool *)opt->set = true;
+
                /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
                if (opt->flags & PARSE_OPT_NOEMPTY) {
                        const char *val = *(const char **)opt->value;
index 8866ac438b3441d9e82c739da41273e93466e48b..11c3be3bcce79598bd758d436270399f0f240842 100644 (file)
@@ -137,6 +137,11 @@ struct option {
        { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), \
          .value = check_vtype(v, const char **), (a), .help = (h), \
          .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
+#define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \
+       { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
+         .value = check_vtype(v, const char **), (a), .help = (h), \
+         .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \
+         .set = check_vtype(os, bool *)}
 #define OPT_STRING_NOEMPTY(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
 #define OPT_DATE(s, l, v, h) \
        { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
index f1ce6006525886169fa239bfaa5cabffa33e3c9f..ec30c2fcbac05c2bef0268ac9494c0c5b4254a23 100644 (file)
@@ -111,7 +111,7 @@ static int sched_switch_handler(struct trace_seq *s,
        trace_seq_printf(s, "%lld ", val);
 
        if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
-               trace_seq_printf(s, "[%lld] ", val);
+               trace_seq_printf(s, "[%d] ", (int) val);
 
        if (pevent_get_field_val(s,  event, "prev_state", record, &val, 0) == 0)
                write_state(s, val);
@@ -129,7 +129,7 @@ static int sched_switch_handler(struct trace_seq *s,
        trace_seq_printf(s, "%lld", val);
 
        if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
-               trace_seq_printf(s, " [%lld]", val);
+               trace_seq_printf(s, " [%d]", (int) val);
 
        return 0;
 }
index 5e0dea2cdc01f65849f49f10392293a21b3a468d..039636ffb6c8a3edb6c14fd9a2b3a854ab84f982 100644 (file)
@@ -150,9 +150,9 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
                *type = INSN_RETURN;
                break;
 
-       case 0xc5: /* iret */
        case 0xca: /* retf */
        case 0xcb: /* retf */
+       case 0xcf: /* iret */
                *type = INSN_CONTEXT_SWITCH;
                break;
 
index 27fc3617c6a42066bf7a64bb2ace9961a350183b..5054d9147f0f03122f96338f96e9acd08cc36992 100644 (file)
@@ -430,6 +430,10 @@ that gets then processed, possibly via a perf script, to decide if that
 particular perf.data snapshot should be kept or not.
 
 Implies --timestamp-filename, --no-buildid and --no-buildid-cache.
+The reason for the latter two is to reduce the data file switching
+overhead. You can still switch them on with:
+
+  --switch-output --no-no-buildid  --no-no-buildid-cache
 
 --dry-run::
 Parse options then exit. --dry-run can be used to detect errors in cmdline
index 8fc24824705e0bfecd696bfc50a53ec4924cf9d7..8bb16aa9d661d0e5b8104adc0ef3d14a1fc296f9 100644 (file)
@@ -704,9 +704,9 @@ install-tests: all install-gtk
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
                $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
 
-install-bin: install-tools install-tests
+install-bin: install-tools install-tests install-traceevent-plugins
 
-install: install-bin try-install-man install-traceevent-plugins
+install: install-bin try-install-man
 
 install-python_ext:
        $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
index 9ff0db4e2d0cd1bcc35d2ea137871093ebfcb405..933aeec46f4a128754ef586c07df8e6d7d81eae0 100644 (file)
@@ -1199,7 +1199,7 @@ static int ui_init(void)
                BUG_ON(1);
        }
 
-       perf_hpp__register_sort_field(fmt);
+       perf_hpp__prepend_sort_field(fmt);
        return 0;
 }
 
index 35a02f8e5a4aa90548c643c0de80e85b07a0b3bb..915869e00d863af03ca409f0f9ffa98147c45385 100644 (file)
@@ -655,7 +655,6 @@ static const struct {
        { "__GFP_RECLAIM",              "R" },
        { "__GFP_DIRECT_RECLAIM",       "DR" },
        { "__GFP_KSWAPD_RECLAIM",       "KR" },
-       { "__GFP_OTHER_NODE",           "ON" },
 };
 
 static size_t max_gfp_len;
index 74d6a035133a96a7303287e130abe73af3fc4622..4ec10e9427d915a041e0510eaac2ded2daf9fc07 100644 (file)
@@ -1405,7 +1405,7 @@ static bool dry_run;
  * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
  * using pipes, etc.
  */
-struct option __record_options[] = {
+static struct option __record_options[] = {
        OPT_CALLBACK('e', "event", &record.evlist, "event",
                     "event selector. use 'perf list' to list available events",
                     parse_events_option),
@@ -1636,7 +1636,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
                 * overhead. Still generate buildid if they are required
                 * explicitly using
                 *
-                *  perf record --signal-trigger --no-no-buildid \
+                *  perf record --switch-output --no-no-buildid \
                 *              --no-no-buildid-cache
                 *
                 * Following code equals to:
index d53e706a6f1706d2d69caa93132521f55d89d072..5b134b0d1ff37e42a1b82b5973528c4003bb80f3 100644 (file)
@@ -209,6 +209,7 @@ struct perf_sched {
        u64             skipped_samples;
        const char      *time_str;
        struct perf_time_interval ptime;
+       struct perf_time_interval hist_time;
 };
 
 /* per thread run time data */
@@ -2460,6 +2461,11 @@ static int timehist_sched_change_event(struct perf_tool *tool,
                timehist_print_sample(sched, sample, &al, thread, t);
 
 out:
+       if (sched->hist_time.start == 0 && t >= ptime->start)
+               sched->hist_time.start = t;
+       if (ptime->end == 0 || t <= ptime->end)
+               sched->hist_time.end = t;
+
        if (tr) {
                /* time of this sched_switch event becomes last time task seen */
                tr->last_time = sample->time;
@@ -2624,6 +2630,7 @@ static void timehist_print_summary(struct perf_sched *sched,
        struct thread *t;
        struct thread_runtime *r;
        int i;
+       u64 hist_time = sched->hist_time.end - sched->hist_time.start;
 
        memset(&totals, 0, sizeof(totals));
 
@@ -2665,7 +2672,7 @@ static void timehist_print_summary(struct perf_sched *sched,
                        totals.sched_count += r->run_stats.n;
                        printf("    CPU %2d idle for ", i);
                        print_sched_time(r->total_run_time, 6);
-                       printf(" msec\n");
+                       printf(" msec  (%6.2f%%)\n", 100.0 * r->total_run_time / hist_time);
                } else
                        printf("    CPU %2d idle entire time window\n", i);
        }
@@ -2701,12 +2708,16 @@ static void timehist_print_summary(struct perf_sched *sched,
 
        printf("\n"
               "    Total number of unique tasks: %" PRIu64 "\n"
-              "Total number of context switches: %" PRIu64 "\n"
-              "           Total run time (msec): ",
+              "Total number of context switches: %" PRIu64 "\n",
               totals.task_count, totals.sched_count);
 
+       printf("           Total run time (msec): ");
        print_sched_time(totals.total_run_time, 2);
        printf("\n");
+
+       printf("    Total scheduling time (msec): ");
+       print_sched_time(hist_time, 2);
+       printf(" (x %d)\n", sched->max_cpu);
 }
 
 typedef int (*sched_handler)(struct perf_tool *tool,
index 37388397b5bc051b66dca810c65a4434eea07bb6..18cfcdc90356f89f75b328870cc5fcc621b2005f 100644 (file)
@@ -521,6 +521,12 @@ void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
        list_add_tail(&format->sort_list, &list->sorts);
 }
 
+void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
+                                      struct perf_hpp_fmt *format)
+{
+       list_add(&format->sort_list, &list->sorts);
+}
+
 void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
 {
        list_del(&format->list);
@@ -560,6 +566,10 @@ void perf_hpp__setup_output_field(struct perf_hpp_list *list)
        perf_hpp_list__for_each_sort_list(list, fmt) {
                struct perf_hpp_fmt *pos;
 
+               /* skip sort-only fields ("sort_compute" in perf diff) */
+               if (!fmt->entry && !fmt->color)
+                       continue;
+
                perf_hpp_list__for_each_format(list, pos) {
                        if (fmt_equal(fmt, pos))
                                goto next;
index 42922512c1c62fe09eb12f301c281ceb57c2bf3c..8b610dd9e2f682046ba412b31ab39f85b3b7f670 100644 (file)
@@ -437,7 +437,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
                }
                call->ip = cursor_node->ip;
                call->ms.sym = cursor_node->sym;
-               call->ms.map = cursor_node->map;
+               call->ms.map = map__get(cursor_node->map);
 
                if (cursor_node->branch) {
                        call->branch_count = 1;
@@ -477,6 +477,7 @@ add_child(struct callchain_node *parent,
 
                list_for_each_entry_safe(call, tmp, &new->val, list) {
                        list_del(&call->list);
+                       map__zput(call->ms.map);
                        free(call);
                }
                free(new);
@@ -761,6 +762,7 @@ merge_chain_branch(struct callchain_cursor *cursor,
                                        list->ms.map, list->ms.sym,
                                        false, NULL, 0, 0);
                list_del(&list->list);
+               map__zput(list->ms.map);
                free(list);
        }
 
@@ -811,7 +813,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
        }
 
        node->ip = ip;
-       node->map = map;
+       map__zput(node->map);
+       node->map = map__get(map);
        node->sym = sym;
        node->branch = branch;
        node->nr_loop_iter = nr_loop_iter;
@@ -1142,11 +1145,13 @@ static void free_callchain_node(struct callchain_node *node)
 
        list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
                list_del(&list->list);
+               map__zput(list->ms.map);
                free(list);
        }
 
        list_for_each_entry_safe(list, tmp, &node->val, list) {
                list_del(&list->list);
+               map__zput(list->ms.map);
                free(list);
        }
 
@@ -1210,6 +1215,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
                                goto out;
                        *new = *chain;
                        new->has_children = false;
+                       map__get(new->ms.map);
                        list_add_tail(&new->list, &head);
                }
                parent = parent->parent;
@@ -1230,6 +1236,7 @@ int callchain_node__make_parent_list(struct callchain_node *node)
 out:
        list_for_each_entry_safe(chain, new, &head, list) {
                list_del(&chain->list);
+               map__zput(chain->ms.map);
                free(chain);
        }
        return -ENOMEM;
index 35c8e379530f2f1e02d050a25a2ef786ee10a819..4f4b60f1558a827cbe34d9d387e6a91a917b58dd 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include "event.h"
+#include "map.h"
 #include "symbol.h"
 
 #define HELP_PAD "\t\t\t\t"
@@ -184,8 +185,13 @@ int callchain_merge(struct callchain_cursor *cursor,
  */
 static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
 {
+       struct callchain_cursor_node *node;
+
        cursor->nr = 0;
        cursor->last = &cursor->first;
+
+       for (node = cursor->first; node != NULL; node = node->next)
+               map__zput(node->map);
 }
 
 int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
index 6770a964560954e0b7d028698a50b8bcab0cf891..7d1b7d33e644bd7dd97fef11f5b473770ec8a236 100644 (file)
@@ -1,6 +1,7 @@
 #include "util.h"
 #include "build-id.h"
 #include "hist.h"
+#include "map.h"
 #include "session.h"
 #include "sort.h"
 #include "evlist.h"
@@ -1019,6 +1020,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
                         int max_stack_depth, void *arg)
 {
        int err, err2;
+       struct map *alm = NULL;
+
+       if (al && al->map)
+               alm = map__get(al->map);
 
        err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
                                        iter->evsel, al, max_stack_depth);
@@ -1058,6 +1063,8 @@ out:
        if (!err)
                err = err2;
 
+       map__put(alm);
+
        return err;
 }
 
index d4b6514eeef5dae417cfc76f1fc2de9cc869575f..28c216e3d5b72557825a8918ab2aa6d6369c40f8 100644 (file)
@@ -283,6 +283,8 @@ void perf_hpp_list__column_register(struct perf_hpp_list *list,
                                    struct perf_hpp_fmt *format);
 void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
                                        struct perf_hpp_fmt *format);
+void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
+                                      struct perf_hpp_fmt *format);
 
 static inline void perf_hpp__column_register(struct perf_hpp_fmt *format)
 {
@@ -294,6 +296,11 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
        perf_hpp_list__register_sort_field(&perf_hpp_list, format);
 }
 
+static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format)
+{
+       perf_hpp_list__prepend_sort_field(&perf_hpp_list, format);
+}
+
 #define perf_hpp_list__for_each_format(_list, format) \
        list_for_each_entry(format, &(_list)->fields, list)
 
index d281ae2b54e8fef7b85574a8b799dc33c21e9e44..6a6f44dd594bc4c6275694335ebaa02b22118982 100644 (file)
@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module)
 
        /* A file path -- this is an offline module */
        if (module && strchr(module, '/'))
-               return machine__findnew_module_map(host_machine, 0, module);
+               return dso__new_map(module);
 
        if (!module)
                module = "kernel";
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module)
                if (strncmp(pos->dso->short_name + 1, module,
                            pos->dso->short_name_len - 2) == 0 &&
                    module[pos->dso->short_name_len - 2] == '\0') {
+                       map__get(pos);
                        return pos;
                }
        }
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user)
                return kernel_get_module_map(target);
 }
 
-static void put_target_map(struct map *map, bool user)
-{
-       if (map && user) {
-               /* Only the user map needs to be released */
-               map__put(map);
-       }
-}
-
-
 static int convert_exec_to_group(const char *exec, char **result)
 {
        char *ptr1, *ptr2, *exec_copy;
@@ -267,21 +259,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
        return true;
 }
 
-/*
- * NOTE:
- * '.gnu.linkonce.this_module' section of kernel module elf directly
- * maps to 'struct module' from linux/module.h. This section contains
- * actual module name which will be used by kernel after loading it.
- * But, we cannot use 'struct module' here since linux/module.h is not
- * exposed to user-space. Offset of 'name' has remained same from long
- * time, so hardcoding it here.
- */
-#ifdef __LP64__
-#define MOD_NAME_OFFSET 24
-#else
-#define MOD_NAME_OFFSET 12
-#endif
-
 /*
  * @module can be module name of module file path. In case of path,
  * inspect elf and find out what is actual module name.
@@ -296,6 +273,7 @@ static char *find_module_name(const char *module)
        Elf_Data *data;
        Elf_Scn *sec;
        char *mod_name = NULL;
+       int name_offset;
 
        fd = open(module, O_RDONLY);
        if (fd < 0)
@@ -317,7 +295,21 @@ static char *find_module_name(const char *module)
        if (!data || !data->d_buf)
                goto ret_err;
 
-       mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
+       /*
+        * NOTE:
+        * '.gnu.linkonce.this_module' section of kernel module elf directly
+        * maps to 'struct module' from linux/module.h. This section contains
+        * actual module name which will be used by kernel after loading it.
+        * But, we cannot use 'struct module' here since linux/module.h is not
+        * exposed to user-space. Offset of 'name' has remained same from long
+        * time, so hardcoding it here.
+        */
+       if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
+               name_offset = 12;
+       else    /* expect ELFCLASS64 by default */
+               name_offset = 24;
+
+       mod_name = strdup((char *)data->d_buf + name_offset);
 
 ret_err:
        elf_end(elf);
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
        }
 
 out:
-       put_target_map(map, uprobes);
+       map__put(map);
        return ret;
 
 }
@@ -618,6 +610,67 @@ error:
        return ret ? : -ENOENT;
 }
 
+/* Adjust symbol name and address */
+static int post_process_probe_trace_point(struct probe_trace_point *tp,
+                                          struct map *map, unsigned long offs)
+{
+       struct symbol *sym;
+       u64 addr = tp->address + tp->offset - offs;
+
+       sym = map__find_symbol(map, addr);
+       if (!sym)
+               return -ENOENT;
+
+       if (strcmp(sym->name, tp->symbol)) {
+               /* If we have no realname, use symbol for it */
+               if (!tp->realname)
+                       tp->realname = tp->symbol;
+               else
+                       free(tp->symbol);
+               tp->symbol = strdup(sym->name);
+               if (!tp->symbol)
+                       return -ENOMEM;
+       }
+       tp->offset = addr - sym->start;
+       tp->address -= offs;
+
+       return 0;
+}
+
+/*
+ * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions
+ * and generate new symbols with suffixes such as .constprop.N or .isra.N
+ * etc. Since those symbols are not recorded in DWARF, we have to find
+ * correct generated symbols from offline ELF binary.
+ * For online kernel or uprobes we don't need this because those are
+ * rebased on _text, or already a section relative address.
+ */
+static int
+post_process_offline_probe_trace_events(struct probe_trace_event *tevs,
+                                       int ntevs, const char *pathname)
+{
+       struct map *map;
+       unsigned long stext = 0;
+       int i, ret = 0;
+
+       /* Prepare a map for offline binary */
+       map = dso__new_map(pathname);
+       if (!map || get_text_start_address(pathname, &stext) < 0) {
+               pr_warning("Failed to get ELF symbols for %s\n", pathname);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ntevs; i++) {
+               ret = post_process_probe_trace_point(&tevs[i].point,
+                                                    map, stext);
+               if (ret < 0)
+                       break;
+       }
+       map__put(map);
+
+       return ret;
+}
+
 static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
                                          int ntevs, const char *exec)
 {
@@ -645,18 +698,31 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
        return ret;
 }
 
-static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
-                                           int ntevs, const char *module)
+static int
+post_process_module_probe_trace_events(struct probe_trace_event *tevs,
+                                      int ntevs, const char *module,
+                                      struct debuginfo *dinfo)
 {
+       Dwarf_Addr text_offs = 0;
        int i, ret = 0;
        char *mod_name = NULL;
+       struct map *map;
 
        if (!module)
                return 0;
 
-       mod_name = find_module_name(module);
+       map = get_target_map(module, false);
+       if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
+               pr_warning("Failed to get ELF symbols for %s\n", module);
+               return -EINVAL;
+       }
 
+       mod_name = find_module_name(module);
        for (i = 0; i < ntevs; i++) {
+               ret = post_process_probe_trace_point(&tevs[i].point,
+                                               map, (unsigned long)text_offs);
+               if (ret < 0)
+                       break;
                tevs[i].point.module =
                        strdup(mod_name ? mod_name : module);
                if (!tevs[i].point.module) {
@@ -666,6 +732,8 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
        }
 
        free(mod_name);
+       map__put(map);
+
        return ret;
 }
 
@@ -679,7 +747,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
 
        /* Skip post process if the target is an offline kernel */
        if (symbol_conf.ignore_vmlinux_buildid)
-               return 0;
+               return post_process_offline_probe_trace_events(tevs, ntevs,
+                                               symbol_conf.vmlinux_name);
 
        reloc_sym = kernel_get_ref_reloc_sym();
        if (!reloc_sym) {
@@ -722,7 +791,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unuse
 static int post_process_probe_trace_events(struct perf_probe_event *pev,
                                           struct probe_trace_event *tevs,
                                           int ntevs, const char *module,
-                                          bool uprobe)
+                                          bool uprobe, struct debuginfo *dinfo)
 {
        int ret;
 
@@ -730,7 +799,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev,
                ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
        else if (module)
                /* Currently ref_reloc_sym based probe is not for drivers */
-               ret = add_module_to_probe_trace_events(tevs, ntevs, module);
+               ret = post_process_module_probe_trace_events(tevs, ntevs,
+                                                            module, dinfo);
        else
                ret = post_process_kernel_probe_trace_events(tevs, ntevs);
 
@@ -774,30 +844,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
                }
        }
 
-       debuginfo__delete(dinfo);
-
        if (ntevs > 0) {        /* Succeeded to find trace events */
                pr_debug("Found %d probe_trace_events.\n", ntevs);
                ret = post_process_probe_trace_events(pev, *tevs, ntevs,
-                                               pev->target, pev->uprobes);
+                                       pev->target, pev->uprobes, dinfo);
                if (ret < 0 || ret == ntevs) {
+                       pr_debug("Post processing failed or all events are skipped. (%d)\n", ret);
                        clear_probe_trace_events(*tevs, ntevs);
                        zfree(tevs);
+                       ntevs = 0;
                }
-               if (ret != ntevs)
-                       return ret < 0 ? ret : ntevs;
-               ntevs = 0;
-               /* Fall through */
        }
 
+       debuginfo__delete(dinfo);
+
        if (ntevs == 0) {       /* No error but failed to find probe point. */
                pr_warning("Probe point '%s' not found.\n",
                           synthesize_perf_probe_point(&pev->point));
                return -ENOENT;
-       }
-       /* Error path : ntevs < 0 */
-       pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
-       if (ntevs < 0) {
+       } else if (ntevs < 0) {
+               /* Error path : ntevs < 0 */
+               pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
                if (ntevs == -EBADF)
                        pr_warning("Warning: No dwarf info found in the vmlinux - "
                                "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
@@ -2869,7 +2936,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
        }
 
 out:
-       put_target_map(map, pev->uprobes);
+       map__put(map);
        free(syms);
        return ret;
 
@@ -3362,10 +3429,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
                return ret;
 
        /* Get a symbol map */
-       if (user)
-               map = dso__new_map(target);
-       else
-               map = kernel_get_module_map(target);
+       map = get_target_map(target, user);
        if (!map) {
                pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
                return -EINVAL;
@@ -3397,9 +3461,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
         }
 
 end:
-       if (user) {
-               map__put(map);
-       }
+       map__put(map);
        exit_probe_symbol_maps();
 
        return ret;
index df4debe564daabce2e739289b14360d49185bc6f..0d9d6e0803b88b6fe3909c0b8b83f24fa47580f6 100644 (file)
@@ -1501,7 +1501,8 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
 }
 
 /* For the kernel module, we need a special code to get a DIE */
-static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+                               bool adjust_offset)
 {
        int n, i;
        Elf32_Word shndx;
@@ -1530,6 +1531,8 @@ static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
                        if (!shdr)
                                return -ENOENT;
                        *offs = shdr->sh_addr;
+                       if (adjust_offset)
+                               *offs -= shdr->sh_offset;
                }
        }
        return 0;
@@ -1543,16 +1546,12 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
        Dwarf_Addr _addr = 0, baseaddr = 0;
        const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
        int baseline = 0, lineno = 0, ret = 0;
-       bool reloc = false;
 
-retry:
+       /* We always need to relocate the address for aranges */
+       if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
+               addr += baseaddr;
        /* Find cu die */
        if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
-               if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
-                       addr += baseaddr;
-                       reloc = true;
-                       goto retry;
-               }
                pr_warning("Failed to find debug information for address %lx\n",
                           addr);
                ret = -EINVAL;
index f1d8558f498e96771c13b3f42046a757e888bdf2..2956c51986529ee7481f922d488a449c0a7619a0 100644 (file)
@@ -46,6 +46,9 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
 int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
                                struct perf_probe_point *ppt);
 
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+                              bool adjust_offset);
+
 /* Find a line range */
 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);
 
index 99400b0e8f2a892dcfbfe2572758ef3eae73be59..adbc6c02c3aaac757028e6bbe1ae63cd11ee437a 100644 (file)
@@ -537,6 +537,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
                                break;
                } else {
                        int n = namesz + descsz;
+
+                       if (n > (int)sizeof(bf)) {
+                               n = sizeof(bf);
+                               pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n",
+                                        __func__, filename, nhdr.n_namesz, nhdr.n_descsz);
+                       }
                        if (read(fd, bf, n) != n)
                                break;
                }
index 71b05891a6a14adfe7537e70333352b844966134..831022b12848de68695065040b38bd7ec55f7577 100644 (file)
@@ -90,7 +90,7 @@ ifdef INSTALL_PATH
        done;
 
        @# Ask all targets to emit their test scripts
-       echo "#!/bin/bash" > $(ALL_SCRIPT)
+       echo "#!/bin/sh" > $(ALL_SCRIPT)
        echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT)
        echo "ROOT=\$$PWD" >> $(ALL_SCRIPT)
 
index 92e627adf3540f5c79ca4a2d372f81c74fa3bf8b..6d58cca8e23574a1fe15993d1da8f1558ecf8e06 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 SRC_TREE=../../../../
 
index b13fed534d761742700c21491887667f22a403c9..9f7bd1915c217bedc9b2ae51bb347b9a39bd1192 100644 (file)
@@ -67,21 +67,23 @@ static int map_equal(int lru_map, int expected)
        return map_subset(lru_map, expected) && map_subset(expected, lru_map);
 }
 
-static int sched_next_online(int pid, int next_to_try)
+static int sched_next_online(int pid, int *next_to_try)
 {
        cpu_set_t cpuset;
+       int next = *next_to_try;
+       int ret = -1;
 
-       if (next_to_try == nr_cpus)
-               return -1;
-
-       while (next_to_try < nr_cpus) {
+       while (next < nr_cpus) {
                CPU_ZERO(&cpuset);
-               CPU_SET(next_to_try++, &cpuset);
-               if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset))
+               CPU_SET(next++, &cpuset);
+               if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) {
+                       ret = 0;
                        break;
+               }
        }
 
-       return next_to_try;
+       *next_to_try = next;
+       return ret;
 }
 
 /* Size of the LRU amp is 2
@@ -96,11 +98,12 @@ static void test_lru_sanity0(int map_type, int map_flags)
 {
        unsigned long long key, value[nr_cpus];
        int lru_map_fd, expected_map_fd;
+       int next_cpu = 0;
 
        printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
               map_flags);
 
-       assert(sched_next_online(0, 0) != -1);
+       assert(sched_next_online(0, &next_cpu) != -1);
 
        if (map_flags & BPF_F_NO_COMMON_LRU)
                lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus);
@@ -183,6 +186,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
        int lru_map_fd, expected_map_fd;
        unsigned int batch_size;
        unsigned int map_size;
+       int next_cpu = 0;
 
        if (map_flags & BPF_F_NO_COMMON_LRU)
                /* Ther percpu lru list (i.e each cpu has its own LRU
@@ -196,7 +200,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free)
        printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
               map_flags);
 
-       assert(sched_next_online(0, 0) != -1);
+       assert(sched_next_online(0, &next_cpu) != -1);
 
        batch_size = tgt_free / 2;
        assert(batch_size * 2 == tgt_free);
@@ -262,6 +266,7 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
        int lru_map_fd, expected_map_fd;
        unsigned int batch_size;
        unsigned int map_size;
+       int next_cpu = 0;
 
        if (map_flags & BPF_F_NO_COMMON_LRU)
                /* Ther percpu lru list (i.e each cpu has its own LRU
@@ -275,7 +280,7 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free)
        printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
               map_flags);
 
-       assert(sched_next_online(0, 0) != -1);
+       assert(sched_next_online(0, &next_cpu) != -1);
 
        batch_size = tgt_free / 2;
        assert(batch_size * 2 == tgt_free);
@@ -370,11 +375,12 @@ static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free)
        int lru_map_fd, expected_map_fd;
        unsigned int batch_size;
        unsigned int map_size;
+       int next_cpu = 0;
 
        printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
               map_flags);
 
-       assert(sched_next_online(0, 0) != -1);
+       assert(sched_next_online(0, &next_cpu) != -1);
 
        batch_size = tgt_free / 2;
        assert(batch_size * 2 == tgt_free);
@@ -430,11 +436,12 @@ static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free)
        int lru_map_fd, expected_map_fd;
        unsigned long long key, value[nr_cpus];
        unsigned long long end_key;
+       int next_cpu = 0;
 
        printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type,
               map_flags);
 
-       assert(sched_next_online(0, 0) != -1);
+       assert(sched_next_online(0, &next_cpu) != -1);
 
        if (map_flags & BPF_F_NO_COMMON_LRU)
                lru_map_fd = create_map(map_type, map_flags,
@@ -502,9 +509,8 @@ static void do_test_lru_sanity5(unsigned long long last_key, int map_fd)
 static void test_lru_sanity5(int map_type, int map_flags)
 {
        unsigned long long key, value[nr_cpus];
-       int next_sched_cpu = 0;
+       int next_cpu = 0;
        int map_fd;
-       int i;
 
        if (map_flags & BPF_F_NO_COMMON_LRU)
                return;
@@ -519,27 +525,20 @@ static void test_lru_sanity5(int map_type, int map_flags)
        key = 0;
        assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST));
 
-       for (i = 0; i < nr_cpus; i++) {
+       while (sched_next_online(0, &next_cpu) != -1) {
                pid_t pid;
 
                pid = fork();
                if (pid == 0) {
-                       next_sched_cpu = sched_next_online(0, next_sched_cpu);
-                       if (next_sched_cpu != -1)
-                               do_test_lru_sanity5(key, map_fd);
+                       do_test_lru_sanity5(key, map_fd);
                        exit(0);
                } else if (pid == -1) {
-                       printf("couldn't spawn #%d process\n", i);
+                       printf("couldn't spawn process to test key:%llu\n",
+                              key);
                        exit(1);
                } else {
                        int status;
 
-                       /* It is mostly redundant and just allow the parent
-                        * process to update next_shced_cpu for the next child
-                        * process
-                        */
-                       next_sched_cpu = sched_next_online(pid, next_sched_cpu);
-
                        assert(waitpid(pid, &status, 0) == pid);
                        assert(status == 0);
                        key++;
@@ -547,6 +546,8 @@ static void test_lru_sanity5(int map_type, int map_flags)
        }
 
        close(map_fd);
+       /* At least one key should be tested */
+       assert(key > 0);
 
        printf("Pass\n");
 }
index c09a682df56ae9fb3cc91214ae9d79da19714633..16058bbea7a8501324ce6c9c639f5219d69979ba 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 echo "--------------------"
 echo "running socket test"
index c22860ab973378f76417d2bc85f1daf2c828e0c7..30e1ac62e8cb4249350c89aa64163e3d4ee3bedd 100644 (file)
@@ -66,7 +66,7 @@ int pmc56_overflow(void)
 
        FAIL_IF(ebb_event_enable(&event));
 
-       mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
+       mtspr(SPRN_PMC2, pmc_sample_period(sample_period));
        mtspr(SPRN_PMC5, 0);
        mtspr(SPRN_PMC6, 0);
 
index bdd58c78902e96948f92475f4898de1ec0c14a57..df9e0a0cdf294e1e334c6558c9c4f87a38387e1d 100644 (file)
@@ -1367,7 +1367,7 @@ void run_tests_once(void)
                tracing_off();
                close_test_fds();
 
-               printf("test %2d PASSED (itertation %d)\n", test_nr, iteration_nr);
+               printf("test %2d PASSED (iteration %d)\n", test_nr, iteration_nr);
                dprintf1("======================\n\n");
        }
        iteration_nr++;
index 34e63cc4c572bfcafe6fecb4784fc4ba5079bf8a..14142faf040b7e81a1c38a983aa76d9ae50ee4e1 100644 (file)
@@ -26,6 +26,16 @@ static inline void wait_cycles(unsigned long long cycles)
 #define VMEXIT_CYCLES 500
 #define VMENTRY_CYCLES 500
 
+#elif defined(__s390x__)
+static inline void wait_cycles(unsigned long long cycles)
+{
+       asm volatile("0: brctg %0,0b" : : "d" (cycles));
+}
+
+/* tweak me */
+#define VMEXIT_CYCLES 200
+#define VMENTRY_CYCLES 200
+
 #else
 static inline void wait_cycles(unsigned long long cycles)
 {
@@ -81,6 +91,8 @@ extern unsigned ring_size;
 /* Is there a portable way to do this? */
 #if defined(__x86_64__) || defined(__i386__)
 #define cpu_relax() asm ("rep; nop" ::: "memory")
+#elif defined(__s390x__)
+#define cpu_relax() barrier()
 #else
 #define cpu_relax() assert(0)
 #endif
index 2e69ca812b4cf4b39d653cd774286587fcc87bc7..29b0d3920bfc412a049b1478a7074869cbd113df 100755 (executable)
@@ -1,12 +1,13 @@
 #!/bin/sh
 
+CPUS_ONLINE=$(lscpu --online -p=cpu|grep -v -e '#')
 #use last CPU for host. Why not the first?
 #many devices tend to use cpu0 by default so
 #it tends to be busier
-HOST_AFFINITY=$(lscpu -p=cpu | tail -1)
+HOST_AFFINITY=$(echo "${CPUS_ONLINE}"|tail -n 1)
 
 #run command on all cpus
-for cpu in $(seq 0 $HOST_AFFINITY)
+for cpu in $CPUS_ONLINE
 do
        #Don't run guest and host on same CPU
        #It actually works ok if using signalling
index 17a513268325d197b76aa36d7c26c337a70b9a4d..0b87e71c00fcc9c6cb0de2248b191e89228bf9b6 100644 (file)
@@ -5,8 +5,10 @@
 klibcdirs:;
 PHONY += klibcdirs
 
-suffix_y = $(CONFIG_INITRAMFS_COMPRESSION)
-AFLAGS_initramfs_data.o += -DINITRAMFS_IMAGE="usr/initramfs_data.cpio$(suffix_y)"
+suffix_y = $(subst $\",,$(CONFIG_INITRAMFS_COMPRESSION))
+datafile_y = initramfs_data.cpio$(suffix_y)
+AFLAGS_initramfs_data.o += -DINITRAMFS_IMAGE="usr/$(datafile_y)"
+
 
 # Generate builtin.o based on initramfs_data.o
 obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
@@ -14,7 +16,7 @@ obj-$(CONFIG_BLK_DEV_INITRD) := initramfs_data.o
 # initramfs_data.o contains the compressed initramfs_data.cpio image.
 # The image is included using .incbin, a dependency which is not
 # tracked automatically.
-$(obj)/initramfs_data.o: $(obj)/initramfs_data.cpio$(suffix_y) FORCE
+$(obj)/initramfs_data.o: $(obj)/$(datafile_y) FORCE
 
 #####
 # Generate the initramfs cpio archive
@@ -38,10 +40,8 @@ endif
 quiet_cmd_initfs = GEN     $@
       cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
 
-targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 \
-       initramfs_data.cpio.lzma initramfs_data.cpio.xz \
-       initramfs_data.cpio.lzo initramfs_data.cpio.lz4 \
-       initramfs_data.cpio
+targets := $(datafile_y)
+
 # do not try to update files included in initramfs
 $(deps_initramfs): ;
 
@@ -51,6 +51,6 @@ $(deps_initramfs): klibcdirs
 # 2) There are changes in which files are included (added or deleted)
 # 3) If gen_init_cpio are newer than initramfs_data.cpio
 # 4) arguments to gen_initramfs.sh changes
-$(obj)/initramfs_data.cpio$(suffix_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
+$(obj)/$(datafile_y): $(obj)/gen_init_cpio $(deps_initramfs) klibcdirs
        $(Q)$(initramfs) -l $(ramfs-input) > $(obj)/.initramfs_data.cpio.d
        $(call if_changed,initfs)
index a2dbbccbb6a3fe96751fafde8cd01658aa1301a5..6a084cd57b883e1c4bb8420bee37ed0a74321d98 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
+#include <asm/kvm_hyp.h>
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
@@ -89,9 +90,6 @@ static void kvm_timer_inject_irq_work(struct work_struct *work)
        struct kvm_vcpu *vcpu;
 
        vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
-       vcpu->arch.timer_cpu.armed = false;
-
-       WARN_ON(!kvm_timer_should_fire(vcpu));
 
        /*
         * If the vcpu is blocked we want to wake it up so that it will see
@@ -512,3 +510,25 @@ void kvm_timer_init(struct kvm *kvm)
 {
        kvm->arch.timer.cntvoff = kvm_phys_timer_read();
 }
+
+/*
+ * On VHE system, we only need to configure trap on physical timer and counter
+ * accesses in EL0 and EL1 once, not for every world switch.
+ * The host kernel runs at EL2 with HCR_EL2.TGE == 1,
+ * and this makes those bits have no effect for the host kernel execution.
+ */
+void kvm_timer_init_vhe(void)
+{
+       /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */
+       u32 cnthctl_shift = 10;
+       u64 val;
+
+       /*
+        * Disallow physical timer access for the guest.
+        * Physical counter access is allowed.
+        */
+       val = read_sysreg(cnthctl_el2);
+       val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift);
+       val |= (CNTHCTL_EL1PCTEN << cnthctl_shift);
+       write_sysreg(val, cnthctl_el2);
+}
index 798866a8d8756b07dd815d7a8bc8dec8f6019e13..63e28dd18bb09755b035f6e30bb4aaa6eca082fc 100644 (file)
@@ -35,10 +35,16 @@ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
        /* Disable the virtual timer */
        write_sysreg_el0(0, cntv_ctl);
 
-       /* Allow physical timer/counter access for the host */
-       val = read_sysreg(cnthctl_el2);
-       val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
-       write_sysreg(val, cnthctl_el2);
+       /*
+        * We don't need to do this for VHE since the host kernel runs in EL2
+        * with HCR_EL2.TGE ==1, which makes those bits have no impact.
+        */
+       if (!has_vhe()) {
+               /* Allow physical timer/counter access for the host */
+               val = read_sysreg(cnthctl_el2);
+               val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
+               write_sysreg(val, cnthctl_el2);
+       }
 
        /* Clear cntvoff for the host */
        write_sysreg(0, cntvoff_el2);
@@ -50,14 +56,17 @@ void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
        u64 val;
 
-       /*
-        * Disallow physical timer access for the guest
-        * Physical counter access is allowed
-        */
-       val = read_sysreg(cnthctl_el2);
-       val &= ~CNTHCTL_EL1PCEN;
-       val |= CNTHCTL_EL1PCTEN;
-       write_sysreg(val, cnthctl_el2);
+       /* Those bits are already configured at boot on VHE-system */
+       if (!has_vhe()) {
+               /*
+                * Disallow physical timer access for the guest
+                * Physical counter access is allowed
+                */
+               val = read_sysreg(cnthctl_el2);
+               val &= ~CNTHCTL_EL1PCEN;
+               val |= CNTHCTL_EL1PCTEN;
+               write_sysreg(val, cnthctl_el2);
+       }
 
        if (timer->enabled) {
                write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
index 5114391b7e5af52ee5f815baead6b4561243a31a..c737ea0a310a732cc6f878c57877aa3086e67280 100644 (file)
@@ -268,15 +268,11 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
 
-       mutex_lock(&kvm->lock);
-
        dist->ready = false;
        dist->initialized = false;
 
        kfree(dist->spis);
        dist->nr_spis = 0;
-
-       mutex_unlock(&kvm->lock);
 }
 
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -286,7 +282,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
        INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
 }
 
-void kvm_vgic_destroy(struct kvm *kvm)
+/* To be called with kvm->lock held */
+static void __kvm_vgic_destroy(struct kvm *kvm)
 {
        struct kvm_vcpu *vcpu;
        int i;
@@ -297,6 +294,13 @@ void kvm_vgic_destroy(struct kvm *kvm)
                kvm_vgic_vcpu_destroy(vcpu);
 }
 
+void kvm_vgic_destroy(struct kvm *kvm)
+{
+       mutex_lock(&kvm->lock);
+       __kvm_vgic_destroy(kvm);
+       mutex_unlock(&kvm->lock);
+}
+
 /**
  * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest
  * is a GICv2. A GICv3 must be explicitly initialized by the guest using the
@@ -348,6 +352,10 @@ int kvm_vgic_map_resources(struct kvm *kvm)
                ret = vgic_v2_map_resources(kvm);
        else
                ret = vgic_v3_map_resources(kvm);
+
+       if (ret)
+               __kvm_vgic_destroy(kvm);
+
 out:
        mutex_unlock(&kvm->lock);
        return ret;
index 9bab86757fa4f3613c372fbc0250c146284306ff..834137e7b83ff0c37515a1c36300c24aeadb9925 100644 (file)
@@ -293,8 +293,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
        dist->ready = true;
 
 out:
-       if (ret)
-               kvm_vgic_destroy(kvm);
        return ret;
 }
 
index 5c9f9745e6cab8284161397c3d810df65304fae8..e6b03fd8c374ca7a4dcb1e272141504f66c697d6 100644 (file)
@@ -302,8 +302,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
        dist->ready = true;
 
 out:
-       if (ret)
-               kvm_vgic_destroy(kvm);
        return ret;
 }
 
index 52abac4bb6a2532ad55f4ec690530a6a7b593df0..6d2fcd6fcb2509e801c84b88e6c18e3e7a1d1fa0 100644 (file)
@@ -195,7 +195,7 @@ int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer)
        mutex_lock(&lock);
 
        list_for_each_entry(tmp, &consumers, node) {
-               if (tmp->token == consumer->token) {
+               if (tmp->token == consumer->token || tmp == consumer) {
                        mutex_unlock(&lock);
                        module_put(THIS_MODULE);
                        return -EBUSY;
@@ -245,7 +245,7 @@ void irq_bypass_unregister_consumer(struct irq_bypass_consumer *consumer)
        mutex_lock(&lock);
 
        list_for_each_entry(tmp, &consumers, node) {
-               if (tmp->token != consumer->token)
+               if (tmp != consumer)
                        continue;
 
                list_for_each_entry(producer, &producers, node) {