Merge branch 'for-4.11/block' into for-4.11/linus-merge
authorJens Axboe <axboe@fb.com>
Fri, 17 Feb 2017 21:06:45 +0000 (14:06 -0700)
committerJens Axboe <axboe@fb.com>
Fri, 17 Feb 2017 21:06:45 +0000 (14:06 -0700)
Signed-off-by: Jens Axboe <axboe@fb.com>
1155 files changed:
.mailmap
CREDITS
Documentation/ABI/testing/sysfs-devices-deferred_probe [deleted file]
Documentation/devicetree/bindings/i2c/i2c.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/spi/sh-msiof.txt
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/vm/page_frags [new file with mode: 0644]
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/boot/dts/Makefile
arch/arm/boot/dts/am335x-icev2.dts
arch/arm/boot/dts/bcm-nsp.dtsi
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra72-evm-revc.dts
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.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/omap5.dtsi
arch/arm/boot/dts/orion5x-linkstation-lschl.dts [moved from arch/arm/boot/dts/orion5x-lschl.dts with 98% similarity]
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/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/virt.h
arch/arm/include/uapi/asm/types.h [moved from arch/arm/include/asm/types.h with 94% similarity]
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/smp_tlb.c
arch/arm/kvm/arm.c
arch/arm/mach-imx/mmdc.c
arch/arm/mach-omap1/dma.c
arch/arm/mach-omap2/pdata-quirks.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-odroidc2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
arch/arm64/boot/dts/exynos/exynos5433.dtsi
arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
arch/arm64/boot/dts/xilinx/zynqmp.dtsi
arch/arm64/crypto/aes-modes.S
arch/arm64/include/asm/assembler.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/hugetlbpage.c
arch/arm64/mm/init.c
arch/frv/include/asm/atomic.h
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/smpboot.c
arch/x86/kernel/tsc.c
arch/x86/kernel/tsc_sync.c
arch/x86/kernel/unwind_frame.c
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
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 [moved from arch/x86/platform/intel-mid/device_libs/platform_spidev.c with 91% similarity]
arch/xtensa/kernel/setup.c
block/blk-lib.c
block/blk-zoned.c
block/partition-generic.c
crypto/algapi.c
crypto/algif_aead.c
drivers/acpi/acpica/tbdata.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/nfit/core.c
drivers/acpi/sleep.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/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/samsung/clk-exynos5420.c
drivers/clocksource/exynos_mct.c
drivers/cpufreq/brcmstb-avs-cpufreq.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/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/efi/fake_mem.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/fdt.c
drivers/firmware/efi/memmap.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_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_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_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/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/adc/palmas_gpadc.c
drivers/iio/health/afe4403.c
drivers/iio/health/afe4404.c
drivers/iio/health/max30100.c
drivers/iio/humidity/dht11.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/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/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/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/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/pinctrl-amd.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/uniphier/pinctrl-uniphier-ld20.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/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/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/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/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/dwc3-exynos.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/atmel_usba_udc.h
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_debugfs.c
drivers/usb/serial/ch341.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/qcserial.c
drivers/usb/wusbcore/crypto.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/platform-pci.c
drivers/xen/swiotlb-xen.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/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/export.h
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_connector.h
include/drm/drm_mode_config.h
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/gfp.h
include/linux/gpio/driver.h
include/linux/hyperv.h
include/linux/i2c.h
include/linux/irq.h
include/linux/jump_label_ratelimit.h
include/linux/kernel.h
include/linux/log2.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/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/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/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/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/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/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/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/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/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/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/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/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/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/pci/hda/patch_hdmi.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/line6/driver.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
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 02d2614..67dc22f 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 c585607..c5626bf 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 5fa691e..cee9d50 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 0dcb7c7..9446576 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 ad5a02f..cd1bf2a 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 c010faf..c7194e8 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 ff1bc4b..fb5056b 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 85bf945..afe9630 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 da6614c..dc97506 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 72624a1..c94b467 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 8267c31..895d9c2 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 9e8dbb1..7dcfd17 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 af3f5b5..0304388 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 cfb73e6..6a863cf 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 4a19ea5..07ee2b8 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 2b0ddb1..a0e961f 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 b878637..09f09bb 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 3357deb..a3cdc75 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 e256c66..6e589a1 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 4f5818b..e4ded9d 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 bdf015b..dc2adb3 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 44bb5a7..95a23a2 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 8a39ce4..008ecb5 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.
 
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 c0e6e9d..864e1fd 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
@@ -4106,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/
@@ -4153,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
@@ -4304,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
 
@@ -6724,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/
@@ -7498,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*
@@ -7706,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/
@@ -8179,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
@@ -8903,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
 
@@ -9720,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
@@ -10179,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/
@@ -13061,7 +13075,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
@@ -13096,6 +13110,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
@@ -13368,10 +13383,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
@@ -13447,6 +13460,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
@@ -13618,6 +13632,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
@@ -13673,6 +13688,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 5f1a847..503dae1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 4
 PATCHLEVEL = 10
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
-NAME = Roaring Lionus
+EXTRAVERSION = -rc8
+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 c75d290..283099c 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 b3410ff..5008021 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 a36e860..d5da211 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 b5ff87e..aee1a77 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 6e91d8b..567590e 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 69095da..47111d5 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 cb954cd..c568a9d 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 689dd86..8b90d25 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 994dca7..ecef0fb 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 ce9deb9..8c1fd5c 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 560c4af..9f6b68f 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 42e964d..3d99a60 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 88674d9..2afbafa 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 abd961f..5f69c3b 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 ec86ac0..d408fa2 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 399e2f2..8c9415e 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 7327250..01d178a 100644 (file)
@@ -617,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 \
@@ -846,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 1463df3..8ed46f9 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 b6142bd..15f07f9 100644 (file)
 
        axi {
                compatible = "simple-bus";
-               ranges = <0x00000000 0x18000000 0x0011c40a>;
+               ranges = <0x00000000 0x18000000 0x0011c40c>;
                #address-cells = <1>;
                #size-cells = <1>;
 
index 41de15f..78492a0 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 1faf24a..5ba1616 100644 (file)
                        phy-names = "sata-phy";
                        clocks = <&sata_ref_clk>;
                        ti,hwmods = "sata";
+                       ports-implemented = <0x1>;
                };
 
                rtc: rtc@48838000 {
index c3d939c..3f808a4 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 b792eee..2ee40bc 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 ac2a9da..43ccbbf 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 831d09a..acd4756 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 9d8b596..b397384 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 3aabf65..d6a2190 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 85cd8be..23b0d2c 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;
index 9f40e62..d0496c6 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 fe0221e..ceae909 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 33526ca..1ee1d54 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 ca51dc0..2e516f4 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 1ade195..7aa120f 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 34887a1..47ba972 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 d80f21a..31d4cc6 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 89b834f..e7d30f4 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 19cbd87..cc9572e 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 10f3330..dd4ec85 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;
index 39845a7..53d3f8e 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 8ff2cbd..be33dfc 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 da85984..38faa90 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 7cd92ba..0844737 100644 (file)
                        phy-names = "sata-phy";
                        clocks = <&sata_ref_clk>;
                        ti,hwmods = "sata";
+                       ports-implemented = <0x1>;
                };
 
                dss: dss@58000000 {
similarity index 98%
rename from arch/arm/boot/dts/orion5x-lschl.dts
rename to arch/arm/boot/dts/orion5x-linkstation-lschl.dts
index 9474092..ea6c881 100644 (file)
@@ -2,7 +2,7 @@
  * Device Tree file for Buffalo Linkstation LS-CHLv3
  *
  * Copyright (C) 2016 Ash Hughes <ashley.hughes@blueyonder.co.uk>
- * Copyright (C) 2015, 2016
+ * Copyright (C) 2015-2017
  * Roger Shimizu <rogershimizu@gmail.com>
  *
  * This file is dual-licensed: you can use it either under the terms
@@ -52,7 +52,7 @@
 #include <dt-bindings/gpio/gpio.h>
 
 / {
-       model = "Buffalo Linkstation Live v3 (LS-CHL)";
+       model = "Buffalo Linkstation LiveV3 (LS-CHL)";
        compatible = "buffalo,lschl", "marvell,orion5x-88f5182", "marvell,orion5x";
 
        memory { /* 128 MB */
index 5ae4ec5..c852b69 100644 (file)
                };
 
                amba {
-                       compatible = "arm,amba-bus";
+                       compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
index c8b2944..ace97e8 100644 (file)
                                phy-names       = "usb2-phy", "usb3-phy";
                                phys            = <&usb2_picophy0>,
                                                  <&phy_port2 PHY_TYPE_USB3>;
+                               snps,dis_u3_susphy_quirk;
                        };
                };
 
index 735914f..7cae328 100644 (file)
        cpu-supply = <&reg_dcdc3>;
 };
 
+&de {
+       status = "okay";
+};
+
 &ehci0 {
        status = "okay";
 };
index 2b26175..e78faaf 100644 (file)
        de: display-engine {
                compatible = "allwinner,sun6i-a31-display-engine";
                allwinner,pipelines = <&fe0>;
+               status = "disabled";
        };
 
        soc@01c00000 {
index 5ea4915..10d3074 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 ea316c4..d3f1768 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 18e59fe..7f479cd 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 b01a438..028d2b7 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
@@ -893,7 +893,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 4364040..1e6c48d 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 522b5fe..b62eaeb 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 bfe2a2f..22b7311 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 */
index a2e75b8..6dae195 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[];
similarity index 94%
rename from arch/arm/include/asm/types.h
rename to arch/arm/include/uapi/asm/types.h
index a53cdb8..9435a42 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _ASM_TYPES_H
-#define _ASM_TYPES_H
+#ifndef _UAPI_ASM_TYPES_H
+#define _UAPI_ASM_TYPES_H
 
 #include <asm-generic/int-ll64.h>
 
@@ -37,4 +37,4 @@
 #define __UINTPTR_TYPE__       unsigned long
 #endif
 
-#endif /* _ASM_TYPES_H */
+#endif /* _UAPI_ASM_TYPES_H */
index 188180b..be3b3fb 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 ce131ed..ae738a6 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 22313cb..9af0701 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 1167678..9d74464 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 6991577..c03bf28 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 f6ba589..c821c1d 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 477910a..70c0047 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 8538910..a970e7f 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 3a2e678..0122ad1 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 67532f2..afc1f84 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 eada0b5..0cbe24b 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>;
index 238fbea..c59403a 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 596240c..b353073 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 {
index 64226d5..135890c 100644 (file)
                };
 
                amba {
-                       compatible = "arm,amba-bus";
+                       compatible = "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
index 3580896..ef1b9e5 100644 (file)
@@ -27,7 +27,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x40000000>;
        };
index 68a9083..54dc283 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 c53dbea..838dad5 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 446f6c4..3a43011 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 bfe6328..90c39a6 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 fea1073..439f6b5 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 b5c3933..d1ff83d 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 923841f..43512d4 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 fc35e06..a22161c 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 23e9e13..655e65f 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 5b830be..659b2e6 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 964b754..e25584d 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 716d122..380ebe7 100644 (file)
@@ -404,6 +404,8 @@ void __init mem_init(void)
        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 1c2a5e2..e93c949 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 393d311..67e333a 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 3f9406d..da87943 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 e0a23c7..07fa7e5 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 e78403b..928e1bb 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 a8ee573..281f4f1 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 1c64bc6..0c4e470 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 f61cad3..4c935f7 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 b312b15..6e834ca 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 ede2151..7f4025a 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 a34c764..233a7e8 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 cc12c61..5388551 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 1728497..0cd8a38 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 56398e7..47120bf 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 e157489..ae0a230 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 49c0a5a..9c0f5db 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 e7f4f3e..8bd3b13 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 c56ea8c..c4ced1d 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 0d4531a..dff7979 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 f0b2385..e0b9e57 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 23f8082..f4c2b52 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 0601e6a..195a9fc 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 8180bfd..9de7f79 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 d88573b..b948871 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 5742dbd..3841d74 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 bb18071..0b0f896 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 04885ce..5dd056d 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 ec47a93..ac83eb0 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 e4744ff..925a4ef 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 6fd30ac..62a50d6 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;
        }
@@ -391,20 +394,6 @@ good_area:
 
        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 8033493..67e19a0 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 d5026f3..37b5f91 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 289df38..8c3389c 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 a175cd8..f2108c4 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 93abf8a..8e15880 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 ebf9782..653ff6c 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 cfa53cc..34f1a0d 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 61b7911..952713d 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 fd3e403..270eb9b 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 6447dc1..929b56d 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 346010e..7332634 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 c789258..eec0e8d 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 d38e86f..f9670ea 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 e659daf..e009753 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 95ceac5..f05d2d6 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 bc7b176..2cf8734 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 2d40ef0..d00e368 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 d7697ab..8e136b8 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 7447ba5..12020b5 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 bec71e9..6484a25 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 7a1897c..d56ef26 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 b84be67..d031799 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 3bebf39..4d0248a 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 c59af54..3caed40 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 4bc10e4..dfc97a4 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 d89b701..e279572 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 cc3bd58..9e240fc 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 725e820..113588d 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 31c34ee..7ff1b0c 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 701d29f..57f7ec3 100644 (file)
@@ -255,23 +255,6 @@ ENTRY(__switch_to_asm)
 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.
  *
  * eax: prev task we switched from
@@ -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 5b21970..044d18e 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 05612a2..496e603 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 019c588..1635c0c 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 8613826..eb1484c 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 fec8a46..1076c9a 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 be20239..9dfeeec 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 bd34124..22ef4f7 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 97c246f..1ab4597 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 e6832be..dae2fed 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 34a46dc..8167fdb 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 38711df..2266f86 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 195becc..e793fc9 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 eaf1005..e6cfe7b 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 a3269c8..2e41c50 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 5cb436a..fcc5cd3 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 945e512..bd6b8c2 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 71cae73..2b4cf04 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 dc1697c..ede03e8 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 fcd484d..203f860 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 00ef432..537c664 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 6a31e26..079e817 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 2af69d2..73102d9 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 b624b54..8325d8a 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 e4e97a5..de72344 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 85e87b4..dc6ba5b 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 46732dc..99b920d 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 be3a49e..37e7cf5 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 d0db011..728f753 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 4443e49..23d1556 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 56628a4..cedbba0 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 5fe290c..2f6ef51 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 e0c8023..ff8039d 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 2f22810..e52c908 100644 (file)
@@ -3182,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;
 
        /*
@@ -3342,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;
@@ -6045,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))
@@ -6168,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 ea9c49a..8aa6bea 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 324e571..af59f80 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 e76d1af..bb660e5 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 3cd6983..3961103 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 936a488..274dfc4 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 319148b..2f25a36 100644 (file)
@@ -269,6 +269,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
         * text and allocate a new stack because we can't rely on the
index 10aca63..30031d5 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 61b5ed2..90e4f2a 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
@@ -11,6 +11,7 @@
  * of the License.
  */
 
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/sfi.h>
 #include <linux/spi/pxa2xx_spi.h>
@@ -34,6 +35,9 @@ 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;
 
index 848e856..8fd4be6 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 ed89c8f..ed1e78e 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 472211f..3bd15d8 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 d7beb6b..7afb990 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 df939b5..1fad2a6 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 f849311..533265f 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 82b0b57..b0399e8 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 5fdf251..01e1b3d 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 2f82b8e..7361d00 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 9b6cebe..54abb26 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 02ded25..7f48156 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 9cd0a2d..c2d3785 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 823e938..2f32782 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 4ef4c5c..8a8e403 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 ada9dce..e19b100 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 020ea7f..8c25e68 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 a8b258e..a1fbf55 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 4497d26..ac350c5 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 8ab8ea1..fa26ffd 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 872eac4..a14fac6 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 f642c42..168fa17 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 b4f6520..62f5bfa 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 96f1713..89af807 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 38c576f..9fd06ee 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 5545a67..10332c2 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 b2bdfa8..265f1a7 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 15f58ab..e5ab7d9 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 6ce5ce8..87fba42 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 5bb1985..6d9cc2d 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 02819e0..87885d1 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 8b00e79..17857be 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 8c8b495..cdc092a 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 4da1dc2..670ff0f 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 4fda623..c943606 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 f91c257..50bd6d9 100644 (file)
@@ -1235,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;
@@ -1845,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;
@@ -1875,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;
@@ -2005,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;
@@ -2047,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;
 }
 
index e2ce819..612898b 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 830f35e..649e561 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 6553912..e5d9278 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 2ed1e24..b4b78b3 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 918da8e..1c65f07 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 d5af7d6..7ec0a8f 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 bc5cbc1..5b2d78a 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 e882253..33f0a62 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 1e480f1..8c4fd25 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 d5ba43a..200828c 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 e00c9b0..5a37b9f 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 8e67895..abcc51b 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 90eddd9..cc5259b 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 ac68666..daf479c 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 87fd015..7539f73 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 2e441d0..4c357d4 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 3688d08..3056ce7 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 3f24aeb..2403475 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 7829846..7c1e3a7 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 520a40e..6c7d60c 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 b98824e..0e2a96b 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 a6a9311..260c4b4 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 f03ddec..7868644 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 1e8fde8..2292742 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 f4c26c7..a07ae9e 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 9ada56c..4c851fd 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 29d6d84..41e41f9 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 60bd4af..fe3bb94 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 8cb937b..2534ada 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 fc592c2..95a568d 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 a81dfae..1d564be 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 69b66b9..8fec802 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 9999dc7..ccb5e02 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 b3d62b9..a7af5b3 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 b4e4ec6..39df6a5 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 584abe8..28102bb 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 762f8e8..e9a1768 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 d0ec009..3733741 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 45a573e..0635829 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 0daac3a..476bc9f 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 1170a64..034ace7 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 6c65a1a..6e150db 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 96444e4..7fb9137 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 a79e283..6de6bec 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 6b3293a..37ca685 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 bf088d6..c2ac54f 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 c02469a..85f3587 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 b0c63c5..6bb79c9 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 4b14f25..0fb4e8c 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 dc6700a..b036064 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 26477f0..6cd1287 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 e5812aa..6e618aa 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 908011d..7abda94 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 f75c642..533e762 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 810c51d..5331ee1 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 eb9bf87..18eefdc 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 04b3c16..7f4cc6e 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 6069748..fdfb1ec 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 583f47f..4594477 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 5a45262..7a7019a 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 aa64448..f59771d 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 a525751..6594b40 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 ac6a352..e6b19bc 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 ac953f0..cf8f012 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 169ac96..fe0e85b 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 6ca1f31..75eeb83 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 0d41ebc..f7bce86 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;
@@ -314,6 +316,22 @@ void intel_vgpu_free_resource(struct intel_vgpu *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
  * @param: vGPU creation params
index 711c31c..4a6a2ed 100644 (file)
@@ -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 d26a092..e456398 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 f32bb6f..3408373 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 6c5fdf5..47dec4a 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;
 }
 
@@ -2208,7 +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_addr;
+       void *page;
 
        gvt_dbg_core("init gtt\n");
 
@@ -2221,17 +2204,14 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
                return -ENODEV;
        }
 
-       gvt->gtt.scratch_ggtt_page =
-               alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
-       if (!gvt->gtt.scratch_ggtt_page) {
+       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);
 
-       page_addr = page_address(gvt->gtt.scratch_ggtt_page);
-
-       gvt->gtt.scratch_ggtt_mfn =
-               intel_gvt_hypervisor_virt_to_mfn(page_addr);
+       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);
@@ -2297,3 +2277,30 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
        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 b315ab3..f88eb5e 100644 (file)
@@ -208,6 +208,7 @@ 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 398877c..e6bf5c5 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 0af1701..e227caf 100644 (file)
@@ -323,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);
@@ -375,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);
 
 
@@ -411,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);
 
@@ -424,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 5228097..ab2ea15 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 faaae07..3f656e3 100644 (file)
@@ -230,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;
@@ -269,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,
@@ -398,6 +398,7 @@ 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(mdev);
        gvt = kdev_to_i915(pdev)->gvt;
@@ -406,13 +407,15 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
        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);
@@ -422,7 +425,10 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
 
        gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
                     dev_name(mdev_dev(mdev)));
-       return 0;
+       ret = 0;
+
+out:
+       return ret;
 }
 
 static int intel_vgpu_remove(struct mdev_device *mdev)
index 09c9450..4df078b 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 87d5b5e..3bc620f 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 81cd921..d9fb41a 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;
@@ -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 0dfe789..fbd023a 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 4db2422..e91885d 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 3b30c28..2833dfa 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 536d2b9..7295bc8 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 445fec9..728ca3e 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 243224a..8493e19 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 3dd7fc6..24b5b04 100644 (file)
@@ -595,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)
@@ -2036,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;
@@ -3504,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 bd08814..d534a31 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 097d9d8..b8b877c 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 4b3ff3e..d09c749 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 a792dcb..e924a95 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 dbe9fb4..8d3e515 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 86ecec5..588470e 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 3dc8724..891c86a 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;
+       lockdep_assert_held(&vma->vm->dev->struct_mutex);
 
-       WARN_ON(!mutex_is_locked(&obj->base.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);
@@ -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 58a756f..a2f0e07 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 cd132c2..03a2112 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 62f215b..f3a1d6a 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 beb0898..f4a8c4f 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 d4961fa..beabc17 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 aeb637d..91cb4c4 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 8f131a0..242a73e 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 4942ca0..7890e30 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 d836b22..f7c8701 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 c809c08..a2bcc70 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 a181261..686a580 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 5f6cd87..c396d45 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 17b0cc1..cdfc63d 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 c099da7..25d9d0a 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 d8bc59c..8098677 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 166e84e..4896765 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 f326cf6..67b34e0 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 74856a8..e64f524 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 cef08da..6a15776 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 59348fc..bc85a45 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 8d5ed5b..42c1fa5 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 2f2a3dc..fa2d0a9 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 ccdce1b..d5e58a3 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 187ecdb..21a5775 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 08f9c6f..1fba386 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 2c2c645..32097fd 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 52b87ae..f0b322b 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 6f0436d..f8f2f16 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 567466f..0db8efb 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 fb16070..4a4f953 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 00ea000..30bd4a6 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 0bcffd8..96683f5 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 ad4d7b8..4147768 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 8b5e697..2944916 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 725dffa..6dfdb14 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 a0fd3e6..7aadce1 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 db92077..ab30169 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 881bf48..686cdd3 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 08886a3..5cdd003 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 dd21f95..cde9f37 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 723fd76..7a96798 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 cff060b..ea36b55 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 717704e..c0303f6 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 f31a778..b22d0f8 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 1b764d1..1689568 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 54bd22d..350accf 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 c5c5fbe..52026dc 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 78fb32a..ea3c354 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 e9d6cc7..30a2977 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 b9779bc..8aeca03 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 b1a9a3c..672145b 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 cd49cb1..308dbda 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 6869712..45d6771 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 6d81c56..e9db857 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 26250b4..c1db3a5 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 c62b7cd..3310f2e 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 c2268cd..c21ca7b 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 cf9e396..583e950 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 66f323f..6f638bb 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 2bbf0c5..7d61b56 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 9a08146..6bb23a4 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 4526640..964f523 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 90ab8a2..183c143 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 9c47bc9..2a22ad9 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 e7dcfac..3e70a9c 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 1e62a5f..4609b92 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 9d5fe18..6262dc0 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 f1510cc..9398143 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 19c6477..bec82a6 100644 (file)
@@ -505,6 +505,15 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *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.
         *      2) opcode not reflected 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 516b0ae..40c0e7b 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 4788e1a..8cd4d05 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 49b51b7..3345e1c 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 cda5542..04c1c38 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 862381a..640d221 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 29e97df..4c000d6 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 aff9fb1..5a31f3c 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 7b74d09..3ac8aa5 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 620badd..bb32e47 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 63890eb..a9a8d87 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 57c8de2..c7d6c9a 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 231a1ce..bd8fbd3 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 5489137..c2aa526 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 d0faca2..86a6585 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 342e781..4abdeb3 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 486d576..44b2108 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 3435eff..5bcf073 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 9104e6b..e71af71 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 0be6a7c..9d0b22a 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 8ae7a3b..6a9d1cb 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 8ddc071..79bf484 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 f3135ae..abd18f3 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 6d94996..c7d5b2b 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 a8b0a2e..7fed92f 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 92595b9..022be0e 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 cde6f4b..6d279aa 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 fa598f7..1e1d0ad 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 aa7c5da..cb2bf20 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 30cc627..bb7762b 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 11447ab..bf5c36e 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 77551f5..a761877 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 02aec28..3e6003d 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 83cf113..c9d1c91 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 54a5e87..efbcf84 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 1730470..05fa9f7 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 1a1d997..296f141 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 7c6c572..8a9f742 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 6400cff..3570bcb 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 9d7275f..6e702fc 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 82821ee..01175da 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 e38936d..2a51403 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 a162fed..848365d 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 a1f3fbe..7b0f647 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 ab5e862..1920756 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 d7bfb6f..302dea3 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 06d7279..3c7e106 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 ed8e136..1440fa2 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 0ea4efb..ccda41c 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 bc5e8cf..8f11d7e 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 b31fa6f..b979ea1 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 59872b3..f4e92bd 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 3a0fe8c..48646a7 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 25a9949..30a48c2 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 9796340..d5c911c 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 ed00dc9..00f773e 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 07fa08b..d54ebe7 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 a4dcaec..8c1f926 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 a0547db..76382c8 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 18e05ca..3600c99 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 c6c051b..c6217a4 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 dd7f15a..25b4a1b 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 9daf3f9..e1e4d47 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 699693c..8dadb98 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 b61b52f..0fccca0 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 b11c345..e6ea850 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 b44306b..73db085 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 b352760..0973935 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 01a8047..b597244 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 44ecebd..c8b8ac6 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 160f695..278a5a4 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 2390980..0def995 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 353a9dd..9ce5dcb 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 5553a5d..846a66c 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 28c7f47..4a5e948 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 1f2948c..895101a 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 b8c2933..a306de4 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 7be393c..cf7c189 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 680d1ff..6749b18 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 9ec33b5..2ce7ae9 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 c12d261..3872ab9 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 5b7ba25..8a280e7 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 aaf0350..a7d16db 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 155190d..1c87cc2 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 e76b7f6..c2730f1 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 f52a9bd..0010881 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 c8f5255..7dcc907 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 3b14d51..c483618 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 7e8cf21..744ed6d 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 9608cb4..4fcc6a8 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 185e9e0..ae42de4 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 c0fb80a..baba2db 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 d67adad..fc8550a 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 9211c75..1e46952 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 c18ebfe..a60f189 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 67befed..578c7f8 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 0e74529..30e8550 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 225e9a4..cd49a54 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 38160c2..8be7034 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 a6e7afa..957bfc2 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 8722668..8fa18fc 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 672b646..8aed728 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 a831f94..309f5c6 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 c125966..a07b8d7 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 a761001..1515aba 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 3dd8788..1c29c86 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 c7e9399..53daa6c 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 a849da9..6b86353 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 d9c9f86..9aa4226 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 edbe200..3b4961a 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 eac527e..cc003fd 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 cd3638e..0509996 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 0e8b7c4..8258d08 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 88ee7d8..086920b 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 ba1c6cd..cec59bc 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 56185a0..1822382 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 3797cc7..caa837e 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 951dbd5..d5ecb8f 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 f0b460f..0523ed4 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 33a399a..bb67863 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 1fe80de..a0e5a69 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 d088eff..f33f72d 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 1236b27..f14ca33 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 0e2fb3e..06d5e6f 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 1fffe48..cbfac06 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 f8829b5..2ebbe80 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 f14d9c9..d0c8bf0 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 03293ed..595f7c7 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 c4478ec..b53fc85 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 0ac7a2f..6346a8f 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 6547f22..3c315eb 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 d2ec9d2..fd12e0a 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 269e440..7129c30 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 d147ddd..0af3338 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 d768c7b..003093a 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 01d0efa..9e494a4 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 150ccf5..2e88115 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 8e5cb76..873ce2c 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 6625a3a..3141792 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 2a16547..2dbdb32 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 99a14df..2851b4c 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 422289c..f46d300 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 44389c9..8f1623b 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 92d7692..301f487 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 00fafab..f729a6b 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 be3c91c..5484fd7 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 39eb7a6..e3f6389 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 a283177..3da4737 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 082cd48..36942f5 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 77c88fc..9b8a30b 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 b203143..6508822 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 93dc10b..aa02a03 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 8b6810b..99d3df7 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 ece59c5..4a40a3d 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 5a1cc08..86e5749 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 c9414c0..fcab801 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 46d53a6..76ba7ec 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 1253f86..ef68851 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 1e05b7c..0844f84 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 5c26653..c27011b 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 d361835..8dbd59b 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 e741bf6..b0492ef 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 800b39f..a10d0e7 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 1b63924..ca1b462 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 e269262..ed0d235 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 c0b4e65..46fe1ae 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 9a77289..6742070 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 25f93a9..7cc1b7d 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 92b0838..8c8e15b 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 fa62bdf..94ca42e 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 cd8e02c..bfabe18 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 3daa41b..0acc9b6 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 fe7b288..86144f9 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 24e803f..3667448 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 6fe1cdb..24d5272 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 7dc6122..ad42295 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 95b7bd0..c81c791 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 12071f1..d9440bc 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 4a10500..765c2d6 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 23dfb0e..454f907 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 bb70dd5..50b62db 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,7 @@ 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, NULL, info);
                if (IS_ERR(rt))
                        return PTR_ERR(rt);
                ip_rt_put(rt);
@@ -2441,7 +2450,7 @@ 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, NULL, info);
                if (IS_ERR(ndst))
                        return PTR_ERR(ndst);
                dst_release(ndst);
@@ -2883,7 +2892,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 +3060,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 d02ca14..8d3e53f 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 636c8b0..09e9e2e 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 63a051b..bec7d9c 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 bc7397d..08bc782 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 ce731d0..e8724e8 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 2f0c84b..5fa1c3e 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 691ddef..a33a06d 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 0a50864..49015b0 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 3ce1f7d..530586b 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 e30ffd2..50fa169 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 3124eae..85b742e 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 a479cd9..1e4125a 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 eca9688..c002384 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 f81aa4b..02ca45f 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 e75d4fd..434e1d4 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 6307088..ce3e8df 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 a2ac9e6..6c033c9 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 7282d74..5b536be 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 b4e743d..138c6fa 100644 (file)
@@ -1135,12 +1135,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 aa0bc60..e65041c 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 b097722..14cfc6f 100644 (file)
@@ -229,14 +229,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 85896d4..d67d0d0 100644 (file)
@@ -307,11 +307,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);
@@ -421,12 +421,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);
@@ -502,7 +501,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;
@@ -520,7 +519,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;
@@ -581,7 +580,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;
 
        /*
@@ -601,13 +599,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 f587af3..557f29b 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 6f50741..be8c800 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 b1d66ed..fc5ba2f 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 173e842..ba57f98 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 23d5eb1..cc7ad06 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 8c3760a..6099022 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 dd6d4cc..3858b87 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 1f38d08..f1b633b 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 bed1999..af8f6e9 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 10c9c0b..ec0b4c1 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 50c5003..7f73bac 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 a881c0d..7904d02 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 17ac1dc..3dd8bcb 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 7175293..2dd1c68 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 e164b5c..204960e 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 0917204..c617ec4 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 3730063..d94aef1 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 59cb7a6..901b356 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 1e13967..6df35dc 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 b218961..4d4ef42 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 c3928aa..e0bca4d 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 25694f7..b69743b 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 c9a1469..537b520 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++) {
index 0eb51e3..207a8de 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 aa8bd97..9668633 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 410741a..f46ece2 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 1fc0de8..3617705 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 97b4c3a..25f15df 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 cbf4d83..25b1769 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 e6a512e..a3ade9e 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 a43b0e8..988a747 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 4864b9d..7161910 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 9a507e7..90b05c7 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 a79cb5a..1cfb775 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 c93c5a8..5dc673d 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 72918c1..64989af 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 75f820c..27ff38f 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 639ed4e..070c4da 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 4f56b10..5b48bed 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 d9e1521..5caf5f3 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 a9a0016..b2e8c0d 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 f9e8620..cfcfff4 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 9ddc920..9e4b770 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 2544a37..adb3d58 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 3d3768a..0f80779 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 236e4e5..7b6bd8e 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 4faa767..a78a3df 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 394fe13..dcb33f4 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 b5c966e..0b5b423 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 23ca8a2..2133145 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 47eb4d5..f201f40 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 f7df01b..5b1287a 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 632d5f3..7b6317c 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 5093ca9..a94b0b6 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 2819ceb..67f64db 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 54380b4..0a1723c 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 6201dce..77624ea 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 007192d..dc1ec9b 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 02fe3c4..83c1b7e 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 8521cfe..4066046 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 bff9689..e4fda84 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 f26c5f6..0824a81 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 36935c9..8a58ef3 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 6643f6f..d925910 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 37e026a..cf8430b 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 c35b6de..e9e1e14 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;
 }
 
@@ -2893,7 +2893,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 b193304..1f5d92a 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 8c9a35c..50adabb 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 396b32d..7cf70aa 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 ec91bd0..c680d76 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 8823cc8..5bb3760 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 ec4aa25..2922a99 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 e89da0a..0314c6b 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 319225d..6ab4c77 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 d36c11b..02fb967 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 e31971f..837cb8d 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 b715a26..054012f 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 dd7b5b4..d6239fa 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 0012ad0..1f00eeb 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 113f3d6..27f75b1 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 ee01f20..9afa6be 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 1ebd13e..26929c4 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 4879e70..df7b6e9 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 7dfefd6..437591b 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 37d5cae..cac5a20 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 4d3d4dd..7c0b105 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 b811b0f..4c77965 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 641faab..6555913 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 61569a7..76e03a7 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 aa0166b..116436b 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 fe4399b..c13fec4 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 168b10c..fabbe76 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 52bbd27..701c085 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 d2e50a2..24f9f98 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 9548d3e..302b8f5 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 c55db4a..77c5fcf 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,8 +3749,8 @@ 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_ATOMIC);
@@ -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 911c3b3..46d0ad5 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 11fe68a..bcd1e19 100644 (file)
@@ -385,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);
 }
 
 /**
@@ -1178,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 e27899b..e956306 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 002822d..49d685a 100644 (file)
@@ -2147,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 5e746ad..fd80c1b 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;
@@ -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;
index f3212db..12c7687 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 3e1c9d5..b03b2eb 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 ddfab30..e5834dd 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 25f522b..e32029a 100644 (file)
@@ -913,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, "
index 0c8deb9..9a0ec11 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];
index fca288b..772f158 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)
@@ -2710,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
@@ -2766,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 ade902e..ce5a18c 100644 (file)
@@ -410,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;
index 4fef50e..dd70c88 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 2597b83..95aa523 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 0ee190f..6cb4575 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 7ce31a4..42cc72e 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 46fca6b..1db4b61 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) },
index e3b7af8..09d9be8 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 1bc6089..696458d 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 79451f7..062c205 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 c882357..59b3f62 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 9266271..b3cc33f 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>
 
@@ -495,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 253310c..fd6c8b6 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 d643260..8f99fe0 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 bbbf588..ce5e63d 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 f89245b..68a1135 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 d47a2fc..c71fde5 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 6b5ee89..7cc5122 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 112ce42..2a165cc 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 f905d6e..f8afc6d 100644 (file)
@@ -414,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
@@ -575,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 c2a377c..83eab52 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 4ab67e8..873b4ca 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 29a02da..4223702 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 5db5d13..3c47614 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 63d1977..ff0b0be 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 7f39084..c4444d6 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 e97302f..dcd2e79 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 f2b281a..1e861a0 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 33f967d..21e51b0 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 f10bf52..eeffff8 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 161342b..726f928 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 9cd0c0e..e4b066c 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 baea866..94fd76d 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 d7a9369..8ab1fdf 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 398e532..5e659d0 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 4f49253..c9d2e55 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 8f6a2a5..a27fc87 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 e525b60..ae6b056 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 5c74f60..c45598b 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 769903d..95d71ed 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 aeae8c0..c87bae4 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 36bea5a..c634874 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 7b90691..e38039f 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 0738f48..0d88024 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 702638e..46fd30d 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 4304072..40d6107 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 9b28649..a8aa00b 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 9e792e3..7a182c8 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 70ea57c..f117926 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 1f7c732..811fd89 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 354a123..a51cb4c 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 e973cd5..28d6f35 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 b5b1259..487ba30 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 6dcbc5d..0a0eaec 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 1d152f4..daeb94e 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 59554f3..dd04249 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 596205d..1fc07a9 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 4b4beaa..a0dee8a 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 7ecf16b..8fae53c 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 c939936..4516e8b 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 83d576f..77d1632 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 52c0734..8203590 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 f2dce10..e3036e1 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 9ad48d9..023bb0b 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 5955220..c9d48dc 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 8e7e61b..87c9a9a 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 a2066e6..2726536 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 55313d9..d4e37ac 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 27c059e..1d887ef 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 d0f8a38..0186fe6 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 873d831..4ef78aa 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 0a908ae..b0d0623 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 1c5331a..528369f 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 78d7136..da519ba 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 a459211..294519b 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 74ae2de..709aa09 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 d96e2f3..43953e0 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 d346d42..33db69b 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 5050056..9f06a21 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,36 +362,12 @@ 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
  * actual (current) free extent fbno for flen blocks.
@@ -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);
@@ -699,20 +670,6 @@ xfs_alloc_ag_vextent(
        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.
         */
        args->wasfromfl = 0;
@@ -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 7c404a6..1d0f48a 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 af1ecb1..6622d46 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 2760bc3..bfc00de 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 cecd094..cdef87d 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 d6330c2..d9be241 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 c58d72c..2f389d3 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 0197590..d6e6d9d 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 0fd086d..7c47188 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) {
@@ -123,6 +125,27 @@ xfs_inobt_alloc_block(
 }
 
 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,
        struct xfs_buf          *bp)
@@ -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 bd88453..aa81e2e 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 dd483e2..d93f9d9 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 2580262..584ec89 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 0f56fcd..631e7c0 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 b9abce5..c141791 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 7f0a01f..ac3b4db 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 7a30b8f..9d06cc3 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 b955779..de32f0f 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 0d14742..1aa3abd 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 308bebb..22c1615 100644 (file)
@@ -98,12 +98,27 @@ 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 e467218..7a989de 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 c39ac14..b1469f0 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 84f7852..7f351f7 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 45e50ea..b669b12 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 63554e9..719db19 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 192016e..9c4ee14 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 d6d241f..56814e8 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 a9b9524..045a97c 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
@@ -608,6 +611,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
         * be used as an array index. It is invariant over the lifetime of the
@@ -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 bf9991b..1374323 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;
        /**
index b717ed9..5c970ce 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 883b8ab..05675b1 100644 (file)
@@ -747,7 +747,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;
 }
@@ -1008,6 +1008,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)
 {
@@ -1544,12 +1557,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 92bc89a..c970a25 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 f74ae68..3ed1f3b 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 d67ab83..79591c3 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 a087500..df08a41 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 d016a12..28ffa94 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 20bfefb..921acaa 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 c717f5e..b3d2c1a 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 a07a476..5b1af30 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 2a0f61f..1a1dfdb 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 a0934e6..e4eb254 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 13ba552..4c467ef 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 4175dca..0fe0b62 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 c2748ac..e973fab 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 42fe43f..183efde 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 b2109c5..4b45ec4 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 e798755..39e3254 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 089f70f..23da3af 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 56aec84..cb09238 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 fd7ff3d..ef3d4f6 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 61d20c1..2546988 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 01033fa..134a2f6 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 257173e..f541da6 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 fe6b403..b84615b 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 71613e8..41d376e 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 36d9896..f4aac87 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 7c84273..cc7cba2 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 994f742..2791467 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 bca5363..1b1ca04 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 aacca82..0a3fadc 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 1c7eec0..3a481a4 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 4741ecd..78ed810 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 f7d95f6..7fc1105 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 a2daea0..b37b05b 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 321f9ed..01f71e1 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 e2f3a32..8265d35 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 4d19052..ad3ec9e 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 b53c0cf..a410715 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 084b12b..4c53635 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 85cc819..333ad11 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 e5d1934..7440290 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 0c729c3..d971837 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 09f4be1..7f47b70 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 fc5848d..c93f4b3 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 bd36ce4..bab0b1a 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 6620400..5209b5e 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 3ebb168..a34b141 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 487e573..dbf0abb 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 d4c1c75..0388b9c 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 924325c..7dfdb51 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 cbedda0..5ceb220 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 f0e867f..c4f5e6f 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 958a24d..b567e44 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 96dd0b3..da5033d 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 6902c2a..4b6b489 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 530c57b..915c435 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 2b502f6..b86168a 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 29e6858..da854fb 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 c14bed4..88d18a8 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 9e687ca..15bf875 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 a8b93e6..f330ba4 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 0eb0e87..d2b0ac7 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 3cbc327..c451eec 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 f0db778..3dc91a4 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 85ddb74..b23c191 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 8be21e0..d0b5fa9 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 881d49e..e3f27e0 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 6b76e3b..bea982a 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 cb4bcdc..a4dcd88 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 c396a80..052799e 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 a6b88a6..975b50d 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 46e8a2e..45184a2 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 82bdf56..bb68cb1 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 48a19bd..d24eee1 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 dfdfe4e..f4f87cf 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 223b734..4dd8bd2 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 e08b948..3ec5742 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 a2ac051..3d55d95 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 a515f7b..da0f536 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 1eb4f13..503d421 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 34debc1..a753bbe 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 732ae16..be85191 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 e89acea..bbb016a 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 83ed2f8..cdc43b8 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 a98e814..f97fe77 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 2ee9ec3..53bbca7 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 f75c4d0..0a5f630 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 ab15509..e235bb9 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 8c0a0ae..b59e676 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 93ad6c1..a9b8cf5 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 b501e39..9ecedc2 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 5088784..3d8f126 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 c51edaa..08aa88d 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 df9e8e9..eef2ce9 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 f67ceb7..15e6bae 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 80adef7..0d6ff3e 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 1898559..b23a4d0 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 196f030..c64b827 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 96c52e4..cb4e205 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 d3053e9..e59e184 100644 (file)
@@ -532,18 +532,28 @@ struct rcu_exp_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.
  */
 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 85c5a88..56583e7 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 f19271d..4f6db7e 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 ff046b7..3603d93 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 b6e4c16..9c15a91 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 8dbaec0..1aea594 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 775569e..af344a1 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 a133ecd..7ad9e53 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 9d20d5d..95c6336 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 d4b0fa0..63177be 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 84016c8..12b8dd6 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 b06848a..eb9e9a7 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 86c8911..a3e14ce 100644 (file)
@@ -144,4 +144,3 @@ int ioremap_page_range(unsigned long addr,
 
        return err;
 }
-EXPORT_SYMBOL_GPL(ioremap_page_range);
index 25f5723..e68604a 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 0b92d60..84812a9 100644 (file)
@@ -769,7 +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(&node->private_list));
+                       WARN_ON_ONCE(!list_empty(&old->private_list));
                        radix_tree_node_free(old);
                        if (old == entry_to_node(node))
                                return;
index 975b8fc..a8d74a7 100644 (file)
@@ -483,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;
index d0e4d10..3f9afde 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 10eedbf..5f3ad65 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 3edb759..c7025c1 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 b82b3e2..f479365 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 e32389a..77ae323 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 4048897..b822e15 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 9f2c15c..6bf2b47 100644 (file)
@@ -3772,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;
@@ -3790,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);
@@ -3810,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 e43142c..b8c11e0 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 2e34664..1e7873e 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 2c6d5f6..f3e0c69 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 bb53285..3a7587a 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 29bc6c0..4f2ec6b 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 067598a..7ec0a96 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 1c6e032..4761701 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 6aa5b01..532a2a7 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 067a0d6..cabf09e 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 a100500..a29bb4b 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 4855d18..038b109 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 9c561e6..0854ebd 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 8ca6a92..95087e6 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 71c7453..7109b38 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 1108079..5488e4a 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 fca0fe9..b86f512 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 21ac753..95d13b2 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 a54ab0c..7056a1a 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 b075f02..6dc546a 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 3949ce7..292e33b 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 662bea5..ea63334 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 8db5a0b..29101c9 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 e23766c..d92de0a 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 fe4e153..1b7673a 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 71bb3e2..b3eef90 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 a5d4e86..c234650 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 7bb12e0..e7c12ca 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 5a03730..734c714 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 f560e08..4eca27d 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 adfc790..c4e879c 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 5fff951..0f99297 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 68c9eea..7d45961 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 8c5a479..516c87e 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 89a8cac..51b27ae 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 72d6f05..ae20616 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 eae0332..7db2ad2 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 7a5b4c7..9a375b9 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 5b15459..44fd86d 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 fac275c..b67719f 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 53ae0c6..9000117 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 fed3d29..0fd1976 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 21db00d..0a783cd 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 f273098..37fb955 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 fd82202..146d861 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 965b1a1..2981291 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 86cca61..68d77b1 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 0fcac8e..709ffe6 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 22cbd61..b2fa498 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 4a04496..0efb4c7 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 4e777a3..dd2560c 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 6c79075..41dcbd5 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 d46f4d5..ba8f02d 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 1d5331a..8ce50dc 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 f6c50af..3d063eb 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 1307a7c..8aab7d7 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 c1e124b..a7bcc0a 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 a3eaafd..eec27f8 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 e419850..275cac6 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 a7bc54a..13b5e85 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 7396e75..75c3082 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 75b6108..630b73b 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 89c59e6..fc7b401 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 38122d0..e164684 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,9 @@ 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)))
+               return -EAFNOSUPPORT;
 
        return 0;
 
@@ -1344,7 +1347,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 36d2921..75fac93 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 f4b4a4a..d82042c 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 14a3903..1bdc703 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 d5263dc..b12e61b 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 1009040..eedee5d 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 c947aad..765facf 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 8417c41..7ea8537 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 b172d85..a855eb3 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 ef1c8a4..6ef3dfb 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 bbfca22..c46f8cb 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 fad992a..99853c6 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 73bc8fc..4c60c6f 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 4d5c4ee..221825a 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 cfb9e5f..13190b3 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 7e08a4d..a646f34 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 8f560f7..aebf281 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 3d73278..28c2154 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 331ccf5..f47c452 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 3e821da..8bc5a1b 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 d0e1e80..5404d0d 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 e75cbf6..a0d901d 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 ecfdd97..5c3af5e 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 41497b6..d37ae7d 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 1822c77..56fb479 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 42120d9..50e1b7f 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 3e289a6..3090dd4 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 b6cfcf0..50c3090 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 0d8b716..797e847 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 6832bf6..43e45bb 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 15fe976..5b77377 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 2f7ccd9..1d281c1 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 63729b4..bbc45f8 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 3a073cd..4e8083c 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 3dca90d..ffb9e8a 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 a019a87..1b91376 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 7de2f46..049ad2d 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 6271e40..6f6e644 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 d4f97fa..e21aea7 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 415a65b..1ae8c49 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 36d2b10..7d699bb 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 3e19fa1..dbb6aaf 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 bd6efc5..2d6fe35 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 1e20e2b..e36069f 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 08376e5..f06f55e 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 28c56b9..ea7c670 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 6b78bab..54253ea 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 b9e1a13..0f03f6a 100644 (file)
@@ -1619,6 +1619,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 +1642,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 &&
@@ -1704,11 +1710,11 @@ 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;
 }
 
@@ -1717,23 +1723,22 @@ static void fanout_release(struct sock *sk)
        struct packet_sock *po = pkt_sk(sk);
        struct packet_fanout *f;
 
-       f = po->fanout;
-       if (!f)
-               return;
-
        mutex_lock(&fanout_mutex);
-       po->fanout = NULL;
+       f = po->fanout;
+       if (f) {
+               po->fanout = 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 (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);
 }
 
 static bool packet_extra_vlan_len_allowed(const struct net_device *dev,
@@ -1976,7 +1981,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 +2242,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 +2760,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 +2821,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;
index c985ecb..ae5ac17 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 2095c83..e10456e 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 1c60317..520baa4 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 adc7760..d9c9701 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 970db7a..5752789 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 f935429..b12bc2a 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 5ed8e79..64dfd35 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 7e869d0..4f5a2b5 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 e540826..34efaa4 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 318c678..1b5d669 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 a8c2307..0758e13 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 dc6fb79..25d9a9c 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 886e9d3..1530825 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 1efbe48..1dc9f3b 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 d1c330a..c73de18 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 3bc1d61..9c9db55 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 57d35fb..172b537 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 6b109a8..02462d6 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 bda89bf..4e8647a 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 a22be50..ab02d07 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 8d40861..2c3dc38 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 c1cfd92..23f8899 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 9d2f4c2..2775332 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 215849c..3cd6402 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 0dd0224..9d94e65 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 be60103..ffdc214 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 127656e..cef7987 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 3df85a7..aee396b 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 09f7fe7..d801406 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 92a4472..7ef2a12 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 5040586..4bfcaf9 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 6e69be3..3049b1f 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 0791b94..c3cfb23 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 455ef0d..db03607 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 f4fa6af..ccca1e3 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 85c38ec..0f4f6e8 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 1fc57a5..ca49568 100644 (file)
@@ -1073,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;
@@ -1082,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:
@@ -1180,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:
        {
@@ -1201,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:
@@ -1221,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:
        {
index eadcd4d..d883116 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 06121ce..c9235d8 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 299b92c..5d55441 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 29c89a6..4dedd0d 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 c7c6619..d98550a 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 c850345..dfa5156 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 0bec02e..450c518 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 cf9bc04..3fc201c 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 efe3a44..4576f98 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 5d1704e..514fd13 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 10c2a56..1ac96ef 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 8877b74..bb94d50 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 593b7d1..d72ccef 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 2998954..bdf8398 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 5034943..fde0866 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 507a86a..8d2fb2d 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 84b5101..6c6b63a 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 8fc3178..b30bd38 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 4bd68de..99b5b08 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 f1901bb..baa1afa 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 e7a1eaa..6aba140 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 65670b2..fbfb1fa 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 90009c0..ab3c280 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 b3fd238..eb4b9f7 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 0eb0e87..d2b0ac7 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 3ddb58a..ae752fa 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 a2f9853..4ac6c4b 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 3284bb1..8aad811 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 8866ac4..11c3be3 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 f1ce600..ec30c2f 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 5e0dea2..039636f 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 27fc361..5054d91 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 8fc2482..8bb16aa 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 9ff0db4..933aeec 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 35a02f8..915869e 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 74d6a03..4ec10e9 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 d53e706..5b134b0 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 3738839..18cfcdc 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 4292251..8b610dd 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 35c8e37..4f4b60f 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 6770a96..7d1b7d3 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 d4b6514..28c216e 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 d281ae2..6a6f44d 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;
@@ -268,21 +260,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
 }
 
 /*
- * 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.
  * Caller has to free mod_name after using it.
@@ -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 df4debe..0d9d6e0 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 f1d8558..2956c51 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 99400b0..adbc6c0 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 71b0589..831022b 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 b13fed5..9f7bd19 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 c09a682..16058bb 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 echo "--------------------"
 echo "running socket test"
index c22860a..30e1ac6 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 bdd58c7..df9e0a0 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 34e63cc..14142fa 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 2e69ca8..29b0d39 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 a2dbbcc..6a084cd 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 798866a..63e28dd 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 5114391..c737ea0 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 9bab867..834137e 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 5c9f974..e6b03fd 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 52abac4..6d2fcd6 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) {